@kubun/client 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,10 @@
1
- import { AttachmentID } from '@kubun/id';
2
- import { Block } from 'multiformats/block';
3
- import * as codec from 'multiformats/codecs/raw';
4
- export type BinaryBlock = Block<Uint8Array, typeof codec.code, 18, 1>;
5
- export declare function createBlock(value: Uint8Array): BinaryBlock;
1
+ /** @internal */
6
2
  export type Attachment = {
7
- block: BinaryBlock;
8
- id: AttachmentID;
3
+ data: string;
4
+ id: string;
9
5
  };
10
- export declare function createAttachment(value: Uint8Array, mimeType?: string): Attachment;
6
+ /** @internal */
7
+ export declare function createAttachment(bytes: Uint8Array, mimeType?: string): Attachment;
8
+ /** @internal */
9
+ export declare function toAttachmentsRecord(attachments?: Array<Attachment>): Record<string, string>;
11
10
  //# sourceMappingURL=attachments.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../src/attachments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuC,MAAM,WAAW,CAAA;AAC7E,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,KAAK,KAAK,MAAM,yBAAyB,CAAA;AAEhD,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,EAAE,OAAO,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;AAErE,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAI1D;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,WAAW,CAAA;IAClB,EAAE,EAAE,YAAY,CAAA;CACjB,CAAA;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,UAAU,CAGjF"}
1
+ {"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../src/attachments.ts"],"names":[],"mappings":"AAGA,gBAAgB;AAChB,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED,gBAAgB;AAChB,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,UAAU,CAEjF;AAED,gBAAgB;AAChB,wBAAgB,mBAAmB,CAAC,WAAW,GAAE,KAAK,CAAC,UAAU,CAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAM/F"}
@@ -1,19 +1,15 @@
1
- import { AttachmentID, createAttachmentCID, toSHA256Digest } from '@kubun/id';
2
- import { Block } from 'multiformats/block';
3
- import * as codec from 'multiformats/codecs/raw';
4
- export function createBlock(value) {
5
- const bytes = codec.encode(value);
6
- const cid = createAttachmentCID(toSHA256Digest(bytes));
7
- return new Block({
8
- value,
9
- bytes,
10
- cid
11
- });
12
- }
13
- export function createAttachment(value, mimeType) {
14
- const block = createBlock(value);
1
+ import { toB64 } from '@enkaku/codec';
2
+ import { AttachmentID } from '@kubun/id';
3
+ /** @internal */ export function createAttachment(bytes, mimeType) {
15
4
  return {
16
- block,
17
- id: new AttachmentID(block.cid, value.byteLength, mimeType)
5
+ data: toB64(bytes),
6
+ id: AttachmentID.create(bytes, mimeType).toString()
18
7
  };
19
8
  }
9
+ /** @internal */ export function toAttachmentsRecord(attachments = []) {
10
+ const record = {};
11
+ for (const attachment of attachments){
12
+ record[attachment.id] = attachment.data;
13
+ }
14
+ return record;
15
+ }
package/lib/client.d.ts CHANGED
@@ -1,474 +1,43 @@
1
- import type { Signer } from '@enkaku/jwt';
2
- import type { ClientTransport, CreateGraphParams, ExecuteGraphParams, LoadGraphParams, MutateGraphParams as ProtocolMutateGraphParams } from '@kubun/protocol';
3
- import type { Attachment } from './attachments.js';
4
- export type ClientParams = {
5
- signer: Signer;
6
- transport: ClientTransport;
1
+ import { Client, type RequestCall } from '@enkaku/client';
2
+ import type { TokenSigner } from '@enkaku/token';
3
+ import type { ClientTransport, DeployGraphParams, DeployGraphResult, ExecuteGraphParams, ExecuteGraphResult, ListGraphResult, LoadGraphParams, LoadGraphResult, Protocol } from '@kubun/protocol';
4
+ export type MutateGraphParams = ExecuteGraphParams & {
5
+ attachments?: Record<string, string>;
6
+ };
7
+ export type KubunClientType = {
8
+ deployGraph: (params: DeployGraphParams) => RequestCall<DeployGraphResult>;
9
+ listGraphs: () => RequestCall<ListGraphResult>;
10
+ loadGraph: (params: LoadGraphParams) => RequestCall<LoadGraphResult>;
11
+ queryGraph: <Data extends Record<string, unknown> = Record<string, unknown>>(params: ExecuteGraphParams) => RequestCall<ExecuteGraphResult<Data>>;
12
+ mutateGraph: (params: MutateGraphParams) => RequestCall<ExecuteGraphResult>;
7
13
  };
8
- export type MutateGraphInvocationParams = Omit<ProtocolMutateGraphParams, 'attachments'> & {
9
- attachments?: Array<Attachment>;
14
+ export type ReadClientParams = {
15
+ getRandomID?: () => string;
16
+ serverID?: string;
17
+ signer?: TokenSigner | Promise<TokenSigner>;
18
+ transport: ClientTransport;
10
19
  };
11
- export type MutateGraphParams = Omit<ExecuteGraphParams, 'attachments'> & {
12
- attachments?: Array<Attachment>;
20
+ export type ClientParams = Omit<ReadClientParams, 'signer'> & {
21
+ signer: TokenSigner | Promise<TokenSigner>;
13
22
  };
14
- export declare class KubunClient {
23
+ export declare class KubunReadClient {
24
+ #private;
25
+ constructor(params: ReadClientParams);
26
+ /** @internal */
27
+ get client(): Client<Protocol>;
28
+ listGraphs(signal?: AbortSignal): RequestCall<ListGraphResult>;
29
+ loadGraph(param: LoadGraphParams, signal?: AbortSignal): RequestCall<LoadGraphResult>;
30
+ queryGraph<Data extends Record<string, unknown> = Record<string, unknown>>(param: ExecuteGraphParams, signal?: AbortSignal): RequestCall<ExecuteGraphResult<Data>>;
31
+ }
32
+ export declare class KubunLightClient extends KubunReadClient implements KubunClientType {
33
+ deployGraph(param: DeployGraphParams, signal?: AbortSignal): RequestCall<DeployGraphResult>;
34
+ mutateGraph<Data extends Record<string, unknown> = Record<string, unknown>>(param: MutateGraphParams, signal?: AbortSignal): RequestCall<ExecuteGraphResult<Data>>;
35
+ }
36
+ export declare class KubunClient extends KubunReadClient implements KubunClientType {
15
37
  #private;
16
38
  constructor(params: ClientParams);
17
- createGraph(params: CreateGraphParams): Promise<import("@enkaku/client").InvokeReturn<{
18
- id: string;
19
- models: {
20
- [x: string]: {
21
- name: string;
22
- version: "1.0";
23
- interfaces: string[];
24
- schema: {
25
- $defs: {
26
- [x: string]: {
27
- default?: boolean | undefined;
28
- type: "boolean";
29
- } | {
30
- default?: number | undefined;
31
- min?: number | undefined;
32
- max?: number | undefined;
33
- type: "integer";
34
- } | {
35
- default?: number | undefined;
36
- min?: number | undefined;
37
- max?: number | undefined;
38
- type: "number";
39
- } | {
40
- default?: string | undefined;
41
- title?: string | undefined;
42
- maxLength?: number | undefined;
43
- minLength?: number | undefined;
44
- pattern?: string | undefined;
45
- type: "string";
46
- } | {
47
- default?: string | undefined;
48
- enum: string[];
49
- title: string;
50
- type: "string";
51
- } | {
52
- format: "date" | "date-time" | "duration" | "time" | "uri";
53
- type: "string";
54
- } | {
55
- title: string;
56
- type: "array";
57
- items: {
58
- $ref: string;
59
- };
60
- } | {
61
- title: string;
62
- type: "object";
63
- additionalProperties: boolean;
64
- properties: {
65
- [x: string]: {
66
- $ref: string;
67
- };
68
- };
69
- required: string[];
70
- };
71
- };
72
- type: "object";
73
- additionalProperties: boolean;
74
- properties: {
75
- [x: string]: {
76
- $ref: string;
77
- };
78
- };
79
- required: string[];
80
- };
81
- fieldsMeta: {
82
- [x: string]: {
83
- relationModel?: string | null | undefined;
84
- };
85
- };
86
- behavior: "interface";
87
- } | {
88
- name: string;
89
- version: "1.0";
90
- interfaces: string[];
91
- schema: {
92
- $defs: {
93
- [x: string]: {
94
- default?: boolean | undefined;
95
- type: "boolean";
96
- } | {
97
- default?: number | undefined;
98
- min?: number | undefined;
99
- max?: number | undefined;
100
- type: "integer";
101
- } | {
102
- default?: number | undefined;
103
- min?: number | undefined;
104
- max?: number | undefined;
105
- type: "number";
106
- } | {
107
- default?: string | undefined;
108
- title?: string | undefined;
109
- maxLength?: number | undefined;
110
- minLength?: number | undefined;
111
- pattern?: string | undefined;
112
- type: "string";
113
- } | {
114
- default?: string | undefined;
115
- enum: string[];
116
- title: string;
117
- type: "string";
118
- } | {
119
- format: "date" | "date-time" | "duration" | "time" | "uri";
120
- type: "string";
121
- } | {
122
- title: string;
123
- type: "array";
124
- items: {
125
- $ref: string;
126
- };
127
- } | {
128
- title: string;
129
- type: "object";
130
- additionalProperties: boolean;
131
- properties: {
132
- [x: string]: {
133
- $ref: string;
134
- };
135
- };
136
- required: string[];
137
- };
138
- };
139
- type: "object";
140
- additionalProperties: boolean;
141
- properties: {
142
- [x: string]: {
143
- $ref: string;
144
- };
145
- };
146
- required: string[];
147
- };
148
- fieldsMeta: {
149
- [x: string]: {
150
- relationModel?: string | null | undefined;
151
- };
152
- };
153
- behavior: "list";
154
- } | {
155
- name: string;
156
- version: "1.0";
157
- interfaces: string[];
158
- schema: {
159
- $defs: {
160
- [x: string]: {
161
- default?: boolean | undefined;
162
- type: "boolean";
163
- } | {
164
- default?: number | undefined;
165
- min?: number | undefined;
166
- max?: number | undefined;
167
- type: "integer";
168
- } | {
169
- default?: number | undefined;
170
- min?: number | undefined;
171
- max?: number | undefined;
172
- type: "number";
173
- } | {
174
- default?: string | undefined;
175
- title?: string | undefined;
176
- maxLength?: number | undefined;
177
- minLength?: number | undefined;
178
- pattern?: string | undefined;
179
- type: "string";
180
- } | {
181
- default?: string | undefined;
182
- enum: string[];
183
- title: string;
184
- type: "string";
185
- } | {
186
- format: "date" | "date-time" | "duration" | "time" | "uri";
187
- type: "string";
188
- } | {
189
- title: string;
190
- type: "array";
191
- items: {
192
- $ref: string;
193
- };
194
- } | {
195
- title: string;
196
- type: "object";
197
- additionalProperties: boolean;
198
- properties: {
199
- [x: string]: {
200
- $ref: string;
201
- };
202
- };
203
- required: string[];
204
- };
205
- };
206
- type: "object";
207
- additionalProperties: boolean;
208
- properties: {
209
- [x: string]: {
210
- $ref: string;
211
- };
212
- };
213
- required: string[];
214
- };
215
- fieldsMeta: {
216
- [x: string]: {
217
- relationModel?: string | null | undefined;
218
- };
219
- };
220
- behavior: "set";
221
- setFields: string[];
222
- };
223
- };
224
- }>>;
225
- loadGraph(params: LoadGraphParams): Promise<import("@enkaku/client").InvokeReturn<{
226
- aliases?: {
227
- [x: string]: string;
228
- } | undefined;
229
- models: {
230
- [x: string]: {
231
- name: string;
232
- version: "1.0";
233
- interfaces: string[];
234
- schema: {
235
- $defs: {
236
- [x: string]: {
237
- default?: boolean | undefined;
238
- type: "boolean";
239
- } | {
240
- default?: number | undefined;
241
- min?: number | undefined;
242
- max?: number | undefined;
243
- type: "integer";
244
- } | {
245
- default?: number | undefined;
246
- min?: number | undefined;
247
- max?: number | undefined;
248
- type: "number";
249
- } | {
250
- default?: string | undefined;
251
- title?: string | undefined;
252
- maxLength?: number | undefined;
253
- minLength?: number | undefined;
254
- pattern?: string | undefined;
255
- type: "string";
256
- } | {
257
- default?: string | undefined;
258
- enum: string[];
259
- title: string;
260
- type: "string";
261
- } | {
262
- format: "date" | "date-time" | "duration" | "time" | "uri";
263
- type: "string";
264
- } | {
265
- title: string;
266
- type: "array";
267
- items: {
268
- $ref: string;
269
- };
270
- } | {
271
- title: string;
272
- type: "object";
273
- additionalProperties: boolean;
274
- properties: {
275
- [x: string]: {
276
- $ref: string;
277
- };
278
- };
279
- required: string[];
280
- };
281
- };
282
- type: "object";
283
- additionalProperties: boolean;
284
- properties: {
285
- [x: string]: {
286
- $ref: string;
287
- };
288
- };
289
- required: string[];
290
- };
291
- fieldsMeta: {
292
- [x: string]: {
293
- relationModel?: string | null | undefined;
294
- };
295
- };
296
- behavior: "interface";
297
- } | {
298
- name: string;
299
- version: "1.0";
300
- interfaces: string[];
301
- schema: {
302
- $defs: {
303
- [x: string]: {
304
- default?: boolean | undefined;
305
- type: "boolean";
306
- } | {
307
- default?: number | undefined;
308
- min?: number | undefined;
309
- max?: number | undefined;
310
- type: "integer";
311
- } | {
312
- default?: number | undefined;
313
- min?: number | undefined;
314
- max?: number | undefined;
315
- type: "number";
316
- } | {
317
- default?: string | undefined;
318
- title?: string | undefined;
319
- maxLength?: number | undefined;
320
- minLength?: number | undefined;
321
- pattern?: string | undefined;
322
- type: "string";
323
- } | {
324
- default?: string | undefined;
325
- enum: string[];
326
- title: string;
327
- type: "string";
328
- } | {
329
- format: "date" | "date-time" | "duration" | "time" | "uri";
330
- type: "string";
331
- } | {
332
- title: string;
333
- type: "array";
334
- items: {
335
- $ref: string;
336
- };
337
- } | {
338
- title: string;
339
- type: "object";
340
- additionalProperties: boolean;
341
- properties: {
342
- [x: string]: {
343
- $ref: string;
344
- };
345
- };
346
- required: string[];
347
- };
348
- };
349
- type: "object";
350
- additionalProperties: boolean;
351
- properties: {
352
- [x: string]: {
353
- $ref: string;
354
- };
355
- };
356
- required: string[];
357
- };
358
- fieldsMeta: {
359
- [x: string]: {
360
- relationModel?: string | null | undefined;
361
- };
362
- };
363
- behavior: "list";
364
- } | {
365
- name: string;
366
- version: "1.0";
367
- interfaces: string[];
368
- schema: {
369
- $defs: {
370
- [x: string]: {
371
- default?: boolean | undefined;
372
- type: "boolean";
373
- } | {
374
- default?: number | undefined;
375
- min?: number | undefined;
376
- max?: number | undefined;
377
- type: "integer";
378
- } | {
379
- default?: number | undefined;
380
- min?: number | undefined;
381
- max?: number | undefined;
382
- type: "number";
383
- } | {
384
- default?: string | undefined;
385
- title?: string | undefined;
386
- maxLength?: number | undefined;
387
- minLength?: number | undefined;
388
- pattern?: string | undefined;
389
- type: "string";
390
- } | {
391
- default?: string | undefined;
392
- enum: string[];
393
- title: string;
394
- type: "string";
395
- } | {
396
- format: "date" | "date-time" | "duration" | "time" | "uri";
397
- type: "string";
398
- } | {
399
- title: string;
400
- type: "array";
401
- items: {
402
- $ref: string;
403
- };
404
- } | {
405
- title: string;
406
- type: "object";
407
- additionalProperties: boolean;
408
- properties: {
409
- [x: string]: {
410
- $ref: string;
411
- };
412
- };
413
- required: string[];
414
- };
415
- };
416
- type: "object";
417
- additionalProperties: boolean;
418
- properties: {
419
- [x: string]: {
420
- $ref: string;
421
- };
422
- };
423
- required: string[];
424
- };
425
- fieldsMeta: {
426
- [x: string]: {
427
- relationModel?: string | null | undefined;
428
- };
429
- };
430
- behavior: "set";
431
- setFields: string[];
432
- };
433
- };
434
- }>>;
435
- queryGraph(params: ExecuteGraphParams): Promise<import("@enkaku/client").InvokeReturn<{
436
- data?: {
437
- [x: string]: unknown;
438
- } | null | undefined;
439
- errors?: {
440
- locations?: {
441
- line: number;
442
- column: number;
443
- }[] | undefined;
444
- path?: string[] | undefined;
445
- extensions?: {
446
- [x: string]: unknown;
447
- } | undefined;
448
- message: string;
449
- }[] | undefined;
450
- extensions?: {
451
- [x: string]: unknown;
452
- } | undefined;
453
- }>>;
454
- mutateGraph(params: MutateGraphParams): Promise<import("@enkaku/client").InvokeReturn<{
455
- data?: {
456
- [x: string]: unknown;
457
- } | null | undefined;
458
- errors?: {
459
- locations?: {
460
- line: number;
461
- column: number;
462
- }[] | undefined;
463
- path?: string[] | undefined;
464
- extensions?: {
465
- [x: string]: unknown;
466
- } | undefined;
467
- message: string;
468
- }[] | undefined;
469
- extensions?: {
470
- [x: string]: unknown;
471
- } | undefined;
472
- }>>;
39
+ deployGraph(param: DeployGraphParams, signal?: AbortSignal): RequestCall<DeployGraphResult>;
40
+ loadGraph(param: LoadGraphParams, signal?: AbortSignal): RequestCall<LoadGraphResult>;
41
+ mutateGraph<Data extends Record<string, unknown> = Record<string, unknown>>(param: MutateGraphParams, signal?: AbortSignal): RequestCall<ExecuteGraphResult<Data>>;
473
42
  }
474
43
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EAEjB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,IAAI,yBAAyB,EAC/C,MAAM,iBAAiB,CAAA;AAExB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAKlD,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,eAAe,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG,IAAI,CAAC,yBAAyB,EAAE,aAAa,CAAC,GAAG;IACzF,WAAW,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,kBAAkB,EAAE,aAAa,CAAC,GAAG;IACxE,WAAW,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;CAChC,CAAA;AAED,qBAAa,WAAW;;gBAKV,MAAM,EAAE,YAAY;IAM1B,WAAW,CAAC,MAAM,EAAE,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IASrC,SAAS,CAAC,MAAM,EAAE,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IASjC,UAAU,CAAC,MAAM,EAAE,kBAAkB;;;;;;;;;;;;;;;;;;;IAIrC,WAAW,CAAC,MAAM,EAAE,iBAAiB;;;;;;;;;;;;;;;;;;;CAmC5C"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/lib/client.js CHANGED
@@ -1,74 +1,144 @@
1
1
  import { Client } from '@enkaku/client';
2
- import { toB64 } from '@enkaku/codec';
2
+ import { fromB64 } from '@enkaku/codec';
3
3
  import { GraphQLExecutionError } from './errors.js';
4
4
  import { ClientSchemaBuilder } from './graphql.js';
5
5
  import { MutationsRunner } from './mutations-runner.js';
6
- export class KubunClient {
6
+ export class KubunReadClient {
7
7
  #client;
8
- #mutationsRunner;
9
- #signer;
10
8
  constructor(params){
11
- this.#client = new Client({
12
- transport: params.transport
9
+ this.#client = new Client(params);
10
+ }
11
+ /** @internal */ get client() {
12
+ return this.#client;
13
+ }
14
+ listGraphs(signal) {
15
+ return this.#client.request('graph/list', {
16
+ signal
13
17
  });
14
- this.#mutationsRunner = new MutationsRunner();
15
- this.#signer = params.signer;
16
18
  }
17
- async createGraph(params) {
18
- const request = await this.#client.request('graph/create', params);
19
- request.result.then((res)=>{
20
- const builder = new ClientSchemaBuilder({
21
- record: res.models
22
- });
23
- this.#mutationsRunner.setSchema(res.id, builder.build());
19
+ loadGraph(param, signal) {
20
+ return this.#client.request('graph/load', {
21
+ param,
22
+ signal
23
+ });
24
+ }
25
+ queryGraph(param, signal) {
26
+ return this.#client.request('graph/query', {
27
+ param,
28
+ signal
29
+ });
30
+ }
31
+ }
32
+ export class KubunLightClient extends KubunReadClient {
33
+ deployGraph(param, signal) {
34
+ return this.client.request('graph/deploy', {
35
+ param,
36
+ signal
24
37
  });
25
- return request;
26
38
  }
27
- async loadGraph(params) {
28
- const request = await this.#client.request('graph/load', params);
29
- request.result.then((res)=>{
39
+ mutateGraph(param, signal) {
40
+ return this.client.request('graph/mutate', {
41
+ param: {
42
+ ...param,
43
+ mutations: {}
44
+ },
45
+ signal
46
+ });
47
+ }
48
+ }
49
+ export class KubunClient extends KubunReadClient {
50
+ #mutationsRunner;
51
+ #signerPromise;
52
+ constructor(params){
53
+ super(params);
54
+ this.#mutationsRunner = new MutationsRunner();
55
+ this.#signerPromise = Promise.resolve(params.signer);
56
+ }
57
+ deployGraph(param, signal) {
58
+ const request = this.client.request('graph/deploy', {
59
+ param,
60
+ signal
61
+ });
62
+ const call = request.then((result)=>{
30
63
  const builder = new ClientSchemaBuilder({
31
- record: res.models
64
+ record: result.models
32
65
  });
33
- this.#mutationsRunner.setSchema(params.id, builder.build());
66
+ this.#mutationsRunner.setSchema(result.id, builder.build());
67
+ return result;
68
+ });
69
+ return Object.assign(call, {
70
+ abort: request.abort,
71
+ signal: request.signal
34
72
  });
35
- return request;
36
73
  }
37
- async queryGraph(params) {
38
- return await this.#client.request('graph/query', params);
74
+ loadGraph(param, signal) {
75
+ const request = super.loadGraph(param, signal);
76
+ const call = request.then((result)=>{
77
+ if (result.models != null) {
78
+ const builder = new ClientSchemaBuilder({
79
+ record: result.models
80
+ });
81
+ this.#mutationsRunner.setSchema(param.id, builder.build());
82
+ }
83
+ return result;
84
+ });
85
+ return Object.assign(call, {
86
+ abort: request.abort,
87
+ signal: request.signal
88
+ });
39
89
  }
40
- async mutateGraph(params) {
41
- const { attachments, id, ...rest } = params;
90
+ async #mutateGraph(param, signal) {
91
+ const { id, ...rest } = param;
42
92
  if (!this.#mutationsRunner.hasSchema(id)) {
43
- const loadGraphRequest = await this.loadGraph({
93
+ await this.loadGraph({
44
94
  id
45
- });
46
- await loadGraphRequest.result;
95
+ }, signal);
47
96
  }
97
+ signal.throwIfAborted();
48
98
  const context = {
99
+ // TODO: local cache for documents state, ideally updated after successful mutations
100
+ loadState: async (docID)=>{
101
+ const res = await this.client.request('document/sync', {
102
+ param: {
103
+ documents: {
104
+ [docID]: null
105
+ }
106
+ }
107
+ });
108
+ const state = res.states[docID];
109
+ return state ? fromB64(state) : null;
110
+ },
49
111
  mutations: {},
50
- signer: this.#signer
112
+ signer: await this.#signerPromise
51
113
  };
52
114
  const { errors } = await this.#mutationsRunner.execute({
53
115
  context,
54
116
  schemaID: id,
55
- source: params.text,
56
- variables: params.variables
117
+ source: param.text,
118
+ variables: param.variables
57
119
  });
58
120
  if (errors != null && errors.length !== 0) {
59
121
  throw new GraphQLExecutionError(errors);
60
122
  }
61
- const attachmentsRecord = {};
62
- if (attachments != null) {
63
- for (const { id, block } of attachments){
64
- attachmentsRecord[id.toString()] = toB64(block.bytes);
65
- }
66
- }
67
- return await this.#client.request('graph/mutate', {
68
- id,
69
- attachments: attachmentsRecord,
70
- mutations: context.mutations,
71
- ...rest
123
+ return await this.client.request('graph/mutate', {
124
+ param: {
125
+ id,
126
+ mutations: context.mutations,
127
+ ...rest
128
+ },
129
+ signal
130
+ });
131
+ }
132
+ mutateGraph(param, signal) {
133
+ const controller = new AbortController();
134
+ const anySignal = signal ? AbortSignal.any([
135
+ controller.signal,
136
+ signal
137
+ ]) : controller.signal;
138
+ const promise = this.#mutateGraph(param, anySignal);
139
+ return Object.assign(promise, {
140
+ abort: ()=>controller.abort(),
141
+ signal: anySignal
72
142
  });
73
143
  }
74
144
  }
package/lib/graphql.d.ts CHANGED
@@ -1,9 +1,11 @@
1
- import { type Signer } from '@enkaku/jwt';
1
+ import { type TokenSigner } from '@enkaku/token';
2
2
  import { type DocumentType, SchemaBuilder, type SharedDefinitions } from '@kubun/graphql';
3
3
  export type Context = {
4
+ loadState: (id: string) => Promise<Uint8Array | null>;
4
5
  mutations: Record<string, string>;
5
- signer: Signer;
6
+ signer: TokenSigner;
6
7
  };
8
+ /** @internal */
7
9
  export declare class ClientSchemaBuilder extends SchemaBuilder<DocumentType, Context> {
8
10
  buildMutations(id: string, definitions: SharedDefinitions<DocumentType, Context>): void;
9
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"graphql.d.ts","sourceRoot":"","sources":["../src/graphql.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,MAAM,EAAkB,MAAM,aAAa,CAAA;AAC3E,OAAO,EAAE,KAAK,YAAY,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAOzF,MAAM,MAAM,OAAO,GAAG;IACpB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEjC,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,qBAAa,mBAAoB,SAAQ,aAAa,CAAC,YAAY,EAAE,OAAO,CAAC;IAC3E,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG,IAAI;CAkGxF"}
1
+ {"version":3,"file":"graphql.d.ts","sourceRoot":"","sources":["../src/graphql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAkB,MAAM,eAAe,CAAA;AAChE,OAAO,EACL,KAAK,YAAY,EAEjB,aAAa,EACb,KAAK,iBAAiB,EAGvB,MAAM,gBAAgB,CAAA;AAWvB,MAAM,MAAM,OAAO,GAAG;IACpB,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;IACrD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,MAAM,EAAE,WAAW,CAAA;CACpB,CAAA;AAED,gBAAgB;AAChB,qBAAa,mBAAoB,SAAQ,aAAa,CAAC,YAAY,EAAE,OAAO,CAAC;IAC3E,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG,IAAI;CA4GxF"}
package/lib/graphql.js CHANGED
@@ -1,10 +1,9 @@
1
- import { fromUTF } from '@enkaku/codec';
2
- import { stringifyToken } from '@enkaku/jwt';
3
- import { SchemaBuilder } from '@kubun/graphql';
1
+ import { stringifyToken } from '@enkaku/token';
2
+ import { PatchOperation, SchemaBuilder, getUniqueDocValue, toList } from '@kubun/graphql';
4
3
  import { GraphQLID, GraphQLNonNull } from 'graphql';
5
4
  import { mutationWithClientMutationId } from 'graphql-relay';
6
5
  import { createChangeMutation, createSetMutation } from './mutations.js';
7
- export class ClientSchemaBuilder extends SchemaBuilder {
6
+ /** @internal */ export class ClientSchemaBuilder extends SchemaBuilder {
8
7
  buildMutations(id, definitions) {
9
8
  const model = this._record[id];
10
9
  if (model == null) {
@@ -15,7 +14,7 @@ export class ClientSchemaBuilder extends SchemaBuilder {
15
14
  case 'interface':
16
15
  // Interfaces don't have mutations
17
16
  return;
18
- case 'list':
17
+ case 'default':
19
18
  {
20
19
  this._mutations[`create${name}`] = mutationWithClientMutationId({
21
20
  name: `Create${name}`,
@@ -50,7 +49,7 @@ export class ClientSchemaBuilder extends SchemaBuilder {
50
49
  });
51
50
  break;
52
51
  }
53
- case 'set':
52
+ case 'unique':
54
53
  {
55
54
  this._mutations[`set${name}`] = mutationWithClientMutationId({
56
55
  name: `Set${name}`,
@@ -67,13 +66,12 @@ export class ClientSchemaBuilder extends SchemaBuilder {
67
66
  }),
68
67
  mutateAndGetPayload: async (input, ctx, info)=>{
69
68
  // Create the mutation token
70
- const unique = model.setFields.map((field)=>String(input.data[field] ?? '')).join('|');
71
69
  const mutation = await createSetMutation({
72
70
  signer: ctx.signer,
73
71
  modelID: id,
74
72
  data: input.data,
75
73
  // owner: ctx.owner,
76
- unique: fromUTF(unique)
74
+ unique: getUniqueDocValue(model.uniqueFields, input.data)
77
75
  });
78
76
  // Add the signed mutation to context so it can be retrieved by the client
79
77
  ctx.mutations[info.path.key] = stringifyToken(mutation);
@@ -92,7 +90,10 @@ export class ClientSchemaBuilder extends SchemaBuilder {
92
90
  id: {
93
91
  type: new GraphQLNonNull(GraphQLID)
94
92
  },
95
- data: {
93
+ patch: {
94
+ type: new GraphQLNonNull(toList(PatchOperation))
95
+ },
96
+ from: {
96
97
  type: this._inputObjects[`${id}-update`]
97
98
  }
98
99
  }),
@@ -103,11 +104,20 @@ export class ClientSchemaBuilder extends SchemaBuilder {
103
104
  }
104
105
  }),
105
106
  mutateAndGetPayload: async (input, ctx, info)=>{
106
- // TODO: add existing doc if available
107
107
  const mutation = await createChangeMutation({
108
+ loadState: ctx.loadState,
108
109
  signer: ctx.signer,
109
110
  docID: input.id,
110
- data: input.data
111
+ patch: input.patch.map((patch)=>{
112
+ // convert GraphQL patch input types to PatchOperationType
113
+ const entries = Object.entries(patch);
114
+ const [op, rest] = entries[0];
115
+ return {
116
+ ...rest,
117
+ op
118
+ };
119
+ }),
120
+ from: input.from
111
121
  });
112
122
  // Add the signed mutation to context so it can be retrieved by the client
113
123
  ctx.mutations[info.path.key] = stringifyToken(mutation);
package/lib/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
- export { createAttachment } from './attachments.js';
2
- export { type ClientParams, KubunClient, type MutateGraphParams, } from './client.js';
1
+ export { type Attachment, createAttachment, toAttachmentsRecord } from './attachments.js';
2
+ export { type ClientParams, KubunClient, type KubunClientType, KubunLightClient, KubunReadClient, type MutateGraphParams, type ReadClientParams, } from './client.js';
3
+ export { ClientSchemaBuilder } from './graphql.js';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EACL,KAAK,YAAY,EACjB,WAAW,EACX,KAAK,iBAAiB,GACvB,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AACzF,OAAO,EACL,KAAK,YAAY,EACjB,WAAW,EACX,KAAK,eAAe,EACpB,gBAAgB,EAChB,eAAe,EACf,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA"}
package/lib/index.js CHANGED
@@ -1,2 +1,3 @@
1
- export { createAttachment } from './attachments.js';
2
- export { KubunClient } from './client.js';
1
+ export { createAttachment, toAttachmentsRecord } from './attachments.js';
2
+ export { KubunClient, KubunLightClient, KubunReadClient } from './client.js';
3
+ export { ClientSchemaBuilder } from './graphql.js';
@@ -1,21 +1,45 @@
1
- import * as A from '@automerge/automerge';
2
- import { type SignedToken, type Signer } from '@enkaku/jwt';
3
- import { DocumentID, type GraphModelID } from '@kubun/id';
1
+ import type { SignedToken, TokenSigner } from '@enkaku/token';
2
+ import { DocumentID, type DocumentModelID } from '@kubun/id';
4
3
  import type { ChangeDocumentMutation, DocumentData, SetDocumentMutation } from '@kubun/protocol';
5
- export declare function getMutationData<Data extends DocumentData = DocumentData>(data: Data | null, doc?: A.Doc<Data>): string | null;
4
+ export type PatchAddOperation = {
5
+ op: 'add';
6
+ path: string;
7
+ value: unknown;
8
+ };
9
+ export type PatchRemoveOperation = {
10
+ op: 'remove';
11
+ path: string;
12
+ };
13
+ export type PatchReplaceOperation = {
14
+ op: 'replace';
15
+ path: string;
16
+ value: unknown;
17
+ };
18
+ export type PatchMoveOperation = {
19
+ op: 'move';
20
+ from: string;
21
+ path: string;
22
+ };
23
+ export type PatchCopyOperation = {
24
+ op: 'copy';
25
+ from: string;
26
+ path: string;
27
+ };
28
+ export type PatchOperation = PatchAddOperation | PatchCopyOperation | PatchMoveOperation | PatchRemoveOperation | PatchReplaceOperation;
6
29
  export type SetMutationParams<Data extends DocumentData = DocumentData> = {
7
- signer: Signer;
8
- owner?: string;
9
- modelID: GraphModelID | string;
10
30
  data: Data | null;
31
+ modelID: DocumentModelID | string;
32
+ owner?: string;
33
+ signer: TokenSigner;
11
34
  unique: Uint8Array;
12
35
  };
13
36
  export declare function createSetMutation<Data extends DocumentData = DocumentData>(params: SetMutationParams<Data>): Promise<SignedToken<SetDocumentMutation>>;
14
37
  export type CreateChangeMutationParams<Data extends DocumentData = DocumentData> = {
15
- signer: Signer;
16
38
  docID: DocumentID | string;
17
- data: Data | null;
18
- doc?: A.Doc<Data>;
39
+ from?: Partial<Data>;
40
+ loadState: (id: string) => Promise<Uint8Array | null>;
41
+ patch: Array<PatchOperation>;
42
+ signer: TokenSigner;
19
43
  };
20
44
  export declare function createChangeMutation<Data extends DocumentData = DocumentData>(params: CreateChangeMutationParams<Data>): Promise<SignedToken<ChangeDocumentMutation>>;
21
45
  //# sourceMappingURL=mutations.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mutations.d.ts","sourceRoot":"","sources":["../src/mutations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,sBAAsB,CAAA;AAEzC,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,MAAM,EAAqB,MAAM,aAAa,CAAA;AAC9E,OAAO,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAA;AACzD,OAAO,KAAK,EAAE,sBAAsB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAEhG,wBAAgB,eAAe,CAAC,IAAI,SAAS,YAAY,GAAG,YAAY,EACtE,IAAI,EAAE,IAAI,GAAG,IAAI,EACjB,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAChB,MAAM,GAAG,IAAI,CAWf;AAED,MAAM,MAAM,iBAAiB,CAAC,IAAI,SAAS,YAAY,GAAG,YAAY,IAAI;IACxE,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,YAAY,GAAG,MAAM,CAAA;IAC9B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;IACjB,MAAM,EAAE,UAAU,CAAA;CACnB,CAAA;AAED,wBAAsB,iBAAiB,CAAC,IAAI,SAAS,YAAY,GAAG,YAAY,EAC9E,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,GAC9B,OAAO,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC,CAU3C;AAED,MAAM,MAAM,0BAA0B,CAAC,IAAI,SAAS,YAAY,GAAG,YAAY,IAAI;IACjF,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,UAAU,GAAG,MAAM,CAAA;IAC1B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;IACjB,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;CAClB,CAAA;AAED,wBAAsB,oBAAoB,CAAC,IAAI,SAAS,YAAY,GAAG,YAAY,EACjF,MAAM,EAAE,0BAA0B,CAAC,IAAI,CAAC,GACvC,OAAO,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC,CAQ9C"}
1
+ {"version":3,"file":"mutations.d.ts","sourceRoot":"","sources":["../src/mutations.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC7D,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAA;AAC5D,OAAO,KAAK,EAAE,sBAAsB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAIhG,MAAM,MAAM,iBAAiB,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAC3E,MAAM,MAAM,oBAAoB,GAAG;IAAE,EAAE,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AACjE,MAAM,MAAM,qBAAqB,GAAG;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AACnF,MAAM,MAAM,kBAAkB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAC3E,MAAM,MAAM,kBAAkB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAC3E,MAAM,MAAM,cAAc,GACtB,iBAAiB,GACjB,kBAAkB,GAClB,kBAAkB,GAClB,oBAAoB,GACpB,qBAAqB,CAAA;AA+EzB,MAAM,MAAM,iBAAiB,CAAC,IAAI,SAAS,YAAY,GAAG,YAAY,IAAI;IACxE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;IACjB,OAAO,EAAE,eAAe,GAAG,MAAM,CAAA;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,WAAW,CAAA;IACnB,MAAM,EAAE,UAAU,CAAA;CACnB,CAAA;AAED,wBAAsB,iBAAiB,CAAC,IAAI,SAAS,YAAY,GAAG,YAAY,EAC9E,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,GAC9B,OAAO,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC,CAa3C;AAED,MAAM,MAAM,0BAA0B,CAAC,IAAI,SAAS,YAAY,GAAG,YAAY,IAAI;IACjF,KAAK,EAAE,UAAU,GAAG,MAAM,CAAA;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;IACpB,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;IACrD,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,CAAA;IAC5B,MAAM,EAAE,WAAW,CAAA;CACpB,CAAA;AAED,wBAAsB,oBAAoB,CAAC,IAAI,SAAS,YAAY,GAAG,YAAY,EACjF,MAAM,EAAE,0BAA0B,CAAC,IAAI,CAAC,GACvC,OAAO,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC,CAkB9C"}
package/lib/mutations.js CHANGED
@@ -1,36 +1,113 @@
1
- import * as A from '@automerge/automerge';
1
+ // @ts-ignore missing type definition
2
+ import { automergeWasmBase64 } from '@automerge/automerge/automerge.wasm.base64.js';
3
+ import * as A from '@automerge/automerge/slim';
4
+ import { lazy } from '@enkaku/async';
2
5
  import { toB64 } from '@enkaku/codec';
3
- import { createSignedToken } from '@enkaku/jwt';
4
6
  import { DocumentID } from '@kubun/id';
5
- export function getMutationData(data, doc) {
6
- if (data == null) {
7
- return null;
7
+ const automergeReady = lazy(()=>A.initializeBase64Wasm(automergeWasmBase64));
8
+ function parsePath(path) {
9
+ return path.slice(1).split('/').map((key)=>{
10
+ // Convert array indices to numbers
11
+ const index = Number(key);
12
+ return Number.isNaN(index) ? key : index;
13
+ });
14
+ }
15
+ function getPath(obj, path) {
16
+ const keys = parsePath(path);
17
+ // @ts-ignore index signature
18
+ return keys.reduce((acc, key)=>acc?.[key], obj);
19
+ }
20
+ function setPath(obj, path, value) {
21
+ const keys = parsePath(path);
22
+ const lastKey = keys.pop();
23
+ if (lastKey !== undefined) {
24
+ // @ts-ignore unknown object
25
+ const target = keys.reduce((acc, key)=>acc[key], obj);
26
+ if (Array.isArray(target) && typeof lastKey === 'number' && lastKey === target.length) {
27
+ target.push(value) // Append to array if index is equal to array length
28
+ ;
29
+ } else {
30
+ ;
31
+ target[lastKey] = value;
32
+ }
33
+ }
34
+ }
35
+ function deletePath(obj, path) {
36
+ const keys = parsePath(path);
37
+ const lastKey = keys.pop();
38
+ if (lastKey !== undefined) {
39
+ // @ts-ignore unknown object
40
+ const target = keys.reduce((acc, key)=>acc[key], obj);
41
+ if (Array.isArray(target) && typeof lastKey === 'number') {
42
+ target.splice(lastKey, 1) // Remove from array if lastKey is an index
43
+ ;
44
+ } else {
45
+ delete target[lastKey];
46
+ }
8
47
  }
9
- if (doc == null) {
10
- return toB64(A.save(A.from(data)));
48
+ }
49
+ function applyPatches(data, patches) {
50
+ for (const patch of patches){
51
+ switch(patch.op){
52
+ case 'add':
53
+ case 'replace':
54
+ setPath(data, patch.path, patch.value);
55
+ break;
56
+ case 'remove':
57
+ deletePath(data, patch.path);
58
+ break;
59
+ case 'copy':
60
+ {
61
+ const value = getPath(data, patch.from);
62
+ setPath(data, patch.path, value);
63
+ break;
64
+ }
65
+ case 'move':
66
+ {
67
+ const value = getPath(data, patch.from);
68
+ deletePath(data, patch.from);
69
+ setPath(data, patch.path, value);
70
+ break;
71
+ }
72
+ default:
73
+ // @ts-ignore never type
74
+ throw new Error(`Unknown operation: ${patch.op}`);
75
+ }
11
76
  }
12
- const changedDoc = A.change(doc, (proxy)=>{
13
- Object.assign(proxy, data);
14
- });
15
- return toB64(A.saveSince(changedDoc, A.getHeads(doc)));
16
77
  }
17
78
  export async function createSetMutation(params) {
18
- const owner = params.owner ?? params.signer.did;
19
- return await createSignedToken(params.signer, {
79
+ const issuer = params.signer.id;
80
+ const owner = params.owner ?? issuer;
81
+ await automergeReady;
82
+ const docID = await DocumentID.create(params.modelID, owner, params.unique);
83
+ return await params.signer.createToken({
20
84
  typ: 'set',
21
- iss: params.signer.did,
85
+ iss: issuer,
22
86
  aud: owner,
23
- sub: DocumentID.create(params.modelID, owner, params.unique).toString(),
24
- data: getMutationData(params.data),
87
+ sub: docID.toString(),
88
+ data: params.data == null ? null : toB64(A.save(A.from(params.data))),
25
89
  unq: toB64(params.unique)
26
90
  });
27
91
  }
28
92
  export async function createChangeMutation(params) {
29
- return await createSignedToken(params.signer, {
93
+ const docID = DocumentID.from(params.docID).toString();
94
+ // Load current state of document from DB
95
+ const [state] = await Promise.all([
96
+ params.loadState(docID),
97
+ automergeReady
98
+ ]);
99
+ const loadedDoc = state ? A.load(state) : null;
100
+ // Apply patches to loaded doc or locally created one
101
+ const newDoc = A.change(loadedDoc ?? A.from(params.from ?? {}), (proxy)=>{
102
+ applyPatches(proxy, params.patch);
103
+ });
104
+ // Save incremental or full data state
105
+ const data = loadedDoc ? A.saveSince(newDoc, A.getHeads(loadedDoc)) : A.save(newDoc);
106
+ return await params.signer.createToken({
30
107
  typ: 'change',
31
- iss: params.signer.did,
32
- sub: DocumentID.from(params.docID).toString(),
33
- data: getMutationData(params.data, params.doc),
34
- inc: params.doc != null
108
+ iss: params.signer.id,
109
+ sub: docID,
110
+ data: toB64(data),
111
+ inc: loadedDoc != null
35
112
  });
36
113
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubun/client",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "license": "see LICENSE.md",
5
5
  "keywords": [],
6
6
  "type": "module",
@@ -16,17 +16,18 @@
16
16
  "sideEffects": false,
17
17
  "dependencies": {
18
18
  "@automerge/automerge": "^2.2.8",
19
- "@enkaku/client": "^0.2.2",
20
- "@enkaku/codec": "^0.2.0",
21
- "@enkaku/jwt": "^0.2.3",
19
+ "@enkaku/async": "^0.11.0",
20
+ "@enkaku/client": "^0.11.0",
21
+ "@enkaku/codec": "^0.11.0",
22
+ "@enkaku/token": "^0.11.0",
22
23
  "graphql": "^16.9.0",
23
24
  "graphql-relay": "^0.10.2",
24
- "multiformats": "^13.3.0",
25
- "@kubun/graphql": "^0.1.0",
26
- "@kubun/id": "^0.1.0"
25
+ "multiformats": "^13.3.2",
26
+ "@kubun/graphql": "^0.2.1",
27
+ "@kubun/id": "^0.2.0"
27
28
  },
28
29
  "devDependencies": {
29
- "@kubun/protocol": "^0.1.0"
30
+ "@kubun/protocol": "^0.2.2"
30
31
  },
31
32
  "scripts": {
32
33
  "build:clean": "del lib",