diff --git a/global.d.ts b/global.d.ts deleted file mode 100644 index ffb1799c..00000000 --- a/global.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { IGun } from './types/gun/IGun'; -declare global { - var Gun: IGun; -} diff --git a/gun.d.ts b/gun.d.ts index 7cd5f72a..30f9dc54 100644 --- a/gun.d.ts +++ b/gun.d.ts @@ -1,3 +1,23 @@ -import { IGun } from './types/gun/IGun'; +import { IGun, LEX } from './types/gun'; + declare const Gun: IGun; -export = Gun; \ No newline at end of file +export default Gun; + +import {} from './types/gun/IGun'; +declare module './types/gun/IGun' { + export interface IGun { + window: Window + } +} + +declare global { + interface Window { + Gun: IGun; + GUN: IGun; + } + + interface StringConstructor { + match(t: string, o: LEX | string): boolean; + random(length?: number, alphabet?: string): string; + } +} diff --git a/index.d.ts b/index.d.ts index 0db8a5f8..7922ffeb 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,3 +1,19 @@ -import { IGun } from './types/gun/IGun'; +export * from './types/gun'; +export * from './types/sea'; + +import { IGun, LEX } from './types/gun'; +import { ISEA } from './types/sea'; + declare const Gun: IGun; -export = Gun; +export default Gun; + +export const SEA: ISEA; + +declare global { + const Gun: IGun; + + interface StringConstructor { + match(t: string, o: LEX | string): boolean; + random(length?: number, alphabet?: string): string; + } +} diff --git a/lib/later.d.ts b/lib/later.d.ts new file mode 100644 index 00000000..f5a5f02f --- /dev/null +++ b/lib/later.d.ts @@ -0,0 +1,31 @@ +import {} from '../types/gun/IGunChain'; +declare module '../types/gun/IGunChain' { + export interface IGunChain { + /** + * > Warning: Dependency script for browser: ` + * + * Exact timing is not guaranteed! Because it uses `setTimeout` underneath. Further, after + * the timeout, it must then open and load the snapshot, this will likely add at least 1ms + * to the delay. Experimental: If this is problematic, please report it, as we can modify + * the implementation of later to be more precise.) + * + * If a process/browser has to restart, the timeout will not be called. Experimental: If + * this behavior is needed, please report it, as it could be added to the implementation + * + * Say you save some data, but want to do something with it later, like expire it or refresh + * it. Well, then later is for you! You could use this to easily implement a TTL or similar + * behavior + * + * @param seconds the number of seconds you want to wait before firing the callback + */ + later( + /** + * @param data a safe snapshot of what you saved, including full depth documents or circular + * graphs, without any of the metadata + * @param key name of the data + */ + callback: (data: TNode, key: string) => void, + seconds: number + ): IGunChain; + } +} diff --git a/lib/load.d.ts b/lib/load.d.ts new file mode 100644 index 00000000..08dce483 --- /dev/null +++ b/lib/load.d.ts @@ -0,0 +1,13 @@ +import {} from '../types/gun/IGunChain'; +declare module '../types/gun/IGunChain' { + export interface IGunChain { + /** + * > Warning: Dependency script for browser: ` + * + * Loads the full object once. It is the same as open but with the behavior of once + */ + load( + callback: (data: TNode) => void + ): IGunChain; + } +} diff --git a/lib/not.d.ts b/lib/not.d.ts new file mode 100644 index 00000000..60ae2814 --- /dev/null +++ b/lib/not.d.ts @@ -0,0 +1,17 @@ +import {} from '../types/gun/IGunChain'; +declare module '../types/gun/IGunChain' { + export interface IGunChain { + /** + * > Warning: `.not` has no guarantees, since data could theoretically exist on an unrelated + * peer that we have no knowledge of. If you only have one server, and data is synced + * through it, then you have a pretty reasonable assurance that a not found means that + * the data doesn't exist yet. Just be mindful of how you use it + * + * @param callack If there's reason to believe the data doesn't exist, the callback will be + * invoked. This can be used as a check to prevent implicitly writing data + */ + not( + callack: (key: string) => void + ): IGunChain; + } +} diff --git a/lib/open.d.ts b/lib/open.d.ts new file mode 100644 index 00000000..198d30cf --- /dev/null +++ b/lib/open.d.ts @@ -0,0 +1,23 @@ +import {} from '../types/gun/IGunChain'; +declare module '../types/gun/IGunChain' { + export interface IGunChain { + /** + * Note: This will automatically load everything it can find on the context. This may sound + * convenient, but may be unnecessary and excessive - resulting in more bandwidth and + * slower load times for larger data. It could also result in your entire database being + * loaded, if your app is highly interconnected + * + * Open behaves very similarly to `gun.on`, except it gives you the full depth of a document + * on every update. It also works with graphs, tables, or other data structures. Think of + * it as opening up a live connection to a document + * + * @param callback The callback has 1 parameter, and will get called every time an update + * happens anywhere in the full depth of the data. Unlike most of the API, open does not + * give you a node. It gives you a copy of your data with all metadata removed. Updates to + * the callback will return the same data, with changes modified onto it + */ + open( + callback: (data: TNode) => void + ): IGunChain; + } +} diff --git a/lib/path.d.ts b/lib/path.d.ts new file mode 100644 index 00000000..c3b900c3 --- /dev/null +++ b/lib/path.d.ts @@ -0,0 +1,57 @@ +import { IGunChain, GunSchema } from '../types/gun'; + +import {} from '../types/gun/IGunInstance'; +declare module '../types/gun/IGunInstance' { + export interface IGunInstance { + /** + * > Warning: This extension was removed from core, you probably shouldn't be using it! + * + * Path does the same thing as get but has some conveniences built in + * + * Once you've changed the context, you can read, write, and path again from that field. + * While you can just chain one path after another, it becomes verbose, so there are two + * shorthand styles: + * - dot format + * - array format + * + * The dot notation can do some strange things if you're not expecting it. Under the hood, + * everything is changed into a string, including floating point numbers. If you use a + * decimal in your path, it will split into two paths... + * + * This can be especially confusing as the chain might never resolve to a value + */ + path>( + value: string | string[] + ): IGunChain, string>; + } +} + +import {} from '../types/gun/IGunChain'; +declare module '../types/gun/IGunChain' { + export interface IGunChain { + /** + * > Warning: This extension was removed from core, you probably shouldn't be using it! + * + * > Warning: Not included by default! You must + * include it yourself via `require('gun/lib/path.js')` or + * ``! + * + * Path does the same thing as get but has some conveniences built in + * + * Once you've changed the context, you can read, write, and path again from that field. + * While you can just chain one path after another, it becomes verbose, so there are two + * shorthand styles: + * - dot format + * - array format + * + * The dot notation can do some strange things if you're not expecting it. Under the hood, + * everything is changed into a string, including floating point numbers. If you use a + * decimal in your path, it will split into two paths... + * + * This can be especially confusing as the chain might never resolve to a value + */ + path>( + value: string | string[] + ): IGunChain; + } +} diff --git a/lib/promise.d.ts b/lib/promise.d.ts new file mode 100644 index 00000000..48a1beaf --- /dev/null +++ b/lib/promise.d.ts @@ -0,0 +1,105 @@ +import { IGunChain2TNode } from '../types/utils.d'; +import { + GunCallbackOn, + GunDataNode, + GunMessagePut, + GunOptionsOn, + GunOptionsOnce, + GunOptionsPut, + IGunChain, + GunSchema, + GunSoul, +} from '../types/gun'; + +import {} from '../types/gun/IGunInstance'; +declare module '../types/gun/IGunInstance' { + export interface IGunInstance { + /** + * @param value the data to save + * @param options `put` options + */ + promPut>( + value: V, + options: GunOptionsPut + ): Promise<{ + ref: IGunChain, IGunInstance, ''>; + ack: GunMessagePut; + }>; + } +} + +import {} from '../types/gun/IGunChain'; +declare module '../types/gun/IGunChain' { + export interface IGunChain { + /** + * @param value the data to save + * @param options `put` options + */ + promPut< + V extends + | (TNode extends object ? Partial : TNode) + | GunSoul + | IGunChain + | IGunChain, any, any, any> + >( + value: V, + options: GunOptionsPut + ): Promise<{ + ref: IGunChain; + ack: GunMessagePut; + }>; + + /** + * @param value the data to save + * @param options `put` options + */ + promSet< + V extends Partial | GunSoul | IGunChain, + K extends keyof TNode & string, + N extends TNode[K] & Record + >( + value: V, + options: GunOptionsPut + ): Promise<{ + ref: V extends GunSchema + ? IGunChain< + N, + IGunChain, + TGunInstance, + K + > + : IGunChain< + IGunChain2TNode, + IGunChain, + TGunInstance, + K + >; + ack: GunMessagePut; + }>; + + /** + * @param callback function to be called upon changes to data + * @param options `put` options + */ + promOn( + callback: GunCallbackOn, + options: GunOptionsOn + ): Promise>; + + /** + * @param limit due to promises resolving too fast if we do not set a timer we will not be + * able receive any data back from gun before returning the promise works both following a + * `Chain.get` and a `Chain.map` (limit only applies to map). If no limit is chosen, + * defaults to 100 ms (quite sufficient to fetch about 2000 nodes or more) + * @param options `once` options + */ + promOnce( + limit: number, + options: GunOptionsOnce + ): Promise<{ + ref: IGunChain; + data: GunDataNode; + key: keyof IGunChain2TNode & string; + }>; + } +} diff --git a/lib/radisk.d.ts b/lib/radisk.d.ts new file mode 100644 index 00000000..8ece2bfe --- /dev/null +++ b/lib/radisk.d.ts @@ -0,0 +1,15 @@ +import { IRadix } from './radix'; + +import {} from './radisk' +declare module './radisk' { + export const Radisk: IRadisk; + export interface IRadisk { + Radix: IRadix; + } +} + +declare global { + interface Window { + Radisk: IRadisk; + } +} diff --git a/lib/radix.d.ts b/lib/radix.d.ts new file mode 100644 index 00000000..7a0f534d --- /dev/null +++ b/lib/radix.d.ts @@ -0,0 +1,11 @@ +import {} from './radix' +declare module './radix' { + export const Radix: IRadix; + export interface IRadix {} +} + +declare global { + interface Window { + Radix: IRadix; + } +} diff --git a/lib/rindexed.d.ts b/lib/rindexed.d.ts new file mode 100644 index 00000000..164986d9 --- /dev/null +++ b/lib/rindexed.d.ts @@ -0,0 +1,14 @@ +import {} from './rindexed' +declare module './rindexed' { + export const Store: IRindexedDB; + export interface IRindexedDB { + indexedDB: IRindexedDB; + window: Window; + } +} + +declare global { + interface Window { + RindexedDB: IRindexedDB; + } +} diff --git a/lib/store.d.ts b/lib/store.d.ts new file mode 100644 index 00000000..9397b98e --- /dev/null +++ b/lib/store.d.ts @@ -0,0 +1,2 @@ +import {} from './store' +declare module './store' {} diff --git a/lib/then.d.ts b/lib/then.d.ts new file mode 100644 index 00000000..f51b07cc --- /dev/null +++ b/lib/then.d.ts @@ -0,0 +1,26 @@ +import { GunDataNode, IGunChain } from '..'; + +import {} from '../types/gun/IGunChain'; +declare module '../types/gun/IGunChain' { + export interface IGunChain { + /** + * Could be buggy until official! + * + * Note: a gun chain is not promises! You must include and call `.then()` to promisify a gun + * chain! + */ + then(): Promise>; + + /** + * Could be buggy until official! + * + * `.then()` has a cousin of `.promise()` which behaves the same way except that resolved + * is an object in case you need more context or metadata + */ + promise(): Promise<{ + put: GunDataNode; + get: TKey; + gun: IGunChain; + }>; + } +} diff --git a/lib/unset.d.ts b/lib/unset.d.ts new file mode 100644 index 00000000..fb991a34 --- /dev/null +++ b/lib/unset.d.ts @@ -0,0 +1,23 @@ +import { GunSchema, GunSoul, IGunChain } from '..'; + +import {} from '../types/gun/IGunChain'; +import { IGunChain2TNode } from '../types/utils'; +declare module '../types/gun/IGunChain' { + export interface IGunChain { + /** + * After you save some data in an unordered list, you may need to remove it + */ + unset< + T extends Partial | GunSoul | IGunChain, + K extends keyof TNode & string, + V extends TNode[K] & Record + >( + node: IGunChain< + IGunChain2TNode, + IGunChain, + TGunInstance, + K + > + ): IGunChain; + } +} diff --git a/lib/webrtc.d.ts b/lib/webrtc.d.ts new file mode 100644 index 00000000..2dab2fd8 --- /dev/null +++ b/lib/webrtc.d.ts @@ -0,0 +1,2 @@ +import {} from './webrtc' +declare module './webrtc' {} diff --git a/sea.d.ts b/sea.d.ts new file mode 100644 index 00000000..cf6c647a --- /dev/null +++ b/sea.d.ts @@ -0,0 +1,21 @@ +import { ISEA } from './types/sea/ISEA'; + +import {} from './types/sea/ISEA'; +declare module './types/sea/ISEA' { + export interface ISEA { + window: Window + } +} + +import {} from './types/gun/IGun'; +declare module './types/gun/IGun' { + export interface IGun { + SEA: ISEA; + } +} + +declare global { + interface Window { + SEA: ISEA; + } +} diff --git a/tsconfig.json b/tsconfig.json index c726358e..84fab29a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,14 +4,14 @@ "declaration": true, }, "include": [ - // only compile the type definitions by default. - // That is, ignore the files in 'examples/**' - "types/**.d.ts" + // only compile the type definitions by default. + // That is, ignore the files in 'examples/**' + "**/*.d.ts" ], "exclude": [ // Among the type definitions, don't try to compile // the test file which implements bad types. // It implements bad types for testing purposes. - "types/index.test-d.ts" + "**/*.test-d.ts" ] } diff --git a/types/gun/AckCallback.d.ts b/types/gun/AckCallback.d.ts deleted file mode 100644 index 936080e4..00000000 --- a/types/gun/AckCallback.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -export declare type AckCallback = (ack: { - err: string; - ok: undefined; -} | { - err: undefined; - ok: string; -}) => void; \ No newline at end of file diff --git a/types/gun/AuthCallback.d.ts b/types/gun/AuthCallback.d.ts deleted file mode 100644 index 291a0ff1..00000000 --- a/types/gun/AuthCallback.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ISEAPair } from "../sea/ISEAPair"; - -export type AuthCallback = (ack: { - ack: 2; - ing: false, - id: number, - get: string; - on: (tag:unknown , args:unknown, as: unknown) => unknown; - put: { - alias: string; - auth: string; - epub: string; - pub: string; - }; - sea: ISEAPair; - err?: undefined; - soul: string; -} | { - err: string; -}) => void \ No newline at end of file diff --git a/types/gun/CreateCallback.d.ts b/types/gun/CreateCallback.d.ts deleted file mode 100644 index f5ad3d29..00000000 --- a/types/gun/CreateCallback.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type CreateCallback = (ack: { - ok: 0; - pub: string; - err?:undefined -} | { - ok?: 0; - pub?: string; - err: string; -}) => any \ No newline at end of file diff --git a/types/gun/GunCallbackGet.d.ts b/types/gun/GunCallbackGet.d.ts new file mode 100644 index 00000000..1a7dfde8 --- /dev/null +++ b/types/gun/GunCallbackGet.d.ts @@ -0,0 +1,18 @@ +import { GunDataNode, GunSchema, GunSoul } from '.'; +import { GunSoul2Soul } from '../utils'; + +type GunMessageGet< + N extends GunSchema, + K extends (keyof N & string) | GunSoul2Soul>, + V = K extends keyof N & string ? N[K] : N +> = { + /** key */ + get: K; + /** value */ + put: GunDataNode; +}; + +export type GunCallbackGet< + N extends GunSchema, + K extends (keyof N & string) | GunSoul2Soul> +> = (ack: GunMessageGet) => void; diff --git a/types/gun/GunCallbackMap.d.ts b/types/gun/GunCallbackMap.d.ts new file mode 100644 index 00000000..cb8640d9 --- /dev/null +++ b/types/gun/GunCallbackMap.d.ts @@ -0,0 +1,7 @@ +import { GunDataNode, GunSchema } from '.'; + +export type GunCallbackMap< + V extends N[K], + K extends keyof N & string, + N extends GunSchema +> = (data: GunDataNode, key: K) => any; diff --git a/types/gun/GunCallbackOn.d.ts b/types/gun/GunCallbackOn.d.ts new file mode 100644 index 00000000..287d58b7 --- /dev/null +++ b/types/gun/GunCallbackOn.d.ts @@ -0,0 +1,8 @@ +import { GunDataNode, GunHookMessagePut, IGunOnEvent, GunSchema } from '.'; + +export type GunCallbackOn = ( + data: GunDataNode, + key: K, + message: GunHookMessagePut, + event: IGunOnEvent +) => void; diff --git a/types/gun/GunCallbackOnce.d.ts b/types/gun/GunCallbackOnce.d.ts new file mode 100644 index 00000000..9a613883 --- /dev/null +++ b/types/gun/GunCallbackOnce.d.ts @@ -0,0 +1,6 @@ +import { GunDataNode, GunSchema } from '.'; + +export type GunCallbackOnce = ( + data: GunDataNode, + key: K +) => void; diff --git a/types/gun/GunCallbackPut.d.ts b/types/gun/GunCallbackPut.d.ts new file mode 100644 index 00000000..94d9b241 --- /dev/null +++ b/types/gun/GunCallbackPut.d.ts @@ -0,0 +1,11 @@ +export type GunMessagePut = + | { + /** if there was an error during save */ + err: string; + } + | { + /** if there was a success message (none is required though) */ + ok: { '': 1 }; + }; + +export type GunCallbackPut = (ack: GunMessagePut) => void; diff --git a/types/gun/GunDataNode.d.ts b/types/gun/GunDataNode.d.ts new file mode 100644 index 00000000..e018510f --- /dev/null +++ b/types/gun/GunDataNode.d.ts @@ -0,0 +1,16 @@ +import { GunSchema, GunSoul, IGunMeta } from '.'; + +export type GunDataNode = T extends GunSchema & object + ? { + [K in keyof T]: Exclude< + T[K], + string | number | boolean | null | undefined + > extends never + ? T[K] + : + | GunSoul< + Exclude + > + | Exclude; + } & IGunMeta + : T; diff --git a/types/gun/GunHookCallbackBye.d.ts b/types/gun/GunHookCallbackBye.d.ts new file mode 100644 index 00000000..a64f2b2b --- /dev/null +++ b/types/gun/GunHookCallbackBye.d.ts @@ -0,0 +1,6 @@ +import { IGunHookContext, GunPeer } from '.'; + +export type GunHookCallbackBye = ( + this: IGunHookContext, + peer: GunPeer +) => void; diff --git a/types/gun/GunHookCallbackCreate.d.ts b/types/gun/GunHookCallbackCreate.d.ts new file mode 100644 index 00000000..e0e43d03 --- /dev/null +++ b/types/gun/GunHookCallbackCreate.d.ts @@ -0,0 +1,6 @@ +import { IGunHookContext, _GunRoot } from '.'; + +export type GunHookCallbackCreate = ( + this: IGunHookContext<_GunRoot>, + root: _GunRoot +) => void; diff --git a/types/gun/GunHookCallbackGet.d.ts b/types/gun/GunHookCallbackGet.d.ts new file mode 100644 index 00000000..9eede286 --- /dev/null +++ b/types/gun/GunHookCallbackGet.d.ts @@ -0,0 +1,12 @@ +import { pany, IGunHookContext, GunNodeGet, _GunRoot } from '.'; + +type GunHookMessageGet = { + $: { _: _GunRoot }; + '#': string; + get: GunNodeGet; +} & Partial; + +export type GunHookCallackGet = ( + this: IGunHookContext>, + message: GunHookMessageGet +) => void; diff --git a/types/gun/GunHookCallbackHi.d.ts b/types/gun/GunHookCallbackHi.d.ts new file mode 100644 index 00000000..6d16b90d --- /dev/null +++ b/types/gun/GunHookCallbackHi.d.ts @@ -0,0 +1,6 @@ +import { IGunHookContext, GunPeer } from '.'; + +export type GunHookCallbackHi = ( + this: IGunHookContext, + peer: GunPeer +) => void; diff --git a/types/gun/GunHookCallbackIn.d.ts b/types/gun/GunHookCallbackIn.d.ts new file mode 100644 index 00000000..6f1cc6a3 --- /dev/null +++ b/types/gun/GunHookCallbackIn.d.ts @@ -0,0 +1,19 @@ +import { pany, IGunHookContext, GunDataNode, GunNodeGet, _GunRoot } from '.'; + +export type GunHookMessageIn< + MessageExtension extends pany, + MetaExtension extends pany +> = { + $: { _: _GunRoot }; + '#': string; + get?: GunNodeGet; + put?: { [nodePath: string]: GunDataNode & { _: MetaExtension } }; +} & Partial; + +export type GunHookCallbackIn< + MessageExtension extends pany, + MetaExtension extends pany +> = ( + this: IGunHookContext>, + message: GunHookMessageIn +) => void; diff --git a/types/gun/GunHookCallbackOpt.d.ts b/types/gun/GunHookCallbackOpt.d.ts new file mode 100644 index 00000000..9491298f --- /dev/null +++ b/types/gun/GunHookCallbackOpt.d.ts @@ -0,0 +1,3 @@ +import { IGunHookContext, _GunRoot } from '.'; + +export type GunHookCallbackOpt = (this: IGunHookContext<_GunRoot>, root: _GunRoot) => void; diff --git a/types/gun/GunHookCallbackOut.d.ts b/types/gun/GunHookCallbackOut.d.ts new file mode 100644 index 00000000..10c567ca --- /dev/null +++ b/types/gun/GunHookCallbackOut.d.ts @@ -0,0 +1,19 @@ +import { IGunHookContext, pany, GunDataNode, GunNodeGet, _GunRoot } from '.'; + +export type GunHookMessageOut< + MessageExtension extends pany, + MetaExtension extends pany +> = { + $: { _: _GunRoot }; + '#': string; + get?: GunNodeGet; + put?: { [nodePath: string]: GunDataNode & { _: MetaExtension } }; +} & Partial; + +export type GunHookCallbackOut< + MessageExtension extends pany, + MetaExtension extends pany +> = ( + this: IGunHookContext>, + message: GunHookMessageOut +) => void; diff --git a/types/gun/GunHookCallbackPut.d.ts b/types/gun/GunHookCallbackPut.d.ts new file mode 100644 index 00000000..fa47ee54 --- /dev/null +++ b/types/gun/GunHookCallbackPut.d.ts @@ -0,0 +1,12 @@ +import { GunNodePut, IGunHookContext, _GunRoot } from '.'; + +type GunHookMessagePut = { + $: { _: _GunRoot }; + '#'?: string; + put: GunNodePut; +}; + +export type GunHookCallbackPut = ( + this: IGunHookContext, + message: GunHookMessagePut +) => void; diff --git a/types/gun/GunNodeGet.d.ts b/types/gun/GunNodeGet.d.ts new file mode 100644 index 00000000..a00bef31 --- /dev/null +++ b/types/gun/GunNodeGet.d.ts @@ -0,0 +1,6 @@ +export type GunNodeGet = { + /** Node path */ + '#': string; + /** Leaf name */ + '.': string; +}; diff --git a/types/gun/GunNodePut.d.ts b/types/gun/GunNodePut.d.ts new file mode 100644 index 00000000..c0da11e5 --- /dev/null +++ b/types/gun/GunNodePut.d.ts @@ -0,0 +1,8 @@ +import { GunNodeGet, GunValueSimple } from '.'; + +export type GunNodePut = GunNodeGet & { + /** Leaf value */ + ':': GunValueSimple; + /** Leaf timestamp */ + '>': number; +}; diff --git a/types/gun/GunOptions.d.ts b/types/gun/GunOptions.d.ts new file mode 100644 index 00000000..09234c48 --- /dev/null +++ b/types/gun/GunOptions.d.ts @@ -0,0 +1,37 @@ +export type GunOptions = + | Partial<{ + /** Undocumented but mentioned. Write data to a JSON. */ + file: string; + + /** Undocumented but mentioned. Create a websocket server */ + web: any; + + /** Undocumented but mentioned. Amazon S3 */ + s3: { + key: string; + secret: string; + bucket: string; + region?: string; + fakes3?: any; + }; + + /** the URLs are properties, and the value is an empty object. */ + peers: string[] | Record; + + /** default: true, creates and persists local (nodejs) data using Radisk. */ + radisk: boolean; + + /** default: true, persists local (browser) data to localStorage. */ + localStorage: boolean; + + /** uuid allows you to override the default 24 random alphanumeric soul generator with your own function. */ + uuid(): string; + + /** + * allows you to pass options to a 3rd party module. Their project README will likely list the exposed options + * @see https://github.com/amark/gun/wiki/Modules + */ + [key: string]: any; + }> + | string + | string[]; diff --git a/types/gun/GunOptionsOn.d.ts b/types/gun/GunOptionsOn.d.ts new file mode 100644 index 00000000..37b9e008 --- /dev/null +++ b/types/gun/GunOptionsOn.d.ts @@ -0,0 +1,6 @@ +export type GunOptionsOn = Partial< + | { + change: boolean; + } + | boolean +>; diff --git a/types/gun/GunOptionsOnce.d.ts b/types/gun/GunOptionsOnce.d.ts new file mode 100644 index 00000000..b4b7d809 --- /dev/null +++ b/types/gun/GunOptionsOnce.d.ts @@ -0,0 +1,6 @@ +export type GunOptionsOnce = Partial<{ + /** + * controls the asynchronous timing + */ + wait: number; +}>; diff --git a/types/gun/GunOptionsPut.d.ts b/types/gun/GunOptionsPut.d.ts new file mode 100644 index 00000000..707de5bd --- /dev/null +++ b/types/gun/GunOptionsPut.d.ts @@ -0,0 +1,5 @@ +export type GunOptionsPut = Partial<{ + opt: { + /** certificate that gives other people write permission */ cert: string; + }; +}>; diff --git a/types/gun/GunPeer.d.ts b/types/gun/GunPeer.d.ts new file mode 100644 index 00000000..908168f5 --- /dev/null +++ b/types/gun/GunPeer.d.ts @@ -0,0 +1,6 @@ +export type GunPeer = { + id: string; + url: string; + queue: string[]; + wire: null | WebSocket | RTCDataChannel; +}; diff --git a/types/gun/GunSchema.d.ts b/types/gun/GunSchema.d.ts new file mode 100644 index 00000000..6a8e4692 --- /dev/null +++ b/types/gun/GunSchema.d.ts @@ -0,0 +1,17 @@ +import { GunValueSimple, IGunChain, IGunInstanceRoot } from '.'; + +interface IGunSchema { + [key: string]: + | Exclude< + IGunSchema, + IGunChain | IGunInstanceRoot + > + | GunValueSimple; +} + +export type GunSchema = + | Exclude< + IGunSchema, + IGunChain | IGunInstanceRoot + > + | GunValueSimple; diff --git a/types/gun/GunSoul.d.ts b/types/gun/GunSoul.d.ts new file mode 100644 index 00000000..672405b6 --- /dev/null +++ b/types/gun/GunSoul.d.ts @@ -0,0 +1,4 @@ +import { GunSchema } from '.'; +export type GunSoul<_N extends GunSchema, Soul extends string = string> = { + '#': Soul; +}; diff --git a/types/gun/GunValueSimple.d.ts b/types/gun/GunValueSimple.d.ts new file mode 100644 index 00000000..3f357114 --- /dev/null +++ b/types/gun/GunValueSimple.d.ts @@ -0,0 +1 @@ +export type GunValueSimple = string | number | boolean | null; diff --git a/types/gun/IGun.d.ts b/types/gun/IGun.d.ts index d8bf183b..9ff1af80 100644 --- a/types/gun/IGun.d.ts +++ b/types/gun/IGun.d.ts @@ -1,45 +1,37 @@ -import { ISEA } from '../sea/ISEA'; -import { AckCallback } from './AckCallback'; -import { IGunConstructorOptions } from './IGunConstructorOptions'; -import { IGunDataType } from './IGunDataType'; -import { IGunInstance } from './IGunInstance'; -import { IGunReturnObject } from './IGunReturnObject'; +import { + GunOptions, + IGunInstance, + _GunRoot, + GunHookCallbackCreate, + GunHookCallbackOpt, + GunSchema, + IGunChain, +} from '.'; export interface IGun { - /** - * @description - * no parameters creates a local datastore using the default persistence layer, either localStorage or Radisk. - * @param options - * passing a URL creates the above local datastore that also tries to sync with the URL. - * - * or you can pass in an array of URLs to sync with multiple peers. - * DataType must be type not interface - */ - (options?: IGunConstructorOptions): IGunInstance; - new (options?: IGunConstructorOptions): IGunInstance; - readonly node: IGun; - - /** @see https://gun.eco/docs/SEA */ - readonly SEA: ISEA; - readonly version: string; - readonly chain: IGunInstance; - readonly log: { - (...argv: any[]): void; - once(...argv: any[]): void; - off: boolean; - }; - /** Returns true if data is a gun node, otherwise false. */ - is(anything: any): anything is IGunInstance; + = any>(options?: GunOptions): IGunInstance; + new = any>(options?: GunOptions): IGunInstance; - /** - * Returns data's gun ID (instead of manually grabbing its metadata i.e. data["_"]["#"], which is faster but could change in the future) - * - * Returns undefined if data is not correct gun data. - */ - soul(data: IGunReturnObject): string | undefined; + /** + * Returns GUN state timestamp + */ + state(): number; - /** Returns a "gun-ified" variant of the json input by injecting a new gun ID into the metadata field. */ - ify(json: any): any; + chain: IGunChain & IGunInstance; - state():number -} \ No newline at end of file + /** + * Listener for a GUN instance creation + */ + on( + event: 'create', + callback: GunHookCallbackCreate + ): void; + + /** + * Listener for a GUN options update + */ + on( + event: 'opt', + callback: GunHookCallbackOpt + ): void; +} diff --git a/types/gun/IGunChain.d.ts b/types/gun/IGunChain.d.ts new file mode 100644 index 00000000..e7152ac6 --- /dev/null +++ b/types/gun/IGunChain.d.ts @@ -0,0 +1,218 @@ +import { + _GunRoot, + GunCallbackPut, + GunOptionsPut, + LEXQuery, + GunCallbackOn, + GunOptionsOn, + GunCallbackOnce, + GunOptionsOnce, + GunSchema, + GunDataNode, + GunCallbackGet, + IGunInstanceRoot, + GunSoul, + GunCallbackMap, +} from '.'; +import { IGunChain2TNode } from '../utils'; + +export interface IGunChain< + TNode extends GunSchema, + TChainParent extends + | IGunChain + | IGunInstanceRoot = any, + TGunInstance extends IGunInstanceRoot = any, + TKey extends string = any +> { + _: _GunRoot; + + /** + * Save data into gun, syncing it with your connected peers + * + * @param value the data to save + * @param callback an optional callback, invoked on each acknowledgment + * @param options `put` options + */ + put< + V extends + | (TNode extends object ? Partial : TNode) + | GunSoul + | IGunChain + | IGunChain, any, any, any> + >( + value: V, + callback?: GunCallbackPut, + options?: GunOptionsPut + ): IGunChain; + + /** + * Where to read data from + * + * @param key The key is the ID or property name of the data that you saved from + * earlier (or that will be saved later) + * @param callback The callback is a listener for read errors, not found, and updates. + * It may be called multiple times for a single request, since gun uses a reactive + * streaming architecture. Generally, you'll find `.not`, `.on`, and `.once` as more + * convenient for every day use + */ + get( + key: K, + callback?: GunCallbackGet + ): V extends GunSchema + ? IGunChain< + V, + IGunChain, + TGunInstance, + K + > + : never; + + /** + * Where to read data from + * + * @param query LEX query + * @param callback The callback is a listener for read errors, not found, and updates. + * It may be called multiple times for a single request, since gun uses a reactive + * streaming architecture. Generally, you'll find `.not`, `.on`, and `.once` as more + * convenient for every day use + */ + get< + V extends N[K], + K extends keyof TNode & string = keyof TNode & string, + N extends TNode = TNode + >( + query: LEXQuery, + callback?: GunCallbackGet + ): Record extends GunSchema + ? IGunChain, TChainParent, TGunInstance, TKey> + : never; + + /** + * Add a unique item to an unordered list. Works like a mathematical set, where each + * item in the list is unique. If the item is added twice, it will be merged. This + * means only objects, for now, are supported + * + * @param value the data to save + * @param callback the callback is invoked exactly the same as `.put`, since `.set` is + * just a convenience wrapper around `.put` + */ + set< + V extends Partial | GunSoul | IGunChain, + K extends keyof TNode & string, + N extends TNode[K] & Record + >( + value: V, + callback?: GunCallbackPut + ): V extends GunSchema + ? IGunChain< + N, + IGunChain, + TGunInstance, + K + > + : IGunChain< + IGunChain2TNode, + IGunChain, + TGunInstance, + K + >; + + /** + * Move up to the parent context on the chain. Every time a new chain is created, a + * reference to the old context is kept to go back to + * + * @param amount The number of times you want to go back up the chain. `-1` will take you + * to the root. `Infinity` is not yet supported in TypeScript + */ + back(amount: -1): GI; + back(): CP; + back(): IGunChain; + back( + amount: number + ): IGunChain; + + /** + * Subscribe to updates and changes on a node or property in realtime + * + * @param callback Once initially and whenever the property or node you're focused on + * changes, this callback is immediately fired with the data as it is at that point in + * time. Once initially and whenever the property or node you're focused on changes, + * this callback is immediately fired with the data as it is at that point in time + * @param options currently, the only option is to filter out old data, and just be + * given the changes. If you're listening to a node with 100 fields, and just one + * changes, you'll instead be passed a node with a single property representing that + * change rather than the full node every time + */ + on( + callback?: GunCallbackOn, + options?: GunOptionsOn + ): IGunChain; + + /** + * Removes all listeners + */ + off(): IGunChain; + + /** + * Get the current data without subscribing to updates. Or undefined if it cannot be + * found + * + * `.once` is synchronous and immediate (at extremely high performance) if the data has + * already been loaded. + * + * `.once` is asynchronous and on a debounce timeout while data is still being loaded + * - so it may be called completely out of order compared to other functions. This is + * intended because gun streams partials of data, so once avoids firing immediately + * because it may not represent the "complete" data set yet. You can control this + * timeout with the wait option + * + * `.once` fires again if you update that node from within it + * + * @param callback The data is the value for that chain at that given point in time. + * And the key is the last property name or ID of the node + * @param options `once` options + */ + once( + callback?: GunCallbackOnce, + options?: GunOptionsOnce + ): IGunChain; + + /** + * Iterates over each property and item on a node, passing it down the chain, behaving + * like a forEach on your data. It also subscribes to every item as well and listens + * for newly inserted items. It accepts one argument: + * - a `callback` function that transforms the data as it passes through. If the data is + * transformed to undefined it gets filtered out of the chain + * - the `callback` gets two arguments (value, key) and will be called once for each + * key value pair in the objects that are returned from map + * + * If your data is cyclic and has a lot of self-references, you may receive multiple + * callbacks with the same result. For example: "Alice is both the president of the + * company, the wife of Bob, and the friend to the cat." This would return 3 times: + * ``` + * key: president value: alice, + * key: wife value: alice, + * key: friend value: alice + * ``` + * + * Here's a summary of .map() behavior depending on where it is on the chain: + * - `users.map().on(cb)` subscribes to changes on every user and to users as they are + * added. + * - `users.map().once(cb)` gets each user once, including ones that are added over + * time. + * - `users.once().map().on(cb)` gets the user list once, but subscribes to changes on + * each of those users (not added ones). + * - `users.once().map().once(cb)` gets the user list once, gets each of those users + * only once (not added ones). + */ + map( + callback?: GunCallbackMap + ): V extends GunSchema + ? IGunChain< + V, + IGunChain, + TGunInstance, + K + > + : never; +} diff --git a/types/gun/IGunConstructorOptions.d.ts b/types/gun/IGunConstructorOptions.d.ts deleted file mode 100644 index cfe97e00..00000000 --- a/types/gun/IGunConstructorOptions.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -export type IGunConstructorOptions = Partial<{ - - /** Undocumented but mentioned. Write data to a JSON. */ - file: string; - - /** Undocumented but mentioned. Create a websocket server */ - web: any; - - /** Undocumented but mentioned. Amazon S3 */ - s3: { - key: any; - secret: any; - bucket: any; - }; - - /** the URLs are properties, and the value is an empty object. */ - peers: string[] | Record; - - /** default: true, creates and persists local (nodejs) data using Radisk. */ - radisk: boolean; - - /** default: true, persists local (browser) data to localStorage. */ - localStorage: boolean; - - /** uuid allows you to override the default 24 random alphanumeric soul generator with your own function. */ - uuid(): string | number; - - /** - * allows you to pass options to a 3rd party module. Their project README will likely list the exposed options - * @see https://github.com/amark/gun/wiki/Modules - */ - [key: string]: any; -}> | string | string[]; \ No newline at end of file diff --git a/types/gun/IGunDataType.d.ts b/types/gun/IGunDataType.d.ts deleted file mode 100644 index 52917aa8..00000000 --- a/types/gun/IGunDataType.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type IGunDataType = { - [P in string]: IGunDataType | string | number | boolean | null -}& -{ - [T in number]: IGunDataType | string | number | boolean | null -} - -export type IGunNodeDataType = IGunDataType | string | number | boolean | null diff --git a/types/gun/IGunFinalTreeMethods.d.ts b/types/gun/IGunFinalTreeMethods.d.ts deleted file mode 100644 index 54337b17..00000000 --- a/types/gun/IGunFinalTreeMethods.d.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { AckCallback } from "./AckCallback"; -import { AuthCallback } from "./AuthCallback"; -import { IGunDataType } from "./IGunDataType"; -import { IGunInstance } from "./IGunInstance"; -import { IGunReturnObject } from "./IGunReturnObject"; - -export interface IGunFinalTreeMethods { - - not?(callback: (key: TKey) => void): IGunFinalTreeMethods ; - /** - * Say you save some data, but want to do something with it later, like expire it or refresh it. - * Well, then `later` is for you! You could use this to easily implement a TTL or similar behavior. - * - * **Warning**: Not included by default! You must include it yourself via `require('gun/lib/later.js')` or - * ``! - */ - later?(callback: (data: TValue, key: TKey) => void, seconds: number): IGunFinalTreeMethods ; - off(): IGunFinalTreeMethods ; - /* /** - * Save data into gun, syncing it with your connected peers. - * - * * You cannot save primitive values at the root level. - * - * @param data You do not need to re-save the entire object every time, - * gun will automatically merge your data into what already exists as a "partial" update. - * - * * `undefined`, `NaN`, `Infinity`, `array`, will be rejected. - * * Traditional arrays are dangerous in real-time apps. Use `gun.set` instead. - * - * @param callback invoked on each acknowledgment - * @param options additional options (used for specifying certs) - */ - put(data: Partial, callback?: AckCallback | null, options?: { opt?: { cert?: string } }): IGunFinalTreeMethods - - /** - * Subscribe to updates and changes on a node or property in real-time. - * @param option Currently, the only option is to filter out old data, and just be given the changes. - * If you're listening to a node with 100 fields, and just one changes, - * you'll instead be passed a node with a single property representing that change rather than the full node every time. - * @param callback - * Once initially and whenever the property or node you're focused on changes, this callback is immediately fired with the data as it is at that point in time. - * - * Since gun streams data, the callback will probably be called multiple times as new chunks come in. - * To remove a listener call .off() on the same property or node. - */ - on(callback: (data: IGunReturnObject, key: TKey, _msg:any, _ev:any) => void, option?: { - change: boolean; - } | boolean, eas?:{$?:any, subs?: unknown[] | { push(arg: unknown) }}, as?:any): IGunFinalTreeMethods | Promise>; - - /** - * Subscribe to database event. - * @param eventName event name that you want listen to (currently only 'auth') - * @param callback once event fire callback - */ - on(eventName: 'auth', cb: AuthCallback, eas?:{$?:any, subs?: unknown[] | { push(arg: unknown) }}, as?:any): IGunFinalTreeMethods - - /** - * Get the current data without subscribing to updates. Or `undefined` if it cannot be found. - * @returns In the document, it said the return value may change in the future. Don't rely on it. - */ - once(callback?: (data: IGunReturnObject, key: TKey) => void, option?: { - wait: number; - }): IGunFinalTreeMethods | Promise>; - - /** - * Open behaves very similarly to gun.on, except it gives you the **full depth of a document** on every update. - * It also works with graphs, tables, or other data structures. Think of it as opening up a live connection to a document. - * - * **Warning**: Not included by default! You must include it yourself via `require('gun/lib/open.js')` or - * ``! - */ - open?(callback: (data: IGunReturnObject) => any, opt?: { at?: any, key?: any, doc?: any, ids?: any, any?: any, meta?: any, ev?: { off?: () => {} } }, at?: Partial): IGunFinalTreeMethods | Promise>; - - /** - * Loads the full object once. It is the same as `open` but with the behavior of `once`. - * - * **Warning**: Not included by default! You must include it yourself via `require('gun/lib/load.js')` or - * ``! - */ - load?(callback: (data: IGunReturnObject) => void, opt?: { at?: any, key?: any, doc?: any, ids?: any, any?: any, meta?: any, ev?: { off?: () => {} } }, at?: Partial): IGunFinalTreeMethods | Promise> - - - /**goes back user chain */ - back(amount?:number) : IGunInstance - -} \ No newline at end of file diff --git a/types/gun/IGunFinalUserTreeMethods.d.ts b/types/gun/IGunFinalUserTreeMethods.d.ts deleted file mode 100644 index 1ec51405..00000000 --- a/types/gun/IGunFinalUserTreeMethods.d.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { AckCallback } from "./AckCallback"; -import { AuthCallback } from "./AuthCallback"; -import { IGunDataType } from "./IGunDataType"; -import { IGunReturnObject } from "./IGunReturnObject"; -import { IGunUserInstance } from "./IGunUserInstance"; - -export interface IGunFinalUserTreeMethods { - /** - * check out https://gun.eco/docs/User#user-secret - * save secret that only trusted users can read - * - */ - not?(callback: (key: TKey) => void): IGunFinalUserTreeMethods ; - /** - * Say you save some data, but want to do something with it later, like expire it or refresh it. - * Well, then `later` is for you! You could use this to easily implement a TTL or similar behavior. - * - * **Warning**: Not included by default! You must include it yourself via `require('gun/lib/later.js')` or - * ``! - */ - later?(callback: (data: TValue, key: TKey) => void, seconds: number): IGunFinalUserTreeMethods; - off(): IGunFinalUserTreeMethods ; - /* /** - * Save data into gun, syncing it with your connected peers. - * - * * You cannot save primitive values at the root level. - * - * @param data You do not need to re-save the entire object every time, - * gun will automatically merge your data into what already exists as a "partial" update. - * - * * `undefined`, `NaN`, `Infinity`, `array`, will be rejected. - * * Traditional arrays are dangerous in real-time apps. Use `gun.set` instead. - * - * @param callback invoked on each acknowledgment - * @param options additional options (used for specifying certs) - */ - put(data: Partial, callback?: AckCallback | null, options?: { opt?: { cert?: string } }): IGunFinalUserTreeMethods - - /** - * Subscribe to updates and changes on a node or property in real-time. - * @param option Currently, the only option is to filter out old data, and just be given the changes. - * If you're listening to a node with 100 fields, and just one changes, - * you'll instead be passed a node with a single property representing that change rather than the full node every time. - * @param callback - * Once initially and whenever the property or node you're focused on changes, this callback is immediately fired with the data as it is at that point in time. - * - * Since gun streams data, the callback will probably be called multiple times as new chunks come in. - * To remove a listener call .off() on the same property or node. - */ - on(callback: (data: IGunReturnObject, key: TKey, _msg:any, _ev:any) => void, option?: { - change: boolean; - } | boolean, eas?:{$?:any, subs?: unknown[] | { push(arg: unknown) }}, as?:any): IGunFinalUserTreeMethods | Promise>; - - /** - * Subscribe to database event. - * @param eventName event name that you want listen to (currently only 'auth') - * @param callback once event fire callback - */ - on(eventName: 'auth', cb: AuthCallback, eas?:{$?:any, subs?: unknown[] | { push(arg: unknown) }}, as?:any):IGunFinalUserTreeMethods - - /** - * Get the current data without subscribing to updates. Or `undefined` if it cannot be found. - * @returns In the document, it said the return value may change in the future. Don't rely on it. - */ - once(callback?: (data: IGunReturnObject, key: TKey) => void, option?: { - wait: number; - }): IGunFinalUserTreeMethods | Promise>; - - /** - * Open behaves very similarly to gun.on, except it gives you the **full depth of a document** on every update. - * It also works with graphs, tables, or other data structures. Think of it as opening up a live connection to a document. - * - * **Warning**: Not included by default! You must include it yourself via `require('gun/lib/open.js')` or - * ``! - */ - open?(callback: (data: IGunReturnObject) => any, opt?: { at?: any, key?: any, doc?: any, ids?: any, any?: any, meta?: any, ev?: { off?: () => {} } }, at?: Partial): IGunFinalUserTreeMethods | Promise>; - - /** - * Loads the full object once. It is the same as `open` but with the behavior of `once`. - * - * **Warning**: Not included by default! You must include it yourself via `require('gun/lib/load.js')` or - * ``! - */ - load?(callback: (data: IGunReturnObject) => void, opt?: { at?: any, key?: any, doc?: any, ids?: any, any?: any, meta?: any, ev?: { off?: () => {} } }, at?: Partial): IGunFinalUserTreeMethods | Promise> - - - /**goes back user chain */ - back(amount?:number) : IGunUserInstance -secret(string: string, callback : (...args:unknown[])=> any): IGunFinalUserTreeMethods -} \ No newline at end of file diff --git a/types/gun/IGunHookContext.d.ts b/types/gun/IGunHookContext.d.ts new file mode 100644 index 00000000..aa619873 --- /dev/null +++ b/types/gun/IGunHookContext.d.ts @@ -0,0 +1,6 @@ +export interface IGunHookContext { + off: () => void; + to: { + next: (subject: T) => void; + }; +} diff --git a/types/gun/IGunInstance.d.ts b/types/gun/IGunInstance.d.ts index 60bc4457..045c57de 100644 --- a/types/gun/IGunInstance.d.ts +++ b/types/gun/IGunInstance.d.ts @@ -1,181 +1,4 @@ +import { IGunInstanceRoot, GunSchema } from '.'; -import { And } from "../shared/And"; -import { AckCallback } from "./AckCallback"; -import { AuthCallback } from "./AuthCallback"; -import { IGunConstructorOptions } from "./IGunConstructorOptions"; -import { IGunDataType, IGunNodeDataType } from "./IGunDataType"; -import { IGunFinalTreeMethods } from "./IGunFinalTreeMethods"; -import { IGunReturnObject } from "./IGunReturnObject"; -import { IGunTree } from "./IGunTree"; -import { IGunUserInstance } from "./IGunUserInstance"; - - - - -export interface IGunInstance< - CurrentTreeDataType extends IGunNodeDataType, - TSoul extends string | undefined - >{ - - not?(callback: (key: TSoul) => void): IGunInstance ; - /** - * Say you save some data, but want to do something with it later, like expire it or refresh it. - * Well, then `later` is for you! You could use this to easily implement a TTL or similar behavior. - * - * **Warning**: Not included by default! You must include it yourself via `require('gun/lib/later.js')` or - * ``! - */ - later?(callback: (data: CurrentTreeDataType, key: TSoul) => void, seconds: number): IGunInstance ; - off(): IGunInstance ; - /* /** - * Save data into gun, syncing it with your connected peers. - * - * * You cannot save primitive values at the root level. - * - * @param data You do not need to re-save the entire object every time, - * gun will automatically merge your data into what already exists as a "partial" update. - * - * * `undefined`, `NaN`, `Infinity`, `array`, will be rejected. - * * Traditional arrays are dangerous in real-time apps. Use `gun.set` instead. - * - * @param callback invoked on each acknowledgment - * @param options additional options (used for specifying certs) - */ - put(data: Partial, callback?: AckCallback | null, options?: { opt?: { cert?: string } }): IGunInstance - - /** - * Subscribe to updates and changes on a node or property in real-time. - * @param option Currently, the only option is to filter out old data, and just be given the changes. - * If you're listening to a node with 100 fields, and just one changes, - * you'll instead be passed a node with a single property representing that change rather than the full node every time. - * @param callback - * Once initially and whenever the property or node you're focused on changes, this callback is immediately fired with the data as it is at that point in time. - * - * Since gun streams data, the callback will probably be called multiple times as new chunks come in. - * To remove a listener call .off() on the same property or node. - */ - on(callback: (data: IGunReturnObject, key: TSoul, _msg:any, _ev:any) => void, option?: { - change: boolean; - } | boolean, eas?:{$?:any, subs?: unknown[] | { push(arg: unknown) }}, as?:any): IGunInstance | Promise>; - - /** - * Subscribe to database event. - * @param eventName event name that you want listen to (currently only 'auth') - * @param callback once event fire callback - */ - on(eventName: 'auth', cb: AuthCallback, eas?:{$?:any, subs?: unknown[] | { push(arg: unknown) }}, as?:any): IGunInstance - - /** - * Get the current data without subscribing to updates. Or `undefined` if it cannot be found. - * @returns In the document, it said the return value may change in the future. Don't rely on it. - */ - once(callback?: (data: IGunReturnObject, key: TSoul) => void, option?: { - wait: number; - }): IGunInstance| Promise>; - - /** - * Open behaves very similarly to gun.on, except it gives you the **full depth of a document** on every update. - * It also works with graphs, tables, or other data structures. Think of it as opening up a live connection to a document. - * - * **Warning**: Not included by default! You must include it yourself via `require('gun/lib/open.js')` or - * ``! - */ - open?(callback: (data: IGunReturnObject) => any, opt?: { at?: any, key?: any, doc?: any, ids?: any, any?: any, meta?: any, ev?: { off?: () => {} } }, at?: Partial): IGunInstance | Promise>; - - /** - * Loads the full object once. It is the same as `open` but with the behavior of `once`. - * - * **Warning**: Not included by default! You must include it yourself via `require('gun/lib/load.js')` or - * ``! - */ - load?(callback: (data: IGunReturnObject) => void, opt?: { at?: any, key?: any, doc?: any, ids?: any, any?: any, meta?: any, ev?: { off?: () => {} } }, at?: Partial): IGunInstance | Promise> - - - /**goes back user chain */ - back(amount?:number) : IGunInstance -/** - * **.set does not mean 'set data', it means a Mathematical Set** - * - * Add a unique item to an unordered list. - * `gun.set` works like a mathematical set, where each item in the list is unique. - * If the item is added twice, it will be merged. - * - * **This means only objects, for now, are supported.** - * @param data the object to add to the set - * @param callback optional function to invoke when the operation is complete - * @param options additional options (used for specifying certs) - */ - set(data: CurrentTreeDataType[K], callback?: AckCallback | null, options?: { opt?: { cert?: string } }): CurrentTreeDataType[K] extends IGunDataType ? IGunInstance: IGunFinalTreeMethods; - -/** - * Where to read data from. - * @param key The key is the ID or property name of the data that you saved from earlier - * (or that will be saved later). - * * Note that if you use .put at any depth after a get it first reads the data and then writes, merging the data as a partial update. - * @param callback You will usually be using gun.on or gun.once to actually retrieve your data, - * not this callback (it is intended for more low-level control, for module and extensions). - * - * **Avoid use callback. The type in the document may be wrong.** - * - * **Here the type of callback respect to the actual behavior** - */ -get(key: K, callback?: ( - data: IGunReturnObject, - key: K) => any): - And< Promise, - CurrentTreeDataType[K] extends IGunDataType ? - IGunInstance & IGunFinalTreeMethods : - IGunDataType extends CurrentTreeDataType[K] ? - IGunFinalTreeMethods & IGunInstance - : IGunFinalTreeMethods> - - -map(match: (data: CurrentTreeDataType) => T ): IGunFinalTreeMethods - /** - * After you save some data in an unordered list, you may need to remove it. - * - * **Warning**: Not included by default! You must include it yourself via `require('gun/lib/unset.js')` or - * ``! - */ - unset?(data: K): CurrentTreeDataType[K] extends IGunDataType ? IGunInstance: IGunFinalTreeMethods; - - -/** - * Map iterates over each property and item on a node, passing it down the chain, - * behaving like a forEach on your data. - * It also subscribes to every item as well and listens for newly inserted items. - */ - map(match: IGunTree): CurrentTreeDataType[keyof CurrentTreeDataType] extends IGunDataType? IGunInstance : IGunFinalTreeMethods - - -opt(opt: IGunConstructorOptions): unknown -/** - * - * Path does the same thing as `.get` but has some conveniences built in. - * @deprecated This is not friendly with type system. - * - * **Warning**: This extension was removed from core, you probably shouldn't be using it! - * - * **Warning**: Not included by default! You must include it yourself via `require('gun/lib/path.js')` or - * ``! - */ -path?(path: string | string[]): unknown; - - -/** - * Subscribes to all future events that occur on the Timegraph and retrieve a specified number of old events - * - * **Warning**: The Timegraph extension isn't required by default, you would need to include at "gun/lib/time.js" - */ -time?(callback: (data: CurrentTreeDataType[K], key: K, time: number) => void, alsoReceiveNOldEvents?: number): CurrentTreeDataType[K] extends IGunDataType ? IGunInstance: IGunFinalTreeMethods; - -/** Pushes data to a Timegraph with it's time set to Gun.state()'s time */ -time?(data: CurrentTreeDataType[K]): CurrentTreeDataType[K] extends IGunDataType ? IGunInstance: IGunFinalTreeMethods; - - -/** - * @param publicKey If you know a users publicKey you can get their user graph and see any unencrypted data they may have stored there. - */ - user(): IGunUserInstance - user(publicKey: string): IGunUserInstance -} \ No newline at end of file +export interface IGunInstance = any> + extends IGunInstanceRoot> {} diff --git a/types/gun/IGunInstanceHookHandler.d.ts b/types/gun/IGunInstanceHookHandler.d.ts new file mode 100644 index 00000000..fe6e7d30 --- /dev/null +++ b/types/gun/IGunInstanceHookHandler.d.ts @@ -0,0 +1,71 @@ +import { + GunHookCallbackCreate, + GunHookCallbackPut, + pany, + GunHookCallackGet, + GunHookCallbackOut, + GunHookCallbackIn, + GunHookCallbackBye, + IGunHookContext, +} from '.'; + +export interface IGunInstanceHookHandler { + /** + * Listener for the GUN instance creation + */ + on(event: 'create', callback: GunHookCallbackCreate): void; + + /** + * Listener for the GUN `put` event + */ + on(event: 'put', callback: GunHookCallbackPut): void; + + /** + * Listener for the GUN `get` event + * + * @template MessageExtension extension properties for message + */ + on( + event: 'get', + callback: GunHookCallackGet + ): void; + + /** + * Listener for the GUN `out` event + * + * > NEVER PASS ARROW FUNCTIONS AS A CALLBACK OR YOU LOSE `this` CONTEXT! + * + * > NEVER FORGET TO CALL `this.to.next(message);` IF YOU WANT YOUR MESSAGE TO PASS + * + * @template MessageExtension extension properties for message + * @template MetaExtension extension properties for meta data + */ + on( + event: 'out', + callback: GunHookCallbackOut + ): void; + + /** + * Listener for the GUN `in` event + * + * @template MessageExtension extension properties for message + * @template MetaExtension extension properties for meta data + */ + on( + event: 'in', + callback: GunHookCallbackIn + ): void; + + /** + * Listener for new peers + */ + on( + event: 'hi', + callback: (this: IGunHookContext, peer: any) => void + ): void; + + /** + * Listener for leaving peers + */ + on(event: 'bye', callback: GunHookCallbackBye): void; +} diff --git a/types/gun/IGunInstanceRoot.d.ts b/types/gun/IGunInstanceRoot.d.ts new file mode 100644 index 00000000..370e3555 --- /dev/null +++ b/types/gun/IGunInstanceRoot.d.ts @@ -0,0 +1,94 @@ +import { + _GunRoot, + GunCallbackPut, + GunOptionsPut, + IGunChain, + LEXQuery, + GunOptions, + IGunInstanceHookHandler, + GunSchema, + GunCallbackGet, + GunSoul, +} from '.'; +import { GunSoul2Soul, GunSoul2TNode } from '../utils'; + +export interface IGunInstanceRoot< + TNode extends Record, + TGunInstance extends IGunInstanceRoot +> extends IGunInstanceHookHandler { + _: _GunRoot; + + /** + * Save data into gun, syncing it with your connected peers + * + * @param value the data to save + * @param callback an optional callback, invoked on each acknowledgment + * @param options `put` options + * @param options.cert certificate that gives other people write permission + */ + put & Record>( + value: V, + callback?: GunCallbackPut, + options?: GunOptionsPut + ): TGunInstance; + + /** + * Where to read data from + * + * @param soul The soul of an object that you saved from earlier + * @param callback The callback is a listener for read errors, not found, and updates. + * It may be called multiple times for a single request, since gun uses a reactive + * streaming architecture. Generally, you'll find `.not`, `.on`, and `.once` as more + * convenient for every day use + */ + get< + V extends GunSoul2TNode, + S extends GunSoul, + N extends TNode + >( + soul: S, + callback?: GunCallbackGet> + ): IGunChain>; + + /** + * Where to read data from + * + * @param key The key is the ID or property name of the data that you saved from + * earlier (or that will be saved later) + * @param callback The callback is a listener for read errors, not found, and updates. + * It may be called multiple times for a single request, since gun uses a reactive + * streaming architecture. Generally, you'll find `.not`, `.on`, and `.once` as more + * convenient for every day use + */ + get< + V extends N[K], + K extends keyof N & string = keyof TNode & string, + N extends TNode = TNode + >( + key: K, + callback?: GunCallbackGet + ): IGunChain; + + /** + * Where to read data from + * + * @param query LEX query + * @param callback The callback is a listener for read errors, not found, and updates. + * It may be called multiple times for a single request, since gun uses a reactive + * streaming architecture. Generally, you'll find `.not`, `.on`, and `.once` as more + * convenient for every day use + */ + get( + query: LEXQuery, + callback?: GunCallbackGet + ): IGunChain; + + /** + * Change the configuration of the gun database instance + * + * @param options The options argument is the same object you pass to the constructor. + * The options's properties replace those in the instance's configuration but + * `options.peers` are added to peers known to the gun instance + */ + opt(options: GunOptions): void; +} diff --git a/types/gun/IGunMeta.d.ts b/types/gun/IGunMeta.d.ts new file mode 100644 index 00000000..cd2b778f --- /dev/null +++ b/types/gun/IGunMeta.d.ts @@ -0,0 +1,8 @@ +export interface IGunMeta { + _: { + '#': string; + '>': { + [key in keyof T]: number; + }; + }; +} diff --git a/types/gun/IGunOnEvent.d.ts b/types/gun/IGunOnEvent.d.ts new file mode 100644 index 00000000..a494141f --- /dev/null +++ b/types/gun/IGunOnEvent.d.ts @@ -0,0 +1,3 @@ +export interface IGunOnEvent { + off(): void; +} diff --git a/types/gun/IGunReturnObject.d.ts b/types/gun/IGunReturnObject.d.ts deleted file mode 100644 index 057b0181..00000000 --- a/types/gun/IGunReturnObject.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -export declare type IGunReturnObject = (TObject & { - _:{ - '#': TSoul, - '>': TObject extends number |string|boolean?unknown : Record - } -})|undefined \ No newline at end of file diff --git a/types/gun/IGunTree.d.ts b/types/gun/IGunTree.d.ts deleted file mode 100644 index 2a76291f..00000000 --- a/types/gun/IGunTree.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -export interface IGunTree{ - "+"?:string|IGunTree, - "#"?:string|IGunTree, - "."?:string|IGunTree, - "="?:string|IGunTree, - "*"?:string|IGunTree, - ">"?:string|IGunTree, - "<"?:string|IGunTree, - '-'?:string|number|IGunTree -} \ No newline at end of file diff --git a/types/gun/IGunUserInstance.d.ts b/types/gun/IGunUserInstance.d.ts deleted file mode 100644 index f0895fe7..00000000 --- a/types/gun/IGunUserInstance.d.ts +++ /dev/null @@ -1,232 +0,0 @@ -import { ISEAPair } from "../sea/ISEAPair"; -import { And } from "../shared/And"; -import { AckCallback } from "./AckCallback"; -import { AuthCallback } from "./AuthCallback"; -import { CreateCallback } from "./CreateCallback"; -import { IGunConstructorOptions } from "./IGunConstructorOptions"; -import { IGunDataType, IGunNodeDataType } from "./IGunDataType"; -import { IGunFinalUserTreeMethods } from "./IGunFinalUserTreeMethods"; -import { IGunReturnObject } from "./IGunReturnObject"; -import { IGunTree } from "./IGunTree"; - -export interface IGunUserInstance { - /** - * check out https://gun.eco/docs/User#user-secret - * save secret that only trusted users can read - * - */ - not?(callback: (key: TKey) => void): IGunUserInstance ; - /** - * Say you save some data, but want to do something with it later, like expire it or refresh it. - * Well, then `later` is for you! You could use this to easily implement a TTL or similar behavior. - * - * **Warning**: Not included by default! You must include it yourself via `require('gun/lib/later.js')` or - * ``! - */ - later?(callback: (data: CurrentDataType, key: TKey) => void, seconds: number): IGunUserInstance ; - off(): IGunUserInstance ; - /* /** - * Save data into gun, syncing it with your connected peers. - * - * * You cannot save primitive values at the root level. - * - * @param data You do not need to re-save the entire object every time, - * gun will automatically merge your data into what already exists as a "partial" update. - * - * * `undefined`, `NaN`, `Infinity`, `array`, will be rejected. - * * Traditional arrays are dangerous in real-time apps. Use `gun.set` instead. - * - * @param callback invoked on each acknowledgment - * @param options additional options (used for specifying certs) - */ - put(data: Partial, callback?: AckCallback | null, options?: { opt?: { cert?: string } }):IGunUserInstance - - /** - * Subscribe to updates and changes on a node or property in real-time. - * @param option Currently, the only option is to filter out old data, and just be given the changes. - * If you're listening to a node with 100 fields, and just one changes, - * you'll instead be passed a node with a single property representing that change rather than the full node every time. - * @param callback - * Once initially and whenever the property or node you're focused on changes, this callback is immediately fired with the data as it is at that point in time. - * - * Since gun streams data, the callback will probably be called multiple times as new chunks come in. - * To remove a listener call .off() on the same property or node. - */ - on(callback: (data: IGunReturnObject, key: TKey, _msg:any, _ev:any) => void, option?: { - change: boolean; - } | boolean, eas?:{$?:any, subs?: unknown[] | { push(arg: unknown) }}, as?:any): IGunUserInstance | Promise>; - - /** - * Subscribe to database event. - * @param eventName event name that you want listen to (currently only 'auth') - * @param callback once event fire callback - */ - on(eventName: 'auth', cb: AuthCallback, eas?:{$?:any, subs?: unknown[] | { push(arg: unknown) }}, as?:any):IGunUserInstance - - /** - * Get the current data without subscribing to updates. Or `undefined` if it cannot be found. - * @returns In the document, it said the return value may change in the future. Don't rely on it. - */ - once(callback?: (data: IGunReturnObject, key: TKey) => void, option?: { - wait: number; - }): IGunUserInstance | Promise>; - - /** - * Open behaves very similarly to gun.on, except it gives you the **full depth of a document** on every update. - * It also works with graphs, tables, or other data structures. Think of it as opening up a live connection to a document. - * - * **Warning**: Not included by default! You must include it yourself via `require('gun/lib/open.js')` or - * ``! - */ - open?(callback: (data: IGunReturnObject) => any, opt?: { at?: any, key?: any, doc?: any, ids?: any, any?: any, meta?: any, ev?: { off?: () => {} } }, at?: Partial): IGunUserInstance | Promise>; - - /** - * Loads the full object once. It is the same as `open` but with the behavior of `once`. - * - * **Warning**: Not included by default! You must include it yourself via `require('gun/lib/load.js')` or - * ``! - */ - load?(callback: (data: IGunReturnObject) => void, opt?: { at?: any, key?: any, doc?: any, ids?: any, any?: any, meta?: any, ev?: { off?: () => {} } }, at?: Partial): IGunUserInstance | Promise> - - - /**goes back user chain */ - back(amount?:number) : IGunUserInstance - secret(string: string, callback : (...args:unknown[])=> any): IGunUserInstance - - - - - - - - - is?: { - alias: string | ISEAPair - epub: string - pub: string - } -/** - * 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?: CreateCallback, opt?: {}): unknown; - - /** - * Creates a new user and calls callback upon completion. - * @param pair User cryptographic pair - * @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(pair: ISEAPair, cb?: AuthCallback, opt?: {}): unknown; - - /** - * 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 authentication. (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?:AuthCallback, opt?: {}): unknown - - /** - * Authenticates a user, previously created via User.create. - * @param pair Public/Private Key Pair - * @param cb Callback that is to be called upon authentication of the user. - * @param opt Option Object containing options for authentication. (In gun options are added at end of syntax. opt is rarely used, hence is added at the end.) - */ - auth(pair: ISEAPair, cb?: AuthCallback, opt?: {}): unknown; - - - - /** - * 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): unknown; - - /** - * 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; - - -/** - * Where to read data from. - * @param key The key is the ID or property name of the data that you saved from earlier - * (or that will be saved later). - * * Note that if you use .put at any depth after a get it first reads the data and then writes, merging the data as a partial update. - * @param callback You will usually be using gun.on or gun.once to actually retrieve your data, - * not this callback (it is intended for more low-level control, for module and extensions). - * - * **Avoid use callback. The type in the document may be wrong.** - * - * **Here the type of callback respect to the actual behavior** - */ - get(key: K, callback?: ( - data: IGunReturnObject, - key: K) => any): - And< Promise, - CurrentDataType[K] extends IGunDataType ? - IGunUserInstance & IGunFinalUserTreeMethods : - IGunDataType extends CurrentDataType[K] ? - IGunFinalUserTreeMethods & IGunUserInstance< IGunDataType , string> - : IGunFinalUserTreeMethods> - -/** - * **.set does not mean 'set data', it means a Mathematical Set** - * - * Add a unique item to an unordered list. - * `gun.set` works like a mathematical set, where each item in the list is unique. - * If the item is added twice, it will be merged. - * - * **This means only objects, for now, are supported.** - * @param data the object to add to the set - * @param callback optional function to invoke when the operation is complete - * @param options additional options (used for specifying certs) - */ - set(data: CurrentDataType[K], callback?: AckCallback | null, options?: { opt?: { cert?: string } }): CurrentDataType[K] extends IGunDataType? IGunUserInstance: IGunFinalUserTreeMethods ; - - - opt(opt: IGunConstructorOptions): unknown - - /** - * 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 log the user back in. Refer to user.auth for callback documentation. - */ - recall(opt?: { - sessionStorage: boolean; - }, cb?: AuthCallback): IGunUserInstance; - - map(match: IGunTree ): CurrentDataType[keyof CurrentDataType] extends IGunDataType? IGunUserInstance : IGunFinalUserTreeMethods - - - map(match: (data: CurrentDataType) => T ): IGunFinalUserTreeMethods -/** - * Subscribes to all future events that occur on the Timegraph and retrieve a specified number of old events - * - * **Warning**: The Timegraph extension isn't required by default, you would need to include at "gun/lib/time.js" - */ - time?(callback: (data: CurrentDataType[K], key: K, time: number) => void, alsoReceiveNOldEvents?: number): CurrentDataType[K] extends IGunDataType ? IGunUserInstance: IGunFinalUserTreeMethods; - - /** Pushes data to a Timegraph with it's time set to Gun.state()'s time */ - time?(data: CurrentDataType[K]): CurrentDataType[K] extends IGunDataType ? IGunUserInstance: IGunFinalUserTreeMethods; - - -/** - * @param publicKey If you know a users publicKey you can get their user graph and see any unencrypted data they may have stored there. - */ - user(): IGunUserInstance - user(publicKey: string): IGunUserInstance - - -} \ No newline at end of file diff --git a/types/gun/LEX.d.ts b/types/gun/LEX.d.ts new file mode 100644 index 00000000..e8871d11 --- /dev/null +++ b/types/gun/LEX.d.ts @@ -0,0 +1,12 @@ +export type LEX = { + /** exact match */ + '='?: T; + /** prefix match */ + '*'?: string; + /** gte match */ + '>'?: string; + /** lte match */ + '<'?: string; + /** 1 for reverse */ + '-'?: number; +}; diff --git a/types/gun/LEXQuery.d.ts b/types/gun/LEXQuery.d.ts new file mode 100644 index 00000000..07d1662c --- /dev/null +++ b/types/gun/LEXQuery.d.ts @@ -0,0 +1,3 @@ +import { LEX } from '.'; + +export type LEXQuery = { '.': LEX; ':'?: number }; diff --git a/types/gun/_GunRoot.d.ts b/types/gun/_GunRoot.d.ts new file mode 100644 index 00000000..e77c7e93 --- /dev/null +++ b/types/gun/_GunRoot.d.ts @@ -0,0 +1,10 @@ +import { GunOptions, IGunInstanceHookHandler } from '.'; + +export interface _GunRoot extends IGunInstanceHookHandler { + $: { _: _GunRoot }; + + /** + * Current GUN options + */ + opt: GunOptions; +} diff --git a/types/gun/index.d.ts b/types/gun/index.d.ts new file mode 100644 index 00000000..ea0a84a1 --- /dev/null +++ b/types/gun/index.d.ts @@ -0,0 +1,36 @@ +export * from './_GunRoot'; +export * from './GunCallbackGet'; +export * from './GunCallbackMap'; +export * from './GunCallbackOn'; +export * from './GunCallbackOnce'; +export * from './GunCallbackPut'; +export * from './GunDataNode'; +export * from './GunHookCallbackBye'; +export * from './GunHookCallbackCreate'; +export * from './GunHookCallbackGet'; +export * from './GunHookCallbackHi'; +export * from './GunHookCallbackIn'; +export * from './GunHookCallbackOpt'; +export * from './GunHookCallbackOut'; +export * from './GunHookCallbackPut'; +export * from './GunNodeGet'; +export * from './GunNodePut'; +export * from './GunOptions'; +export * from './GunOptionsOn'; +export * from './GunOptionsOnce'; +export * from './GunOptionsPut'; +export * from './GunPeer'; +export * from './GunSoul'; +export * from './GunValueSimple'; +export * from './IGun'; +export * from './IGunChain'; +export * from './IGunHookContext'; +export * from './IGunInstance'; +export * from './IGunInstanceHookHandler'; +export * from './IGunInstanceRoot'; +export * from './IGunMeta'; +export * from './IGunOnEvent'; +export * from './GunSchema'; +export * from './LEX'; +export * from './LEXQuery'; +export * from './pany'; diff --git a/types/gun/pany.d.ts b/types/gun/pany.d.ts new file mode 100644 index 00000000..4ad659d6 --- /dev/null +++ b/types/gun/pany.d.ts @@ -0,0 +1 @@ +export type pany = Partial; diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 00000000..5352ed4a --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,2 @@ +export * from './gun'; +export * from './sea'; diff --git a/types/sea/GunCallbackUserAuth.d.ts b/types/sea/GunCallbackUserAuth.d.ts new file mode 100644 index 00000000..6d6d8841 --- /dev/null +++ b/types/sea/GunCallbackUserAuth.d.ts @@ -0,0 +1,15 @@ +import { GunUser, ISEAPair } from '..'; + +export type GunCallbackUserAuth = ( + ack: + | { + ack: 2; + /** ~publicKeyOfUser */ + soul: string; + /** ~publicKeyOfUser */ + get: string; + put: GunUser; + sea: ISEAPair; + } + | { err: string } +) => void; diff --git a/types/sea/GunCallbackUserCreate.d.ts b/types/sea/GunCallbackUserCreate.d.ts new file mode 100644 index 00000000..97262f7b --- /dev/null +++ b/types/sea/GunCallbackUserCreate.d.ts @@ -0,0 +1,3 @@ +export type GunCallbackUserCreate = ( + ack: { ok: 0; pub: string } | { err: string } +) => void; diff --git a/types/sea/GunHookCallbackAuth.d.ts b/types/sea/GunHookCallbackAuth.d.ts new file mode 100644 index 00000000..14224fb9 --- /dev/null +++ b/types/sea/GunHookCallbackAuth.d.ts @@ -0,0 +1,7 @@ +import { GunHookMessagePut, GunUser, IGunOnEvent } from '..'; + +export type GunHookCallbackAuth = ( + user: GunUser, + message: GunHookMessagePut, + event: IGunOnEvent +) => void; diff --git a/types/sea/GunUser.d.ts b/types/sea/GunUser.d.ts new file mode 100644 index 00000000..871ee3c1 --- /dev/null +++ b/types/sea/GunUser.d.ts @@ -0,0 +1,9 @@ +export type GunUser = { + /** Username or Alias which can be used to find a user */ + alias: string; + // auth: string; + /** public key for encryption */ + epub: string; + /** public key */ + pub: string; +}; diff --git a/types/sea/IGun.d.ts b/types/sea/IGun.d.ts new file mode 100644 index 00000000..5363ea7e --- /dev/null +++ b/types/sea/IGun.d.ts @@ -0,0 +1,8 @@ +import { ISEA } from '.'; + +import {} from '../gun/IGun'; +declare module '../gun/IGun' { + export interface IGun { + SEA: ISEA; + } +} diff --git a/types/sea/IGunInstance.d.ts b/types/sea/IGunInstance.d.ts new file mode 100644 index 00000000..5cb6aecc --- /dev/null +++ b/types/sea/IGunInstance.d.ts @@ -0,0 +1,27 @@ +import { IGunInstanceRoot, GunSchema, IGunUserInstance } from '..'; + +import {} from '../gun/IGunInstance'; +declare module '../gun/IGunInstance' { + export interface IGunInstance { + user< + UNode extends Record = any, + UNodeInstance extends IGunUserInstance< + UNode, + UNodeInstance, + TNode, + IGunInstanceRoot> + > = any + >(): IGunUserInstance>>; + user< + UNode extends Record = any, + UNodeInstance extends IGunUserInstance< + UNode, + UNodeInstance, + TNode, + IGunInstanceRoot> + > = any + >( + publicKey: string + ): IGunUserInstance>>; + } +} diff --git a/types/sea/IGunInstanceHookHandler.d.ts b/types/sea/IGunInstanceHookHandler.d.ts new file mode 100644 index 00000000..f42c2651 --- /dev/null +++ b/types/sea/IGunInstanceHookHandler.d.ts @@ -0,0 +1,9 @@ +import { GunHookCallbackAuth } from '..'; + +import {} from '../gun/IGunInstanceHookHandler'; +declare module '../gun/IGunInstanceHookHandler' { + export interface IGunInstanceHookHandler { + /** Called upon successful user authentication */ + on(event: 'auth', callback: GunHookCallbackAuth): void; + } +} diff --git a/types/sea/IGunInstanceRoot.d.ts b/types/sea/IGunInstanceRoot.d.ts new file mode 100644 index 00000000..495c5695 --- /dev/null +++ b/types/sea/IGunInstanceRoot.d.ts @@ -0,0 +1,27 @@ +import { GunSchema, IGunUserInstance } from '..'; + +import {} from '../gun/IGunInstanceRoot'; +declare module '../gun/IGunInstanceRoot' { + export interface IGunInstanceRoot { + user< + UNode extends Record = any, + UNodeInstance extends IGunUserInstance< + UNode, + UNodeInstance, + TNode, + TGunInstance + > = any + >(): IGunUserInstance; + user< + UNode extends Record = any, + UNodeInstance extends IGunUserInstance< + UNode, + UNodeInstance, + TNode, + TGunInstance + > = any + >( + publicKey: string + ): IGunUserInstance; + } +} diff --git a/types/sea/IGunUserInstance.d.ts b/types/sea/IGunUserInstance.d.ts new file mode 100644 index 00000000..f2d6a471 --- /dev/null +++ b/types/sea/IGunUserInstance.d.ts @@ -0,0 +1,80 @@ +import { + GunCallbackUserAuth, + GunCallbackUserCreate, + OptionsUserAuth, + ISEAPair, + OptionsUserRecall, + IGunInstanceRoot, + GunSchema, +} from '..'; +import { IGunInstanceRoot2TGunInstance } from '../utils'; + +export interface IGunUserInstance< + UNode extends Record = any, + UNodeInstance extends IGunUserInstance< + UNode, + UNodeInstance, + TNode, + TNodeInstanceRoot + > = any, + TNode extends Record = any, + TNodeInstanceRoot extends IGunInstanceRoot = any +> extends IGunInstanceRoot { + /** Creates a new user and calls callback upon completion + * @param alias Username or Alias which can be used to find a user + * @param password Passphrase that will be extended with PBKDF2 + * to make it a secure way to login + * @param callback that is to be called upon creation of the user + */ + create( + alias: string, + password: string, + callback: GunCallbackUserCreate + ): UNodeInstance; + + /** Authenticates a user, previously created via User.create + * @param pair Object containing the key pair of the user + * @param callback that is to be called upon authentication of the user + * @param options Options for authentication + */ + auth( + pair: ISEAPair, + callback?: GunCallbackUserAuth, + options?: OptionsUserAuth + ): UNodeInstance; + /** Authenticates a user, previously created via User.create + * @param alias Username or Alias which can be used to find a user + * @param password Passphrase for the user + * @param callback that is to be called upon authentication of the user + * @param options Options for authentication + */ + auth( + alias: string, + password: string, + callback?: GunCallbackUserAuth, + options?: OptionsUserAuth + ): UNodeInstance; + + /** To check if you are currently logged in */ + is?: { + alias: string | ISEAPair; + /** public key for encryption */ + epub: string; + /** public key */ + pub: string; + }; + + /** Log out currently authenticated user + * @returns A reference to the gun root chain + */ + leave(): IGunInstanceRoot2TGunInstance; + + /** + * 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 */ + recall( + options: OptionsUserRecall, + callback?: GunCallbackUserAuth + ): UNodeInstance; +} diff --git a/types/sea/IPolicy.d.ts b/types/sea/IPolicy.d.ts new file mode 100644 index 00000000..1124eca9 --- /dev/null +++ b/types/sea/IPolicy.d.ts @@ -0,0 +1,13 @@ +import { LEX } from '..'; + +export interface IPolicy extends LEX { + /** Path */ + '#'?: LEX; + /** Key */ + '.'?: LEX; + /** + * Either Path string or Key string must + * contain Certificate's Pub string + */ + '+'?: '*'; +} diff --git a/types/sea/ISEA.d.ts b/types/sea/ISEA.d.ts index ac4c47e8..2ce4a5ea 100644 --- a/types/sea/ISEA.d.ts +++ b/types/sea/ISEA.d.ts @@ -1,84 +1,163 @@ -import { ISEAPair } from "./ISEAPair"; -import { ISEAPolicy } from "./ISEAPolicy"; -/** @see https://gun.eco/docs/SEA */ +import { ISEAPair, Policy } from '.'; + +/** + * Security, Encryption, and Authorization system used with GUN + */ export interface ISEA { + /** Last known error */ + err?: string; - /** If you want SEA to throw while in development, turn SEA.throw = true on, but please do not use this in production. */ - throw?: boolean; + /** + * 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 options default: `{ name: 'PBKDF2', encode: 'base64' }` + * @returns a promise with a string - hash of data if successful, + * otherwise - undefined + */ + work( + data: any, + pair?: ISEAPair | null, + callback?: ((data: string | undefined) => void) | null, + options?: { + name?: 'SHA-256' | 'PBKDF2'; + encode?: 'base64' | 'utf8' | 'hex'; + salt?: any; + hash?: string; + length?: number; + } + ): Promise; - /** Last known error */ - err?: string; + /** + * 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(callback?: (data: ISEAPair) => void): Promise; - /** - * 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 | undefined) => 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; - - /** - * 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: ISEAPair) => void, opt?: {}): Promise; - - /** - * 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: { pub: string; priv: string }): Promise; - - /** - * 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: string, pair: { pub: string } | string): Promise; - - /** - * 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: { epriv: string } | string): Promise; - - /** - * 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: { epriv: string } | string): Promise; - - /** - * determine secret between users. - * @param key public key of first user. - * @param pair from .pair or the passphrase to decypher the message - */ - secret(key: string|{epub:string}, pair:{epriv:string, epub:string }, cb?: (arg: string|undefined)=>any, opt?:{ why?:string}) :Promise + /** + * Adds a signature to a message, for data that you want to + * prevent attackers tampering with. The default + * cryptographic primitive signs a SHA256 fingerprint of the + * data + * + * @param data the content that you want to prove is authorized + * @param pair SEA pair + */ + sign(data: any, pair: { priv: string; pub: string }): Promise; + /** + * Do you want to allow others to write to parts of your own + * organization's graph without sharing your keypair with + * them? Then this feature is for you! With SEA.certify, you + * can create a cryptographically signed Certificate that + * gives other people write permission. A Certificate + * describes WHO has the right to write to your graph, WHERE + * they can write, and (pending security review) until WHEN. + * The Certificate should not be encrypted because it must be + * plain text so that it is interpretable by any and every + * peer and machine in the network, so every peer enforces + * the same security rules, whether it is a browser, phone, + * IoT device, or relay + * + * @see https://gun.eco/docs/SEA.certify + * + * @param who Who the certificate is for. These are the people you allow to + * write to your own graph + * @param policy The rules of the Certificate + * @param authority Certificate Authority or Certificate Issuer. + * This is your priv, or your key pair + * @param callback A callback function that runs after a + * Certificate is created + */ + certify( + who: '*' | string | string[] | { pub: string } | { pub: string }[], + policy: Policy, + authority: { priv: string; pub: string }, + callback?: () => void, + options?: { /** - * Certify other users to use your graph. - * @param certificants users for certification. - * @param policy policises for certificants permissions - * @param authority user that gives rights - * @param cb callback - * @param opt options - */ - certify (certificants: string | string[] | { pub: string } | { pub: string }[], policy: ISEAPolicy, authority: { pub: string; priv: string }, cb?: (cert: string) => any | null, opt?: - { blacklist?: string, expiry?: number }): Promise + * A timestamp (ie. `Date.now() + 10000` or `Gun.state() + 10000`) + * to set the Certificate to expire in the future + * + * If `options.expiry` IS NOT SET, the Certificate is valid PERMANENTLY, and this is + * dangerous! + */ + expiry: number; + } + ): Promise; + + /** + * Gets the data if and only if the message can be verified + * as coming from the person you expect + * + * @param message what comes from `.sign` + * @param pair from `.pair` or its public key text (`pair.pub`) + * @returns the data if and only if the message can be + * verified as coming from the person you expect + */ + verify( + message: string, + pair: string | { pub: string } | string + ): Promise; + + /** + * Takes some data that you want to keep secret and encrypts + * it so nobody else can read it + * + * @param data the content that you want to encrypt + * @param pair from `.pair` to use as a cypher to encrypt with + */ + encrypt(data: any, pair: { epriv: string }): Promise; + + /** + * Takes some data that you want to keep secret and encrypts + * it so nobody else can read it + * + * @param data the content that you want to encrypt + * @param passphrase the passphrase you want to use as a cypher to encrypt with + */ + encrypt(data: any, passphrase: string): Promise; + + /** + * Read the secret data, if and only if you are allowed to + * + * @param message what comes from `.encrypt` + * @param pair from `.pair` to decypher the message + */ + decrypt( + message: string, + pair: { epriv: string } + ): Promise; + + /** + * Read the secret data, if and only if you are allowed to + * + * @param message what comes from `.encrypt` + * @param passphrase the passphrase to decypher the message + */ + decrypt( + message: string, + passphrase: string + ): Promise; + + /** + * Derive shared secret from other's pub and my epub/epriv + * + * @param key other's public encryption key + * @param pair encyption key pair from `.pair` + * @param callback A callback function that runs after a secret is created + */ + secret( + key: string | { epub: string }, + pair: { epriv: string; epub: string }, + callback?: (secret: string | undefined) => void + ): Promise; } diff --git a/types/sea/ISEACertifyOptions.d.ts b/types/sea/ISEACertifyOptions.d.ts deleted file mode 100644 index f2c95b28..00000000 --- a/types/sea/ISEACertifyOptions.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface ISEACertifyOptions{ - blacklist?: string | { - read: string|{'#': string} - write: string|{'#': string} - } - expiry?: number -} \ No newline at end of file diff --git a/types/sea/ISEAPair.d.ts b/types/sea/ISEAPair.d.ts index 59d38c81..d9f46ed2 100644 --- a/types/sea/ISEAPair.d.ts +++ b/types/sea/ISEAPair.d.ts @@ -1,6 +1,10 @@ -export declare interface ISEAPair { - pub: string - priv:string - epub:string - epriv:string -} \ No newline at end of file +export interface ISEAPair { + /** private key for encryption */ + epriv: string; + /** public key for encryption */ + epub: string; + /** private key */ + priv: string; + /** public key */ + pub: string; +} diff --git a/types/sea/ISEAPolicy.d.ts b/types/sea/ISEAPolicy.d.ts deleted file mode 100644 index 6f67577e..00000000 --- a/types/sea/ISEAPolicy.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -interface ISEAPolicyTree{ - "+"?:string|ISEAPolicyTree, - "#"?:string|ISEAPolicyTree, - "."?:string|ISEAPolicyTree, - "="?:string|ISEAPolicyTree, - "*"?:string|ISEAPolicyTree, - ">"?:string|ISEAPolicyTree, - "<"?:string|ISEAPolicyTree -} - - -interface ISEAPolicySingle extends ISEAPolicyTree{ - read?:string |ISEAPolicyTree, - write?:string|ISEAPolicyTree, -} - -export declare type ISEAPolicy = ISEAPolicySingle |string | string[] | ISEAPolicySingle[] \ No newline at end of file diff --git a/types/sea/OptionsUserAuth.d.ts b/types/sea/OptionsUserAuth.d.ts new file mode 100644 index 00000000..31292ae4 --- /dev/null +++ b/types/sea/OptionsUserAuth.d.ts @@ -0,0 +1 @@ +export type OptionsUserAuth = { change: 'newPassword' }; diff --git a/types/sea/OptionsUserRecall.d.ts b/types/sea/OptionsUserRecall.d.ts new file mode 100644 index 00000000..60fe2512 --- /dev/null +++ b/types/sea/OptionsUserRecall.d.ts @@ -0,0 +1 @@ +export type OptionsUserRecall = { sessionStorage: boolean }; diff --git a/types/sea/Policy.d.ts b/types/sea/Policy.d.ts new file mode 100644 index 00000000..7d47a4b3 --- /dev/null +++ b/types/sea/Policy.d.ts @@ -0,0 +1,3 @@ +import { IPolicy } from '.'; + +export type Policy = string | IPolicy | (string | IPolicy)[]; diff --git a/types/sea/index.d.ts b/types/sea/index.d.ts new file mode 100644 index 00000000..2dff91af --- /dev/null +++ b/types/sea/index.d.ts @@ -0,0 +1,14 @@ +export * from './GunCallbackUserAuth'; +export * from './GunCallbackUserCreate'; +export * from './GunHookCallbackAuth'; +export * from './GunUser'; +export * from './IGun'; +export * from './IGunInstance'; +export * from './IGunInstanceHookHandler'; +export * from './IGunUserInstance'; +export * from './IPolicy'; +export * from './ISEA'; +export * from './ISEAPair'; +export * from './OptionsUserAuth'; +export * from './OptionsUserRecall'; +export * from './Policy'; diff --git a/types/shared/And.d.ts b/types/shared/And.d.ts deleted file mode 100644 index ee724d55..00000000 --- a/types/shared/And.d.ts +++ /dev/null @@ -1 +0,0 @@ -export type And = A & B \ No newline at end of file diff --git a/types/test/gun-back.test-d.ts b/types/test/gun-back.test-d.ts index abb4507a..c33db82f 100644 --- a/types/test/gun-back.test-d.ts +++ b/types/test/gun-back.test-d.ts @@ -1,6 +1,28 @@ -import Gun = require('../../index'); -Gun().get('users') - /* now change the context to alice */ - .get('alice') - .put({}) - .back().map(x=>x) \ No newline at end of file +import Gun from '../..'; + +new Gun<{ a: { b: number; c: number } }>() + .get('a') + .get('b') + .back() + .get('c') + .once((c) => c.toFixed(2)); + +new Gun() + .get<{ b: number; c: number }>('a') + .get('b') + .back() + .get('c') + .once((c) => c.toFixed(2)); + +new Gun() + .get('a') + .back<{ a: number; b: number }>() + .get('b') + .once((b) => b.toFixed(2)); + +new Gun() + .get('a') + .get('b') + .back<{ a: number; c: number }>(-2) + .get('c') + .once((c) => c.toFixed(2)); diff --git a/types/test/gun-get.test-d.ts b/types/test/gun-get.test-d.ts index 52c1daa0..673555f3 100644 --- a/types/test/gun-get.test-d.ts +++ b/types/test/gun-get.test-d.ts @@ -1,14 +1,5 @@ -//import { expectError } from 'tsd'; +import Gun from '../..'; -import Gun = require('../../index'); +new Gun<{ a: { b: number; c: number } }>().get('a').get('b'); - -//Documentation should work - -async function get(){ - const gun = new Gun(); - const alice = await gun.get('user').get('alice') - - const gun2 = new Gun<{user:{alice:string}}>(); - const alice2 = (await gun2.get('user')).alice -} +new Gun().get<{ b: number; c: number }>('a').get('b'); diff --git a/types/test/gun-instance.test-d.ts b/types/test/gun-instance.test-d.ts index 52d3e893..f20023da 100644 --- a/types/test/gun-instance.test-d.ts +++ b/types/test/gun-instance.test-d.ts @@ -1,15 +1,15 @@ -import Gun = require('../../index'); +import Gun from '../..'; -Gun() -Gun(['http://server1.com/gun', 'http://server2.com/gun']); -Gun({ +new Gun(); +new Gun(['http://server1.com/gun', 'http://server2.com/gun']); +new Gun({ s3: { key: '', secret: '', - bucket: '' + bucket: '', }, file: 'file/path.json', uuid() { return 'xxxxxx'; - } -}); \ No newline at end of file + }, +}); diff --git a/types/test/gun-map.test-d.ts b/types/test/gun-map.test-d.ts index b084d498..7e4905ca 100644 --- a/types/test/gun-map.test-d.ts +++ b/types/test/gun-map.test-d.ts @@ -1,3 +1,11 @@ -import Gun = require('../../index'); +import Gun from '../..'; -Gun().get('users').map(user => user.name === 'Mark'? user : undefined) \ No newline at end of file +new Gun<{ users: Record }>() + .get('users') + .on() + .map((user) => (user.name === 'Mark' ? user : undefined)); + +new Gun() + .get>('users') + .map((user) => (user.name === 'Mark' ? user : undefined)) + .once((user) => console.log(user.name)); diff --git a/types/test/gun-on.test-d.ts b/types/test/gun-on.test-d.ts index 1486d1cd..3ca51ba3 100644 --- a/types/test/gun-on.test-d.ts +++ b/types/test/gun-on.test-d.ts @@ -1,23 +1,39 @@ +import Gun from '../..'; -import Gun = require('../../index'); -const gun = Gun() -var listenerHandler = (value, key, _msg, _ev) => { +type TOnlinable = { online: boolean }; -} +const gun = new Gun<{ + users: Record; + foo: TOnlinable; + home: { lights: TOnlinable }; +}>(); -Gun().on(listenerHandler) +var listenerHandler = (_value, _key, _msg, _ev) => {}; // add listener to foo -gun.get('foo').on(listenerHandler, true) +gun.get('foo').on(listenerHandler, true); // remove listener to foo -gun.get('foo').off() +gun.get('foo').off(); -gun.get('users').get('username').on(function(user : any){ +gun + .get('users') + .get('username') + .on(function (user) { // update in real-time if (user.online) { } else { } - }) + }); - gun.get('home').get('lights').on(listenerHandler,true); \ No newline at end of file +gun.get('home').get('lights').on(listenerHandler, true); + +new Gun() + .get('home') + .get('lights') + .on(function (user) { + // update in real-time + if (user.online) { + } else { + } + }); diff --git a/types/test/gun-once.test-d.ts b/types/test/gun-once.test-d.ts index 919c9a5e..de7c588f 100644 --- a/types/test/gun-once.test-d.ts +++ b/types/test/gun-once.test-d.ts @@ -1,17 +1,35 @@ +import Gun from '../..'; -import Gun = require('../../index'); -const gun= Gun() -let view; -gun.get('peer').get('userID').get('profile').once(function(profile){ +const gun = new Gun<{ + peer: { userID: { profile: {} } }; + IoT: { temperature: number }; + something: string; +}>(); + +let view: any; + +gun + .get('peer') + .get('userID') + .get('profile') + .once(function (profile) { // render it, but only once. No updates. - view.show.user(profile) - }) - - gun.get('IoT').get('temperature').once(function(number){ - view.show.temp(number) - }) + view.show.user(profile); + }); +gun + .get('IoT') + .get('temperature') + .once(function (number) { + view.show.temp(number); + }); - gun.once(function(data, key) { - gun.get('something').put('something') - }) \ No newline at end of file +gun.get('something').once(function (_data, _key) { + gun.put({ something: 'something' }); + gun.get('something').put('something'); +}); + +new Gun().get('something').once(function (data, _key) { + gun.put({ something: data }); + gun.get('something').put(data); +}); diff --git a/types/test/gun-opt.test-d.ts b/types/test/gun-opt.test-d.ts index 179ea470..e8b5df22 100644 --- a/types/test/gun-opt.test-d.ts +++ b/types/test/gun-opt.test-d.ts @@ -1,6 +1,7 @@ -import Gun = require('../../index'); -Gun().opt({ - uuid: function () { - return Math.floor(Math.random() * 4294967296); - } - }) \ No newline at end of file +import Gun from '../..'; + +new Gun().opt({ + uuid: function () { + return Math.floor(Math.random() * 4294967296).toString(); + }, +}); diff --git a/types/test/gun-put.test-d.ts b/types/test/gun-put.test-d.ts index 1a5b40c4..349c49e7 100644 --- a/types/test/gun-put.test-d.ts +++ b/types/test/gun-put.test-d.ts @@ -1,12 +1,12 @@ //import { expectError } from 'tsd'; -import Gun = require('../../index'); - +import Gun from '../..'; //Documentation should work - const gun = new Gun(); - gun.get('user').put('alice') +type User = { name: string }; - const gun2 = new Gun<{user:{alice:string}}>(); - gun2.get('user').put({alice:"asd"}) +const gun = new Gun<{ user: User; user2: User }>(); +gun.get('user').put({ name: '' }); +gun.get('user').get('name').put(gun.get('user').get('name')); +gun.get('user2').put(gun.get('user')); diff --git a/types/test/gun-set.test-d.ts b/types/test/gun-set.test-d.ts index 0dd35ec1..13bfb4d9 100644 --- a/types/test/gun-set.test-d.ts +++ b/types/test/gun-set.test-d.ts @@ -1,4 +1,8 @@ -import Gun = require('../../index'); -const gun = Gun() -var user = gun.get('alice').put({name: "Alice"}) -gun.get('users').set("sa"); \ No newline at end of file +import Gun from '../..'; + +type User = { name: string }; + +const gun = new Gun<{ users: Record; alice: User }>(); +const user = gun.get('alice').put({ name: 'Alice' }); +gun.get('users').set({ name: 'Bob' }); +gun.get('users').set(user).get('name').put('Sally'); diff --git a/types/test/gun-typed.test-d.ts b/types/test/gun-typed.test-d.ts deleted file mode 100644 index 6d7437cd..00000000 --- a/types/test/gun-typed.test-d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import Gun = require('../../index'); -const gun = Gun() - -type ExampleState={ - a:{ - b:{ - c:{ - d: Record - } - } - } -} - -gun.get("a").get("b").get("c").get("d").get("anystring").on(x=>x.startsWith("some")) \ No newline at end of file diff --git a/types/test/gun-user-auth.test-d.ts b/types/test/gun-user-auth.test-d.ts index fe19194b..7a71c79f 100644 --- a/types/test/gun-user-auth.test-d.ts +++ b/types/test/gun-user-auth.test-d.ts @@ -1,13 +1,9 @@ - -import Gun = require('../../index'); - +import Gun from '../..'; //Documentation should work -const gun = Gun() -gun.on('auth', data => { +const gun = new Gun(); +gun.on('auth', (_data) => {}); -}) - -gun.user().auth("a","b") -async () => gun.user().auth(await Gun.SEA.pair()) \ No newline at end of file +gun.user().auth('a', 'b'); +async () => gun.user().auth(await Gun.SEA.pair()); diff --git a/types/test/gun-user-delete.test-d.ts b/types/test/gun-user-delete.test-d.ts deleted file mode 100644 index 55437d68..00000000 --- a/types/test/gun-user-delete.test-d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import Gun = require('../../index'); - - -//Documentation should work - -const gun = Gun() - -gun.user().delete('alias', 'pass', data => data) \ No newline at end of file diff --git a/types/test/gun-user-leave.test-d.ts b/types/test/gun-user-leave.test-d.ts index b52c253f..ba595a2b 100644 --- a/types/test/gun-user-leave.test-d.ts +++ b/types/test/gun-user-leave.test-d.ts @@ -1,8 +1,7 @@ -import Gun = require('../../index'); - +import Gun from '../..'; //Documentation should work -const gun = Gun() +const gun = new Gun(); -gun.user().leave() \ No newline at end of file +gun.user().leave(); diff --git a/types/test/gun-user-recall.test-d.ts b/types/test/gun-user-recall.test-d.ts index 15da62da..1531e036 100644 --- a/types/test/gun-user-recall.test-d.ts +++ b/types/test/gun-user-recall.test-d.ts @@ -1,3 +1,4 @@ -import Gun = require('../../index'); -var gun = Gun(); -var user = gun.user().recall({sessionStorage: true}); \ No newline at end of file +import Gun from '../..'; + +const gun = new Gun(); +gun.user().recall({ sessionStorage: true }); diff --git a/types/test/gun-user-secret.test-d.ts b/types/test/gun-user-secret.test-d.ts deleted file mode 100644 index 4ed90012..00000000 --- a/types/test/gun-user-secret.test-d.ts +++ /dev/null @@ -1,4 +0,0 @@ -import Gun = require('../../index'); -var gun = Gun(); -var user = gun.user().recall({sessionStorage: true}); -user.get('mysecrets').secret('string', data => data) \ No newline at end of file diff --git a/types/test/gun-user.test-d.ts b/types/test/gun-user.test-d.ts index a49ac39e..333b0d49 100644 --- a/types/test/gun-user.test-d.ts +++ b/types/test/gun-user.test-d.ts @@ -1,3 +1,4 @@ -import Gun = require('../../index'); -var gun = Gun(); -gun.user("publicKey").once(console.log) \ No newline at end of file +import Gun from '../..'; + +var gun = new Gun(); +gun.user('publicKey'); diff --git a/types/test/sea-certify.test-d.ts b/types/test/sea-certify.test-d.ts index 842b2f3e..61df8630 100644 --- a/types/test/sea-certify.test-d.ts +++ b/types/test/sea-certify.test-d.ts @@ -1,29 +1,30 @@ -import Gun = require('../../index'); +import Gun from '../..'; /*Documentation example*/ -async function certify(){ - const SEA = Gun.SEA; - const gun = Gun(); - const user = gun.user(); - var Alice = await SEA.pair() - var AliceHusband = await SEA.pair() - var Bob = await SEA.pair() - var Dave = await SEA.pair() - - // Alice wants to allow Bob and Dave to use write to her "inbox" and "stories" UNTIL TOMORROW - // On Alice's side: - var certificate = await SEA.certify([Bob.pub, Dave.pub], [{"*": "inbox", "+": "*"}, {"*": "stories"}], Alice, null, {expiry: Gun.state()+(60*60*24*1000), blacklist: 'blacklist'}) - - // Now on Bob/Dave's side, they can write to Alice's graph using gun.put: - gun.get('~'+Alice.pub).get('inbox').get('deeper'+Bob.pub).put('hello world', null, {opt: {cert: certificate}}) // {opt: {cert: certificate}} is how you use Certificate in gun.put - - // Now Alice wants to revoke access of Bob. She has TWO OPTIONS. OPTION 1 is to manage the blacklist by herself. - user.get('blacklist').get(Bob.pub).put(true) // OPTION 1: She directly manages her blacklist, in her graph. - - // OPTION 2: Alice could point the blacklist to her husband's graph: - user.get('blacklist').put({'#': '~'+AliceHusband.pub+'/blacklist'}) - - // Now on AliceHusband's side, HE can add Bob to his blacklist: - user.get('blacklist').get(Bob.pub).put(true) +async function certify() { + const SEA = Gun.SEA; + const gun = new Gun(); + const user = gun.user(); + const Alice = await SEA.pair(); + const AliceHusband = await SEA.pair(); + const Bob = await SEA.pair(); + const Dave = await SEA.pair(); -} \ No newline at end of file + // Alice wants to allow Bob and Dave to use write to her "inbox" and "stories" UNTIL TOMORROW + // On Alice's side: + const certificate = await SEA.certify( + [Bob.pub, Dave.pub], + [{ '*': 'inbox', '+': '*' }, { '*': 'stories' }], + Alice, + null, + { expiry: Gun.state() + 60 * 60 * 24 * 1000 } + ); + + // Now on Bob/Dave's side, they can write to Alice's graph using gun.put: + gun + .get('~' + Alice.pub) + .get('inbox') + .put({ ['deeper' + Bob.pub]: 'hello world' }, null, { + opt: { cert: certificate }, + }); // {opt: {cert: certificate}} is how you use Certificate in gun.put +} diff --git a/types/test/sea.test-d.ts b/types/test/sea.test-d.ts index b3c10f82..be8701f3 100644 --- a/types/test/sea.test-d.ts +++ b/types/test/sea.test-d.ts @@ -1,28 +1,36 @@ -import Gun = require('../../index'); -const SEA = Gun.SEA -;(async () => { -var pair = await SEA.pair(); -var enc = await SEA.encrypt('hello self', pair); -var data = await SEA.sign(enc, pair); -console.log(data); -var msg = await SEA.verify(data, pair.pub); -var dec = await SEA.decrypt(msg, pair); -var proof = await SEA.work(dec, pair); -var check = await SEA.work('hello self', pair); -console.log(dec); -console.log(proof === check); -// now let's share private data with someone: -var alice = await SEA.pair(); -var bob = await SEA.pair(); -var enc = await SEA.encrypt('shared data', await SEA.secret(bob.epub, alice)); -await SEA.decrypt(enc, await SEA.secret(alice.epub, bob)); -// `.secret` is Elliptic-curve Diffie–Hellman -// Bob allows Alice to write to part of his graph, he creates a certificate for Alice -var certificate = await SEA.certify(alice.pub, ["^AliceOnly.*"], bob) -// Alice logs in -const gun = Gun(); -await gun.user().auth(alice); -// and uses the certificate -await gun.get('~'+bob.pub).get('AliceOnly').get('do-not-tell-anyone').put(enc, null, {opt: {cert: certificate}}) -await gun.get('~'+bob.pub).get('AliceOnly').get('do-not-tell-anyone').once(console.log) // return 'enc' -})(); \ No newline at end of file +import Gun from '../..'; + +const SEA = Gun.SEA; +(async () => { + const pair = await SEA.pair(); + let enc = await SEA.encrypt('hello self', pair); + const data = await SEA.sign(enc, pair); + console.log(data); + const msg = await SEA.verify(data, pair.pub); + const dec = await SEA.decrypt(msg, pair); + const proof = await SEA.work(dec, pair); + const check = await SEA.work('hello self', pair); + console.log(dec); + console.log(proof === check); + // now let's share private data with someone: + const alice = await SEA.pair(); + const bob = await SEA.pair(); + enc = await SEA.encrypt('shared data', await SEA.secret(bob.epub, alice)); + await SEA.decrypt(enc, await SEA.secret(alice.epub, bob)); + // `.secret` is Elliptic-curve Diffie–Hellman + // Bob allows Alice to write to part of his graph, he creates a certificate for Alice + const certificate = await SEA.certify(alice.pub, ['^AliceOnly.*'], bob); + // Alice logs in + const gun = Gun(); + gun.user().auth(alice); + // and uses the certificate + gun + .get('~' + bob.pub) + .get('AliceOnly') + .put({ 'do-not-tell-anyone': enc }, null, { opt: { cert: certificate } }); + gun + .get('~' + bob.pub) + .get('AliceOnly') + .get('do-not-tell-anyone') + .once(console.log); // return 'enc' +})(); diff --git a/types/utils.d.ts b/types/utils.d.ts new file mode 100644 index 00000000..7d3c361c --- /dev/null +++ b/types/utils.d.ts @@ -0,0 +1,25 @@ +import { GunSoul, IGunChain, IGunInstanceRoot } from '.'; + +export type GunSoul2TNode = T extends GunSoul + ? TNode + : never; + +export type GunSoul2Soul = T extends GunSoul + ? Soul + : never; + +export type IGunChain2TNode = T extends IGunChain< + infer TNode, + infer _TChainParent, + infer _TNodeRoot, + infer _TKey +> + ? TNode + : never; + +export type IGunInstanceRoot2TGunInstance = T extends IGunInstanceRoot< + infer _TNode, + infer TGunInstance +> + ? TGunInstance + : never;