Skip to content

Commit

Permalink
📦 NEW: Support localStorage getter (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
fengmk2 authored Dec 8, 2022
1 parent c75bab2 commit 71d7ddd
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 40 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ $ npm install sdk-base
Constructor argument:
- {Object} options
- {String} [initMethod] - the async init method name, the method should be a function return promise. If set, will execute the function in the constructor.
- {AsyncLocalStorage} [localStorage] - async localStorage instance.

```js
const Base = require('sdk-base');
Expand All @@ -35,6 +36,7 @@ Constructor argument:
constructor() {
super({
initMethod: 'init',
localStorage: app.ctxStorage,
});
}

Expand Down
46 changes: 21 additions & 25 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,29 @@
// Type definitions for sdk-base 3.4
// Project: https://github.com/node-modules/sdk-base
// Definitions by: Sang Lv <https://github.com/sang4lv>
// TypeScript Version: 2.9.2

/* =================== USAGE ===================
import Base from "sdk-base";
class newSDK extends Base {}
=============================================== */

/// <reference types="node" />
import Base from "sdk-base";
class newSDK extends Base {}
class newSDK extends Base<FooContext> {}
=============================================== */

import { EventEmitter } from 'events';
import { AsyncLocalStorage } from 'async_hooks';

interface BaseOptions {
initMethod?: string;
[key: string]: any;
export interface BaseOptions {
initMethod?: string;
localStorage?: any;
[key: string]: any;
}

export default class Base extends EventEmitter {
constructor(option?: BaseOptions);
export default class Base<TContext = any> extends EventEmitter {
constructor(option?: BaseOptions);

isReady: boolean;
options: BaseOptions;
await(...args: any[]): Promise<any>;
awaitFirst(...args: any[]): Promise<any>;
ready(): Promise<any>;
ready(err: Error): void;
ready(ready: boolean): void;
ready(readyCallback: Function): void;
readyOrTimeout(milliseconds: number): Promise<void>;
isReady: boolean;
options: BaseOptions;
localStorage?: AsyncLocalStorage<TContext>;
await(...args: any[]): Promise<any>;
awaitFirst(...args: any[]): Promise<any>;
ready(): Promise<any>;
ready(err: Error): void;
ready(ready: boolean): void;
ready(readyCallback: Function): void;
readyOrTimeout(milliseconds: number): Promise<void>;
}
8 changes: 8 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ class Base extends EventEmitter {
return this._ready;
}

/**
* get AsyncLocalStorage from options
* @return {AsyncLocalStorage} asyncLocalStorage instance or undefined
*/
get localStorage() {
return this.options.localStorage;
}

/**
* set ready state or onready callback
*
Expand Down
24 changes: 22 additions & 2 deletions index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
import { expectType } from 'tsd';
import { AsyncLocalStorage } from 'async_hooks';
import Base from '.';

class Client extends Base {

class MockContenxt {}

class Client extends Base<MockContenxt> {
constructor() {
super({
initMethod: 'init',
localStorage: new AsyncLocalStorage<MockContenxt>,
});
}
}

const client = new Client();

expectType<Promise<void>>(client.readyOrTimeout(1000));
expectType<Promise<any>>(client.ready());
expectType<MockContenxt | undefined>(client.localStorage?.getStore());

class ClientDefaultContext extends Base {
constructor() {
super({
initMethod: 'init',
});
}
}

const client2 = new ClientDefaultContext();
expectType<any | undefined>(client2.localStorage?.getStore());
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"lint": "eslint --ext .js .",
"tsd": "tsd",
"test": "npm run lint && npm run test-local",
"test": "npm run lint && npm run tsd && npm run test-local",
"test-local": "egg-bin test -r co-mocha",
"cov": "egg-bin cov -r co-mocha",
"ci": "npm run lint && npm run tsd && npm run cov",
Expand Down
21 changes: 14 additions & 7 deletions test/fixtures/ts/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import Base, { BaseOptions } from '../../..';

class Client extends Base {
class FooContext {
traceId?: string;
}

class ClientSimple extends Base {}

class Client extends Base<FooContext> {
errorHandlerLength: number = 0;

constructor(options?: BaseOptions) {
super(Object.assign({
constructor(options: BaseOptions & { foo: string }) {
super({
initMethod: 'init',
}, options));
...options,
});
}

init() {
Expand All @@ -32,12 +39,12 @@ class Client extends Base {
}

export async function test() {

let client;
let client: Client;

client = new Client();
client = new Client({ foo: 'bar' });
client.ready(() => {
console.log('ready');
console.log('localStorage should be undefined: %o', client.localStorage?.getStore());
});
await client.await('someEvent');
await client.awaitFirst([ 'one', 'two' ]);
Expand Down
16 changes: 11 additions & 5 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const pedding = require('pedding');
const Base = require('..');
const path = require('path');
const runscript = require('runscript');
const { AsyncLocalStorage } = require('async_hooks');
const baseDir = path.join(__dirname, './fixtures/ts');

function sleep(ms) {
Expand Down Expand Up @@ -121,6 +122,7 @@ describe('test/index.test.js', () => {
yield client.ready();
yield client.ready();
assert(client.foo === 'bar');
assert(client.localStorage === undefined);
});

it('should trigger ready callback without err', done => {
Expand Down Expand Up @@ -190,13 +192,17 @@ describe('test/index.test.js', () => {
}

it('should auto init with options.initMethod', async () => {
const client = new Client({ a: 'a' });
assert.deepEqual(client.options, {
a: 'a',
initMethod: 'init',
});
const localStorage = new AsyncLocalStorage();
const client = new Client({ a: 'a', localStorage });
assert(client.options.initMethod === 'init');
assert(client.isReady === false);
await client.ready();
assert(client.localStorage.getStore() === undefined);
await client.localStorage.run({ foo: 'bar' }, async () => {
assert(client.localStorage.getStore().foo === 'bar');
});
await client.ready();
assert(client.isReady === true);
assert(client.foo === 'bar');
});

Expand Down

0 comments on commit 71d7ddd

Please sign in to comment.