@timeax/digital-service-engine 0.2.9 → 0.3.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.
@@ -1497,7 +1497,7 @@ interface WorkspaceAPI {
1497
1497
  strict?: boolean;
1498
1498
  includeWorkspaceData?: boolean;
1499
1499
  }>): Promise<void>;
1500
- templates(params?: Partial<Pick<TemplatesListParams, "branchId" | "since">>): Promise<void>;
1500
+ templates(params?: Partial<Pick<TemplatesListParams, "branchId" | "since">>): Promise<BackendResult<readonly FieldTemplate[]>>;
1501
1501
  participants(params?: Partial<{
1502
1502
  branchId: string;
1503
1503
  since?: number | string;
@@ -1497,7 +1497,7 @@ interface WorkspaceAPI {
1497
1497
  strict?: boolean;
1498
1498
  includeWorkspaceData?: boolean;
1499
1499
  }>): Promise<void>;
1500
- templates(params?: Partial<Pick<TemplatesListParams, "branchId" | "since">>): Promise<void>;
1500
+ templates(params?: Partial<Pick<TemplatesListParams, "branchId" | "since">>): Promise<BackendResult<readonly FieldTemplate[]>>;
1501
1501
  participants(params?: Partial<{
1502
1502
  branchId: string;
1503
1503
  since?: number | string;
@@ -311,6 +311,70 @@ import * as React6 from "react";
311
311
  function setLoadableError4(updater, error) {
312
312
  updater((s) => ({ ...s, loading: false, error }));
313
313
  }
314
+ function parseTimestamp(value) {
315
+ if (value === void 0 || value === null) return void 0;
316
+ if (typeof value === "number") {
317
+ return Number.isFinite(value) ? value : void 0;
318
+ }
319
+ const parsed = Date.parse(value);
320
+ return Number.isFinite(parsed) ? parsed : void 0;
321
+ }
322
+ function templateTime(template) {
323
+ var _a;
324
+ return (_a = parseTimestamp(template.updatedAt)) != null ? _a : parseTimestamp(template.createdAt);
325
+ }
326
+ function shouldReplaceTemplates(params) {
327
+ if (!params.requestedSince) return true;
328
+ if (!params.lastUpdatedAt) return false;
329
+ const requested = parseTimestamp(params.requestedSince);
330
+ const last = parseTimestamp(params.lastUpdatedAt);
331
+ if (requested === void 0 || last === void 0) {
332
+ return false;
333
+ }
334
+ return requested < last;
335
+ }
336
+ function pickNewestTemplate(current, incoming) {
337
+ const currentTime = templateTime(current);
338
+ const incomingTime = templateTime(incoming);
339
+ if (currentTime !== void 0 && incomingTime !== void 0) {
340
+ return incomingTime >= currentTime ? incoming : current;
341
+ }
342
+ if (currentTime === void 0 && incomingTime !== void 0) return incoming;
343
+ if (currentTime !== void 0 && incomingTime === void 0) return current;
344
+ return incoming;
345
+ }
346
+ function mergeTemplates(current, incoming, opts) {
347
+ var _a;
348
+ const sinceTime = parseTimestamp(opts == null ? void 0 : opts.since);
349
+ const incomingIds = new Set(incoming.map((template) => template.id));
350
+ const deletedIds = new Set((_a = opts == null ? void 0 : opts.deletedIds) != null ? _a : []);
351
+ const byId = /* @__PURE__ */ new Map();
352
+ for (const template of current != null ? current : []) {
353
+ if (deletedIds.has(template.id)) continue;
354
+ const updatedTime = templateTime(template);
355
+ const shouldHaveAppearedInDelta = (opts == null ? void 0 : opts.reconcileMissingSince) === true && sinceTime !== void 0 && updatedTime !== void 0 && updatedTime > sinceTime;
356
+ const missingFromDelta = shouldHaveAppearedInDelta && !incomingIds.has(template.id);
357
+ if (!missingFromDelta) {
358
+ byId.set(template.id, template);
359
+ }
360
+ }
361
+ for (const template of incoming) {
362
+ if (deletedIds.has(template.id)) continue;
363
+ const existing = byId.get(template.id);
364
+ byId.set(
365
+ template.id,
366
+ existing ? pickNewestTemplate(existing, template) : template
367
+ );
368
+ }
369
+ return Array.from(byId.values()).sort((a, b) => {
370
+ const aTime = templateTime(a);
371
+ const bTime = templateTime(b);
372
+ if (aTime !== void 0 && bTime !== void 0 && aTime !== bTime) {
373
+ return bTime - aTime;
374
+ }
375
+ return a.name.localeCompare(b.name);
376
+ });
377
+ }
314
378
  function useTemplatesSlice(params) {
315
379
  const {
316
380
  backend,
@@ -338,16 +402,26 @@ function useTemplatesSlice(params) {
338
402
  };
339
403
  }
340
404
  setTemplates((s) => ({ ...s, loading: true }));
405
+ const requestedSince = (_b = params2 == null ? void 0 : params2.since) != null ? _b : templates.updatedAt;
341
406
  const res = await backend.templates.refresh({
342
407
  workspaceId,
343
408
  branchId,
344
- since: (_b = params2 == null ? void 0 : params2.since) != null ? _b : templates.updatedAt
409
+ since: requestedSince
345
410
  });
346
411
  if (res.ok) {
347
- setTemplates({
348
- data: res.value,
349
- loading: false,
350
- updatedAt: runtime.now()
412
+ setTemplates((current) => {
413
+ const replace = shouldReplaceTemplates({
414
+ requestedSince,
415
+ lastUpdatedAt: current.updatedAt
416
+ });
417
+ return {
418
+ data: replace ? res.value : mergeTemplates(current.data, res.value, {
419
+ since: requestedSince,
420
+ reconcileMissingSince: false
421
+ }),
422
+ loading: false,
423
+ updatedAt: runtime.now()
424
+ };
351
425
  });
352
426
  return res;
353
427
  } else {
@@ -365,14 +439,14 @@ function useTemplatesSlice(params) {
365
439
  );
366
440
  const createTemplate = React6.useCallback(
367
441
  async (input) => {
368
- var _a, _b;
442
+ var _a;
369
443
  const res = await backend.templates.create(workspaceId, {
370
444
  ...input,
371
- branchId: (_a = input.branchId) != null ? _a : getCurrentBranchId()
445
+ branchId: input.branchId !== null ? input.branchId : getCurrentBranchId()
372
446
  });
373
447
  if (res.ok) {
374
448
  await refreshTemplates({
375
- branchId: (_b = res.value.branchId) != null ? _b : getCurrentBranchId()
449
+ branchId: (_a = res.value.branchId) != null ? _a : getCurrentBranchId()
376
450
  });
377
451
  }
378
452
  return res;
@@ -432,11 +506,23 @@ function useTemplatesSlice(params) {
432
506
  async (id) => {
433
507
  const res = await backend.templates.delete(id);
434
508
  if (res.ok) {
435
- await refreshTemplates({ branchId: getCurrentBranchId() });
509
+ const deleteRefreshSince = runtime.now();
510
+ setTemplates((current) => {
511
+ var _a, _b;
512
+ return {
513
+ ...current,
514
+ data: (_b = (_a = current.data) == null ? void 0 : _a.filter((template) => template.id !== id)) != null ? _b : current.data,
515
+ updatedAt: deleteRefreshSince
516
+ };
517
+ });
518
+ await refreshTemplates({
519
+ branchId: getCurrentBranchId(),
520
+ since: deleteRefreshSince
521
+ });
436
522
  }
437
523
  return res;
438
524
  },
439
- [backend.templates, getCurrentBranchId, refreshTemplates]
525
+ [backend.templates, getCurrentBranchId, refreshTemplates, runtime]
440
526
  );
441
527
  const invalidateTemplates = React6.useCallback(() => {
442
528
  setTemplates((s) => ({ ...s, updatedAt: void 0 }));
@@ -2699,7 +2785,7 @@ function WorkspaceProvider(props) {
2699
2785
  },
2700
2786
  branchContext: bootCtl.refreshBranchContext,
2701
2787
  templates: async (params) => {
2702
- await templatesSlice.refreshTemplates(params);
2788
+ return await templatesSlice.refreshTemplates(params);
2703
2789
  },
2704
2790
  participants: async (params) => {
2705
2791
  await branchesSlice.refreshParticipants(params);