@tinyrack/devsync 1.1.0 → 1.2.2

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 (216) hide show
  1. package/README.md +230 -62
  2. package/dist/cli/base-command.d.ts +14 -0
  3. package/dist/cli/base-command.d.ts.map +1 -0
  4. package/dist/cli/base-command.js +22 -0
  5. package/dist/cli/base-command.js.map +1 -0
  6. package/dist/cli/commands/dir.d.ts +8 -0
  7. package/dist/cli/commands/dir.d.ts.map +1 -0
  8. package/dist/cli/commands/dir.js +16 -0
  9. package/dist/cli/commands/dir.js.map +1 -0
  10. package/dist/cli/commands/doctor.d.ts +8 -0
  11. package/dist/cli/commands/doctor.d.ts.map +1 -0
  12. package/dist/cli/commands/doctor.js +18 -0
  13. package/dist/cli/commands/doctor.js.map +1 -0
  14. package/dist/cli/commands/index.d.ts +23 -0
  15. package/dist/cli/commands/index.d.ts.map +1 -0
  16. package/dist/cli/commands/index.js +23 -0
  17. package/dist/cli/commands/index.js.map +1 -0
  18. package/dist/cli/commands/init.d.ts +15 -0
  19. package/dist/cli/commands/init.d.ts.map +1 -0
  20. package/dist/cli/commands/init.js +43 -0
  21. package/dist/cli/commands/init.js.map +1 -0
  22. package/dist/cli/commands/machine/list.d.ts +7 -0
  23. package/dist/cli/commands/machine/list.d.ts.map +1 -0
  24. package/dist/cli/commands/machine/list.js +12 -0
  25. package/dist/cli/commands/machine/list.js.map +1 -0
  26. package/dist/cli/commands/machine/use.d.ts +11 -0
  27. package/dist/cli/commands/machine/use.d.ts.map +1 -0
  28. package/dist/cli/commands/machine/use.js +28 -0
  29. package/dist/cli/commands/machine/use.js.map +1 -0
  30. package/dist/cli/commands/pull.d.ts +12 -0
  31. package/dist/cli/commands/pull.d.ts.map +1 -0
  32. package/dist/cli/commands/pull.js +34 -0
  33. package/dist/cli/commands/pull.js.map +1 -0
  34. package/dist/cli/commands/push.d.ts +12 -0
  35. package/dist/cli/commands/push.d.ts.map +1 -0
  36. package/dist/cli/commands/push.js +34 -0
  37. package/dist/cli/commands/push.js.map +1 -0
  38. package/dist/cli/commands/status.d.ts +11 -0
  39. package/dist/cli/commands/status.d.ts.map +1 -0
  40. package/dist/cli/commands/status.js +27 -0
  41. package/dist/cli/commands/status.js.map +1 -0
  42. package/dist/cli/commands/track.d.ts +16 -0
  43. package/dist/cli/commands/track.d.ts.map +1 -0
  44. package/dist/cli/commands/track.js +82 -0
  45. package/dist/cli/commands/track.js.map +1 -0
  46. package/dist/cli/commands/untrack.d.ts +11 -0
  47. package/dist/cli/commands/untrack.d.ts.map +1 -0
  48. package/dist/cli/commands/untrack.js +28 -0
  49. package/dist/cli/commands/untrack.js.map +1 -0
  50. package/dist/config/global-config.d.ts +21 -0
  51. package/dist/config/global-config.d.ts.map +1 -0
  52. package/dist/config/global-config.js +106 -0
  53. package/dist/config/global-config.js.map +1 -0
  54. package/dist/config/sync.d.ts +96 -0
  55. package/dist/config/sync.d.ts.map +1 -0
  56. package/dist/config/sync.js +412 -0
  57. package/dist/config/sync.js.map +1 -0
  58. package/dist/config/xdg.d.ts +11 -0
  59. package/dist/config/xdg.d.ts.map +1 -0
  60. package/dist/config/xdg.js +79 -0
  61. package/dist/config/xdg.js.map +1 -0
  62. package/dist/index.d.ts +3 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/{src/index.ts → dist/index.js} +1 -1
  65. package/dist/index.js.map +1 -0
  66. package/dist/lib/file-mode.d.ts +3 -0
  67. package/dist/lib/file-mode.d.ts.map +1 -0
  68. package/dist/lib/file-mode.js +7 -0
  69. package/dist/lib/file-mode.js.map +1 -0
  70. package/dist/lib/output.d.ts +31 -0
  71. package/dist/lib/output.d.ts.map +1 -0
  72. package/dist/lib/output.js +198 -0
  73. package/dist/lib/output.js.map +1 -0
  74. package/dist/lib/path.d.ts +5 -0
  75. package/dist/lib/path.d.ts.map +1 -0
  76. package/dist/lib/path.js +25 -0
  77. package/dist/lib/path.js.map +1 -0
  78. package/dist/lib/string.d.ts +2 -0
  79. package/dist/lib/string.d.ts.map +1 -0
  80. package/dist/lib/string.js +4 -0
  81. package/dist/lib/string.js.map +1 -0
  82. package/dist/lib/validation.d.ts +3 -0
  83. package/dist/lib/validation.d.ts.map +1 -0
  84. package/dist/lib/validation.js +9 -0
  85. package/dist/lib/validation.js.map +1 -0
  86. package/dist/services/add.d.ts +20 -0
  87. package/dist/services/add.d.ts.map +1 -0
  88. package/dist/services/add.js +161 -0
  89. package/dist/services/add.js.map +1 -0
  90. package/dist/services/config-file.d.ts +30 -0
  91. package/dist/services/config-file.d.ts.map +1 -0
  92. package/dist/services/config-file.js +34 -0
  93. package/dist/services/config-file.js.map +1 -0
  94. package/dist/services/crypto.d.ts +9 -0
  95. package/dist/services/crypto.d.ts.map +1 -0
  96. package/dist/services/crypto.js +75 -0
  97. package/dist/services/crypto.js.map +1 -0
  98. package/dist/services/doctor.d.ts +16 -0
  99. package/dist/services/doctor.d.ts.map +1 -0
  100. package/dist/services/doctor.js +84 -0
  101. package/dist/services/doctor.js.map +1 -0
  102. package/dist/services/error.d.ts +14 -0
  103. package/dist/services/error.d.ts.map +1 -0
  104. package/dist/services/error.js +38 -0
  105. package/dist/services/error.js.map +1 -0
  106. package/dist/services/filesystem.d.ts +15 -0
  107. package/dist/services/filesystem.d.ts.map +1 -0
  108. package/dist/services/filesystem.js +113 -0
  109. package/dist/services/filesystem.js.map +1 -0
  110. package/dist/services/forget.d.ts +14 -0
  111. package/dist/services/forget.d.ts.map +1 -0
  112. package/dist/services/forget.js +124 -0
  113. package/dist/services/forget.js.map +1 -0
  114. package/dist/services/git.d.ts +10 -0
  115. package/dist/services/git.d.ts.map +1 -0
  116. package/dist/services/git.js +57 -0
  117. package/dist/services/git.js.map +1 -0
  118. package/dist/services/init.d.ts +19 -0
  119. package/dist/services/init.d.ts.map +1 -0
  120. package/dist/services/init.js +203 -0
  121. package/dist/services/init.js.map +1 -0
  122. package/dist/services/local-materialization.d.ts +28 -0
  123. package/dist/services/local-materialization.d.ts.map +1 -0
  124. package/dist/services/local-materialization.js +262 -0
  125. package/dist/services/local-materialization.js.map +1 -0
  126. package/dist/services/local-snapshot.d.ts +25 -0
  127. package/dist/services/local-snapshot.d.ts.map +1 -0
  128. package/dist/services/local-snapshot.js +93 -0
  129. package/dist/services/local-snapshot.js.map +1 -0
  130. package/dist/services/machine.d.ts +40 -0
  131. package/dist/services/machine.d.ts.map +1 -0
  132. package/dist/services/machine.js +113 -0
  133. package/dist/services/machine.js.map +1 -0
  134. package/dist/services/paths.d.ts +12 -0
  135. package/dist/services/paths.d.ts.map +1 -0
  136. package/dist/services/paths.js +71 -0
  137. package/dist/services/paths.js.map +1 -0
  138. package/dist/services/pull.d.ts +28 -0
  139. package/dist/services/pull.d.ts.map +1 -0
  140. package/dist/services/pull.js +67 -0
  141. package/dist/services/pull.js.map +1 -0
  142. package/dist/services/push.d.ts +35 -0
  143. package/dist/services/push.d.ts.map +1 -0
  144. package/dist/services/push.js +96 -0
  145. package/dist/services/push.js.map +1 -0
  146. package/dist/services/repo-artifacts.d.ts +52 -0
  147. package/dist/services/repo-artifacts.d.ts.map +1 -0
  148. package/dist/services/repo-artifacts.js +251 -0
  149. package/dist/services/repo-artifacts.js.map +1 -0
  150. package/dist/services/repo-snapshot.d.ts +6 -0
  151. package/dist/services/repo-snapshot.d.ts.map +1 -0
  152. package/dist/services/repo-snapshot.js +163 -0
  153. package/dist/services/repo-snapshot.js.map +1 -0
  154. package/dist/services/runtime.d.ts +40 -0
  155. package/dist/services/runtime.d.ts.map +1 -0
  156. package/dist/services/runtime.js +71 -0
  157. package/dist/services/runtime.js.map +1 -0
  158. package/dist/services/set.d.ts +38 -0
  159. package/dist/services/set.d.ts.map +1 -0
  160. package/dist/services/set.js +184 -0
  161. package/dist/services/set.js.map +1 -0
  162. package/dist/services/status.d.ts +30 -0
  163. package/dist/services/status.d.ts.map +1 -0
  164. package/dist/services/status.js +35 -0
  165. package/dist/services/status.js.map +1 -0
  166. package/package.json +15 -7
  167. package/src/cli/commands/add.ts +0 -40
  168. package/src/cli/commands/cd.ts +0 -80
  169. package/src/cli/commands/doctor.ts +0 -20
  170. package/src/cli/commands/forget.ts +0 -32
  171. package/src/cli/commands/index.ts +0 -23
  172. package/src/cli/commands/init.ts +0 -43
  173. package/src/cli/commands/list.ts +0 -17
  174. package/src/cli/commands/pull.ts +0 -31
  175. package/src/cli/commands/push.ts +0 -31
  176. package/src/cli/commands/set.ts +0 -47
  177. package/src/cli/commands/status.ts +0 -18
  178. package/src/cli/sync-output.test.ts +0 -173
  179. package/src/cli/sync-output.ts +0 -200
  180. package/src/config/sync.test.ts +0 -609
  181. package/src/config/sync.ts +0 -572
  182. package/src/config/xdg.ts +0 -138
  183. package/src/lib/string.test.ts +0 -13
  184. package/src/lib/string.ts +0 -3
  185. package/src/lib/validation.test.ts +0 -32
  186. package/src/lib/validation.ts +0 -11
  187. package/src/services/add.ts +0 -178
  188. package/src/services/config-file.test.ts +0 -161
  189. package/src/services/config-file.ts +0 -101
  190. package/src/services/crypto.test.ts +0 -132
  191. package/src/services/crypto.ts +0 -83
  192. package/src/services/doctor.ts +0 -142
  193. package/src/services/error.ts +0 -6
  194. package/src/services/filesystem.test.ts +0 -171
  195. package/src/services/filesystem.ts +0 -183
  196. package/src/services/forget.ts +0 -261
  197. package/src/services/git.test.ts +0 -83
  198. package/src/services/git.ts +0 -74
  199. package/src/services/init.test.ts +0 -109
  200. package/src/services/init.ts +0 -244
  201. package/src/services/list.ts +0 -63
  202. package/src/services/local-materialization.ts +0 -421
  203. package/src/services/local-snapshot.ts +0 -173
  204. package/src/services/paths.test.ts +0 -74
  205. package/src/services/paths.ts +0 -98
  206. package/src/services/pull.ts +0 -144
  207. package/src/services/push.ts +0 -168
  208. package/src/services/repo-artifacts.ts +0 -262
  209. package/src/services/repo-snapshot.ts +0 -197
  210. package/src/services/runtime.ts +0 -57
  211. package/src/services/set.ts +0 -383
  212. package/src/services/status.ts +0 -57
  213. package/src/services/sync.dry-run.test.ts +0 -179
  214. package/src/services/sync.runtime.test.ts +0 -756
  215. package/src/services/sync.service.test.ts +0 -1169
  216. package/src/test/helpers/sync-fixture.ts +0 -47
@@ -0,0 +1,52 @@
1
+ import { type ResolvedSyncConfigEntry } from "#app/config/sync.js";
2
+ import type { SnapshotNode } from "./local-snapshot.js";
3
+ import type { EffectiveSyncConfig } from "./runtime.js";
4
+ type ArtifactConfig = EffectiveSyncConfig;
5
+ export declare const collectArtifactNamespaces: (entries: readonly Pick<ResolvedSyncConfigEntry, "machines">[]) => Set<string>;
6
+ export type RepoArtifact = Readonly<{
7
+ category: "plain";
8
+ kind: "directory";
9
+ machine: string;
10
+ repoPath: string;
11
+ }> | Readonly<{
12
+ category: "plain";
13
+ kind: "file";
14
+ repoPath: string;
15
+ machine: string;
16
+ contents: Uint8Array;
17
+ executable: boolean;
18
+ }> | Readonly<{
19
+ category: "plain";
20
+ kind: "symlink";
21
+ machine: string;
22
+ repoPath: string;
23
+ linkTarget: string;
24
+ }> | Readonly<{
25
+ category: "secret";
26
+ kind: "file";
27
+ machine: string;
28
+ repoPath: string;
29
+ contents: Uint8Array;
30
+ executable: boolean;
31
+ }>;
32
+ export declare const buildArtifactKey: (artifact: RepoArtifact) => string;
33
+ export declare const isSecretArtifactPath: (relativePath: string) => boolean;
34
+ export declare const stripSecretArtifactSuffix: (relativePath: string) => string | undefined;
35
+ export declare const assertStorageSafeRepoPath: (repoPath: string) => void;
36
+ export declare const resolveArtifactRelativePath: (artifact: Pick<RepoArtifact, "category" | "machine" | "repoPath">) => string;
37
+ export declare const parseArtifactRelativePath: (relativePath: string) => {
38
+ machine: string;
39
+ repoPath: string;
40
+ secret: boolean;
41
+ };
42
+ export declare const resolveEntryArtifactRelativePath: (entry: Pick<ResolvedSyncConfigEntry, "repoPath">, machine: string) => string;
43
+ export declare const resolveEntryArtifactPath: (artifactsDirectory: string, entry: Pick<ResolvedSyncConfigEntry, "repoPath">, machine: string) => string;
44
+ export declare const buildRepoArtifacts: (snapshot: ReadonlyMap<string, SnapshotNode>, config: ArtifactConfig) => Promise<RepoArtifact[]>;
45
+ export declare const collectExistingArtifactKeys: (syncDirectory: string, config: ArtifactConfig) => Promise<Set<string>>;
46
+ type AgeWriteConfig = Readonly<{
47
+ identityFile: string;
48
+ recipients: readonly string[];
49
+ }>;
50
+ export declare const writeArtifactsToDirectory: (rootDirectory: string, artifacts: readonly RepoArtifact[], ageConfig?: AgeWriteConfig) => Promise<void>;
51
+ export {};
52
+ //# sourceMappingURL=repo-artifacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-artifacts.d.ts","sourceRoot":"","sources":["../../src/services/repo-artifacts.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,uBAAuB,EAK7B,MAAM,qBAAqB,CAAC;AAU7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExD,KAAK,cAAc,GAAG,mBAAmB,CAAC;AAE1C,eAAO,MAAM,yBAAyB,GACpC,SAAS,SAAS,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC,EAAE,gBAY9D,CAAC;AAEF,MAAM,MAAM,YAAY,GACpB,QAAQ,CAAC;IACP,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,GACF,QAAQ,CAAC;IACP,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,UAAU,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC,GACF,QAAQ,CAAC;IACP,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,GACF,QAAQ,CAAC;IACP,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,UAAU,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC,CAAC;AAEP,eAAO,MAAM,gBAAgB,GAAI,UAAU,YAAY,WAMtD,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,cAAc,MAAM,YAExD,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,cAAc,MAAM,uBAM7D,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,UAAU,MAAM,SAazD,CAAC;AAEF,eAAO,MAAM,2BAA2B,GACtC,UAAU,IAAI,CAAC,YAAY,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC,WAOlE,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,cAAc,MAAM;;;;CAqB7D,CAAC;AAEF,eAAO,MAAM,gCAAgC,GAC3C,OAAO,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC,EAChD,SAAS,MAAM,WAOhB,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,oBAAoB,MAAM,EAC1B,OAAO,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC,EAChD,SAAS,MAAM,WAMhB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,UAAU,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,EAC3C,QAAQ,cAAc,4BAmFvB,CAAC;AAsCF,eAAO,MAAM,2BAA2B,GACtC,eAAe,MAAM,EACrB,QAAQ,cAAc,yBAyDvB,CAAC;AAEF,KAAK,cAAc,GAAG,QAAQ,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/B,CAAC,CAAC;AA+BH,eAAO,MAAM,yBAAyB,GACpC,eAAe,MAAM,EACrB,WAAW,SAAS,YAAY,EAAE,EAClC,YAAY,cAAc,kBA6C3B,CAAC"}
@@ -0,0 +1,251 @@
1
+ import { lstat, mkdir, readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { findOwningSyncEntry, hasReservedSyncArtifactSuffixSegment, resolveSyncArtifactsDirectoryPath, resolveSyncRule, syncDefaultMachine, syncSecretArtifactSuffix, } from "#app/config/sync.js";
4
+ import { buildDirectoryKey } from "#app/lib/path.js";
5
+ import { decryptSecretFile, encryptSecretFile } from "./crypto.js";
6
+ import { DevsyncError } from "./error.js";
7
+ import { getPathStats, listDirectoryEntries, writeFileNode, writeSymlinkNode, } from "./filesystem.js";
8
+ export const collectArtifactNamespaces = (entries) => {
9
+ const namespaces = new Set();
10
+ namespaces.add(syncDefaultMachine);
11
+ for (const entry of entries) {
12
+ for (const machine of entry.machines) {
13
+ namespaces.add(machine);
14
+ }
15
+ }
16
+ return namespaces;
17
+ };
18
+ export const buildArtifactKey = (artifact) => {
19
+ const relativePath = resolveArtifactRelativePath(artifact);
20
+ return artifact.kind === "directory"
21
+ ? buildDirectoryKey(relativePath)
22
+ : relativePath;
23
+ };
24
+ export const isSecretArtifactPath = (relativePath) => {
25
+ return relativePath.endsWith(syncSecretArtifactSuffix);
26
+ };
27
+ export const stripSecretArtifactSuffix = (relativePath) => {
28
+ if (!isSecretArtifactPath(relativePath)) {
29
+ return undefined;
30
+ }
31
+ return relativePath.slice(0, -syncSecretArtifactSuffix.length);
32
+ };
33
+ export const assertStorageSafeRepoPath = (repoPath) => {
34
+ if (!hasReservedSyncArtifactSuffixSegment(repoPath)) {
35
+ return;
36
+ }
37
+ throw new DevsyncError(`Tracked sync paths must not use the reserved suffix ${syncSecretArtifactSuffix}.`, {
38
+ code: "RESERVED_SECRET_SUFFIX",
39
+ details: [`Repository path: ${repoPath}`],
40
+ hint: "Rename the tracked path so no segment ends with the secret artifact suffix.",
41
+ });
42
+ };
43
+ export const resolveArtifactRelativePath = (artifact) => {
44
+ const machineRelativePath = `${artifact.machine}/${artifact.repoPath}`;
45
+ return artifact.category === "secret"
46
+ ? `${machineRelativePath}${syncSecretArtifactSuffix}`
47
+ : machineRelativePath;
48
+ };
49
+ export const parseArtifactRelativePath = (relativePath) => {
50
+ const secret = relativePath.endsWith(syncSecretArtifactSuffix);
51
+ const logicalPath = secret
52
+ ? relativePath.slice(0, -syncSecretArtifactSuffix.length)
53
+ : relativePath;
54
+ const segments = logicalPath.split("/");
55
+ if (segments.length < 2 || segments[0] === undefined) {
56
+ throw new DevsyncError("Repository artifact path is invalid.", {
57
+ code: "INVALID_REPO_ENTRY",
58
+ details: [`Repository path: ${relativePath}`],
59
+ });
60
+ }
61
+ const [machine, ...repoPathSegments] = segments;
62
+ return {
63
+ machine,
64
+ repoPath: repoPathSegments.join("/"),
65
+ secret,
66
+ };
67
+ };
68
+ export const resolveEntryArtifactRelativePath = (entry, machine) => {
69
+ return resolveArtifactRelativePath({
70
+ category: "plain",
71
+ machine,
72
+ repoPath: entry.repoPath,
73
+ });
74
+ };
75
+ export const resolveEntryArtifactPath = (artifactsDirectory, entry, machine) => {
76
+ return join(artifactsDirectory, ...resolveEntryArtifactRelativePath(entry, machine).split("/"));
77
+ };
78
+ export const buildRepoArtifacts = async (snapshot, config) => {
79
+ const artifacts = [];
80
+ const seenArtifactKeys = new Set();
81
+ const addArtifact = (artifact) => {
82
+ const key = buildArtifactKey(artifact);
83
+ if (seenArtifactKeys.has(key)) {
84
+ throw new DevsyncError("Duplicate repository artifact was generated.", {
85
+ code: "DUPLICATE_REPO_ARTIFACT",
86
+ details: [`Artifact key: ${key}`],
87
+ });
88
+ }
89
+ seenArtifactKeys.add(key);
90
+ artifacts.push(artifact);
91
+ };
92
+ for (const repoPath of [...snapshot.keys()].sort((left, right) => {
93
+ return left.localeCompare(right);
94
+ })) {
95
+ assertStorageSafeRepoPath(repoPath);
96
+ const node = snapshot.get(repoPath);
97
+ const owningEntry = findOwningSyncEntry(config, repoPath);
98
+ const resolvedRule = resolveSyncRule(config, repoPath, config.activeMachine);
99
+ if (node === undefined ||
100
+ owningEntry === undefined ||
101
+ resolvedRule === undefined) {
102
+ continue;
103
+ }
104
+ if (node.type === "directory") {
105
+ addArtifact({
106
+ category: "plain",
107
+ kind: "directory",
108
+ machine: resolvedRule.machine,
109
+ repoPath,
110
+ });
111
+ continue;
112
+ }
113
+ if (node.type === "symlink") {
114
+ addArtifact({
115
+ category: "plain",
116
+ kind: "symlink",
117
+ linkTarget: node.linkTarget,
118
+ machine: resolvedRule.machine,
119
+ repoPath,
120
+ });
121
+ continue;
122
+ }
123
+ if (!node.secret) {
124
+ addArtifact({
125
+ category: "plain",
126
+ contents: node.contents,
127
+ executable: node.executable,
128
+ kind: "file",
129
+ machine: resolvedRule.machine,
130
+ repoPath,
131
+ });
132
+ continue;
133
+ }
134
+ addArtifact({
135
+ category: "secret",
136
+ contents: node.contents,
137
+ executable: node.executable,
138
+ kind: "file",
139
+ machine: resolvedRule.machine,
140
+ repoPath,
141
+ });
142
+ }
143
+ return artifacts;
144
+ };
145
+ const collectArtifactLeafKeys = async (rootDirectory, keys, prefix) => {
146
+ const rootStats = await getPathStats(rootDirectory);
147
+ if (rootStats === undefined) {
148
+ return;
149
+ }
150
+ if (!rootStats.isDirectory()) {
151
+ if (prefix !== undefined) {
152
+ keys.add(prefix);
153
+ }
154
+ return;
155
+ }
156
+ const entries = await listDirectoryEntries(rootDirectory);
157
+ for (const entry of entries) {
158
+ const absolutePath = join(rootDirectory, entry.name);
159
+ const relativePath = prefix === undefined ? entry.name : `${prefix}/${entry.name}`;
160
+ const stats = await lstat(absolutePath);
161
+ if (stats?.isDirectory()) {
162
+ await collectArtifactLeafKeys(absolutePath, keys, relativePath);
163
+ continue;
164
+ }
165
+ keys.add(relativePath);
166
+ }
167
+ };
168
+ export const collectExistingArtifactKeys = async (syncDirectory, config) => {
169
+ const keys = new Set();
170
+ const artifactsDirectory = resolveSyncArtifactsDirectoryPath(syncDirectory);
171
+ const namespaces = collectArtifactNamespaces(config.entries);
172
+ await Promise.all([...namespaces].map(async (namespace) => {
173
+ await collectArtifactLeafKeys(join(artifactsDirectory, namespace), keys, namespace);
174
+ }));
175
+ for (const key of [...keys]) {
176
+ if (key.startsWith("__dir__:")) {
177
+ continue;
178
+ }
179
+ const artifact = parseArtifactRelativePath(key);
180
+ const rule = resolveSyncRule(config, artifact.repoPath, config.activeMachine);
181
+ if (rule === undefined || rule.machine !== artifact.machine) {
182
+ keys.delete(key);
183
+ }
184
+ }
185
+ for (const entry of config.entries) {
186
+ if (entry.kind !== "directory") {
187
+ continue;
188
+ }
189
+ const rule = resolveSyncRule(config, entry.repoPath, config.activeMachine);
190
+ if (rule === undefined) {
191
+ continue;
192
+ }
193
+ const relativePath = resolveArtifactRelativePath({
194
+ category: "plain",
195
+ machine: rule.machine,
196
+ repoPath: entry.repoPath,
197
+ });
198
+ const path = join(artifactsDirectory, ...relativePath.split("/"));
199
+ if ((await getPathStats(path))?.isDirectory()) {
200
+ keys.add(buildDirectoryKey(relativePath));
201
+ }
202
+ }
203
+ return keys;
204
+ };
205
+ const isSecretArtifactUnchanged = async (artifactPath, plaintext, identityFile) => {
206
+ let existingCiphertext;
207
+ try {
208
+ existingCiphertext = await readFile(artifactPath, "utf8");
209
+ }
210
+ catch {
211
+ return false;
212
+ }
213
+ try {
214
+ const existingPlaintext = await decryptSecretFile(existingCiphertext, identityFile);
215
+ if (existingPlaintext.length !== plaintext.length) {
216
+ return false;
217
+ }
218
+ return existingPlaintext.every((byte, index) => byte === plaintext[index]);
219
+ }
220
+ catch {
221
+ return false;
222
+ }
223
+ };
224
+ export const writeArtifactsToDirectory = async (rootDirectory, artifacts, ageConfig) => {
225
+ await mkdir(rootDirectory, { recursive: true });
226
+ for (const artifact of artifacts) {
227
+ const artifactPath = join(rootDirectory, ...resolveArtifactRelativePath(artifact).split("/"));
228
+ if (artifact.kind === "directory") {
229
+ await mkdir(artifactPath, { recursive: true });
230
+ continue;
231
+ }
232
+ if (artifact.kind === "symlink") {
233
+ await writeSymlinkNode(artifactPath, artifact.linkTarget);
234
+ continue;
235
+ }
236
+ if (artifact.category === "secret" && ageConfig !== undefined) {
237
+ const unchanged = await isSecretArtifactUnchanged(artifactPath, artifact.contents, ageConfig.identityFile);
238
+ if (unchanged) {
239
+ continue;
240
+ }
241
+ const encrypted = await encryptSecretFile(artifact.contents, ageConfig.recipients);
242
+ await writeFileNode(artifactPath, {
243
+ contents: encrypted,
244
+ executable: artifact.executable,
245
+ });
246
+ continue;
247
+ }
248
+ await writeFileNode(artifactPath, artifact);
249
+ }
250
+ };
251
+ //# sourceMappingURL=repo-artifacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-artifacts.js","sourceRoot":"","sources":["../../src/services/repo-artifacts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type SnapshotNode } from "./local-snapshot.js";
2
+ import type { EffectiveSyncConfig } from "./runtime.js";
3
+ type RepositorySnapshotConfig = EffectiveSyncConfig;
4
+ export declare const buildRepositorySnapshot: (syncDirectory: string, config: RepositorySnapshotConfig) => Promise<Map<string, SnapshotNode>>;
5
+ export {};
6
+ //# sourceMappingURL=repo-snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-snapshot.d.ts","sourceRoot":"","sources":["../../src/services/repo-snapshot.ts"],"names":[],"mappings":"AAYA,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAMzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExD,KAAK,wBAAwB,GAAG,mBAAmB,CAAC;AA8LpD,eAAO,MAAM,uBAAuB,GAClC,eAAe,MAAM,EACrB,QAAQ,wBAAwB,uCAyDjC,CAAC"}
@@ -0,0 +1,163 @@
1
+ import { lstat, readFile, readlink } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { resolveManagedSyncMode, resolveSyncArtifactsDirectoryPath, resolveSyncRule, } from "#app/config/sync.js";
4
+ import { isExecutableMode } from "#app/lib/file-mode.js";
5
+ import { decryptSecretFile } from "./crypto.js";
6
+ import { DevsyncError, wrapUnknownError } from "./error.js";
7
+ import { getPathStats, listDirectoryEntries } from "./filesystem.js";
8
+ import { addSnapshotNode } from "./local-snapshot.js";
9
+ import { assertStorageSafeRepoPath, collectArtifactNamespaces, parseArtifactRelativePath, } from "./repo-artifacts.js";
10
+ const isActiveStorageMachine = (storageMachine, config, repoPath) => {
11
+ const rule = resolveSyncRule(config, repoPath, config.activeMachine);
12
+ if (rule === undefined) {
13
+ return false;
14
+ }
15
+ return rule.machine === storageMachine;
16
+ };
17
+ const readArtifactLeaf = async (absolutePath, storagePath, config, snapshot) => {
18
+ const artifact = parseArtifactRelativePath(storagePath);
19
+ if (!isActiveStorageMachine(artifact.machine, config, artifact.repoPath)) {
20
+ return;
21
+ }
22
+ assertStorageSafeRepoPath(artifact.repoPath);
23
+ const rule = resolveSyncRule(config, artifact.repoPath, config.activeMachine);
24
+ if (rule === undefined) {
25
+ throw new DevsyncError("Repository path is not managed by the current sync configuration.", {
26
+ code: "UNMANAGED_SYNC_PATH",
27
+ details: [
28
+ `Repository path: ${artifact.repoPath}`,
29
+ `Context: ${storagePath}`,
30
+ ],
31
+ hint: "Add the parent path to devsync, or remove stray artifacts from the sync repository.",
32
+ });
33
+ }
34
+ if (rule.machine !== artifact.machine) {
35
+ throw new DevsyncError("Repository artifact is stored under the wrong machine namespace.", {
36
+ code: "REPO_PROFILE_MISMATCH",
37
+ details: [
38
+ `Repository path: ${artifact.repoPath}`,
39
+ `Stored machine: ${artifact.machine}`,
40
+ `Expected machine: ${rule.machine}`,
41
+ ],
42
+ });
43
+ }
44
+ if (artifact.secret) {
45
+ if (rule.mode !== "secret") {
46
+ throw new DevsyncError("Plain sync path is stored as a secret artifact in the repository.", {
47
+ code: "PLAIN_STORED_SECRET",
48
+ details: [`Repository path: ${storagePath}`],
49
+ });
50
+ }
51
+ const stats = await lstat(absolutePath);
52
+ if (!stats.isFile()) {
53
+ throw new DevsyncError("Secret repository artifacts must be regular files, not symlinks.", {
54
+ code: "SECRET_ARTIFACT_SYMLINK",
55
+ details: [`Repository path: ${storagePath}`],
56
+ });
57
+ }
58
+ let contents;
59
+ try {
60
+ contents = await decryptSecretFile(await readFile(absolutePath, "utf8"), config.age.identityFile);
61
+ }
62
+ catch (error) {
63
+ throw wrapUnknownError("Failed to decrypt a secret repository artifact.", error, {
64
+ code: "SECRET_ARTIFACT_DECRYPT_FAILED",
65
+ details: [
66
+ `Repository path: ${storagePath}`,
67
+ `Identity file: ${config.age.identityFile}`,
68
+ ],
69
+ });
70
+ }
71
+ addSnapshotNode(snapshot, artifact.repoPath, {
72
+ contents,
73
+ executable: isExecutableMode(stats.mode),
74
+ secret: true,
75
+ type: "file",
76
+ });
77
+ return;
78
+ }
79
+ const mode = resolveManagedSyncMode(config, artifact.repoPath, config.activeMachine, storagePath);
80
+ const stats = await lstat(absolutePath);
81
+ if (stats.isSymbolicLink()) {
82
+ if (mode === "secret") {
83
+ throw new DevsyncError("Secret sync path is stored as a plain artifact in the repository.", {
84
+ code: "SECRET_STORED_PLAIN",
85
+ details: [`Repository path: ${storagePath}`],
86
+ });
87
+ }
88
+ addSnapshotNode(snapshot, artifact.repoPath, {
89
+ linkTarget: await readlink(absolutePath),
90
+ type: "symlink",
91
+ });
92
+ return;
93
+ }
94
+ if (!stats.isFile()) {
95
+ throw new DevsyncError("Repository contains an unsupported plain artifact type.", {
96
+ code: "UNSUPPORTED_REPO_ENTRY",
97
+ details: [`Repository path: ${storagePath}`],
98
+ });
99
+ }
100
+ if (mode === "secret") {
101
+ throw new DevsyncError("Secret sync path is stored as a plain artifact in the repository.", {
102
+ code: "SECRET_STORED_PLAIN",
103
+ details: [`Repository path: ${storagePath}`],
104
+ });
105
+ }
106
+ addSnapshotNode(snapshot, artifact.repoPath, {
107
+ contents: await readFile(absolutePath),
108
+ executable: isExecutableMode(stats.mode),
109
+ secret: false,
110
+ type: "file",
111
+ });
112
+ };
113
+ const walkArtifactTree = async (rootDirectory, config, snapshot, prefix = "") => {
114
+ const entries = await listDirectoryEntries(rootDirectory);
115
+ for (const entry of entries) {
116
+ const absolutePath = join(rootDirectory, entry.name);
117
+ const storagePath = prefix === "" ? entry.name : `${prefix}/${entry.name}`;
118
+ const stats = await lstat(absolutePath);
119
+ if (stats.isDirectory()) {
120
+ await walkArtifactTree(absolutePath, config, snapshot, storagePath);
121
+ continue;
122
+ }
123
+ await readArtifactLeaf(absolutePath, storagePath, config, snapshot);
124
+ }
125
+ };
126
+ export const buildRepositorySnapshot = async (syncDirectory, config) => {
127
+ const snapshot = new Map();
128
+ const artifactsDirectory = resolveSyncArtifactsDirectoryPath(syncDirectory);
129
+ const namespaces = collectArtifactNamespaces(config.entries);
130
+ await Promise.all([...namespaces].map(async (namespace) => {
131
+ const namespaceDirectory = join(artifactsDirectory, namespace);
132
+ const namespaceStats = await getPathStats(namespaceDirectory);
133
+ if (namespaceStats?.isDirectory()) {
134
+ await walkArtifactTree(namespaceDirectory, config, snapshot, namespace);
135
+ }
136
+ }));
137
+ for (const entry of config.entries) {
138
+ if (entry.kind !== "directory") {
139
+ continue;
140
+ }
141
+ const rule = resolveSyncRule(config, entry.repoPath, config.activeMachine);
142
+ if (rule === undefined) {
143
+ continue;
144
+ }
145
+ const hasTrackedChildren = [...snapshot.keys()].some((repoPath) => {
146
+ return repoPath.startsWith(`${entry.repoPath}/`);
147
+ });
148
+ const expectedPath = join(artifactsDirectory, rule.machine, ...entry.repoPath.split("/"));
149
+ const expectedStats = await getPathStats(expectedPath);
150
+ if (expectedStats !== undefined && !expectedStats.isDirectory()) {
151
+ throw new DevsyncError("Directory sync entry is not stored as a directory in the repository.", {
152
+ code: "DIRECTORY_ENTRY_NOT_DIRECTORY",
153
+ details: [`Repository path: ${entry.repoPath}`],
154
+ });
155
+ }
156
+ if ((expectedStats?.isDirectory() ?? false) &&
157
+ (rule.mode !== "ignore" || hasTrackedChildren)) {
158
+ addSnapshotNode(snapshot, entry.repoPath, { type: "directory" });
159
+ }
160
+ }
161
+ return snapshot;
162
+ };
163
+ //# sourceMappingURL=repo-snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-snapshot.js","sourceRoot":"","sources":["../../src/services/repo-snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { type ActiveMachineSelection, type GlobalDevsyncConfig } from "#app/config/global-config.js";
2
+ import { type ResolvedSyncConfig, type ResolvedSyncConfigAge } from "#app/config/sync.js";
3
+ export type ResolvedAgeConfig = Readonly<{
4
+ configuredIdentityFile: string;
5
+ identityFile: string;
6
+ recipients: readonly string[];
7
+ }>;
8
+ export type SyncPaths = Readonly<{
9
+ artifactsDirectory: string;
10
+ configPath: string;
11
+ globalConfigPath: string;
12
+ homeDirectory: string;
13
+ syncDirectory: string;
14
+ }>;
15
+ export type SyncContext = Readonly<{
16
+ cwd: string;
17
+ environment: NodeJS.ProcessEnv;
18
+ paths: SyncPaths;
19
+ }>;
20
+ export type EffectiveSyncConfig = ResolvedSyncConfig & Readonly<{
21
+ activeMachine?: string;
22
+ age: ResolvedAgeConfig;
23
+ }>;
24
+ export type LoadedSyncConfig = Readonly<{
25
+ effectiveConfig: EffectiveSyncConfig;
26
+ fullConfig: ResolvedSyncConfig;
27
+ globalConfig?: GlobalDevsyncConfig;
28
+ }>;
29
+ export declare const createSyncPaths: (environment?: NodeJS.ProcessEnv) => SyncPaths;
30
+ export declare const createSyncContext: (options?: Readonly<{
31
+ cwd?: string;
32
+ environment?: NodeJS.ProcessEnv;
33
+ }>) => SyncContext;
34
+ export declare const ensureSyncRepository: (context: Pick<SyncContext, "paths">) => Promise<void>;
35
+ export declare const resolveAgeFromSyncConfig: (age: ResolvedSyncConfigAge, environment: NodeJS.ProcessEnv) => ResolvedAgeConfig;
36
+ export declare const buildEffectiveSyncConfig: (fullConfig: ResolvedSyncConfig, selection: ActiveMachineSelection, age: ResolvedAgeConfig) => EffectiveSyncConfig;
37
+ export declare const loadSyncConfig: (context: SyncContext, options?: Readonly<{
38
+ machine?: string;
39
+ }>) => Promise<LoadedSyncConfig>;
40
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/services/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EAIzB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAK3B,MAAM,qBAAqB,CAAC;AAU7B,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/B,CAAC,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC;IAC/B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC,UAAU,CAAC;IAC/B,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,kBAAkB,GAClD,QAAQ,CAAC;IACP,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,EAAE,iBAAiB,CAAC;CACxB,CAAC,CAAC;AAEL,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,eAAe,EAAE,mBAAmB,CAAC;IACrC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC,CAAC,CAAC;AAEH,eAAO,MAAM,eAAe,GAC1B,cAAa,MAAM,CAAC,UAAwB,KAC3C,SAUF,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,UAAS,QAAQ,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACjC,CAAM,KACN,WAQF,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,SAAS,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,kBAGpC,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,KAAK,qBAAqB,EAC1B,aAAa,MAAM,CAAC,UAAU,KAC7B,iBAMF,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,YAAY,kBAAkB,EAC9B,WAAW,sBAAsB,EACjC,KAAK,iBAAiB,KACrB,mBAoBF,CAAC;AAEF,eAAO,MAAM,cAAc,GACzB,SAAS,WAAW,EACpB,UAAS,QAAQ,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAM,KACN,OAAO,CAAC,gBAAgB,CA+B1B,CAAC"}
@@ -0,0 +1,71 @@
1
+ import { readGlobalDevsyncConfig, resolveActiveMachineSelection, resolveConfiguredIdentityFile, } from "#app/config/global-config.js";
2
+ import { readSyncConfig, resolveSyncArtifactsDirectoryPath, resolveSyncConfigFilePath, syncDefaultMachine, } from "#app/config/sync.js";
3
+ import { resolveDevsyncGlobalConfigFilePath, resolveDevsyncSyncDirectory, resolveHomeDirectory, } from "#app/config/xdg.js";
4
+ import { DevsyncError } from "./error.js";
5
+ import { ensureGitRepository } from "./git.js";
6
+ export const createSyncPaths = (environment = process.env) => {
7
+ const syncDirectory = resolveDevsyncSyncDirectory(environment);
8
+ return {
9
+ artifactsDirectory: resolveSyncArtifactsDirectoryPath(syncDirectory),
10
+ configPath: resolveSyncConfigFilePath(syncDirectory),
11
+ globalConfigPath: resolveDevsyncGlobalConfigFilePath(environment),
12
+ homeDirectory: resolveHomeDirectory(environment),
13
+ syncDirectory,
14
+ };
15
+ };
16
+ export const createSyncContext = (options = {}) => {
17
+ const environment = options.environment ?? process.env;
18
+ return {
19
+ cwd: options.cwd ?? process.cwd(),
20
+ environment,
21
+ paths: createSyncPaths(environment),
22
+ };
23
+ };
24
+ export const ensureSyncRepository = async (context) => {
25
+ await ensureGitRepository(context.paths.syncDirectory);
26
+ };
27
+ export const resolveAgeFromSyncConfig = (age, environment) => {
28
+ return {
29
+ configuredIdentityFile: age.identityFile,
30
+ identityFile: resolveConfiguredIdentityFile(age.identityFile, environment),
31
+ recipients: age.recipients,
32
+ };
33
+ };
34
+ export const buildEffectiveSyncConfig = (fullConfig, selection, age) => {
35
+ const activeMachine = selection.mode === "single" ? selection.machine : undefined;
36
+ const effectiveMachine = activeMachine !== undefined && activeMachine !== syncDefaultMachine
37
+ ? activeMachine
38
+ : syncDefaultMachine;
39
+ const entries = fullConfig.entries.filter((entry) => entry.machines.length === 0 || entry.machines.includes(effectiveMachine));
40
+ return {
41
+ ...fullConfig,
42
+ entries,
43
+ age,
44
+ ...(activeMachine !== undefined ? { activeMachine } : {}),
45
+ };
46
+ };
47
+ export const loadSyncConfig = async (context, options = {}) => {
48
+ const fullConfig = await readSyncConfig(context.paths.syncDirectory, context.environment);
49
+ const globalConfig = await readGlobalDevsyncConfig(context.environment);
50
+ const selection = options.machine === undefined
51
+ ? resolveActiveMachineSelection(globalConfig)
52
+ : {
53
+ machine: options.machine,
54
+ mode: "single",
55
+ };
56
+ const rawAge = fullConfig.age;
57
+ if (rawAge === undefined) {
58
+ throw new DevsyncError("Age configuration is missing from manifest.json.", {
59
+ code: "AGE_CONFIG_MISSING",
60
+ details: [`Config file: ${context.paths.configPath}`],
61
+ hint: "Run 'devsync init' to set up encryption.",
62
+ });
63
+ }
64
+ const age = resolveAgeFromSyncConfig(rawAge, context.environment);
65
+ return {
66
+ effectiveConfig: buildEffectiveSyncConfig(fullConfig, selection, age),
67
+ fullConfig,
68
+ ...(globalConfig === undefined ? {} : { globalConfig }),
69
+ };
70
+ };
71
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/services/runtime.ts"],"names":[],"mappings":"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"}