Update to include Gun.SEA & user APIs

This commit is contained in:
Jack Works
2019-03-19 13:24:53 +08:00
parent d64ec0ed99
commit fdc13d05d3
2 changed files with 230 additions and 22 deletions
+48
View File
@@ -28,7 +28,9 @@ interface AppState {
object: {
num: number;
str: string;
/** Comment test */
bool: boolean;
specstr: 'a' | 'b';
obj: {
arr2: Array<{ foo: number; bar: string }>;
};
@@ -47,6 +49,9 @@ app.get('object')
.get('obj')
.get('arr2')
.set({ foo: 1, bar: '2' });
app.get('object').put({
bool: true
});
app.get('object')
.get('bool')
@@ -70,3 +75,46 @@ app.get('chatRoom').time!(msg => {
}, 20);
// $ExpectError
app.get('object').time!({ a: 1 });
class X {
val: string;
b() {}
}
interface BadState {
// Top level primitives
a: 1;
b: {
// Ban functions
c: () => void;
// Ban class
d: typeof X;
// Recursive check for banned types
e: {
f: () => void;
};
};
// Filter, remove functions on prototype.
c: X;
}
const bad = new Gun<BadState>();
// $ExpectError
bad.get('a').put(1);
bad.get('b')
.get('c')
// $ExpectError
.put(() => {});
bad.get('b')
.get('d')
// $ExpectError
.put(X);
bad.get('b').put({
// $ExpectError
c: () => {},
// $ExpectError
d: X,
// $ExpectError
e: {
f: () => {}
}
});
+182 -22
View File
@@ -1,4 +1,4 @@
// Type definitions for gun 0.9
// Type definitions for gun 0.9.9999991
// Project: https://github.com/amark/gun#readme
// Definitions by: Jack Works <https://github.com/Jack-Works>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
@@ -12,6 +12,30 @@ declare namespace Gun {
/** Gun does not accept Array value, so we need extract to make types correct */
type AllowArray<T> = ArrayOf<T> extends never ? T : ArrayOf<T>;
type DisallowArray<T> = ArrayOf<T> extends never ? T : never;
/** These types cannot be stored on Gun */
type AlwaysDisallowedType<T> = T extends (...args: any[]) => void
? never
: T extends { new (...args: any[]): any }
? never
: AccessObject<T>;
type AccessObject<T> = T extends object
? { [key in keyof T]: (AlwaysDisallowedType<T[key]> extends never ? never : AccessObject<T[key]>) }
: T;
/** These types cannot be stored on Gun's root level */
type DisallowPrimitives<Open, T> = Open extends false
? T
: T extends string
? never
: T extends number
? never
: T extends boolean
? never
: T extends null
? never
: T extends undefined
? never
: T;
type ArrayAsRecord<DataType> = ArrayOf<DataType> extends never ? DataType : Record<string, any>;
/**
* options['module name'] allows you to pass options to a 3rd party module.
@@ -45,7 +69,8 @@ declare namespace Gun {
}>;
type Saveable<DataType> = Partial<DataType> | string | number | boolean | null | ChainReference<DataType>;
type AckCallback = (ack: { err: Error; ok: any } | { err: undefined; ok: string }) => void;
interface ChainReference<DataType = any, ReferenceKey = any> {
interface ChainReference<DataType = any, ReferenceKey = any, IsTop extends 'pre_root' | 'root' | false = false> {
//#region API
/**
* Save data into gun, syncing it with your connected peers.
*
@@ -59,7 +84,10 @@ declare namespace Gun {
*
* @param callback invoked on each acknowledgment
*/
put(data: DisallowArray<DataType>, callback?: AckCallback): ChainReference<DataType, ReferenceKey>;
put(
data: Partial<AlwaysDisallowedType<DisallowPrimitives<IsTop, DisallowArray<DataType>>>>,
callback?: AckCallback
): ChainReference<DataType, ReferenceKey, IsTop>;
/**
* Where to read data from.
* @param key The key is the ID or property name of the data that you saved from earlier
@@ -83,7 +111,7 @@ declare namespace Gun {
/** the key, ID, or property name of the data. */
paramB: Record<'off' | 'to' | 'next' | 'the' | 'on' | 'as' | 'back' | 'rid' | 'id', any>
) => void
): ChainReference<DataType[K], K>;
): ChainReference<DataType[K], K, IsTop extends 'pre_root' ? 'root' : false>;
/**
* Change the configuration of the gun database instance.
* @param options The options argument is the same object you pass to the constructor.
@@ -115,7 +143,10 @@ declare namespace Gun {
* To remove a listener call .off() on the same property or node.
*/
on(
callback: (data: ArrayAsRecord<DataType>, key: ReferenceKey) => void,
callback: (
data: DisallowPrimitives<IsTop, AlwaysDisallowedType<ArrayAsRecord<DataType>>>,
key: ReferenceKey
) => void,
option?: { change: boolean } | boolean
): ChainReference<DataType, ReferenceKey>;
/**
@@ -123,7 +154,10 @@ declare namespace Gun {
* @returns In the document, it said the return value may change in the future. Don't rely on it.
*/
once(
callback?: (data: (ArrayAsRecord<DataType>) | undefined, key: ReferenceKey) => void,
callback?: (
data: (DisallowPrimitives<IsTop, AlwaysDisallowedType<ArrayAsRecord<DataType>>>) | undefined,
key: ReferenceKey
) => void,
option?: { wait: number }
): ChainReference<DataType, ReferenceKey>;
/**
@@ -136,11 +170,13 @@ declare namespace Gun {
* **This means only objects, for now, are supported.**
*/
set(
data: DataType extends Array<infer U>
? U extends { [key: string]: any; [key: number]: any }
? ArrayOf<DataType>
data: AlwaysDisallowedType<
DataType extends Array<infer U>
? U extends { [key: string]: any; [key: number]: any }
? ArrayOf<DataType>
: never
: never
: never,
>,
callback?: AckCallback
): ChainReference<ArrayOf<DataType>>;
/**
@@ -157,8 +193,8 @@ declare namespace Gun {
* Remove **all** listener on this node.
*/
off(): void;
// Extended API
//#endregion
//#region Extended API
/**
*
* Path does the same thing as `.get` but has some conveniences built in.
@@ -256,15 +292,76 @@ declare namespace Gun {
): ChainReference<DataType, ReferenceKey>;
/** Pushes data to a Timegraph with it's time set to Gun.state()'s time */
time?(data: ArrayOf<DataType>): void;
//#endregion
//#region User
/**
* Creates a new user and calls callback upon completion.
* @param alias Username or Alias which can be used to find a user.
* @param pass Passphrase that will be extended with PBKDF2 to make it a secure way to login.
* @param cb Callback that is to be called upon creation of the user.
* @param opt Option Object containing options for creation. (In gun options are added at end of syntax. opt is rarely used, hence is added at the end.)
*/
create(
alias: string,
pass: string,
cb?: (ack: { ok: 0; pub: string } | { err: string }) => void,
opt?: {}
): ChainReference;
/**
* Authenticates a user, previously created via User.create.
* @param alias Username or Alias which can be used to find a user.
* @param pass Passphrase for the user
* @param cb Callback that is to be called upon authentication of the user.
* @param opt Option Object containing options for authentiaction. (In gun options are added at end of syntax. opt is rarely used, hence is added at the end.)
*/
auth(
alias: string,
pass: string,
cb?: (
ack:
| {
ack: 2;
get: string;
on: (...args: [unknown, unknown, unknown]) => unknown;
put: { alias: string; auth: any; epub: string; pub: string };
sea: CryptoKeyPair;
soul: string;
}
| { err: string }
) => void,
opt?: {}
): ChainReference;
/**
* Returns the key pair in the form of an object as below.
*/
pair(): CryptoKeyPair;
/**
* Log out currently authenticated user. Parameters are unused in the current implementation.
* @param opt unused in current implementation.
* @param cb unused in current implementation.
*/
leave(opt?: never, cb?: never): ChainReference;
/**
* Deletes a user from the current gun instance and propagates the delete to other peers.
* @param alias Username or alias.
* @param pass Passphrase for the user.
* @param cb Callback that is called when the user was successfully deleted.
*/
delete(alias: string, pass: string, cb?: (ack: { ok: 0 }) => void): Promise<void>;
/**
* Recall saves a users credentials in sessionStorage of the browser. As long as the tab of your app is not closed the user stays logged in, even through page refreshes and reloads.
* @param opt option object If you want to use browser sessionStorage to allow users to stay logged in as long as the session is open, set opt.sessionStorage to true
* @param cb internally the callback is passed on to the user.auth function to logged the user back in. Refer to user.auth for callback documentation.
*/
recall(opt?: { sessionStorage: boolean }, cb?: Parameters<ChainReference['auth']>[2]): ChainReference;
/**
* @param publicKey If you know a users publicKey you can get his user graph and see any unencrypted data he may have stored there.
*/
user(publicKey?: string): ChainReference;
//#endregion
}
interface GunSEA {
// There is no the only content in the api document.
user: {
create(alias: string, passphrase: string, callback: (...args: any[]) => void): any;
};
}
type CryptoKeyPair = Record<'pub' | 'priv' | 'epub' | 'epriv', string>;
interface Constructor {
/**
* @description
@@ -274,8 +371,12 @@ declare namespace Gun {
*
* or you can pass in an array of URLs to sync with multiple peers.
*/
<DataType = any>(options?: string | string[] | ConstructorOptions): ChainReference<DataType> & GunSEA;
new <DataType = any>(options?: string | string[] | ConstructorOptions): ChainReference<DataType> & GunSEA;
<DataType = any>(options?: string | string[] | ConstructorOptions): ChainReference<DataType, any, 'pre_root'>;
new <DataType = any>(options?: string | string[] | ConstructorOptions): ChainReference<
DataType,
any,
'pre_root'
>;
node: {
/** Returns true if data is a gun node, otherwise false. */
is(anything: any): anything is ChainReference;
@@ -289,7 +390,66 @@ declare namespace Gun {
ify(json: any): any;
};
/** @see https://gun.eco/docs/SEA */
SEA: any;
SEA: {
/** If you want SEA to throw while in development, turn SEA.throw = true on, but please do not use this in production. */
throw?: boolean;
/** Last known error */
err?: Error;
/**
* This gives you a Proof of Work (POW) / Hashing of Data
* @param data The data to be hashed, work to be performed on.
* @param pair (salt) You can pass pair of keys to use as salt. Salt will prevent others to pre-compute the work,
* so using your public key is not a good idea. If it is not specified, it will be random,
* which ruins your chance of ever being able to re-derive the work deterministically
* @param callback function to executed upon execution of proof
* @param opt default: {name: 'PBKDF2', encode: 'base64'}
*/
work(
data: any,
pair?: any,
callback?: (data: string | void) => void,
opt?: Partial<{
name: 'SHA-256' | 'PBKDF2';
encode: 'base64' | 'base32' | 'base16';
/** iterations to use on subtle.deriveBits */
iterations: number;
salt: any;
hash: string;
length: any;
}>
): Promise<string | undefined>;
/**
* This generates a cryptographically secure public/private key pair - be careful not to leak the private keys!
* Note: API subject to change we may change the parameters to accept data and work, in addition to generation.
* You will need this for most of SEA's API, see those method's examples.
* The default cryptographic primitives for the asymmetric keys are ECDSA for signing and ECDH for encryption.
*/
pair(cb: (data: CryptoKeyPair) => void, opt?: {}): Promise<CryptoKeyPair | undefined>;
/**
* Adds a signature to a message, for data that you want to prevent attackers tampering with.
* @param data is the content that you want to prove is authorized.
* @param pair is from .pair.
*/
sign(data: any, pair: CryptoKeyPair): Promise<string | undefined>;
/**
* Gets the data if and only if the message can be verified as coming from the person you expect.
* @param message is what comes from .sign.
* @param pair from .pair or its public key text (pair.pub).
*/
verify(message: any, pair: CryptoKeyPair | string): Promise<unknown>;
/**
* Takes some data that you want to keep secret and encrypts it so nobody else can read it.
* @param data is the content that you want to encrypt.
* @param pair from .pair or a passphrase you want to use as a cypher to encrypt with.
*/
encrypt(data: any, pair: CryptoKeyPair | string): Promise<string>;
/**
* Read the secret data, if and only if you are allowed to.
* @param message is what comes from .encrypt.
* @param pair from .pair or the passphrase to decypher the message.
*/
decrypt(message: any, pair: CryptoKeyPair | string): Promise<unknown>;
};
}
}
declare const Gun: Gun.Constructor;