codex-overleaf-link 2.2.1 → 2.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.
Files changed (79) hide show
  1. package/README.md +25 -23
  2. package/extension/bootstrap/manifest.template.json +1 -1
  3. package/extension/runtime-manifest.json +5 -71
  4. package/extension/src/background.js +67 -63
  5. package/extension/src/backgroundUpdateCoordinator.js +128 -66
  6. package/extension/src/content/applyResultFormatters.js +2 -3
  7. package/extension/src/content/composerPanel.js +0 -2
  8. package/extension/src/content/contentRuntime.js +757 -1558
  9. package/extension/src/content/contextTray.js +4 -6
  10. package/extension/src/content/diagnosticsController.js +1 -2
  11. package/extension/src/content/diffReviewPanel.js +14 -13
  12. package/extension/src/content/generated/content.bundle.js +41605 -0
  13. package/extension/src/content/generated/content.bundle.meta.json +103 -0
  14. package/extension/src/content/legacyGlobalRegistry.js +129 -0
  15. package/extension/src/content/markdownText.js +17 -17
  16. package/extension/src/content/mathText.js +155 -9
  17. package/extension/src/content/modelPicker.js +1 -1
  18. package/extension/src/content/modelPickerSupport.js +10 -5
  19. package/extension/src/content/moduleRegistryKernel.js +125 -0
  20. package/extension/src/content/nativeCompatibilityController.js +313 -0
  21. package/extension/src/content/otWarmMirror.js +8 -6
  22. package/extension/src/content/pageBridgeClient.js +224 -0
  23. package/extension/src/content/panelMaintenance.js +8 -3
  24. package/extension/src/content/postNavigationSettlementPersistence.js +100 -0
  25. package/extension/src/content/projectProviderSelection.js +4 -12
  26. package/extension/src/content/projectSessionCleanup.js +3 -3
  27. package/extension/src/content/providerSettingsCoordinator.js +59 -26
  28. package/extension/src/content/providerSettingsDialog.js +30 -18
  29. package/extension/src/content/recentProjects.js +15 -23
  30. package/extension/src/content/runGuidanceController.js +1 -1
  31. package/extension/src/content/runQueueScheduler.js +129 -29
  32. package/extension/src/content/runSettlementPersistence.js +51 -0
  33. package/extension/src/content/runTimelineView.js +17 -8
  34. package/extension/src/content/scopedPersistenceCoordinator.js +100 -0
  35. package/extension/src/content/scopedPersistenceDetachedCommit.js +47 -0
  36. package/extension/src/content/scopedPersistencePanelState.js +111 -0
  37. package/extension/src/content/sessionManager.js +15 -12
  38. package/extension/src/content/sessionPersistence.js +67 -8
  39. package/extension/src/content/updateNotice.js +10 -4
  40. package/extension/src/content/writebackOrchestrator.js +89 -68
  41. package/extension/src/contentScript.js +5 -1
  42. package/extension/src/page/trackedChangesLifecycle.js +16 -5
  43. package/extension/src/page/writebackRouter.js +6 -2
  44. package/extension/src/pageBridge.js +47 -98
  45. package/extension/src/shared/agentTranscript.js +18 -8
  46. package/extension/src/shared/compatibility.js +1 -1
  47. package/extension/src/shared/governanceRules.js +1 -1
  48. package/extension/src/shared/i18n.js +2 -4
  49. package/extension/src/shared/managedUpdateProjection.js +337 -0
  50. package/extension/src/shared/nativeRequestIdentity.js +60 -0
  51. package/extension/src/shared/otText.js +0 -19
  52. package/extension/src/shared/pageRpcContract.js +136 -0
  53. package/extension/src/shared/runExecutionSnapshot.js +187 -0
  54. package/extension/src/shared/runExecutionSnapshotCodec.js +171 -0
  55. package/extension/src/shared/runInputQueue.js +81 -34
  56. package/extension/src/shared/scopedPersistenceBrowserAdapter.js +79 -0
  57. package/extension/src/shared/scopedPersistenceQueuePolicy.js +200 -0
  58. package/extension/src/shared/scopedPersistenceReceipt.js +60 -0
  59. package/extension/src/shared/scopedPersistenceTransaction.js +241 -0
  60. package/extension/src/shared/sessionState.js +110 -59
  61. package/extension/src/shared/settlementFacts.js +351 -0
  62. package/extension/src/shared/storageDb.js +25 -10
  63. package/extension/src/shared/storageMigration.js +275 -61
  64. package/extension/src/shared/storageSessionClaims.js +60 -0
  65. package/extension/src/shared/updateConsent.js +4 -0
  66. package/extension/src/shared/updateRevocationIntent.js +109 -0
  67. package/extension/src/shared/writebackEvidenceProjection.js +150 -0
  68. package/extension/src/shared/writebackOperationEvidence.js +153 -0
  69. package/extension/src/shared/writebackSettlement.js +727 -0
  70. package/extension/styles/panel.css +18 -8
  71. package/native-host/src/codexPromptAssembly.js +1 -1
  72. package/native-host/src/codexRuntimeIdentity.js +1 -1
  73. package/native-host/src/codexSessionRunner.js +7 -13
  74. package/native-host/src/index.js +3 -69
  75. package/native-host/src/managedInstall.js +50 -8
  76. package/native-host/src/nativeTransportEnvelope.js +148 -0
  77. package/native-host/src/taskRunnerRuntime.js +14 -84
  78. package/native-host/src/updateManager.js +36 -1
  79. package/package.json +13 -5
@@ -0,0 +1,200 @@
1
+ (function (root, factory) {
2
+ var api = factory();
3
+ if (typeof module === 'object' && module.exports) module.exports = api;
4
+ if (root) root.CodexOverleafScopedPersistenceQueuePolicy = api;
5
+ })(typeof globalThis !== 'undefined' ? globalThis : this, function () {
6
+ 'use strict';
7
+
8
+ function createQueueClaim(input) {
9
+ return Object.freeze({
10
+ itemId: cleanPart(input && input.itemId),
11
+ ownerId: cleanPart(input && input.ownerId),
12
+ queueRevision: normalizeRevision(input && input.queueRevision),
13
+ claimedAt: cleanPart(input && input.claimedAt) || new Date().toISOString()
14
+ });
15
+ }
16
+
17
+ function isClaimCurrent(claim, queueState) {
18
+ return Boolean(claim && queueState
19
+ && cleanPart(claim.itemId) === cleanPart(queueState.itemId)
20
+ && cleanPart(claim.ownerId) === cleanPart(queueState.ownerId)
21
+ && normalizeRevision(claim.queueRevision) === normalizeRevision(queueState.queueRevision));
22
+ }
23
+
24
+ function mergeTombstones(existing, additions, limit) {
25
+ var result = Object.assign({}, existing && typeof existing === 'object' ? existing : {});
26
+ var now = new Date().toISOString();
27
+ (Array.isArray(additions) ? additions : []).forEach(function (id) {
28
+ var cleanId = cleanPart(id);
29
+ if (cleanId) result[cleanId] = now;
30
+ });
31
+ var max = Number.isFinite(Number(limit)) ? Math.max(1, Number(limit)) : 100;
32
+ return Object.fromEntries(Object.entries(result)
33
+ .sort(function (left, right) { return String(right[1]).localeCompare(String(left[1])); })
34
+ .slice(0, max));
35
+ }
36
+
37
+ function normalizeMeta(value) {
38
+ var revision = normalizeRevision(value && value.revision);
39
+ var hasDurableRevision = Boolean(value
40
+ && Object.prototype.hasOwnProperty.call(value, 'durableRevision'));
41
+ var durableRevision = hasDurableRevision
42
+ ? Math.min(normalizeRevision(value.durableRevision), revision)
43
+ : revision;
44
+ var pendingValue = value && value.pendingCommit;
45
+ var pendingRevision = normalizeRevision(pendingValue && pendingValue.revision);
46
+ var pendingCommit = pendingValue && typeof pendingValue === 'object'
47
+ && pendingRevision > durableRevision
48
+ && pendingRevision <= revision
49
+ ? {
50
+ revision: pendingRevision,
51
+ writerId: cleanPart(pendingValue.writerId),
52
+ startedAt: cleanPart(pendingValue.startedAt)
53
+ }
54
+ : null;
55
+ return {
56
+ revision: revision,
57
+ durableRevision: durableRevision,
58
+ pendingCommit: pendingCommit,
59
+ queueRevision: normalizeRevision(value && value.queueRevision),
60
+ writerId: cleanPart(value && value.writerId),
61
+ updatedAt: cleanPart(value && value.updatedAt),
62
+ queueClaims: normalizeQueueClaims(value && value.queueClaims),
63
+ queueTombstones: normalizeTombstoneMap(value && value.queueTombstones),
64
+ sessionTombstones: normalizeTombstoneMap(value && value.sessionTombstones)
65
+ };
66
+ }
67
+
68
+ function normalizeQueueMutations(options) {
69
+ var values = [];
70
+ if (options && options.queueMutation) values.push(options.queueMutation);
71
+ if (options && Array.isArray(options.queueMutations)) values.push.apply(values, options.queueMutations);
72
+ return values.filter(function (value) {
73
+ return value && typeof value === 'object' && cleanPart(value.type);
74
+ });
75
+ }
76
+
77
+ function applyQueueMutations(meta, mutations, writerId) {
78
+ var next = normalizeMeta(meta);
79
+ for (var mutation of mutations) {
80
+ var type = cleanPart(mutation.type);
81
+ var itemId = cleanPart(mutation.itemId);
82
+ var sessionId = cleanPart(mutation.sessionId);
83
+ if (!itemId && type !== 'transition') {
84
+ return { ok: false, reason: 'invalid_queue_mutation' };
85
+ }
86
+ if (type === 'remove' || type === 'release' || type === 'restore') {
87
+ var claimed = next.queueClaims[itemId];
88
+ var mutationToken = cleanPart(mutation.claimToken);
89
+ if (claimed && !isExpiredClaim(claimed)
90
+ && (claimed.ownerId !== writerId
91
+ || !mutationToken
92
+ || claimed.claimToken !== mutationToken)) {
93
+ return {
94
+ ok: false,
95
+ reason: 'queue_claim_conflict',
96
+ ownerId: claimed.ownerId,
97
+ itemId: itemId
98
+ };
99
+ }
100
+ }
101
+ if (type === 'claim') {
102
+ var existing = next.queueClaims[itemId];
103
+ if (existing && existing.ownerId !== writerId && !isExpiredClaim(existing)) {
104
+ return {
105
+ ok: false,
106
+ reason: 'queue_claim_conflict',
107
+ ownerId: existing.ownerId,
108
+ itemId: itemId
109
+ };
110
+ }
111
+ next.queueRevision += 1;
112
+ next.queueClaims[itemId] = {
113
+ ...createQueueClaim({
114
+ itemId: itemId,
115
+ ownerId: writerId,
116
+ queueRevision: next.queueRevision
117
+ }),
118
+ sessionId: sessionId,
119
+ claimToken: cleanPart(mutation.claimToken)
120
+ };
121
+ continue;
122
+ }
123
+ if (type === 'remove') {
124
+ next.queueRevision += 1;
125
+ next.queueTombstones = mergeTombstones(next.queueTombstones, [itemId], 500);
126
+ delete next.queueClaims[itemId];
127
+ continue;
128
+ }
129
+ if (type === 'release') {
130
+ next.queueRevision += 1;
131
+ delete next.queueClaims[itemId];
132
+ continue;
133
+ }
134
+ if (type === 'restore') {
135
+ next.queueRevision += 1;
136
+ delete next.queueClaims[itemId];
137
+ delete next.queueTombstones[itemId];
138
+ continue;
139
+ }
140
+ if (type === 'enqueue' || type === 'transition') {
141
+ next.queueRevision += 1;
142
+ continue;
143
+ }
144
+ return { ok: false, reason: 'invalid_queue_mutation' };
145
+ }
146
+ return { ok: true, meta: next };
147
+ }
148
+
149
+ function normalizeQueueClaims(value) {
150
+ var source = value && typeof value === 'object' ? value : {};
151
+ var result = {};
152
+ Object.entries(source).forEach(function (entry) {
153
+ var itemId = cleanPart(entry[0]);
154
+ var claim = entry[1] && typeof entry[1] === 'object' ? entry[1] : {};
155
+ var ownerId = cleanPart(claim.ownerId);
156
+ if (!itemId || !ownerId) return;
157
+ result[itemId] = {
158
+ itemId: itemId,
159
+ ownerId: ownerId,
160
+ sessionId: cleanPart(claim.sessionId),
161
+ claimToken: cleanPart(claim.claimToken),
162
+ queueRevision: normalizeRevision(claim.queueRevision),
163
+ claimedAt: cleanPart(claim.claimedAt)
164
+ };
165
+ });
166
+ return result;
167
+ }
168
+
169
+ function normalizeTombstoneMap(value) {
170
+ var source = value && typeof value === 'object' ? value : {};
171
+ return Object.fromEntries(Object.entries(source)
172
+ .map(function (entry) { return [cleanPart(entry[0]), cleanPart(entry[1])]; })
173
+ .filter(function (entry) { return entry[0] && entry[1]; }));
174
+ }
175
+
176
+ function isExpiredClaim(claim, now) {
177
+ var claimedAt = Date.parse(claim && claim.claimedAt || '');
178
+ return !claimedAt || (Number(now || Date.now()) - claimedAt) > 60 * 1000;
179
+ }
180
+
181
+ function normalizeRevision(value) {
182
+ var number = Number(value);
183
+ return Number.isSafeInteger(number) && number >= 0 ? number : 0;
184
+ }
185
+
186
+ function cleanPart(value) {
187
+ return typeof value === 'string' ? value.trim() : '';
188
+ }
189
+
190
+ return Object.freeze({
191
+ applyQueueMutations: applyQueueMutations,
192
+ cleanPart: cleanPart,
193
+ createQueueClaim: createQueueClaim,
194
+ isClaimCurrent: isClaimCurrent,
195
+ mergeTombstones: mergeTombstones,
196
+ normalizeMeta: normalizeMeta,
197
+ normalizeQueueMutations: normalizeQueueMutations,
198
+ normalizeRevision: normalizeRevision
199
+ });
200
+ });
@@ -0,0 +1,60 @@
1
+ (function (root, factory) {
2
+ if (typeof module === 'object' && module.exports) {
3
+ module.exports = factory();
4
+ } else {
5
+ root.CodexOverleafModuleRegistry.define('ScopedPersistenceReceipt', [], factory);
6
+ }
7
+ })(typeof globalThis !== 'undefined' ? globalThis : this, function () {
8
+ 'use strict';
9
+
10
+ function createFenceMeta(meta, currentMeta, writerId) {
11
+ var startedAt = new Date().toISOString();
12
+ var revision = currentMeta.revision + 1;
13
+ return {
14
+ ...meta,
15
+ revision: revision,
16
+ durableRevision: currentMeta.durableRevision,
17
+ pendingCommit: { revision: revision, writerId: writerId, startedAt: startedAt },
18
+ writerId: writerId,
19
+ updatedAt: startedAt
20
+ };
21
+ }
22
+
23
+ function createCommittedMeta(fenceMeta) {
24
+ return {
25
+ ...fenceMeta,
26
+ durableRevision: fenceMeta.revision,
27
+ pendingCommit: null,
28
+ updatedAt: new Date().toISOString()
29
+ };
30
+ }
31
+
32
+ function createRecoveredMeta(currentMeta, fenceMeta, writerId) {
33
+ var revision = fenceMeta.revision + 1;
34
+ return {
35
+ ...currentMeta,
36
+ revision: revision,
37
+ durableRevision: revision,
38
+ pendingCommit: null,
39
+ queueRevision: fenceMeta.queueRevision + 1,
40
+ writerId: writerId,
41
+ updatedAt: new Date().toISOString()
42
+ };
43
+ }
44
+
45
+ function decorateReceiptError(error, revision) {
46
+ if (error && typeof error === 'object') {
47
+ error.code = error.code || 'persistence_receipt_write_failed';
48
+ error.persistenceActionCommitted = true;
49
+ error.persistenceRevision = revision;
50
+ }
51
+ return error;
52
+ }
53
+
54
+ return Object.freeze({
55
+ createFenceMeta: createFenceMeta,
56
+ createCommittedMeta: createCommittedMeta,
57
+ createRecoveredMeta: createRecoveredMeta,
58
+ decorateReceiptError: decorateReceiptError
59
+ });
60
+ });
@@ -0,0 +1,241 @@
1
+ (function (root, factory) {
2
+ if (typeof module === 'object' && module.exports) {
3
+ module.exports = factory(
4
+ require('./scopedPersistenceQueuePolicy'),
5
+ require('./scopedPersistenceBrowserAdapter'),
6
+ require('./scopedPersistenceReceipt')
7
+ );
8
+ } else {
9
+ root.CodexOverleafModuleRegistry.define('ScopedPersistenceTransaction', [
10
+ 'ScopedPersistenceQueuePolicy',
11
+ 'ScopedPersistenceBrowserAdapter',
12
+ 'ScopedPersistenceReceipt'
13
+ ], factory);
14
+ }
15
+ })(typeof globalThis !== 'undefined' ? globalThis : this, function (QueuePolicy, BrowserAdapter, Receipt) {
16
+ 'use strict';
17
+
18
+ var applyQueueMutations = QueuePolicy.applyQueueMutations;
19
+ var cleanPart = QueuePolicy.cleanPart;
20
+ var createQueueClaim = QueuePolicy.createQueueClaim;
21
+ var isClaimCurrent = QueuePolicy.isClaimCurrent;
22
+ var mergeTombstones = QueuePolicy.mergeTombstones;
23
+ var normalizeMeta = QueuePolicy.normalizeMeta;
24
+ var normalizeQueueMutations = QueuePolicy.normalizeQueueMutations;
25
+ var normalizeRevision = QueuePolicy.normalizeRevision;
26
+ var createBrowserAdapter = BrowserAdapter.createBrowserAdapter;
27
+ var normalizeScope = BrowserAdapter.normalizeScope;
28
+ var scopeKey = BrowserAdapter.scopeKey;
29
+
30
+ function sameScope(left, right) {
31
+ return Boolean(left && right
32
+ && left.accountScopeId === right.accountScopeId
33
+ && left.projectId === right.projectId);
34
+ }
35
+
36
+
37
+ function createCoordinator(options) {
38
+ options = options || {};
39
+ var adapter = options.adapter || createBrowserAdapter(options);
40
+ var writerId = cleanPart(options.writerId) || randomId();
41
+ var generation = 0;
42
+ var active = null;
43
+
44
+ async function beginHydration(inputScope) {
45
+ var scope = normalizeScope(inputScope);
46
+ generation += 1;
47
+ var tokenGeneration = generation;
48
+ active = tokenFromMeta(scope, tokenGeneration, false, {});
49
+ var meta = await strictRead(adapter, scope);
50
+ var token = tokenFromMeta(scope, tokenGeneration, false, meta);
51
+ if (active && active.generation === tokenGeneration && sameScope(active, token)) active = token;
52
+ return token;
53
+ }
54
+
55
+ async function captureCommitView(inputScope, captureOptions) {
56
+ var scope = normalizeScope(inputScope);
57
+ var detached = Boolean(captureOptions && captureOptions.detached);
58
+ if (!detached && active && active.projectId === scope.projectId) {
59
+ scope = normalizeScope({
60
+ accountScopeId: active.accountScopeId,
61
+ projectId: scope.projectId
62
+ });
63
+ }
64
+ if (!detached && active && sameScope(active, scope)) {
65
+ return tokenFromMeta(scope, active.generation, false, active);
66
+ }
67
+ var meta = await strictRead(adapter, scope);
68
+ return tokenFromMeta(scope, detached ? 0 : generation, detached, meta);
69
+ }
70
+
71
+ function isCurrent(token) {
72
+ return Boolean(token && active && token.detached !== true
73
+ && token.generation === active.generation && sameScope(token, active));
74
+ }
75
+
76
+ async function commit(token, action, commitOptions) {
77
+ if (!token || typeof action !== 'function' || !token.projectId) {
78
+ return { ok: false, reason: 'invalid_commit' };
79
+ }
80
+ var scope = normalizeScope(token);
81
+ if (!token.detached && !isCurrent(token)) return { ok: false, reason: 'stale_view' };
82
+ return adapter.withLock(scope, async function () {
83
+ if (!token.detached && !isCurrent(token)) return { ok: false, reason: 'stale_view' };
84
+ var currentMeta = await strictRead(adapter, scope);
85
+ if (!token.detached && !isCurrent(token)) return { ok: false, reason: 'stale_view' };
86
+ var conflict = currentMeta.revision !== normalizeRevision(token.revision);
87
+ if (conflict && !(commitOptions && commitOptions.rebase === true)) {
88
+ return {
89
+ ok: false,
90
+ reason: 'revision_conflict',
91
+ expectedRevision: token.revision,
92
+ actualRevision: currentMeta.revision
93
+ };
94
+ }
95
+ var queueMutations = normalizeQueueMutations(commitOptions);
96
+ if (queueMutations.length
97
+ && currentMeta.queueRevision !== normalizeRevision(token.queueRevision)) {
98
+ if (!token.detached && isCurrent(token)) {
99
+ active = tokenFromMeta(scope, token.generation, false, currentMeta);
100
+ }
101
+ return {
102
+ ok: false,
103
+ reason: 'queue_revision_conflict',
104
+ expectedRevision: token.queueRevision,
105
+ actualRevision: currentMeta.queueRevision,
106
+ actualStateRevision: currentMeta.revision
107
+ };
108
+ }
109
+ var projected = applyQueueMutations(currentMeta, queueMutations, writerId);
110
+ if (!projected.ok) return projected;
111
+ var nextMeta = Receipt.createFenceMeta({
112
+ ...projected.meta,
113
+ sessionTombstones: mergeTombstones(
114
+ projected.meta.sessionTombstones,
115
+ commitOptions && commitOptions.sessionTombstones,
116
+ 200
117
+ )
118
+ }, currentMeta, writerId);
119
+ await adapter.write(scope, nextMeta);
120
+ if (!token.detached && isCurrent(token)) {
121
+ active = tokenFromMeta(scope, token.generation, false, nextMeta);
122
+ }
123
+ var value;
124
+ try {
125
+ value = await action({
126
+ scope: scope,
127
+ baseRevision: currentMeta.revision,
128
+ durableRevision: currentMeta.durableRevision,
129
+ conflict: conflict,
130
+ previousCommitIncomplete: Boolean(currentMeta.pendingCommit),
131
+ writerId: writerId,
132
+ currentMeta: currentMeta,
133
+ nextMeta: nextMeta
134
+ });
135
+ } catch (error) {
136
+ if (queueMutations.some(function (mutation) {
137
+ return ['remove', 'release', 'restore'].includes(cleanPart(mutation.type));
138
+ })) {
139
+ var recoveredMeta = Receipt.createRecoveredMeta(currentMeta, nextMeta, writerId);
140
+ try {
141
+ await adapter.write(scope, recoveredMeta);
142
+ if (!token.detached && isCurrent(token)) {
143
+ active = tokenFromMeta(scope, token.generation, false, recoveredMeta);
144
+ }
145
+ } catch (recoveryError) {
146
+ if (error && typeof error === 'object') {
147
+ error.persistenceRecoveryError = recoveryError.message || String(recoveryError);
148
+ }
149
+ }
150
+ }
151
+ throw error;
152
+ }
153
+ var committedMeta = Receipt.createCommittedMeta(nextMeta);
154
+ try {
155
+ await adapter.write(scope, committedMeta);
156
+ } catch (error) {
157
+ throw Receipt.decorateReceiptError(error, nextMeta.revision);
158
+ }
159
+ if (!token.detached && isCurrent(token)) {
160
+ active = tokenFromMeta(scope, token.generation, false, committedMeta);
161
+ }
162
+ return {
163
+ ok: true,
164
+ value: value,
165
+ revision: committedMeta.revision,
166
+ durableRevision: committedMeta.durableRevision,
167
+ queueRevision: committedMeta.queueRevision,
168
+ queueClaims: committedMeta.queueClaims,
169
+ rebased: conflict,
170
+ recoveredIncompleteCommit: Boolean(currentMeta.pendingCommit),
171
+ superseded: !token.detached && !isCurrent(token)
172
+ };
173
+ });
174
+ }
175
+
176
+ return Object.freeze({
177
+ beginHydration: beginHydration,
178
+ captureCommitView: captureCommitView,
179
+ commit: commit,
180
+ getActiveView: function () {
181
+ return active ? tokenFromMeta(active, active.generation, false, active) : null;
182
+ },
183
+ getWriterId: function () { return writerId; },
184
+ invalidate: function () {
185
+ generation += 1;
186
+ active = null;
187
+ },
188
+ isCurrent: isCurrent
189
+ });
190
+ }
191
+
192
+ function makeToken(
193
+ scope,
194
+ tokenGeneration,
195
+ revision,
196
+ detached,
197
+ queueRevision,
198
+ durableRevision,
199
+ pendingCommit
200
+ ) {
201
+ return Object.freeze({
202
+ accountScopeId: scope.accountScopeId,
203
+ projectId: scope.projectId,
204
+ generation: normalizeRevision(tokenGeneration),
205
+ revision: normalizeRevision(revision),
206
+ durableRevision: normalizeRevision(durableRevision),
207
+ pendingCommit: pendingCommit && typeof pendingCommit === 'object'
208
+ ? Object.freeze({ ...pendingCommit })
209
+ : null,
210
+ queueRevision: normalizeRevision(queueRevision),
211
+ detached: detached === true
212
+ });
213
+ }
214
+
215
+ function tokenFromMeta(scope, tokenGeneration, detached, meta) {
216
+ return makeToken(scope, tokenGeneration, meta.revision, detached, meta.queueRevision,
217
+ meta.durableRevision, meta.pendingCommit);
218
+ }
219
+
220
+ async function strictRead(adapter, scope) {
221
+ return normalizeMeta(await adapter.read(scope));
222
+ }
223
+
224
+ function randomId() {
225
+ if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
226
+ return crypto.randomUUID();
227
+ }
228
+ return 'writer-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2);
229
+ }
230
+
231
+ return Object.freeze({
232
+ createBrowserAdapter: createBrowserAdapter,
233
+ createCoordinator: createCoordinator,
234
+ createQueueClaim: createQueueClaim,
235
+ isClaimCurrent: isClaimCurrent,
236
+ mergeTombstones: mergeTombstones,
237
+ normalizeScope: normalizeScope,
238
+ sameScope: sameScope,
239
+ scopeKey: scopeKey
240
+ });
241
+ });