@narumitw/pi-sync 0.49.10 → 0.49.11

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 (60) hide show
  1. package/README.md +10 -1
  2. package/dist/chunks/chunk-3GRWMWUZ.ts +213 -0
  3. package/dist/chunks/chunk-3GRWMWUZ.ts.map +7 -0
  4. package/dist/chunks/chunk-3NDD5QPM.ts +203 -0
  5. package/dist/chunks/chunk-3NDD5QPM.ts.map +7 -0
  6. package/dist/chunks/chunk-4F3W4CSC.ts +195 -0
  7. package/dist/chunks/chunk-4F3W4CSC.ts.map +7 -0
  8. package/dist/chunks/chunk-4U6AFLJB.ts +221 -0
  9. package/dist/chunks/chunk-4U6AFLJB.ts.map +7 -0
  10. package/dist/chunks/chunk-5MQ76BK5.ts +34 -0
  11. package/dist/chunks/chunk-5MQ76BK5.ts.map +7 -0
  12. package/dist/chunks/chunk-APZVBSM6.ts +1238 -0
  13. package/dist/chunks/chunk-APZVBSM6.ts.map +7 -0
  14. package/dist/chunks/chunk-BHJUISB4.ts +134 -0
  15. package/dist/chunks/chunk-BHJUISB4.ts.map +7 -0
  16. package/dist/chunks/chunk-D3S54OXI.ts +653 -0
  17. package/dist/chunks/chunk-D3S54OXI.ts.map +7 -0
  18. package/dist/chunks/chunk-EWX3TPLQ.ts +356 -0
  19. package/dist/chunks/chunk-EWX3TPLQ.ts.map +7 -0
  20. package/dist/chunks/chunk-F5QL2GPY.ts +341 -0
  21. package/dist/chunks/chunk-F5QL2GPY.ts.map +7 -0
  22. package/dist/chunks/chunk-FR6CVXAL.ts +81 -0
  23. package/dist/chunks/chunk-FR6CVXAL.ts.map +7 -0
  24. package/dist/chunks/chunk-HGV24P4T.ts +53 -0
  25. package/dist/chunks/chunk-HGV24P4T.ts.map +7 -0
  26. package/dist/chunks/chunk-JNOOSPEW.ts +82 -0
  27. package/dist/chunks/chunk-JNOOSPEW.ts.map +7 -0
  28. package/dist/chunks/chunk-LJDSHNS3.ts +259 -0
  29. package/dist/chunks/chunk-LJDSHNS3.ts.map +7 -0
  30. package/dist/chunks/chunk-RGJ6SOYR.ts +128 -0
  31. package/dist/chunks/chunk-RGJ6SOYR.ts.map +7 -0
  32. package/dist/chunks/chunk-W64NEHXT.ts +167 -0
  33. package/dist/chunks/chunk-W64NEHXT.ts.map +7 -0
  34. package/dist/chunks/chunk-YQ6UW7IF.ts +394 -0
  35. package/dist/chunks/chunk-YQ6UW7IF.ts.map +7 -0
  36. package/dist/chunks/file-selection-4UABOP44.ts +290 -0
  37. package/dist/chunks/file-selection-4UABOP44.ts.map +7 -0
  38. package/dist/chunks/git-backend-E3UOUUOM.ts +1104 -0
  39. package/dist/chunks/git-backend-E3UOUUOM.ts.map +7 -0
  40. package/dist/chunks/manager-result-dispatcher-YKBLZ7KL.ts +18 -0
  41. package/dist/chunks/manager-result-dispatcher-YKBLZ7KL.ts.map +7 -0
  42. package/dist/chunks/manager-ui-7E25VWUP.ts +2754 -0
  43. package/dist/chunks/manager-ui-7E25VWUP.ts.map +7 -0
  44. package/dist/chunks/remote-selection-ui-J6OW5DKZ.ts +17 -0
  45. package/dist/chunks/remote-selection-ui-J6OW5DKZ.ts.map +7 -0
  46. package/dist/chunks/s3-backend-3QZGO2EF.ts +680 -0
  47. package/dist/chunks/s3-backend-3QZGO2EF.ts.map +7 -0
  48. package/dist/chunks/setup-switch-X3W3FALZ.ts +27 -0
  49. package/dist/chunks/setup-switch-X3W3FALZ.ts.map +7 -0
  50. package/dist/chunks/snapshot-WBSV4MQG.ts +45 -0
  51. package/dist/chunks/snapshot-WBSV4MQG.ts.map +7 -0
  52. package/dist/chunks/sync-operations-MPAFVVHA.ts +1112 -0
  53. package/dist/chunks/sync-operations-MPAFVVHA.ts.map +7 -0
  54. package/dist/chunks/sync-state-36H7ULG2.ts +41 -0
  55. package/dist/chunks/sync-state-36H7ULG2.ts.map +7 -0
  56. package/dist/chunks/webdav-backend-ZD5RHRIU.ts +869 -0
  57. package/dist/chunks/webdav-backend-ZD5RHRIU.ts.map +7 -0
  58. package/dist/index.ts +668 -0
  59. package/dist/index.ts.map +7 -0
  60. package/package.json +10 -6
@@ -0,0 +1,195 @@
1
+ // @generated by scripts/build-runtime.mjs; do not edit.
2
+ // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
+ import {
4
+ effectiveSyncSetupRemoteIdentity,
5
+ localConfigPath,
6
+ syncSetupStorageReview,
7
+ updateLocalConfig,
8
+ validateConfigName
9
+ } from "./chunk-APZVBSM6.js";
10
+ import {
11
+ normalizeSyncInclude
12
+ } from "./chunk-YQ6UW7IF.js";
13
+
14
+ // src/settings-management.ts
15
+ var SyncSetupReviewChangedError = class extends Error {
16
+ constructor(message) {
17
+ super(message);
18
+ this.name = "SyncSetupReviewChangedError";
19
+ }
20
+ };
21
+ async function saveNewV3Settings(input, signal) {
22
+ validateConfigName(input.setupName, "sync setup");
23
+ validateConfigName(input.connectionName, "storage connection");
24
+ const settings = {
25
+ version: 3,
26
+ activeSyncSetup: input.setupName,
27
+ onSwitch: "ask-before-pull",
28
+ storageConnections: { [input.connectionName]: structuredClone(input.connection) },
29
+ syncSetups: {
30
+ [input.setupName]: {
31
+ ...structuredClone(input.setup),
32
+ storage: { ...input.setup.storage, connection: input.connectionName }
33
+ }
34
+ }
35
+ };
36
+ await updateLocalConfig((current) => {
37
+ if (Object.keys(current.storageConnections).length || Object.keys(current.syncSetups).length) {
38
+ throw new Error(`Settings already exist: ${localConfigPath()}`);
39
+ }
40
+ return settings;
41
+ }, signal);
42
+ return settings;
43
+ }
44
+ async function addStorageConnection(name, connection, signal) {
45
+ validateConfigName(name, "storage connection");
46
+ await updateSettings((settings) => {
47
+ if (Object.hasOwn(settings.storageConnections, name)) {
48
+ throw new Error(`Storage connection already exists: ${name}`);
49
+ }
50
+ return {
51
+ ...settings,
52
+ storageConnections: {
53
+ ...settings.storageConnections,
54
+ [name]: structuredClone(connection)
55
+ }
56
+ };
57
+ }, signal);
58
+ }
59
+ async function updateStorageConnection(name, update, expectedSetups, signal) {
60
+ validateConfigName(name, "storage connection");
61
+ await updateSettings((settings) => {
62
+ const connection = settings.storageConnections[name];
63
+ if (!connection) throw new Error(`Storage connection not found: ${name}`);
64
+ const currentSetups = referencingSetupNames(settings.syncSetups, name);
65
+ if (expectedSetups && !sameNames(currentSetups, expectedSetups)) {
66
+ throw new Error(
67
+ `Storage connection \u201C${name}\u201D usage changed while it was open; reopen it and review the affected sync setups.`
68
+ );
69
+ }
70
+ const nextConnection = update(structuredClone(connection));
71
+ const nextConnections = { ...settings.storageConnections, [name]: nextConnection };
72
+ assertUniqueLocations(settings.syncSetups, nextConnections);
73
+ return { ...settings, storageConnections: nextConnections };
74
+ }, signal);
75
+ }
76
+ async function addSyncSetup(name, setup, signal) {
77
+ validateConfigName(name, "sync setup");
78
+ await updateSettings((settings) => {
79
+ if (Object.hasOwn(settings.syncSetups, name))
80
+ throw new Error(`Sync setup already exists: ${name}`);
81
+ if (!Object.hasOwn(settings.storageConnections, setup.storage.connection)) {
82
+ throw new Error(`Storage connection not found: ${setup.storage.connection}`);
83
+ }
84
+ const nextSetups = { ...settings.syncSetups, [name]: structuredClone(setup) };
85
+ assertUniqueLocations(nextSetups, settings.storageConnections);
86
+ return {
87
+ ...settings,
88
+ syncSetups: nextSetups,
89
+ ...settings.activeSyncSetup ? {} : { activeSyncSetup: name }
90
+ };
91
+ }, signal);
92
+ }
93
+ async function updateSyncSetup(name, update, options = {}) {
94
+ validateConfigName(name, "sync setup");
95
+ await updateSettings((settings) => {
96
+ const setup = settings.syncSetups[name];
97
+ if (!setup) throw new Error(`Sync setup not found: ${name}`);
98
+ if (options.expectedInclude && !sameNames(normalizeSyncInclude(setup.sync.include), options.expectedInclude)) {
99
+ throw new SyncSetupReviewChangedError(
100
+ `Sync setup \u201C${name}\u201D included content changed while it was open; reopen it and review the current selection.`
101
+ );
102
+ }
103
+ if (options.expectedStorage) {
104
+ const connectionName = setup.storage.connection;
105
+ const connection = settings.storageConnections[connectionName];
106
+ if (!connection || !sameStorageReview(
107
+ syncSetupStorageReview(name, setup, connectionName, connection),
108
+ options.expectedStorage
109
+ )) {
110
+ throw new SyncSetupReviewChangedError(
111
+ `Sync setup \u201C${name}\u201D storage changed while it was open; reopen it and review the current storage location.`
112
+ );
113
+ }
114
+ }
115
+ const nextSetup = update(structuredClone(setup));
116
+ if (!Object.hasOwn(settings.storageConnections, nextSetup.storage.connection)) {
117
+ throw new Error(`Storage connection not found: ${nextSetup.storage.connection}`);
118
+ }
119
+ const nextSetups = { ...settings.syncSetups, [name]: nextSetup };
120
+ assertUniqueLocations(nextSetups, settings.storageConnections);
121
+ return { ...settings, syncSetups: nextSetups };
122
+ }, options.signal);
123
+ }
124
+ async function removeSyncSetup(name, signal) {
125
+ validateConfigName(name, "sync setup");
126
+ await updateSettings((settings) => {
127
+ if (!Object.hasOwn(settings.syncSetups, name)) throw new Error(`Sync setup not found: ${name}`);
128
+ const isCurrent = settings.activeSyncSetup === name;
129
+ if (isCurrent && Object.keys(settings.syncSetups).length > 1) {
130
+ throw new Error("Switch to another sync setup before removing the current setup.");
131
+ }
132
+ const syncSetups = { ...settings.syncSetups };
133
+ delete syncSetups[name];
134
+ const next = { ...settings, syncSetups };
135
+ if (isCurrent) delete next.activeSyncSetup;
136
+ return next;
137
+ }, signal);
138
+ }
139
+ async function removeStorageConnection(name, signal) {
140
+ validateConfigName(name, "storage connection");
141
+ await updateSettings((settings) => {
142
+ const referenced = referencingSetupNames(settings.syncSetups, name)[0];
143
+ if (referenced) {
144
+ throw new Error(`Storage connection \u201C${name}\u201D is used by sync setup \u201C${referenced}\u201D.`);
145
+ }
146
+ if (!Object.hasOwn(settings.storageConnections, name)) {
147
+ throw new Error(`Storage connection not found: ${name}`);
148
+ }
149
+ const storageConnections = { ...settings.storageConnections };
150
+ delete storageConnections[name];
151
+ return { ...settings, storageConnections };
152
+ }, signal);
153
+ }
154
+ async function updateSettings(update, signal) {
155
+ return updateLocalConfig((settings) => {
156
+ if (settings.version !== 3) {
157
+ throw new Error("Storage connections and sync setups require version 3 pi-sync settings.");
158
+ }
159
+ return update(settings);
160
+ }, signal);
161
+ }
162
+ function referencingSetupNames(setups, connection) {
163
+ return Object.entries(setups).filter(([, setup]) => setup.storage.connection === connection).map(([name]) => name).sort((left, right) => left.localeCompare(right));
164
+ }
165
+ function assertUniqueLocations(setups, connections) {
166
+ const identities = /* @__PURE__ */ new Map();
167
+ for (const [name, setup] of Object.entries(setups)) {
168
+ const connection = connections[setup.storage.connection];
169
+ if (!connection) throw new Error(`Storage connection not found: ${setup.storage.connection}`);
170
+ const identity = effectiveSyncSetupRemoteIdentity(setup, connection);
171
+ const previous = identities.get(identity);
172
+ if (previous) {
173
+ throw new Error(`Sync setup \u201C${name}\u201D duplicates the storage location of \u201C${previous}\u201D.`);
174
+ }
175
+ identities.set(identity, name);
176
+ }
177
+ }
178
+ function sameNames(left, right) {
179
+ return left.length === right.length && left.every((name, index) => name === right[index]);
180
+ }
181
+ function sameStorageReview(left, right) {
182
+ return left.connectionName === right.connectionName && left.storageKind === right.storageKind && left.storagePath === right.storagePath && left.bucket === right.bucket && left.branch === right.branch;
183
+ }
184
+
185
+ export {
186
+ SyncSetupReviewChangedError,
187
+ saveNewV3Settings,
188
+ addStorageConnection,
189
+ updateStorageConnection,
190
+ addSyncSetup,
191
+ updateSyncSetup,
192
+ removeSyncSetup,
193
+ removeStorageConnection
194
+ };
195
+ //# sourceMappingURL=chunk-4F3W4CSC.ts.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/settings-management.ts"],
4
+ "sourcesContent": ["import {\n\teffectiveSyncSetupRemoteIdentity,\n\tlocalConfigPath,\n\tnormalizeSyncInclude,\n\ttype SyncSetupStorageReview,\n\tsyncSetupStorageReview,\n\tupdateLocalConfig,\n\tvalidateConfigName,\n} from \"./config.js\";\nimport type { PiSyncSettingsV3, StorageConnectionSettings, SyncSetupSettings } from \"./types.js\";\n\nexport class SyncSetupReviewChangedError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"SyncSetupReviewChangedError\";\n\t}\n}\n\nexport async function saveNewV3Settings(\n\tinput: {\n\t\tsetupName: string;\n\t\tconnectionName: string;\n\t\tconnection: StorageConnectionSettings;\n\t\tsetup: SyncSetupSettings;\n\t},\n\tsignal?: AbortSignal,\n) {\n\tvalidateConfigName(input.setupName, \"sync setup\");\n\tvalidateConfigName(input.connectionName, \"storage connection\");\n\tconst settings: PiSyncSettingsV3 = {\n\t\tversion: 3,\n\t\tactiveSyncSetup: input.setupName,\n\t\tonSwitch: \"ask-before-pull\",\n\t\tstorageConnections: { [input.connectionName]: structuredClone(input.connection) },\n\t\tsyncSetups: {\n\t\t\t[input.setupName]: {\n\t\t\t\t...structuredClone(input.setup),\n\t\t\t\tstorage: { ...input.setup.storage, connection: input.connectionName },\n\t\t\t},\n\t\t},\n\t};\n\tawait updateLocalConfig((current) => {\n\t\tif (Object.keys(current.storageConnections).length || Object.keys(current.syncSetups).length) {\n\t\t\tthrow new Error(`Settings already exist: ${localConfigPath()}`);\n\t\t}\n\t\treturn settings;\n\t}, signal);\n\treturn settings;\n}\n\nexport async function addStorageConnection(\n\tname: string,\n\tconnection: StorageConnectionSettings,\n\tsignal?: AbortSignal,\n) {\n\tvalidateConfigName(name, \"storage connection\");\n\tawait updateSettings((settings) => {\n\t\tif (Object.hasOwn(settings.storageConnections, name)) {\n\t\t\tthrow new Error(`Storage connection already exists: ${name}`);\n\t\t}\n\t\treturn {\n\t\t\t...settings,\n\t\t\tstorageConnections: {\n\t\t\t\t...settings.storageConnections,\n\t\t\t\t[name]: structuredClone(connection),\n\t\t\t},\n\t\t};\n\t}, signal);\n}\n\nexport async function updateStorageConnection(\n\tname: string,\n\tupdate: (connection: StorageConnectionSettings) => StorageConnectionSettings,\n\texpectedSetups?: readonly string[],\n\tsignal?: AbortSignal,\n) {\n\tvalidateConfigName(name, \"storage connection\");\n\tawait updateSettings((settings) => {\n\t\tconst connection = settings.storageConnections[name];\n\t\tif (!connection) throw new Error(`Storage connection not found: ${name}`);\n\t\tconst currentSetups = referencingSetupNames(settings.syncSetups, name);\n\t\tif (expectedSetups && !sameNames(currentSetups, expectedSetups)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Storage connection \u201C${name}\u201D usage changed while it was open; reopen it and review the affected sync setups.`,\n\t\t\t);\n\t\t}\n\t\tconst nextConnection = update(structuredClone(connection));\n\t\tconst nextConnections = { ...settings.storageConnections, [name]: nextConnection };\n\t\tassertUniqueLocations(settings.syncSetups, nextConnections);\n\t\treturn { ...settings, storageConnections: nextConnections };\n\t}, signal);\n}\n\nexport async function addSyncSetup(name: string, setup: SyncSetupSettings, signal?: AbortSignal) {\n\tvalidateConfigName(name, \"sync setup\");\n\tawait updateSettings((settings) => {\n\t\tif (Object.hasOwn(settings.syncSetups, name))\n\t\t\tthrow new Error(`Sync setup already exists: ${name}`);\n\t\tif (!Object.hasOwn(settings.storageConnections, setup.storage.connection)) {\n\t\t\tthrow new Error(`Storage connection not found: ${setup.storage.connection}`);\n\t\t}\n\t\tconst nextSetups = { ...settings.syncSetups, [name]: structuredClone(setup) };\n\t\tassertUniqueLocations(nextSetups, settings.storageConnections);\n\t\treturn {\n\t\t\t...settings,\n\t\t\tsyncSetups: nextSetups,\n\t\t\t...(settings.activeSyncSetup ? {} : { activeSyncSetup: name }),\n\t\t};\n\t}, signal);\n}\n\nexport async function updateSyncSetup(\n\tname: string,\n\tupdate: (setup: SyncSetupSettings) => SyncSetupSettings,\n\toptions: {\n\t\texpectedStorage?: SyncSetupStorageReview;\n\t\texpectedInclude?: readonly string[];\n\t\tsignal?: AbortSignal;\n\t} = {},\n) {\n\tvalidateConfigName(name, \"sync setup\");\n\tawait updateSettings((settings) => {\n\t\tconst setup = settings.syncSetups[name];\n\t\tif (!setup) throw new Error(`Sync setup not found: ${name}`);\n\t\tif (\n\t\t\toptions.expectedInclude &&\n\t\t\t!sameNames(normalizeSyncInclude(setup.sync.include), options.expectedInclude)\n\t\t) {\n\t\t\tthrow new SyncSetupReviewChangedError(\n\t\t\t\t`Sync setup \u201C${name}\u201D included content changed while it was open; reopen it and review the current selection.`,\n\t\t\t);\n\t\t}\n\t\tif (options.expectedStorage) {\n\t\t\tconst connectionName = setup.storage.connection;\n\t\t\tconst connection = settings.storageConnections[connectionName];\n\t\t\tif (\n\t\t\t\t!connection ||\n\t\t\t\t!sameStorageReview(\n\t\t\t\t\tsyncSetupStorageReview(name, setup, connectionName, connection),\n\t\t\t\t\toptions.expectedStorage,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthrow new SyncSetupReviewChangedError(\n\t\t\t\t\t`Sync setup \u201C${name}\u201D storage changed while it was open; reopen it and review the current storage location.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tconst nextSetup = update(structuredClone(setup));\n\t\tif (!Object.hasOwn(settings.storageConnections, nextSetup.storage.connection)) {\n\t\t\tthrow new Error(`Storage connection not found: ${nextSetup.storage.connection}`);\n\t\t}\n\t\tconst nextSetups = { ...settings.syncSetups, [name]: nextSetup };\n\t\tassertUniqueLocations(nextSetups, settings.storageConnections);\n\t\treturn { ...settings, syncSetups: nextSetups };\n\t}, options.signal);\n}\n\nexport async function removeSyncSetup(name: string, signal?: AbortSignal) {\n\tvalidateConfigName(name, \"sync setup\");\n\tawait updateSettings((settings) => {\n\t\tif (!Object.hasOwn(settings.syncSetups, name)) throw new Error(`Sync setup not found: ${name}`);\n\t\tconst isCurrent = settings.activeSyncSetup === name;\n\t\tif (isCurrent && Object.keys(settings.syncSetups).length > 1) {\n\t\t\tthrow new Error(\"Switch to another sync setup before removing the current setup.\");\n\t\t}\n\t\tconst syncSetups = { ...settings.syncSetups };\n\t\tdelete syncSetups[name];\n\t\tconst next = { ...settings, syncSetups };\n\t\tif (isCurrent) delete next.activeSyncSetup;\n\t\treturn next;\n\t}, signal);\n}\n\nexport async function removeStorageConnection(name: string, signal?: AbortSignal) {\n\tvalidateConfigName(name, \"storage connection\");\n\tawait updateSettings((settings) => {\n\t\tconst referenced = referencingSetupNames(settings.syncSetups, name)[0];\n\t\tif (referenced) {\n\t\t\tthrow new Error(`Storage connection \u201C${name}\u201D is used by sync setup \u201C${referenced}\u201D.`);\n\t\t}\n\t\tif (!Object.hasOwn(settings.storageConnections, name)) {\n\t\t\tthrow new Error(`Storage connection not found: ${name}`);\n\t\t}\n\t\tconst storageConnections = { ...settings.storageConnections };\n\t\tdelete storageConnections[name];\n\t\treturn { ...settings, storageConnections };\n\t}, signal);\n}\n\nasync function updateSettings(\n\tupdate: (settings: PiSyncSettingsV3) => PiSyncSettingsV3,\n\tsignal?: AbortSignal,\n) {\n\treturn updateLocalConfig((settings) => {\n\t\tif (settings.version !== 3) {\n\t\t\tthrow new Error(\"Storage connections and sync setups require version 3 pi-sync settings.\");\n\t\t}\n\t\treturn update(settings);\n\t}, signal);\n}\n\nfunction referencingSetupNames(setups: Record<string, SyncSetupSettings>, connection: string) {\n\treturn Object.entries(setups)\n\t\t.filter(([, setup]) => setup.storage.connection === connection)\n\t\t.map(([name]) => name)\n\t\t.sort((left, right) => left.localeCompare(right));\n}\n\nfunction assertUniqueLocations(\n\tsetups: Record<string, SyncSetupSettings>,\n\tconnections: Record<string, StorageConnectionSettings>,\n) {\n\tconst identities = new Map<string, string>();\n\tfor (const [name, setup] of Object.entries(setups)) {\n\t\tconst connection = connections[setup.storage.connection];\n\t\tif (!connection) throw new Error(`Storage connection not found: ${setup.storage.connection}`);\n\t\tconst identity = effectiveSyncSetupRemoteIdentity(setup, connection);\n\t\tconst previous = identities.get(identity);\n\t\tif (previous) {\n\t\t\tthrow new Error(`Sync setup \u201C${name}\u201D duplicates the storage location of \u201C${previous}\u201D.`);\n\t\t}\n\t\tidentities.set(identity, name);\n\t}\n}\n\nfunction sameNames(left: readonly string[], right: readonly string[]) {\n\treturn left.length === right.length && left.every((name, index) => name === right[index]);\n}\n\nfunction sameStorageReview(left: SyncSetupStorageReview, right: SyncSetupStorageReview) {\n\treturn (\n\t\tleft.connectionName === right.connectionName &&\n\t\tleft.storageKind === right.storageKind &&\n\t\tleft.storagePath === right.storagePath &&\n\t\tleft.bucket === right.bucket &&\n\t\tleft.branch === right.branch\n\t);\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,221 @@
1
+ // @generated by scripts/build-runtime.mjs; do not edit.
2
+ // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
+
4
+ // src/command.ts
5
+ var YES_FLAG_COMPLETIONS = [
6
+ { value: "--yes", label: "--yes", description: "Skip confirmation prompts" },
7
+ { value: "-y", label: "-y", description: "Skip confirmation prompts" }
8
+ ];
9
+ var SYNC_COMMANDS = [
10
+ { name: "help", description: "Show command usage" },
11
+ { name: "use", description: "Switch the current sync setup", usageSuffix: " <setup>" },
12
+ { name: "init", description: "Create local config template" },
13
+ { name: "config", description: "Show resolved configuration" },
14
+ { name: "files", description: "Choose included content" },
15
+ { name: "status", description: "Show sync status" },
16
+ { name: "diff", description: "Show local/remote diff" },
17
+ { name: "doctor", description: "Check config, secrets, and lock state" },
18
+ { name: "push", description: "Upload local settings" },
19
+ { name: "pull", description: "Apply remote settings" },
20
+ { name: "sync", description: "Push or pull as needed" },
21
+ { name: "history", description: "Show recent remote snapshots" },
22
+ { name: "rollback", description: "Apply a previous snapshot", usageSuffix: " <snapshot>" },
23
+ { name: "migrate-state", description: "Move legacy state into pi-sync/" },
24
+ { name: "unlock", description: "Remove a stale local lock", usageSuffix: " --stale" }
25
+ ];
26
+ var SYNC_COMMAND_COMPLETIONS = SYNC_COMMANDS.map(
27
+ ({ name, description }) => ({ value: name, label: name, description })
28
+ );
29
+ var setupCompletionNames = [];
30
+ function setSyncSetupCompletions(names) {
31
+ setupCompletionNames = [...new Set(names)].sort((left, right) => left.localeCompare(right));
32
+ }
33
+ var SETUP_FLAG_COMPLETION = {
34
+ value: "--setup",
35
+ label: "--setup",
36
+ description: "Address a sync setup without switching"
37
+ };
38
+ var SYNC_FLAG_COMPLETIONS = {
39
+ config: [SETUP_FLAG_COMPLETION],
40
+ files: [SETUP_FLAG_COMPLETION],
41
+ status: [SETUP_FLAG_COMPLETION],
42
+ diff: [SETUP_FLAG_COMPLETION],
43
+ doctor: [SETUP_FLAG_COMPLETION],
44
+ push: [
45
+ ...YES_FLAG_COMPLETIONS,
46
+ { value: "--force", label: "--force", description: "Overwrite visible remote changes" },
47
+ SETUP_FLAG_COMPLETION
48
+ ],
49
+ pull: [
50
+ ...YES_FLAG_COMPLETIONS,
51
+ { value: "--force", label: "--force", description: "Overwrite local changes" },
52
+ SETUP_FLAG_COMPLETION
53
+ ],
54
+ sync: [
55
+ ...YES_FLAG_COMPLETIONS,
56
+ { value: "--force", label: "--force", description: "Resolve conflicts by forcing action" },
57
+ SETUP_FLAG_COMPLETION
58
+ ],
59
+ history: [SETUP_FLAG_COMPLETION],
60
+ rollback: [...YES_FLAG_COMPLETIONS, SETUP_FLAG_COMPLETION],
61
+ "migrate-state": YES_FLAG_COMPLETIONS,
62
+ unlock: [{ value: "--stale", label: "--stale", description: "Remove only a stale lock" }]
63
+ };
64
+ function splitArgs(input) {
65
+ return input.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g)?.map((arg) => arg.replace(/^['"]|['"]$/g, "")) ?? [];
66
+ }
67
+ function parseOptions(args) {
68
+ const values = [];
69
+ let yes = false;
70
+ let force = false;
71
+ let stale = false;
72
+ let setup;
73
+ for (let index = 0; index < args.length; index += 1) {
74
+ const arg = args[index];
75
+ if (arg === "--yes" || arg === "-y") yes = true;
76
+ else if (arg === "--force") force = true;
77
+ else if (arg === "--stale") stale = true;
78
+ else if (arg === "--setup") {
79
+ const name = args[index + 1];
80
+ if (!name || name.startsWith("-")) throw new Error("--setup requires a sync setup name.");
81
+ if (setup !== void 0) throw new Error("--setup may be provided only once.");
82
+ setup = name;
83
+ index += 1;
84
+ } else if (arg.startsWith("-")) {
85
+ throw new Error(`Unknown sync option: ${arg}`);
86
+ } else values.push(arg);
87
+ }
88
+ return {
89
+ yes,
90
+ force,
91
+ stale,
92
+ silent: false,
93
+ reload: true,
94
+ auto: false,
95
+ ...setup === void 0 ? {} : { setup },
96
+ args: values
97
+ };
98
+ }
99
+ function validateCommandOptions(command, options) {
100
+ const setupAllowed = /* @__PURE__ */ new Set([
101
+ "config",
102
+ "files",
103
+ "status",
104
+ "diff",
105
+ "doctor",
106
+ "push",
107
+ "pull",
108
+ "sync",
109
+ "history",
110
+ "rollback"
111
+ ]);
112
+ if (options.setup && !setupAllowed.has(command)) {
113
+ throw new Error(`--setup is not supported by /sync ${command}.`);
114
+ }
115
+ if (options.yes && !["push", "pull", "sync", "rollback", "migrate-state"].includes(command)) {
116
+ throw new Error(`Confirmation/force options are not supported by /sync ${command}.`);
117
+ }
118
+ if (options.force && !["push", "pull", "sync", "rollback"].includes(command)) {
119
+ throw new Error(`Confirmation/force options are not supported by /sync ${command}.`);
120
+ }
121
+ if (options.stale && command !== "unlock") {
122
+ throw new Error(`--stale is not supported by /sync ${command}.`);
123
+ }
124
+ const expectedValues = command === "rollback" || command === "use" ? 1 : 0;
125
+ if (options.args.length !== expectedValues) {
126
+ if (command === "rollback")
127
+ throw new Error("Usage: /sync rollback <snapshot-id> [--yes] [--setup <name>]");
128
+ if (command === "use") throw new Error("Usage: /sync use <setup>");
129
+ throw new Error(`Unexpected argument for /sync ${command}: ${options.args.join(" ")}`);
130
+ }
131
+ }
132
+ function completeSyncArguments(argumentPrefix) {
133
+ const prefix = argumentPrefix.trimStart();
134
+ if (prefix === "") return [...SYNC_COMMAND_COMPLETIONS];
135
+ const trailingSpace = /\s$/.test(prefix);
136
+ const tokens = splitArgs(prefix);
137
+ if (tokens.length === 0) return [...SYNC_COMMAND_COMPLETIONS];
138
+ const [command] = tokens;
139
+ if (tokens.length === 1 && !trailingSpace) {
140
+ const matches2 = SYNC_COMMAND_COMPLETIONS.filter((item) => item.value.startsWith(command));
141
+ return matches2.length > 0 ? [...matches2] : null;
142
+ }
143
+ const args = tokens.slice(1);
144
+ if (command === "use") {
145
+ if (args.length > 1 || trailingSpace && args.length > 0) return null;
146
+ return completeSetupValue(prefix, trailingSpace ? "" : args[0] ?? "");
147
+ }
148
+ const setupFlagIndex = args.lastIndexOf("--setup");
149
+ if (setupFlagIndex >= 0 && setupFlagIndex === args.length - (trailingSpace ? 1 : 2)) {
150
+ const currentSetup = trailingSpace ? "" : args.at(-1) ?? "";
151
+ if (!currentSetup.startsWith("-")) return completeSetupValue(prefix, currentSetup);
152
+ }
153
+ const flagCompletions = SYNC_FLAG_COMPLETIONS[command];
154
+ if (!flagCompletions) return null;
155
+ const completedArgs = trailingSpace ? args : args.slice(0, -1);
156
+ const completedValues = completedArgs.filter((arg) => !arg.startsWith("-"));
157
+ if (command === "rollback" ? completedValues.length > 1 : completedValues.length > 0) {
158
+ return null;
159
+ }
160
+ const current = trailingSpace ? "" : args.at(-1) ?? "";
161
+ if (current && !current.startsWith("-")) return null;
162
+ const currentRaw = trailingSpace ? "" : prefix.match(/\S+$/)?.[0] ?? "";
163
+ const completionPrefix = trailingSpace ? prefix : prefix.slice(0, prefix.length - currentRaw.length);
164
+ const matches = flagCompletions.filter((item) => item.value.startsWith(current));
165
+ return matches.length > 0 ? matches.map((item) => ({ ...item, value: `${completionPrefix}${item.value}` })) : null;
166
+ }
167
+ function completeSetupValue(prefix, current) {
168
+ const currentRaw = current ? prefix.match(/\S+$/u)?.[0] ?? "" : "";
169
+ const completionPrefix = currentRaw ? prefix.slice(0, prefix.length - currentRaw.length) : prefix;
170
+ const matches = setupCompletionNames.filter((name) => name.startsWith(current));
171
+ return matches.length > 0 ? matches.map((name) => ({
172
+ value: `${completionPrefix}${name}`,
173
+ label: name,
174
+ description: "Sync setup"
175
+ })) : null;
176
+ }
177
+ function syncMenuOptions() {
178
+ return SYNC_COMMANDS.map(({ name, description }) => `${name} \u2014 ${description}`);
179
+ }
180
+ function syncCommandFromMenuOption(option) {
181
+ return SYNC_COMMANDS.find(({ name, description }) => option === `${name} \u2014 ${description}`)?.name;
182
+ }
183
+ async function resolveSyncCommand(input, ctx) {
184
+ const [subcommand, ...rest] = splitArgs(input);
185
+ if (subcommand) return { subcommand, rest };
186
+ if (!ctx.hasUI) {
187
+ ctx.ui.notify(usage(), "info");
188
+ return void 0;
189
+ }
190
+ const selectedOption = await ctx.ui.select("pi-sync", syncMenuOptions());
191
+ const selected = selectedOption ? syncCommandFromMenuOption(selectedOption) : void 0;
192
+ if (!selected) return void 0;
193
+ if (selected !== "rollback") return { subcommand: selected, rest: [] };
194
+ const target = (await ctx.ui.input("Rollback snapshot", "snapshot id"))?.trim();
195
+ if (!target) {
196
+ ctx.ui.notify("Rollback cancelled.", "info");
197
+ return void 0;
198
+ }
199
+ return { subcommand: selected, rest: [target] };
200
+ }
201
+ function usage() {
202
+ const commands = SYNC_COMMANDS.map(
203
+ (command) => `${command.name}${"usageSuffix" in command ? command.usageSuffix : ""}`
204
+ ).join(", ");
205
+ return [
206
+ "Usage: /sync <command>",
207
+ `Commands: ${commands}`,
208
+ "Settings: use /sync init or edit storage connections and sync setups in ~/.pi/agent/pi-sync.json (or the configured Pi agent directory). Version 1 and version 2 settings are unsupported and are never rewritten."
209
+ ].join("\n");
210
+ }
211
+
212
+ export {
213
+ setSyncSetupCompletions,
214
+ splitArgs,
215
+ parseOptions,
216
+ validateCommandOptions,
217
+ completeSyncArguments,
218
+ resolveSyncCommand,
219
+ usage
220
+ };
221
+ //# sourceMappingURL=chunk-4U6AFLJB.ts.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/command.ts"],
4
+ "sourcesContent": ["import type { ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport type { CommandArgumentCompletion, CommandOptions } from \"./types.js\";\n\nconst YES_FLAG_COMPLETIONS: readonly CommandArgumentCompletion[] = [\n\t{ value: \"--yes\", label: \"--yes\", description: \"Skip confirmation prompts\" },\n\t{ value: \"-y\", label: \"-y\", description: \"Skip confirmation prompts\" },\n];\nexport const SYNC_COMMANDS = [\n\t{ name: \"help\", description: \"Show command usage\" },\n\t{ name: \"use\", description: \"Switch the current sync setup\", usageSuffix: \" <setup>\" },\n\t{ name: \"init\", description: \"Create local config template\" },\n\t{ name: \"config\", description: \"Show resolved configuration\" },\n\t{ name: \"files\", description: \"Choose included content\" },\n\t{ name: \"status\", description: \"Show sync status\" },\n\t{ name: \"diff\", description: \"Show local/remote diff\" },\n\t{ name: \"doctor\", description: \"Check config, secrets, and lock state\" },\n\t{ name: \"push\", description: \"Upload local settings\" },\n\t{ name: \"pull\", description: \"Apply remote settings\" },\n\t{ name: \"sync\", description: \"Push or pull as needed\" },\n\t{ name: \"history\", description: \"Show recent remote snapshots\" },\n\t{ name: \"rollback\", description: \"Apply a previous snapshot\", usageSuffix: \" <snapshot>\" },\n\t{ name: \"migrate-state\", description: \"Move legacy state into pi-sync/\" },\n\t{ name: \"unlock\", description: \"Remove a stale local lock\", usageSuffix: \" --stale\" },\n] as const;\n\nexport type SyncCommandName = (typeof SYNC_COMMANDS)[number][\"name\"];\n\nconst SYNC_COMMAND_COMPLETIONS: readonly CommandArgumentCompletion[] = SYNC_COMMANDS.map(\n\t({ name, description }) => ({ value: name, label: name, description }),\n);\nlet setupCompletionNames: string[] = [];\n\nexport function setSyncSetupCompletions(names: readonly string[]) {\n\tsetupCompletionNames = [...new Set(names)].sort((left, right) => left.localeCompare(right));\n}\nconst SETUP_FLAG_COMPLETION = {\n\tvalue: \"--setup\",\n\tlabel: \"--setup\",\n\tdescription: \"Address a sync setup without switching\",\n} as const;\nconst SYNC_FLAG_COMPLETIONS: Record<string, readonly CommandArgumentCompletion[]> = {\n\tconfig: [SETUP_FLAG_COMPLETION],\n\tfiles: [SETUP_FLAG_COMPLETION],\n\tstatus: [SETUP_FLAG_COMPLETION],\n\tdiff: [SETUP_FLAG_COMPLETION],\n\tdoctor: [SETUP_FLAG_COMPLETION],\n\tpush: [\n\t\t...YES_FLAG_COMPLETIONS,\n\t\t{ value: \"--force\", label: \"--force\", description: \"Overwrite visible remote changes\" },\n\t\tSETUP_FLAG_COMPLETION,\n\t],\n\tpull: [\n\t\t...YES_FLAG_COMPLETIONS,\n\t\t{ value: \"--force\", label: \"--force\", description: \"Overwrite local changes\" },\n\t\tSETUP_FLAG_COMPLETION,\n\t],\n\tsync: [\n\t\t...YES_FLAG_COMPLETIONS,\n\t\t{ value: \"--force\", label: \"--force\", description: \"Resolve conflicts by forcing action\" },\n\t\tSETUP_FLAG_COMPLETION,\n\t],\n\thistory: [SETUP_FLAG_COMPLETION],\n\trollback: [...YES_FLAG_COMPLETIONS, SETUP_FLAG_COMPLETION],\n\t\"migrate-state\": YES_FLAG_COMPLETIONS,\n\tunlock: [{ value: \"--stale\", label: \"--stale\", description: \"Remove only a stale lock\" }],\n};\n\nexport function splitArgs(input: string) {\n\treturn (\n\t\tinput.match(/(?:[^\\s\"']+|\"[^\"]*\"|'[^']*')+/g)?.map((arg) => arg.replace(/^['\"]|['\"]$/g, \"\")) ??\n\t\t[]\n\t);\n}\n\nexport function parseOptions(args: string[]): CommandOptions {\n\tconst values: string[] = [];\n\tlet yes = false;\n\tlet force = false;\n\tlet stale = false;\n\tlet setup: string | undefined;\n\tfor (let index = 0; index < args.length; index += 1) {\n\t\tconst arg = args[index];\n\t\tif (arg === \"--yes\" || arg === \"-y\") yes = true;\n\t\telse if (arg === \"--force\") force = true;\n\t\telse if (arg === \"--stale\") stale = true;\n\t\telse if (arg === \"--setup\") {\n\t\t\tconst name = args[index + 1];\n\t\t\tif (!name || name.startsWith(\"-\")) throw new Error(\"--setup requires a sync setup name.\");\n\t\t\tif (setup !== undefined) throw new Error(\"--setup may be provided only once.\");\n\t\t\tsetup = name;\n\t\t\tindex += 1;\n\t\t} else if (arg.startsWith(\"-\")) {\n\t\t\tthrow new Error(`Unknown sync option: ${arg}`);\n\t\t} else values.push(arg);\n\t}\n\treturn {\n\t\tyes,\n\t\tforce,\n\t\tstale,\n\t\tsilent: false,\n\t\treload: true,\n\t\tauto: false,\n\t\t...(setup === undefined ? {} : { setup }),\n\t\targs: values,\n\t};\n}\n\nexport function validateCommandOptions(command: string, options: CommandOptions) {\n\tconst setupAllowed = new Set([\n\t\t\"config\",\n\t\t\"files\",\n\t\t\"status\",\n\t\t\"diff\",\n\t\t\"doctor\",\n\t\t\"push\",\n\t\t\"pull\",\n\t\t\"sync\",\n\t\t\"history\",\n\t\t\"rollback\",\n\t]);\n\tif (options.setup && !setupAllowed.has(command)) {\n\t\tthrow new Error(`--setup is not supported by /sync ${command}.`);\n\t}\n\tif (options.yes && ![\"push\", \"pull\", \"sync\", \"rollback\", \"migrate-state\"].includes(command)) {\n\t\tthrow new Error(`Confirmation/force options are not supported by /sync ${command}.`);\n\t}\n\tif (options.force && ![\"push\", \"pull\", \"sync\", \"rollback\"].includes(command)) {\n\t\tthrow new Error(`Confirmation/force options are not supported by /sync ${command}.`);\n\t}\n\tif (options.stale && command !== \"unlock\") {\n\t\tthrow new Error(`--stale is not supported by /sync ${command}.`);\n\t}\n\tconst expectedValues = command === \"rollback\" || command === \"use\" ? 1 : 0;\n\tif (options.args.length !== expectedValues) {\n\t\tif (command === \"rollback\")\n\t\t\tthrow new Error(\"Usage: /sync rollback <snapshot-id> [--yes] [--setup <name>]\");\n\t\tif (command === \"use\") throw new Error(\"Usage: /sync use <setup>\");\n\t\tthrow new Error(`Unexpected argument for /sync ${command}: ${options.args.join(\" \")}`);\n\t}\n}\n\nexport function completeSyncArguments(argumentPrefix: string): CommandArgumentCompletion[] | null {\n\tconst prefix = argumentPrefix.trimStart();\n\tif (prefix === \"\") return [...SYNC_COMMAND_COMPLETIONS];\n\n\tconst trailingSpace = /\\s$/.test(prefix);\n\tconst tokens = splitArgs(prefix);\n\tif (tokens.length === 0) return [...SYNC_COMMAND_COMPLETIONS];\n\n\tconst [command] = tokens;\n\tif (tokens.length === 1 && !trailingSpace) {\n\t\tconst matches = SYNC_COMMAND_COMPLETIONS.filter((item) => item.value.startsWith(command));\n\t\treturn matches.length > 0 ? [...matches] : null;\n\t}\n\n\tconst args = tokens.slice(1);\n\tif (command === \"use\") {\n\t\tif (args.length > 1 || (trailingSpace && args.length > 0)) return null;\n\t\treturn completeSetupValue(prefix, trailingSpace ? \"\" : (args[0] ?? \"\"));\n\t}\n\tconst setupFlagIndex = args.lastIndexOf(\"--setup\");\n\tif (setupFlagIndex >= 0 && setupFlagIndex === args.length - (trailingSpace ? 1 : 2)) {\n\t\tconst currentSetup = trailingSpace ? \"\" : (args.at(-1) ?? \"\");\n\t\tif (!currentSetup.startsWith(\"-\")) return completeSetupValue(prefix, currentSetup);\n\t}\n\n\tconst flagCompletions = SYNC_FLAG_COMPLETIONS[command];\n\tif (!flagCompletions) return null;\n\n\tconst completedArgs = trailingSpace ? args : args.slice(0, -1);\n\tconst completedValues = completedArgs.filter((arg) => !arg.startsWith(\"-\"));\n\tif (command === \"rollback\" ? completedValues.length > 1 : completedValues.length > 0) {\n\t\treturn null;\n\t}\n\n\tconst current = trailingSpace ? \"\" : (args.at(-1) ?? \"\");\n\tif (current && !current.startsWith(\"-\")) return null;\n\n\tconst currentRaw = trailingSpace ? \"\" : (prefix.match(/\\S+$/)?.[0] ?? \"\");\n\tconst completionPrefix = trailingSpace\n\t\t? prefix\n\t\t: prefix.slice(0, prefix.length - currentRaw.length);\n\tconst matches = flagCompletions.filter((item) => item.value.startsWith(current));\n\treturn matches.length > 0\n\t\t? matches.map((item) => ({ ...item, value: `${completionPrefix}${item.value}` }))\n\t\t: null;\n}\n\nfunction completeSetupValue(prefix: string, current: string) {\n\tconst currentRaw = current ? (prefix.match(/\\S+$/u)?.[0] ?? \"\") : \"\";\n\tconst completionPrefix = currentRaw ? prefix.slice(0, prefix.length - currentRaw.length) : prefix;\n\tconst matches = setupCompletionNames.filter((name) => name.startsWith(current));\n\treturn matches.length > 0\n\t\t? matches.map((name) => ({\n\t\t\t\tvalue: `${completionPrefix}${name}`,\n\t\t\t\tlabel: name,\n\t\t\t\tdescription: \"Sync setup\",\n\t\t\t}))\n\t\t: null;\n}\n\nexport function syncMenuOptions() {\n\treturn SYNC_COMMANDS.map(({ name, description }) => `${name} \u2014 ${description}`);\n}\n\nexport function syncCommandFromMenuOption(option: string): SyncCommandName | undefined {\n\treturn SYNC_COMMANDS.find(({ name, description }) => option === `${name} \u2014 ${description}`)?.name;\n}\n\nexport async function resolveSyncCommand(input: string, ctx: ExtensionCommandContext) {\n\tconst [subcommand, ...rest] = splitArgs(input);\n\tif (subcommand) return { subcommand, rest };\n\tif (!ctx.hasUI) {\n\t\tctx.ui.notify(usage(), \"info\");\n\t\treturn undefined;\n\t}\n\n\tconst selectedOption = await ctx.ui.select(\"pi-sync\", syncMenuOptions());\n\tconst selected = selectedOption ? syncCommandFromMenuOption(selectedOption) : undefined;\n\tif (!selected) return undefined;\n\tif (selected !== \"rollback\") return { subcommand: selected, rest: [] };\n\n\tconst target = (await ctx.ui.input(\"Rollback snapshot\", \"snapshot id\"))?.trim();\n\tif (!target) {\n\t\tctx.ui.notify(\"Rollback cancelled.\", \"info\");\n\t\treturn undefined;\n\t}\n\treturn { subcommand: selected, rest: [target] };\n}\n\nexport function usage() {\n\tconst commands = SYNC_COMMANDS.map(\n\t\t(command) => `${command.name}${\"usageSuffix\" in command ? command.usageSuffix : \"\"}`,\n\t).join(\", \");\n\treturn [\n\t\t\"Usage: /sync <command>\",\n\t\t`Commands: ${commands}`,\n\t\t\"Settings: use /sync init or edit storage connections and sync setups in ~/.pi/agent/pi-sync.json (or the configured Pi agent directory). Version 1 and version 2 settings are unsupported and are never rewritten.\",\n\t].join(\"\\n\");\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["matches"]
7
+ }
@@ -0,0 +1,34 @@
1
+ // @generated by scripts/build-runtime.mjs; do not edit.
2
+ // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
+
4
+ // src/sync-backend.ts
5
+ var SyncBackendConflictError = class extends Error {
6
+ code = "SYNC_BACKEND_CONFLICT";
7
+ phase;
8
+ currentHead;
9
+ candidateMayHaveBeenActive;
10
+ constructor(message, options = {}) {
11
+ super(message, options);
12
+ this.name = "SyncBackendConflictError";
13
+ this.phase = options.phase ?? "before-commit";
14
+ this.currentHead = options.currentHead;
15
+ this.candidateMayHaveBeenActive = options.candidateMayHaveBeenActive ?? false;
16
+ }
17
+ };
18
+ var SyncBackendPublicationOutcomeUnknownError = class extends Error {
19
+ code = "SYNC_BACKEND_PUBLICATION_OUTCOME_UNKNOWN";
20
+ constructor(message, options) {
21
+ super(message, options);
22
+ this.name = "SyncBackendPublicationOutcomeUnknownError";
23
+ }
24
+ };
25
+ function expectedRemoteHead(head) {
26
+ return head ? { kind: "revision", revision: head.revision } : { kind: "missing" };
27
+ }
28
+
29
+ export {
30
+ SyncBackendConflictError,
31
+ SyncBackendPublicationOutcomeUnknownError,
32
+ expectedRemoteHead
33
+ };
34
+ //# sourceMappingURL=chunk-5MQ76BK5.ts.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/sync-backend.ts"],
4
+ "sourcesContent": ["import type { Snapshot, SnapshotSelection } from \"./types.js\";\n\nexport type PublicationCapability =\n\t| \"read-check-write-verify\"\n\t| \"conditional-required\"\n\t| \"atomic-conditional\"\n\t| \"lease-protected\";\n\nexport interface RemoteHead {\n\t/** Backend-owned reference used only to retrieve this immutable snapshot. */\n\tsnapshotRef: string;\n\t/** Backend-neutral snapshot content identity retained in local sync state. */\n\tsnapshotId: string;\n\trevision: string;\n\tcreatedAt: string;\n\tmachine: string;\n\tsyncSessions: boolean;\n\t/** Validated lightweight projection; revalidate it against the immutable snapshot before adoption. */\n\tselection?: SnapshotSelection;\n}\n\nexport interface RemoteHistoryEntry {\n\tsnapshotRef: string;\n\tsnapshotId: string;\n\tcreatedAt: string;\n\tmachine: string;\n\tsyncSessions: boolean;\n}\n\nexport type ExpectedRemoteHead = { kind: \"missing\" } | { kind: \"revision\"; revision: string };\n\nexport interface PublishSnapshotOptions {\n\tsignal?: AbortSignal;\n\t/** Called at the backend's active-head commit boundary. */\n\tonCommit?: () => void;\n}\n\nexport interface PublishSnapshotResult {\n\thead: RemoteHead;\n\twarnings: string[];\n}\n\nexport interface BackendDiagnostic {\n\tkey: string;\n\tlevel: \"info\" | \"warning\" | \"error\";\n\tmessage: string;\n}\n\nexport interface SyncBackend {\n\treadonly identity: string;\n\treadonly destination: string;\n\treadonly capability: PublicationCapability;\n\t/** Compare opaque revisions produced by this backend identity. */\n\tsameRevision(left: string, right: string): boolean;\n\treadHead(signal?: AbortSignal): Promise<RemoteHead | undefined>;\n\treadSnapshot(reference: string, signal?: AbortSignal): Promise<Snapshot>;\n\tpublishSnapshot(\n\t\tsnapshot: Snapshot,\n\t\texpected: ExpectedRemoteHead,\n\t\toptions?: PublishSnapshotOptions,\n\t): Promise<PublishSnapshotResult>;\n\tlistHistory(signal?: AbortSignal): Promise<RemoteHistoryEntry[]>;\n\tdiagnose(signal?: AbortSignal): Promise<BackendDiagnostic[]>;\n}\n\nexport class SyncBackendConflictError extends Error {\n\treadonly code = \"SYNC_BACKEND_CONFLICT\";\n\treadonly phase: \"before-commit\" | \"after-commit\";\n\treadonly currentHead?: RemoteHead;\n\treadonly candidateMayHaveBeenActive: boolean;\n\n\tconstructor(\n\t\tmessage: string,\n\t\toptions: ErrorOptions & {\n\t\t\tphase?: \"before-commit\" | \"after-commit\";\n\t\t\tcurrentHead?: RemoteHead;\n\t\t\tcandidateMayHaveBeenActive?: boolean;\n\t\t} = {},\n\t) {\n\t\tsuper(message, options);\n\t\tthis.name = \"SyncBackendConflictError\";\n\t\tthis.phase = options.phase ?? \"before-commit\";\n\t\tthis.currentHead = options.currentHead;\n\t\tthis.candidateMayHaveBeenActive = options.candidateMayHaveBeenActive ?? false;\n\t}\n}\n\nexport class SyncBackendPublicationOutcomeUnknownError extends Error {\n\treadonly code = \"SYNC_BACKEND_PUBLICATION_OUTCOME_UNKNOWN\";\n\n\tconstructor(message: string, options?: ErrorOptions) {\n\t\tsuper(message, options);\n\t\tthis.name = \"SyncBackendPublicationOutcomeUnknownError\";\n\t}\n}\n\nexport function expectedRemoteHead(head: RemoteHead | undefined): ExpectedRemoteHead {\n\treturn head ? { kind: \"revision\", revision: head.revision } : { kind: \"missing\" };\n}\n"],
5
+ "mappings": ";;;;AAiEO,IAAM,2BAAN,cAAuC,MAAM;AAAA,EAC1C,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACC,SACA,UAII,CAAC,GACJ;AACD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AACZ,SAAK,QAAQ,QAAQ,SAAS;AAC9B,SAAK,cAAc,QAAQ;AAC3B,SAAK,6BAA6B,QAAQ,8BAA8B;AAAA,EACzE;AACD;AAEO,IAAM,4CAAN,cAAwD,MAAM;AAAA,EAC3D,OAAO;AAAA,EAEhB,YAAY,SAAiB,SAAwB;AACpD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACb;AACD;AAEO,SAAS,mBAAmB,MAAkD;AACpF,SAAO,OAAO,EAAE,MAAM,YAAY,UAAU,KAAK,SAAS,IAAI,EAAE,MAAM,UAAU;AACjF;",
6
+ "names": []
7
+ }