@amalgm/live 0.2.26 → 0.2.28

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.
Files changed (197) hide show
  1. package/PURPOSE.md +52 -29
  2. package/README.md +1 -2
  3. package/dist/contracts/index.d.ts +0 -1
  4. package/dist/contracts/index.d.ts.map +1 -1
  5. package/dist/contracts/index.js +0 -1
  6. package/dist/contracts/index.js.map +1 -1
  7. package/dist/detection/record-proposal.d.ts +3 -2
  8. package/dist/detection/record-proposal.d.ts.map +1 -1
  9. package/dist/detection/record-proposal.js +9 -7
  10. package/dist/detection/record-proposal.js.map +1 -1
  11. package/dist/index.d.ts +3 -2
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +3 -2
  14. package/dist/index.js.map +1 -1
  15. package/dist/machines/index.d.ts +0 -2
  16. package/dist/machines/index.d.ts.map +1 -1
  17. package/dist/machines/index.js +0 -2
  18. package/dist/machines/index.js.map +1 -1
  19. package/dist/records/authority.d.ts +23 -0
  20. package/dist/records/authority.d.ts.map +1 -0
  21. package/dist/records/authority.js +28 -0
  22. package/dist/records/authority.js.map +1 -0
  23. package/dist/records/codec.d.ts +6 -0
  24. package/dist/records/codec.d.ts.map +1 -0
  25. package/dist/records/codec.js +42 -0
  26. package/dist/records/codec.js.map +1 -0
  27. package/dist/records/contracts.d.ts +46 -0
  28. package/dist/records/contracts.d.ts.map +1 -0
  29. package/dist/records/contracts.js +114 -0
  30. package/dist/records/contracts.js.map +1 -0
  31. package/dist/records/inbox.d.ts +18 -0
  32. package/dist/records/inbox.d.ts.map +1 -0
  33. package/dist/records/inbox.js +34 -0
  34. package/dist/records/inbox.js.map +1 -0
  35. package/dist/records/index.d.ts +7 -0
  36. package/dist/records/index.d.ts.map +1 -0
  37. package/dist/records/index.js +7 -0
  38. package/dist/records/index.js.map +1 -0
  39. package/dist/records/outbox.d.ts +20 -0
  40. package/dist/records/outbox.d.ts.map +1 -0
  41. package/dist/records/outbox.js +44 -0
  42. package/dist/records/outbox.js.map +1 -0
  43. package/dist/registration/user-ground.d.ts +5 -2
  44. package/dist/registration/user-ground.d.ts.map +1 -1
  45. package/dist/registration/user-ground.js +14 -3
  46. package/dist/registration/user-ground.js.map +1 -1
  47. package/dist/watching/suspicion.d.ts.map +1 -1
  48. package/dist/watching/suspicion.js +29 -1
  49. package/dist/watching/suspicion.js.map +1 -1
  50. package/dist-cjs/contracts/binding.js +26 -0
  51. package/dist-cjs/contracts/binding.js.map +1 -0
  52. package/dist-cjs/contracts/content.js +99 -0
  53. package/dist-cjs/contracts/content.js.map +1 -0
  54. package/dist-cjs/contracts/docs.js +56 -0
  55. package/dist-cjs/contracts/docs.js.map +1 -0
  56. package/dist-cjs/contracts/events.js +44 -0
  57. package/dist-cjs/contracts/events.js.map +1 -0
  58. package/dist-cjs/contracts/frames/gateway.js +39 -0
  59. package/dist-cjs/contracts/frames/gateway.js.map +1 -0
  60. package/dist-cjs/contracts/frames/stream.js +20 -0
  61. package/dist-cjs/contracts/frames/stream.js.map +1 -0
  62. package/dist-cjs/contracts/frames/tunnel.js +60 -0
  63. package/dist-cjs/contracts/frames/tunnel.js.map +1 -0
  64. package/dist-cjs/contracts/index.js +34 -0
  65. package/dist-cjs/contracts/index.js.map +1 -0
  66. package/dist-cjs/contracts/presence.js +38 -0
  67. package/dist-cjs/contracts/presence.js.map +1 -0
  68. package/dist-cjs/contracts/resources.js +114 -0
  69. package/dist-cjs/contracts/resources.js.map +1 -0
  70. package/dist-cjs/contracts/snapshot.js +31 -0
  71. package/dist-cjs/contracts/snapshot.js.map +1 -0
  72. package/dist-cjs/contracts/validate.js +34 -0
  73. package/dist-cjs/contracts/validate.js.map +1 -0
  74. package/dist-cjs/detection/adapter-contract.js +168 -0
  75. package/dist-cjs/detection/adapter-contract.js.map +1 -0
  76. package/dist-cjs/detection/batch.js +71 -0
  77. package/dist-cjs/detection/batch.js.map +1 -0
  78. package/dist-cjs/detection/classify.js +48 -0
  79. package/dist-cjs/detection/classify.js.map +1 -0
  80. package/dist-cjs/detection/content.js +122 -0
  81. package/dist-cjs/detection/content.js.map +1 -0
  82. package/dist-cjs/detection/continuity.js +88 -0
  83. package/dist-cjs/detection/continuity.js.map +1 -0
  84. package/dist-cjs/detection/diff.js +193 -0
  85. package/dist-cjs/detection/diff.js.map +1 -0
  86. package/dist-cjs/detection/echo.js +25 -0
  87. package/dist-cjs/detection/echo.js.map +1 -0
  88. package/dist-cjs/detection/enrollment.js +189 -0
  89. package/dist-cjs/detection/enrollment.js.map +1 -0
  90. package/dist-cjs/detection/index.js +57 -0
  91. package/dist-cjs/detection/index.js.map +1 -0
  92. package/dist-cjs/detection/record-proposal.js +170 -0
  93. package/dist-cjs/detection/record-proposal.js.map +1 -0
  94. package/dist-cjs/detection/refusal.js +44 -0
  95. package/dist-cjs/detection/refusal.js.map +1 -0
  96. package/dist-cjs/detection/repository.js +67 -0
  97. package/dist-cjs/detection/repository.js.map +1 -0
  98. package/dist-cjs/detection/territory.js +82 -0
  99. package/dist-cjs/detection/territory.js.map +1 -0
  100. package/dist-cjs/detection/watch-boundary.js +51 -0
  101. package/dist-cjs/detection/watch-boundary.js.map +1 -0
  102. package/dist-cjs/entities/bytes.js +92 -0
  103. package/dist-cjs/entities/bytes.js.map +1 -0
  104. package/dist-cjs/entities/cloud.js +171 -0
  105. package/dist-cjs/entities/cloud.js.map +1 -0
  106. package/dist-cjs/entities/index.js +39 -0
  107. package/dist-cjs/entities/index.js.map +1 -0
  108. package/dist-cjs/entities/moves.js +85 -0
  109. package/dist-cjs/entities/moves.js.map +1 -0
  110. package/dist-cjs/entities/repo-states.js +256 -0
  111. package/dist-cjs/entities/repo-states.js.map +1 -0
  112. package/dist-cjs/entities/rules.js +216 -0
  113. package/dist-cjs/entities/rules.js.map +1 -0
  114. package/dist-cjs/entities/types.js +44 -0
  115. package/dist-cjs/entities/types.js.map +1 -0
  116. package/dist-cjs/files/commands.js +120 -0
  117. package/dist-cjs/files/commands.js.map +1 -0
  118. package/dist-cjs/files/index.js +19 -0
  119. package/dist-cjs/files/index.js.map +1 -0
  120. package/dist-cjs/index.js +39 -0
  121. package/dist-cjs/index.js.map +1 -0
  122. package/dist-cjs/machines/arbitration.js +41 -0
  123. package/dist-cjs/machines/arbitration.js.map +1 -0
  124. package/dist-cjs/machines/backoff.js +38 -0
  125. package/dist-cjs/machines/backoff.js.map +1 -0
  126. package/dist-cjs/machines/bootstrap.js +110 -0
  127. package/dist-cjs/machines/bootstrap.js.map +1 -0
  128. package/dist-cjs/machines/chunks.js +72 -0
  129. package/dist-cjs/machines/chunks.js.map +1 -0
  130. package/dist-cjs/machines/index.js +28 -0
  131. package/dist-cjs/machines/index.js.map +1 -0
  132. package/dist-cjs/machines/presence.js +53 -0
  133. package/dist-cjs/machines/presence.js.map +1 -0
  134. package/dist-cjs/merge/index.js +25 -0
  135. package/dist-cjs/merge/index.js.map +1 -0
  136. package/dist-cjs/merge/merge3.js +191 -0
  137. package/dist-cjs/merge/merge3.js.map +1 -0
  138. package/dist-cjs/package.json +1 -0
  139. package/dist-cjs/records/authority.js +31 -0
  140. package/dist-cjs/records/authority.js.map +1 -0
  141. package/dist-cjs/records/codec.js +48 -0
  142. package/dist-cjs/records/codec.js.map +1 -0
  143. package/dist-cjs/records/contracts.js +121 -0
  144. package/dist-cjs/records/contracts.js.map +1 -0
  145. package/dist-cjs/records/inbox.js +37 -0
  146. package/dist-cjs/records/inbox.js.map +1 -0
  147. package/dist-cjs/records/index.js +23 -0
  148. package/dist-cjs/records/index.js.map +1 -0
  149. package/dist-cjs/records/outbox.js +48 -0
  150. package/dist-cjs/records/outbox.js.map +1 -0
  151. package/dist-cjs/registration/index.js +19 -0
  152. package/dist-cjs/registration/index.js.map +1 -0
  153. package/dist-cjs/registration/user-ground.js +183 -0
  154. package/dist-cjs/registration/user-ground.js.map +1 -0
  155. package/dist-cjs/transfer/artifacts.js +75 -0
  156. package/dist-cjs/transfer/artifacts.js.map +1 -0
  157. package/dist-cjs/transfer/batches.js +44 -0
  158. package/dist-cjs/transfer/batches.js.map +1 -0
  159. package/dist-cjs/transfer/download.js +88 -0
  160. package/dist-cjs/transfer/download.js.map +1 -0
  161. package/dist-cjs/transfer/index.js +21 -0
  162. package/dist-cjs/transfer/index.js.map +1 -0
  163. package/dist-cjs/transfer/parallel.js +35 -0
  164. package/dist-cjs/transfer/parallel.js.map +1 -0
  165. package/dist-cjs/transfer/upload.js +161 -0
  166. package/dist-cjs/transfer/upload.js.map +1 -0
  167. package/dist-cjs/watching/coverage.js +54 -0
  168. package/dist-cjs/watching/coverage.js.map +1 -0
  169. package/dist-cjs/watching/index.js +24 -0
  170. package/dist-cjs/watching/index.js.map +1 -0
  171. package/dist-cjs/watching/suspicion.js +105 -0
  172. package/dist-cjs/watching/suspicion.js.map +1 -0
  173. package/dist-cjs/workspace/api.js +66 -0
  174. package/dist-cjs/workspace/api.js.map +1 -0
  175. package/dist-cjs/workspace/identity.js +32 -0
  176. package/dist-cjs/workspace/identity.js.map +1 -0
  177. package/dist-cjs/workspace/index.js +14 -0
  178. package/dist-cjs/workspace/index.js.map +1 -0
  179. package/dist-cjs/workspace/memory-store.js +21 -0
  180. package/dist-cjs/workspace/memory-store.js.map +1 -0
  181. package/dist-cjs/workspace/registry.js +98 -0
  182. package/dist-cjs/workspace/registry.js.map +1 -0
  183. package/dist-cjs/workspace/types.js +3 -0
  184. package/dist-cjs/workspace/types.js.map +1 -0
  185. package/package.json +30 -8
  186. package/dist/contracts/mutation.d.ts +0 -51
  187. package/dist/contracts/mutation.d.ts.map +0 -1
  188. package/dist/contracts/mutation.js +0 -55
  189. package/dist/contracts/mutation.js.map +0 -1
  190. package/dist/machines/journal.d.ts +0 -63
  191. package/dist/machines/journal.d.ts.map +0 -1
  192. package/dist/machines/journal.js +0 -71
  193. package/dist/machines/journal.js.map +0 -1
  194. package/dist/machines/ordering.d.ts +0 -53
  195. package/dist/machines/ordering.d.ts.map +0 -1
  196. package/dist/machines/ordering.js +0 -87
  197. package/dist/machines/ordering.js.map +0 -1
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerFilesWorkspace = registerFilesWorkspace;
4
+ exports.workspaceGraph = workspaceGraph;
5
+ exports.addFilesWorkspace = addFilesWorkspace;
6
+ const index_js_1 = require("../entities/index.js");
7
+ function uuid(value, label) {
8
+ const normalized = typeof value === 'string' ? value.trim().toLowerCase() : '';
9
+ if (!index_js_1.UUID_PATTERN.test(normalized))
10
+ throw new Error(`${label} must be a UUID`);
11
+ return normalized;
12
+ }
13
+ function required(value, label) {
14
+ const normalized = typeof value === 'string' ? value.trim() : '';
15
+ if (!normalized)
16
+ throw new Error(`${label} is required`);
17
+ return normalized;
18
+ }
19
+ /**
20
+ * Declare one external workspace. Deliberately no scan, SQLite, content, or
21
+ * cloud port exists here: Watch observing the rendered reference owns all
22
+ * enrollment and publication.
23
+ */
24
+ async function registerFilesWorkspace(path, ports) {
25
+ const requestedPath = required(path, 'workspace path');
26
+ const inspected = await ports.inspectExternalWorkspace(requestedPath);
27
+ const absolutePath = required(inspected.absolutePath, 'external workspace path');
28
+ const workspaceName = required(inspected.name, 'workspace name');
29
+ const workspaceId = inspected.workspaceId === null
30
+ ? uuid(ports.randomUuid(), 'generated workspace id')
31
+ : uuid(inspected.workspaceId, 'existing workspace id');
32
+ const declared = await ports.declareWorkspaceReference({
33
+ workspaceId,
34
+ workspaceName,
35
+ absolutePath,
36
+ });
37
+ return {
38
+ workspaceId,
39
+ workspaceName,
40
+ externalPath: absolutePath,
41
+ referenceName: required(declared.referenceName, 'reference name'),
42
+ referencePath: required(declared.referencePath, 'reference path'),
43
+ declared: true,
44
+ created: declared.created === true,
45
+ };
46
+ }
47
+ /** Select exactly one referenced materialization boundary. Its portable parent
48
+ * may live outside the selection; UUID, not parentlessness, is the boundary. */
49
+ function workspaceGraph(records, workspaceId) {
50
+ const normalizedId = uuid(workspaceId, 'workspace id');
51
+ const snapshot = (0, index_js_1.snapshotFromRecords)(records);
52
+ const workspace = snapshot.records.find((record) => record.uuid === normalizedId);
53
+ if (!workspace || workspace.status !== 'active') {
54
+ throw new Error(`workspace ${normalizedId} does not exist in this user's cloud registry`);
55
+ }
56
+ if (!['workspace', 'folder', 'repo.git'].includes(workspace.type)) {
57
+ throw new Error(`entity ${normalizedId} is not a registered workspace boundary`);
58
+ }
59
+ const references = snapshot.records.filter((record) => record.status === 'active'
60
+ && record.type === 'reference' && record.payloadVersion === normalizedId);
61
+ if (references.length !== 1) {
62
+ throw new Error(`workspace ${normalizedId} must have exactly one durable reference`);
63
+ }
64
+ const included = new Set([normalizedId]);
65
+ let changed = true;
66
+ while (changed) {
67
+ changed = false;
68
+ for (const record of snapshot.records) {
69
+ if (record.parentUUID !== null && included.has(record.parentUUID) && !included.has(record.uuid)) {
70
+ included.add(record.uuid);
71
+ changed = true;
72
+ }
73
+ }
74
+ }
75
+ return {
76
+ workspace,
77
+ reference: references[0],
78
+ records: snapshot.records.filter((record) => included.has(record.uuid)),
79
+ };
80
+ }
81
+ /** Materialize one owned workspace root and establish Watch coverage for it. */
82
+ async function addFilesWorkspace(workspaceId, destinationParent, ports) {
83
+ const normalizedId = uuid(workspaceId, 'workspace id');
84
+ const destination = required(destinationParent, 'destination directory');
85
+ const cloud = await ports.lookupRegistry();
86
+ const selected = workspaceGraph(cloud.snapshot.records, normalizedId);
87
+ const references = cloud.snapshot.records.filter((record) => record.status === 'active' && record.type === 'reference');
88
+ const installed = await ports.materializeWorkspace({
89
+ ...selected,
90
+ references,
91
+ destinationParent: destination,
92
+ cloudHead: required(cloud.checksum, 'cloud head'),
93
+ });
94
+ const installedRecords = (0, index_js_1.snapshotFromRecords)(installed.records || []).records;
95
+ if (!Number.isSafeInteger(installed.rows)
96
+ || installed.rows !== installedRecords.length
97
+ || !(0, index_js_1.sameRecords)((0, index_js_1.travelingRecords)(installedRecords), selected.records)
98
+ || !(0, index_js_1.sameRecords)([installed.reference], [selected.reference])
99
+ || !(0, index_js_1.sameRecords)(installed.references, references)) {
100
+ throw new Error('workspace materialization did not persist exactly the selected graph');
101
+ }
102
+ const coverage = await ports.coverWorkspace({
103
+ workspaceId: normalizedId,
104
+ baseline: installed.alreadyMaterialized === true ? 'existing' : 'authoritative-install',
105
+ });
106
+ if (coverage.active !== true || !Number.isSafeInteger(coverage.roots) || coverage.roots < 1) {
107
+ throw new Error('workspace watcher coverage is not active');
108
+ }
109
+ return {
110
+ workspaceId: normalizedId,
111
+ workspaceName: selected.workspace.name,
112
+ path: required(installed.path, 'materialized workspace path'),
113
+ rows: installed.rows,
114
+ cloudHead: cloud.checksum,
115
+ materialized: true,
116
+ alreadyMaterialized: installed.alreadyMaterialized === true,
117
+ watcherRoots: coverage.roots,
118
+ };
119
+ }
120
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/files/commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ /** Files product operations. Hosts own effects; Live owns decisions. */
18
+ __exportStar(require("./commands.js"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/files/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wEAAwE;AACxE,gDAA8B"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ /**
3
+ * @amalgm/live — the portable realtime SDK for the Amalgm platform.
4
+ *
5
+ * Portable layers, one rule each:
6
+ *
7
+ * - `contracts/` every wire shape and identity rule, as types + validators
8
+ * - `machines/` the protocol's behavior, as pure state machines
9
+ * - `records/` the entity Record, local Outbox, authority, and Inbox laws
10
+ *
11
+ * Start at PURPOSE.md for the axioms; docs/ holds the normative specs.
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
25
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
26
+ };
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ __exportStar(require("./contracts/index.js"), exports);
29
+ __exportStar(require("./machines/index.js"), exports);
30
+ __exportStar(require("./entities/index.js"), exports);
31
+ __exportStar(require("./watching/index.js"), exports);
32
+ __exportStar(require("./detection/index.js"), exports);
33
+ __exportStar(require("./records/index.js"), exports);
34
+ __exportStar(require("./registration/index.js"), exports);
35
+ __exportStar(require("./files/index.js"), exports);
36
+ __exportStar(require("./transfer/index.js"), exports);
37
+ __exportStar(require("./merge/index.js"), exports);
38
+ __exportStar(require("./workspace/index.js"), exports);
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;;;;;;;;;;;;;;AAEH,uDAAqC;AACrC,sDAAoC;AACpC,sDAAoC;AACpC,sDAAoC;AACpC,uDAAqC;AACrC,qDAAmC;AACnC,0DAAwC;AACxC,mDAAiC;AACjC,sDAAoC;AACpC,mDAAiC;AACjC,uDAAqC"}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ /**
3
+ * Tunnel slot arbitration — who owns `(computer_id, runtime_label)`.
4
+ *
5
+ * The gateway holds one slot per runtime identity; a newcomer's first
6
+ * identity-bearing hello decides the winner (local-live-protocol.md §5).
7
+ * This is the pure decision. The gateway supplies sockets and timers; the
8
+ * fencing rule — mark the loser superseded BEFORE closing it, drop its
9
+ * in-flight frames — is part of the contract and encoded in the verdict.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ARBITRATION_DEADLINE_MS = void 0;
13
+ exports.decideSlot = decideSlot;
14
+ const tunnel_js_1 = require("../contracts/frames/tunnel.js");
15
+ /** A newcomer with a holder present buffers unrouted until its first identity-bearing hello, bounded by this deadline (AMALGM_TUNNEL_HELLO_ARBITRATION_MS). */
16
+ exports.ARBITRATION_DEADLINE_MS = 3_000;
17
+ /**
18
+ * Decide a contested slot.
19
+ *
20
+ * - same `instance_id` → newer socket wins (the same process reconnecting)
21
+ * - different `instance_id` → strictly newer `boot_ts` wins; older or EQUAL loses
22
+ * - unusable identity on either side (or the deadline expired — pass
23
+ * `holder: null` identity via `legacyFallback`) → last-connect-wins, logged as such by the caller
24
+ */
25
+ function decideSlot(holder, newcomer) {
26
+ if (holder === null) {
27
+ return { install: true, fenceHolder: false, rule: 'free-slot' };
28
+ }
29
+ if (!(0, tunnel_js_1.hasUsableIdentity)(newcomer) || !(0, tunnel_js_1.hasUsableIdentity)(holder)) {
30
+ return { install: true, fenceHolder: true, rule: 'legacy-last-connect-wins' };
31
+ }
32
+ const contender = newcomer;
33
+ if (contender.instance_id === holder.instance_id) {
34
+ return { install: true, fenceHolder: true, rule: 'same-instance-reconnect' };
35
+ }
36
+ if (contender.boot_ts > holder.boot_ts) {
37
+ return { install: true, fenceHolder: true, rule: 'newer-boot' };
38
+ }
39
+ return { install: false, closeCode: tunnel_js_1.CLOSE_CODES.supersededInstance, rule: 'older-or-equal-boot' };
40
+ }
41
+ //# sourceMappingURL=arbitration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arbitration.js","sourceRoot":"","sources":["../../src/machines/arbitration.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAuBH,gCAeC;AApCD,6DAAiG;AAEjG,+JAA+J;AAClJ,QAAA,uBAAuB,GAAG,KAAK,CAAC;AAU7C;;;;;;;GAOG;AACH,SAAgB,UAAU,CAAC,MAA2B,EAAE,QAA+B;IACrF,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAClE,CAAC;IACD,IAAI,CAAC,IAAA,6BAAiB,EAAC,QAAQ,CAAC,IAAI,CAAC,IAAA,6BAAiB,EAAC,MAAM,CAAC,EAAE,CAAC;QAC/D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,0BAA0B,EAAE,CAAC;IAChF,CAAC;IACD,MAAM,SAAS,GAAG,QAAwB,CAAC;IAC3C,IAAI,SAAS,CAAC,WAAW,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC;QACjD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,yBAAyB,EAAE,CAAC;IAC/E,CAAC;IACD,IAAI,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;QACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAClE,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,uBAAW,CAAC,kBAAkB,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC;AACpG,CAAC"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ /**
3
+ * Tunnel reconnect policy (local-live-protocol.md §5, runtime client
4
+ * behavior).
5
+ *
6
+ * Two rules keep a two-instance fight from becoming a reconnect war:
7
+ *
8
+ * 1. Exponential backoff resets to 1s only after a connection SURVIVED the
9
+ * stable window; a connection that dies younger keeps (and grows) the
10
+ * previous backoff.
11
+ * 2. A 4009 refusal ("superseded instance") retries after a fixed long
12
+ * delay — never a full stop, because a wrongly-refused instance must
13
+ * still recover once the true holder dies.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.initialBackoff = exports.MAX_DELAY_MS = exports.BASE_DELAY_MS = exports.STABLE_RESET_MS = exports.SUPERSEDED_RETRY_MS = void 0;
17
+ exports.planReconnect = planReconnect;
18
+ const tunnel_js_1 = require("../contracts/frames/tunnel.js");
19
+ /** AMALGM_TUNNEL_SUPERSEDED_RETRY_MS */
20
+ exports.SUPERSEDED_RETRY_MS = 5 * 60_000;
21
+ /** AMALGM_TUNNEL_STABLE_RESET_MS — survival time that earns a reset to the base delay. */
22
+ exports.STABLE_RESET_MS = 30_000;
23
+ exports.BASE_DELAY_MS = 1_000;
24
+ exports.MAX_DELAY_MS = 60_000;
25
+ exports.initialBackoff = { delayMs: exports.BASE_DELAY_MS };
26
+ function planReconnect(state, disconnect) {
27
+ if (disconnect.closeCode === tunnel_js_1.CLOSE_CODES.supersededInstance) {
28
+ // Fixed, slow, and does not disturb the exponential state: an instance
29
+ // alternating between refusals and crashes must not launder its backoff.
30
+ return { waitMs: exports.SUPERSEDED_RETRY_MS, next: state, rule: 'superseded-fixed-retry' };
31
+ }
32
+ if (disconnect.connectedForMs >= exports.STABLE_RESET_MS) {
33
+ return { waitMs: exports.BASE_DELAY_MS, next: exports.initialBackoff, rule: 'stable-reset' };
34
+ }
35
+ const grown = Math.min(state.delayMs * 2, exports.MAX_DELAY_MS);
36
+ return { waitMs: state.delayMs, next: { delayMs: grown }, rule: 'exponential' };
37
+ }
38
+ //# sourceMappingURL=backoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backoff.js","sourceRoot":"","sources":["../../src/machines/backoff.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;AA8BH,sCAWC;AAvCD,6DAA4D;AAE5D,wCAAwC;AAC3B,QAAA,mBAAmB,GAAG,CAAC,GAAG,MAAM,CAAC;AAC9C,0FAA0F;AAC7E,QAAA,eAAe,GAAG,MAAM,CAAC;AACzB,QAAA,aAAa,GAAG,KAAK,CAAC;AACtB,QAAA,YAAY,GAAG,MAAM,CAAC;AAOtB,QAAA,cAAc,GAAiB,EAAE,OAAO,EAAE,qBAAa,EAAE,CAAC;AAcvE,SAAgB,aAAa,CAAC,KAAmB,EAAE,UAAsB;IACvE,IAAI,UAAU,CAAC,SAAS,KAAK,uBAAW,CAAC,kBAAkB,EAAE,CAAC;QAC5D,uEAAuE;QACvE,yEAAyE;QACzE,OAAO,EAAE,MAAM,EAAE,2BAAmB,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,wBAAwB,EAAE,CAAC;IACtF,CAAC;IACD,IAAI,UAAU,CAAC,cAAc,IAAI,uBAAe,EAAE,CAAC;QACjD,OAAO,EAAE,MAAM,EAAE,qBAAa,EAAE,IAAI,EAAE,sBAAc,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;IAC/E,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,EAAE,oBAAY,CAAC,CAAC;IACxD,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;AAClF,CAAC"}
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ /**
3
+ * The bootstrap machine — how a client reaches `live` truthfully.
4
+ *
5
+ * Ordered-bootstrap mode (local-live-protocol.md §3): the snapshot is the
6
+ * first data frame and everything after it is ordered on the same channel,
7
+ * so the machine simply installs and follows. Legacy mode: the snapshot
8
+ * travels out-of-band, so the machine holds events while the snapshot body
9
+ * is in flight and replays only those past its seq — the full-snapshot
10
+ * barrier (§6).
11
+ *
12
+ * Feature detection (§3): a bootstrap request against a legacy engine
13
+ * yields no `snapshot` frame. The client falls back to the legacy path
14
+ * when the first data frame is a `state` event, a `ping` arrives, or the
15
+ * timeout passes — whichever comes first.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.SnapshotBarrier = exports.BootstrapMachine = void 0;
19
+ const stream_js_1 = require("../contracts/frames/stream.js");
20
+ /** One instance per bootstrap-mode connection attempt; discard after it resolves. */
21
+ class BootstrapMachine {
22
+ #held = [];
23
+ #resolved = false;
24
+ timeoutMs = stream_js_1.BOOTSTRAP_SNAPSHOT_TIMEOUT_MS;
25
+ /** Feed each stream frame until a command other than `none` resolves the machine. */
26
+ accept(frame) {
27
+ if (this.#resolved)
28
+ return { command: 'none' };
29
+ switch (frame.type) {
30
+ case 'snapshot': {
31
+ this.#resolved = true;
32
+ const snapshot = { seq: frame.seq, stable: frame.stable !== false, resources: frame.resources };
33
+ const replay = this.#held.filter((event) => event.seq > frame.seq);
34
+ this.#held = [];
35
+ return { command: 'install', snapshot, replay };
36
+ }
37
+ case 'state': {
38
+ if (this.#held.length === 0) {
39
+ // First data frame is an event, not a snapshot: legacy peer.
40
+ this.#resolved = true;
41
+ return { command: 'fallback-legacy', held: [frame.event], reason: 'state-before-snapshot' };
42
+ }
43
+ this.#held.push(frame.event);
44
+ return { command: 'none' };
45
+ }
46
+ case 'ping': {
47
+ this.#resolved = true;
48
+ const held = this.#held;
49
+ this.#held = [];
50
+ return { command: 'fallback-legacy', held, reason: 'ping-before-snapshot' };
51
+ }
52
+ case 'error': {
53
+ this.#resolved = true;
54
+ this.#held = [];
55
+ return frame.status === undefined ? { command: 'fallback-error' } : { command: 'fallback-error', status: frame.status };
56
+ }
57
+ case 'reset':
58
+ case 'presence':
59
+ return { command: 'none' };
60
+ }
61
+ }
62
+ /** The host's timer fired without a snapshot frame. */
63
+ expire() {
64
+ if (this.#resolved)
65
+ return { command: 'none' };
66
+ this.#resolved = true;
67
+ const held = this.#held;
68
+ this.#held = [];
69
+ return { command: 'fallback-legacy', held, reason: 'timeout' };
70
+ }
71
+ }
72
+ exports.BootstrapMachine = BootstrapMachine;
73
+ /**
74
+ * The legacy full-snapshot barrier (§6): hold events while a full snapshot
75
+ * body is in flight; on arrival, replay only those past its seq. Partial
76
+ * snapshots (resources added on a live connection) never pass through
77
+ * here — they hold per-resource and never bump the connection seq.
78
+ */
79
+ class SnapshotBarrier {
80
+ #held = [];
81
+ #inFlight = false;
82
+ get inFlight() {
83
+ return this.#inFlight;
84
+ }
85
+ begin() {
86
+ this.#inFlight = true;
87
+ this.#held = [];
88
+ }
89
+ /** Returns true when the event was held (a snapshot body is in flight). */
90
+ hold(event) {
91
+ if (!this.#inFlight)
92
+ return false;
93
+ this.#held.push(event);
94
+ return true;
95
+ }
96
+ /** The snapshot body landed: install it, then apply the returned events in order. */
97
+ complete(snapshot) {
98
+ this.#inFlight = false;
99
+ const replay = this.#held.filter((event) => event.seq > snapshot.seq).sort((a, b) => a.seq - b.seq);
100
+ this.#held = [];
101
+ return replay;
102
+ }
103
+ /** The snapshot fetch failed: release nothing; the caller re-syncs. */
104
+ abandon() {
105
+ this.#inFlight = false;
106
+ this.#held = [];
107
+ }
108
+ }
109
+ exports.SnapshotBarrier = SnapshotBarrier;
110
+ //# sourceMappingURL=bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/machines/bootstrap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ /**
3
+ * Chunked response reassembly — the receiving half of §5's
4
+ * res_start / res_chunk / res_end train.
5
+ *
6
+ * Chunks reassemble by concatenating in index order; `res_end.chunks` must
7
+ * match the count received, else the whole response is treated as a 502
8
+ * for that request. Control frames interleaving between chunks is the
9
+ * feature, so the assembler tolerates any arrival interleaving across
10
+ * requests — but never within one (indexes must arrive 0,1,2,…).
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.ChunkAssembler = void 0;
14
+ exports.planChunks = planChunks;
15
+ /**
16
+ * One assembler per tunnel connection. The host must call `abandon` when a
17
+ * request times out — the accumulator is memory, and §5 requires cleanup
18
+ * on the request timeout (AMALGM_TUNNEL_REQUEST_TIMEOUT_MS).
19
+ */
20
+ class ChunkAssembler {
21
+ #pending = new Map();
22
+ /** In-flight accumulator count, exposed for diagnostics (§5 getTunnelDebugStats). */
23
+ get pending() {
24
+ return this.#pending.size;
25
+ }
26
+ accept(frame) {
27
+ switch (frame.type) {
28
+ case 'res_start': {
29
+ this.#pending.set(frame.req_id, { status: frame.status, headers: frame.headers, chunks: [] });
30
+ return { done: false };
31
+ }
32
+ case 'res_chunk': {
33
+ const acc = this.#pending.get(frame.req_id);
34
+ if (!acc)
35
+ return { done: true, error: `res_chunk for unknown req_id ${frame.req_id}` };
36
+ if (frame.index !== acc.chunks.length) {
37
+ this.#pending.delete(frame.req_id);
38
+ return { done: true, error: `res_chunk index ${frame.index} arrived out of order (expected ${acc.chunks.length})` };
39
+ }
40
+ acc.chunks.push(frame.body_b64);
41
+ return { done: false };
42
+ }
43
+ case 'res_end': {
44
+ const acc = this.#pending.get(frame.req_id);
45
+ this.#pending.delete(frame.req_id);
46
+ if (!acc)
47
+ return { done: true, error: `res_end for unknown req_id ${frame.req_id}` };
48
+ if (frame.chunks !== acc.chunks.length) {
49
+ return { done: true, error: `res_end declared ${frame.chunks} chunks but ${acc.chunks.length} arrived` };
50
+ }
51
+ return { done: true, response: { status: acc.status, headers: acc.headers, bodyChunksB64: acc.chunks } };
52
+ }
53
+ }
54
+ }
55
+ /** Drop a timed-out request's accumulator. Returns whether one existed. */
56
+ abandon(reqId) {
57
+ return this.#pending.delete(reqId);
58
+ }
59
+ }
60
+ exports.ChunkAssembler = ChunkAssembler;
61
+ /**
62
+ * Sender-side chunk plan for a raw body size: how many chunks a v2 peer
63
+ * will receive. The budget check happens BEFORE materializing any frame
64
+ * (§5): an over-budget response is dropped as a 503 without ever building
65
+ * its chunks — hence the plan is sizes only, never buffers.
66
+ */
67
+ function planChunks(bodyBytes, chunkMaxBytes) {
68
+ if (bodyBytes < 0 || !Number.isSafeInteger(bodyBytes))
69
+ return { chunks: 0 };
70
+ return { chunks: bodyBytes === 0 ? 1 : Math.ceil(bodyBytes / chunkMaxBytes) };
71
+ }
72
+ //# sourceMappingURL=chunks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunks.js","sourceRoot":"","sources":["../../src/machines/chunks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ /**
3
+ * The machines layer: the protocol's behavior as pure, deterministic state
4
+ * machines. Every machine takes wire shapes in and returns decisions as
5
+ * data — the host performs the fetches, timers, and writes. Nothing in
6
+ * here opens a socket, reads a clock, or touches a disk.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
20
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ __exportStar(require("./bootstrap.js"), exports);
24
+ __exportStar(require("./presence.js"), exports);
25
+ __exportStar(require("./arbitration.js"), exports);
26
+ __exportStar(require("./chunks.js"), exports);
27
+ __exportStar(require("./backoff.js"), exports);
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/machines/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;AAEH,iDAA+B;AAC/B,gDAA8B;AAC9B,mDAAiC;AACjC,8CAA4B;AAC5B,+CAA6B"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ /**
3
+ * Presence receiver — arrival-clock TTL over replace-not-merge frames.
4
+ *
5
+ * A presence frame carries the FULL peer list for one resource; receivers
6
+ * replace their view and treat absence as the default that publishing
7
+ * re-earns (local-live-protocol.md §2). The server already expires stale
8
+ * publishers, but receivers must apply their OWN arrival-clock TTL — a
9
+ * frozen stream must not preserve ghosts.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.PresenceView = void 0;
13
+ const presence_js_1 = require("../contracts/presence.js");
14
+ class PresenceView {
15
+ ttlMs;
16
+ #byResource = new Map();
17
+ constructor(ttlMs = presence_js_1.SERVER_TTL_MS) {
18
+ this.ttlMs = ttlMs;
19
+ }
20
+ /** Replace one resource's peer view. `nowMs` is the receiver's clock (host-supplied — the SDK holds no clock). */
21
+ accept(frame, nowMs) {
22
+ const peers = new Map();
23
+ for (const peer of frame.peers) {
24
+ peers.set(peer.session, { ...peer, arrivedAtMs: nowMs });
25
+ }
26
+ if (peers.size === 0)
27
+ this.#byResource.delete(frame.resource);
28
+ else
29
+ this.#byResource.set(frame.resource, peers);
30
+ }
31
+ /** Live peers for a resource, with expired entries dropped as of `nowMs`. */
32
+ peers(resource, nowMs) {
33
+ const peers = this.#byResource.get(resource);
34
+ if (!peers)
35
+ return [];
36
+ const alive = [];
37
+ for (const [session, peer] of peers) {
38
+ if (nowMs - peer.arrivedAtMs > this.ttlMs)
39
+ peers.delete(session);
40
+ else
41
+ alive.push(peer);
42
+ }
43
+ if (peers.size === 0)
44
+ this.#byResource.delete(resource);
45
+ return alive;
46
+ }
47
+ /** Delivery was lost: presence is not replayed after a gap, so the view must not outlive its stream. */
48
+ clear() {
49
+ this.#byResource.clear();
50
+ }
51
+ }
52
+ exports.PresenceView = PresenceView;
53
+ //# sourceMappingURL=presence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence.js","sourceRoot":"","sources":["../../src/machines/presence.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAEH,0DAAgG;AAOhG,MAAa,YAAY;IAGM;IAF7B,WAAW,GAAG,IAAI,GAAG,EAAiC,CAAC;IAEvD,YAA6B,QAAgB,2BAAa;QAA7B,UAAK,GAAL,KAAK,CAAwB;IAAG,CAAC;IAE9D,kHAAkH;IAClH,MAAM,CAAC,KAAoB,EAAE,KAAa;QACxC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAC;QAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC/B,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,GAAG,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC;YAAE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;;YACzD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC;IAED,6EAA6E;IAC7E,KAAK,CAAC,QAAgB,EAAE,KAAa;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,CAAC;QACtB,MAAM,KAAK,GAAe,EAAE,CAAC;QAC7B,KAAK,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;YACpC,IAAI,KAAK,GAAG,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK;gBAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;;gBAC5D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC;YAAE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACxD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,wGAAwG;IACxG,KAAK;QACH,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;CACF;AAhCD,oCAgCC"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ /**
3
+ * The merge layer: the text-reconciliation engine behind live documents.
4
+ * `merge3` is the diff3 core; the doc-write decision policy
5
+ * (`decideDocWrite` — outcome selection, retention-ring base resolution,
6
+ * overwrite-deletes-text) joins it here as the next extraction slice
7
+ * (ROADMAP.md #1).
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
21
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ __exportStar(require("./merge3.js"), exports);
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/merge/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;;;;;;;;;;;AAEH,8CAA4B"}