@tinyrack/devsync 1.1.0 → 1.3.0

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 (220) 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/platform.d.ts +11 -0
  55. package/dist/config/platform.d.ts.map +1 -0
  56. package/dist/config/platform.js +19 -0
  57. package/dist/config/platform.js.map +1 -0
  58. package/dist/config/sync.d.ts +107 -0
  59. package/dist/config/sync.d.ts.map +1 -0
  60. package/dist/config/sync.js +424 -0
  61. package/dist/config/sync.js.map +1 -0
  62. package/dist/config/xdg.d.ts +14 -0
  63. package/dist/config/xdg.d.ts.map +1 -0
  64. package/dist/config/xdg.js +102 -0
  65. package/dist/config/xdg.js.map +1 -0
  66. package/dist/index.d.ts +3 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/{src/index.ts → dist/index.js} +1 -1
  69. package/dist/index.js.map +1 -0
  70. package/dist/lib/file-mode.d.ts +3 -0
  71. package/dist/lib/file-mode.d.ts.map +1 -0
  72. package/dist/lib/file-mode.js +7 -0
  73. package/dist/lib/file-mode.js.map +1 -0
  74. package/dist/lib/output.d.ts +31 -0
  75. package/dist/lib/output.d.ts.map +1 -0
  76. package/dist/lib/output.js +198 -0
  77. package/dist/lib/output.js.map +1 -0
  78. package/dist/lib/path.d.ts +5 -0
  79. package/dist/lib/path.d.ts.map +1 -0
  80. package/dist/lib/path.js +25 -0
  81. package/dist/lib/path.js.map +1 -0
  82. package/dist/lib/string.d.ts +2 -0
  83. package/dist/lib/string.d.ts.map +1 -0
  84. package/dist/lib/string.js +4 -0
  85. package/dist/lib/string.js.map +1 -0
  86. package/dist/lib/validation.d.ts +3 -0
  87. package/dist/lib/validation.d.ts.map +1 -0
  88. package/dist/lib/validation.js +9 -0
  89. package/dist/lib/validation.js.map +1 -0
  90. package/dist/services/add.d.ts +20 -0
  91. package/dist/services/add.d.ts.map +1 -0
  92. package/dist/services/add.js +161 -0
  93. package/dist/services/add.js.map +1 -0
  94. package/dist/services/config-file.d.ts +45 -0
  95. package/dist/services/config-file.d.ts.map +1 -0
  96. package/dist/services/config-file.js +35 -0
  97. package/dist/services/config-file.js.map +1 -0
  98. package/dist/services/crypto.d.ts +9 -0
  99. package/dist/services/crypto.d.ts.map +1 -0
  100. package/dist/services/crypto.js +75 -0
  101. package/dist/services/crypto.js.map +1 -0
  102. package/dist/services/doctor.d.ts +16 -0
  103. package/dist/services/doctor.d.ts.map +1 -0
  104. package/dist/services/doctor.js +84 -0
  105. package/dist/services/doctor.js.map +1 -0
  106. package/dist/services/error.d.ts +14 -0
  107. package/dist/services/error.d.ts.map +1 -0
  108. package/dist/services/error.js +38 -0
  109. package/dist/services/error.js.map +1 -0
  110. package/dist/services/filesystem.d.ts +15 -0
  111. package/dist/services/filesystem.d.ts.map +1 -0
  112. package/dist/services/filesystem.js +113 -0
  113. package/dist/services/filesystem.js.map +1 -0
  114. package/dist/services/forget.d.ts +14 -0
  115. package/dist/services/forget.d.ts.map +1 -0
  116. package/dist/services/forget.js +124 -0
  117. package/dist/services/forget.js.map +1 -0
  118. package/dist/services/git.d.ts +10 -0
  119. package/dist/services/git.d.ts.map +1 -0
  120. package/dist/services/git.js +57 -0
  121. package/dist/services/git.js.map +1 -0
  122. package/dist/services/init.d.ts +19 -0
  123. package/dist/services/init.d.ts.map +1 -0
  124. package/dist/services/init.js +203 -0
  125. package/dist/services/init.js.map +1 -0
  126. package/dist/services/local-materialization.d.ts +28 -0
  127. package/dist/services/local-materialization.d.ts.map +1 -0
  128. package/dist/services/local-materialization.js +262 -0
  129. package/dist/services/local-materialization.js.map +1 -0
  130. package/dist/services/local-snapshot.d.ts +25 -0
  131. package/dist/services/local-snapshot.d.ts.map +1 -0
  132. package/dist/services/local-snapshot.js +93 -0
  133. package/dist/services/local-snapshot.js.map +1 -0
  134. package/dist/services/machine.d.ts +40 -0
  135. package/dist/services/machine.d.ts.map +1 -0
  136. package/dist/services/machine.js +113 -0
  137. package/dist/services/machine.js.map +1 -0
  138. package/dist/services/paths.d.ts +13 -0
  139. package/dist/services/paths.d.ts.map +1 -0
  140. package/dist/services/paths.js +71 -0
  141. package/dist/services/paths.js.map +1 -0
  142. package/dist/services/pull.d.ts +28 -0
  143. package/dist/services/pull.d.ts.map +1 -0
  144. package/dist/services/pull.js +67 -0
  145. package/dist/services/pull.js.map +1 -0
  146. package/dist/services/push.d.ts +35 -0
  147. package/dist/services/push.d.ts.map +1 -0
  148. package/dist/services/push.js +96 -0
  149. package/dist/services/push.js.map +1 -0
  150. package/dist/services/repo-artifacts.d.ts +52 -0
  151. package/dist/services/repo-artifacts.d.ts.map +1 -0
  152. package/dist/services/repo-artifacts.js +251 -0
  153. package/dist/services/repo-artifacts.js.map +1 -0
  154. package/dist/services/repo-snapshot.d.ts +6 -0
  155. package/dist/services/repo-snapshot.d.ts.map +1 -0
  156. package/dist/services/repo-snapshot.js +163 -0
  157. package/dist/services/repo-snapshot.js.map +1 -0
  158. package/dist/services/runtime.d.ts +40 -0
  159. package/dist/services/runtime.d.ts.map +1 -0
  160. package/dist/services/runtime.js +71 -0
  161. package/dist/services/runtime.js.map +1 -0
  162. package/dist/services/set.d.ts +38 -0
  163. package/dist/services/set.d.ts.map +1 -0
  164. package/dist/services/set.js +184 -0
  165. package/dist/services/set.js.map +1 -0
  166. package/dist/services/status.d.ts +30 -0
  167. package/dist/services/status.d.ts.map +1 -0
  168. package/dist/services/status.js +35 -0
  169. package/dist/services/status.js.map +1 -0
  170. package/package.json +15 -7
  171. package/src/cli/commands/add.ts +0 -40
  172. package/src/cli/commands/cd.ts +0 -80
  173. package/src/cli/commands/doctor.ts +0 -20
  174. package/src/cli/commands/forget.ts +0 -32
  175. package/src/cli/commands/index.ts +0 -23
  176. package/src/cli/commands/init.ts +0 -43
  177. package/src/cli/commands/list.ts +0 -17
  178. package/src/cli/commands/pull.ts +0 -31
  179. package/src/cli/commands/push.ts +0 -31
  180. package/src/cli/commands/set.ts +0 -47
  181. package/src/cli/commands/status.ts +0 -18
  182. package/src/cli/sync-output.test.ts +0 -173
  183. package/src/cli/sync-output.ts +0 -200
  184. package/src/config/sync.test.ts +0 -609
  185. package/src/config/sync.ts +0 -572
  186. package/src/config/xdg.ts +0 -138
  187. package/src/lib/string.test.ts +0 -13
  188. package/src/lib/string.ts +0 -3
  189. package/src/lib/validation.test.ts +0 -32
  190. package/src/lib/validation.ts +0 -11
  191. package/src/services/add.ts +0 -178
  192. package/src/services/config-file.test.ts +0 -161
  193. package/src/services/config-file.ts +0 -101
  194. package/src/services/crypto.test.ts +0 -132
  195. package/src/services/crypto.ts +0 -83
  196. package/src/services/doctor.ts +0 -142
  197. package/src/services/error.ts +0 -6
  198. package/src/services/filesystem.test.ts +0 -171
  199. package/src/services/filesystem.ts +0 -183
  200. package/src/services/forget.ts +0 -261
  201. package/src/services/git.test.ts +0 -83
  202. package/src/services/git.ts +0 -74
  203. package/src/services/init.test.ts +0 -109
  204. package/src/services/init.ts +0 -244
  205. package/src/services/list.ts +0 -63
  206. package/src/services/local-materialization.ts +0 -421
  207. package/src/services/local-snapshot.ts +0 -173
  208. package/src/services/paths.test.ts +0 -74
  209. package/src/services/paths.ts +0 -98
  210. package/src/services/pull.ts +0 -144
  211. package/src/services/push.ts +0 -168
  212. package/src/services/repo-artifacts.ts +0 -262
  213. package/src/services/repo-snapshot.ts +0 -197
  214. package/src/services/runtime.ts +0 -57
  215. package/src/services/set.ts +0 -383
  216. package/src/services/status.ts +0 -57
  217. package/src/services/sync.dry-run.test.ts +0 -179
  218. package/src/services/sync.runtime.test.ts +0 -756
  219. package/src/services/sync.service.test.ts +0 -1169
  220. package/src/test/helpers/sync-fixture.ts +0 -47
@@ -0,0 +1,161 @@
1
+ import { resolveConfiguredIdentityFile } from "#app/config/global-config.js";
2
+ import { normalizeSyncMachineName, readSyncConfig, } from "#app/config/sync.js";
3
+ import { createSyncConfigDocument, writeValidatedSyncConfig, } from "./config-file.js";
4
+ import { DevsyncError } from "./error.js";
5
+ import { getPathStats } from "./filesystem.js";
6
+ import { buildConfiguredHomeLocalPath, buildRepoPathWithinRoot, doPathsOverlap, resolveCommandTargetPath, } from "./paths.js";
7
+ import { ensureSyncRepository } from "./runtime.js";
8
+ const buildAddEntryCandidate = async (targetPath, context, input) => {
9
+ const targetStats = await getPathStats(targetPath);
10
+ if (targetStats === undefined) {
11
+ throw new DevsyncError("Sync target does not exist.", {
12
+ code: "TARGET_NOT_FOUND",
13
+ details: [`Target: ${targetPath}`],
14
+ hint: "Create the file or directory first, then run the command again.",
15
+ });
16
+ }
17
+ const kind = (() => {
18
+ if (targetStats.isDirectory()) {
19
+ return "directory";
20
+ }
21
+ if (targetStats.isFile() || targetStats.isSymbolicLink()) {
22
+ return "file";
23
+ }
24
+ throw new DevsyncError("Sync target type is not supported.", {
25
+ code: "TARGET_UNSUPPORTED_TYPE",
26
+ details: [`Target: ${targetPath}`],
27
+ hint: "Track a regular file, symlink, or directory.",
28
+ });
29
+ })();
30
+ if (doPathsOverlap(targetPath, context.paths.syncDirectory)) {
31
+ throw new DevsyncError("Sync target overlaps the devsync repository.", {
32
+ code: "TARGET_OVERLAPS_SYNC_DIR",
33
+ details: [
34
+ `Target: ${targetPath}`,
35
+ `Sync directory: ${context.paths.syncDirectory}`,
36
+ ],
37
+ hint: "Choose a path outside the devsync sync directory.",
38
+ });
39
+ }
40
+ if (input.identityFile !== undefined &&
41
+ doPathsOverlap(targetPath, input.identityFile)) {
42
+ throw new DevsyncError("Sync target contains the configured age identity file.", {
43
+ code: "TARGET_OVERLAPS_IDENTITY",
44
+ details: [
45
+ `Target: ${targetPath}`,
46
+ `Age identity file: ${input.identityFile}`,
47
+ ],
48
+ hint: "Store age key material outside tracked sync targets.",
49
+ });
50
+ }
51
+ const repoPath = buildRepoPathWithinRoot(targetPath, context.paths.homeDirectory, "Sync target");
52
+ const configuredLocalPath = buildConfiguredHomeLocalPath(repoPath);
53
+ return {
54
+ configuredLocalPath,
55
+ kind,
56
+ localPath: targetPath,
57
+ machines: input.machines?.map((m) => normalizeSyncMachineName(m)) ?? [],
58
+ machinesExplicit: input.machines !== undefined,
59
+ mode: input.mode,
60
+ modeExplicit: true,
61
+ name: repoPath,
62
+ repoPath,
63
+ };
64
+ };
65
+ export const trackSyncTarget = async (request, context) => {
66
+ const target = request.target.trim();
67
+ if (target.length === 0) {
68
+ throw new DevsyncError("Target path is required.", {
69
+ code: "TARGET_REQUIRED",
70
+ hint: "Pass a file or directory path, for example 'devsync track ~/.gitconfig'.",
71
+ });
72
+ }
73
+ await ensureSyncRepository(context);
74
+ const config = await readSyncConfig(context.paths.syncDirectory, context.environment);
75
+ const identityFile = config.age !== undefined
76
+ ? resolveConfiguredIdentityFile(config.age.identityFile, context.environment)
77
+ : undefined;
78
+ const isMachineClear = request.machines !== undefined &&
79
+ request.machines.length === 1 &&
80
+ request.machines[0] === "";
81
+ const effectiveMachines = isMachineClear ? [] : request.machines;
82
+ const candidate = await buildAddEntryCandidate(resolveCommandTargetPath(target, context.environment, context.cwd), context, {
83
+ identityFile,
84
+ machines: effectiveMachines,
85
+ mode: request.mode,
86
+ });
87
+ const existingEntry = config.entries.find((entry) => {
88
+ return (entry.localPath === candidate.localPath &&
89
+ entry.repoPath === candidate.repoPath);
90
+ });
91
+ const alreadyTracked = existingEntry !== undefined && existingEntry.kind === candidate.kind;
92
+ if (existingEntry !== undefined && existingEntry.kind !== candidate.kind) {
93
+ throw new DevsyncError("Sync target conflicts with an existing tracked entry.", {
94
+ code: "TARGET_CONFLICT",
95
+ details: [
96
+ `Requested local path: ${candidate.localPath}`,
97
+ `Requested repo path: ${candidate.repoPath}`,
98
+ `Existing entry: ${existingEntry.localPath} -> ${existingEntry.repoPath}`,
99
+ ],
100
+ hint: "Untrack or rename the existing entry before adding this root.",
101
+ });
102
+ }
103
+ if (!alreadyTracked) {
104
+ const nextConfig = createSyncConfigDocument({
105
+ ...config,
106
+ entries: [...config.entries, candidate],
107
+ });
108
+ await writeValidatedSyncConfig(context.paths.syncDirectory, nextConfig, context.environment);
109
+ return {
110
+ alreadyTracked,
111
+ changed: true,
112
+ configPath: context.paths.configPath,
113
+ kind: candidate.kind,
114
+ localPath: candidate.localPath,
115
+ machines: candidate.machines,
116
+ mode: candidate.mode,
117
+ repoPath: candidate.repoPath,
118
+ syncDirectory: context.paths.syncDirectory,
119
+ };
120
+ }
121
+ const modeChanged = existingEntry?.mode !== request.mode;
122
+ const machinesChanged = effectiveMachines !== undefined &&
123
+ (existingEntry?.machines.length !== candidate.machines.length ||
124
+ !candidate.machines.every((m) => existingEntry?.machines.includes(m)));
125
+ const changed = modeChanged || machinesChanged;
126
+ if (changed) {
127
+ const nextConfig = createSyncConfigDocument({
128
+ ...config,
129
+ entries: config.entries.map((entry) => {
130
+ if (entry.repoPath !== candidate.repoPath) {
131
+ return entry;
132
+ }
133
+ return {
134
+ ...entry,
135
+ ...(modeChanged ? { mode: request.mode } : {}),
136
+ ...(machinesChanged
137
+ ? {
138
+ machines: candidate.machines,
139
+ machinesExplicit: candidate.machinesExplicit,
140
+ }
141
+ : {}),
142
+ };
143
+ }),
144
+ });
145
+ await writeValidatedSyncConfig(context.paths.syncDirectory, nextConfig, context.environment);
146
+ }
147
+ return {
148
+ alreadyTracked,
149
+ changed,
150
+ configPath: context.paths.configPath,
151
+ kind: candidate.kind,
152
+ localPath: candidate.localPath,
153
+ machines: machinesChanged
154
+ ? candidate.machines
155
+ : (existingEntry?.machines ?? []),
156
+ mode: modeChanged ? request.mode : (existingEntry?.mode ?? request.mode),
157
+ repoPath: candidate.repoPath,
158
+ syncDirectory: context.paths.syncDirectory,
159
+ };
160
+ };
161
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/services/add.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import { type ResolvedSyncConfig, type SyncConfig } from "#app/config/sync.js";
2
+ export declare const sortSyncConfigEntries: (entries: readonly SyncConfig["entries"][number][]) => {
3
+ kind: "file" | "directory";
4
+ localPath: {
5
+ default: string;
6
+ win?: string | undefined;
7
+ mac?: string | undefined;
8
+ linux?: string | undefined;
9
+ };
10
+ machines?: string[] | undefined;
11
+ mode?: "normal" | "secret" | "ignore" | undefined;
12
+ }[];
13
+ export declare const createSyncConfigDocument: (config: ResolvedSyncConfig) => SyncConfig;
14
+ export declare const writeValidatedSyncConfig: (syncDirectory: string, config: SyncConfig, environment: NodeJS.ProcessEnv) => Promise<{
15
+ version: 5;
16
+ entries: {
17
+ kind: "file" | "directory";
18
+ localPath: {
19
+ default: string;
20
+ win?: string | undefined;
21
+ mac?: string | undefined;
22
+ linux?: string | undefined;
23
+ };
24
+ machines?: string[] | undefined;
25
+ mode?: "normal" | "secret" | "ignore" | undefined;
26
+ }[];
27
+ } | {
28
+ version: 6;
29
+ age: {
30
+ identityFile: string;
31
+ recipients: string[];
32
+ };
33
+ entries: {
34
+ kind: "file" | "directory";
35
+ localPath: {
36
+ default: string;
37
+ win?: string | undefined;
38
+ mac?: string | undefined;
39
+ linux?: string | undefined;
40
+ };
41
+ machines?: string[] | undefined;
42
+ mode?: "normal" | "secret" | "ignore" | undefined;
43
+ }[];
44
+ }>;
45
+ //# sourceMappingURL=config-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-file.d.ts","sourceRoot":"","sources":["../../src/services/config-file.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,kBAAkB,EAEvB,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAI7B,eAAO,MAAM,qBAAqB,GAChC,SAAS,SAAS,UAAU,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,EAAE;;;;;;;;;;GAOlD,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,QAAQ,kBAAkB,KACzB,UAsBF,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,eAAe,MAAM,EACrB,QAAQ,UAAU,EAClB,aAAa,MAAM,CAAC,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAW/B,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { getDefaultLocalPath } from "#app/config/platform.js";
2
+ import { formatSyncConfig, parseSyncConfig, resolveSyncConfigFilePath, } from "#app/config/sync.js";
3
+ import { writeTextFileAtomically } from "./filesystem.js";
4
+ export const sortSyncConfigEntries = (entries) => {
5
+ return [...entries].sort((left, right) => {
6
+ return getDefaultLocalPath(left.localPath).localeCompare(getDefaultLocalPath(right.localPath));
7
+ });
8
+ };
9
+ export const createSyncConfigDocument = (config) => {
10
+ const entries = sortSyncConfigEntries(config.entries.map((entry) => ({
11
+ kind: entry.kind,
12
+ localPath: entry.configuredLocalPath,
13
+ ...(entry.modeExplicit ? { mode: entry.mode } : {}),
14
+ ...(entry.machinesExplicit ? { machines: [...entry.machines] } : {}),
15
+ })));
16
+ return {
17
+ version: 6,
18
+ ...(config.age === undefined
19
+ ? {}
20
+ : {
21
+ age: {
22
+ identityFile: config.age.identityFile,
23
+ recipients: [...config.age.recipients],
24
+ },
25
+ }),
26
+ entries,
27
+ };
28
+ };
29
+ export const writeValidatedSyncConfig = async (syncDirectory, config, environment) => {
30
+ const resolvedConfig = parseSyncConfig(config, environment);
31
+ const nextConfig = createSyncConfigDocument(resolvedConfig);
32
+ await writeTextFileAtomically(resolveSyncConfigFilePath(syncDirectory), formatSyncConfig(nextConfig));
33
+ return nextConfig;
34
+ };
35
+ //# sourceMappingURL=config-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-file.js","sourceRoot":"","sources":["../../src/services/config-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EACL,gBAAgB,EAChB,eAAe,EAEf,yBAAyB,GAE1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,OAAiD,EACjD,EAAE;IACF,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACvC,OAAO,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,aAAa,CACtD,mBAAmB,CAAC,KAAK,CAAC,SAAS,CAAC,CACrC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,MAA0B,EACd,EAAE;IACd,MAAM,OAAO,GAAG,qBAAqB,CACnC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAiC,EAAE,CAAC,CAAC;QAC5D,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,SAAS,EAAE,KAAK,CAAC,mBAAmB;QACpC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrE,CAAC,CAAC,CACJ,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,CAAC;QACV,GAAG,CAAC,MAAM,CAAC,GAAG,KAAK,SAAS;YAC1B,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC;gBACE,GAAG,EAAE;oBACH,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,YAAY;oBACrC,UAAU,EAAE,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC;iBACvC;aACF,CAAC;QACN,OAAO;KACM,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,EAC3C,aAAqB,EACrB,MAAkB,EAClB,WAA8B,EAC9B,EAAE;IACF,MAAM,cAAc,GAAG,eAAe,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,wBAAwB,CAAC,cAAc,CAAC,CAAC;IAE5D,MAAM,uBAAuB,CAC3B,yBAAyB,CAAC,aAAa,CAAC,EACxC,gBAAgB,CAAC,UAAU,CAAC,CAC7B,CAAC;IAEF,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare const readAgeIdentityLines: (identityFile: string) => Promise<string[]>;
2
+ export declare const readAgeRecipientsFromIdentityFile: (identityFile: string) => Promise<string[]>;
3
+ export declare const createAgeIdentityFile: (identityFile: string) => Promise<{
4
+ identity: string;
5
+ recipient: string;
6
+ }>;
7
+ export declare const encryptSecretFile: (contents: Uint8Array, recipients: readonly string[]) => Promise<string>;
8
+ export declare const decryptSecretFile: (armoredCiphertext: string, identityFile: string) => Promise<Uint8Array<ArrayBufferLike>>;
9
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/services/crypto.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,oBAAoB,GAAU,cAAc,MAAM,sBAqB9D,CAAC;AAEF,eAAO,MAAM,iCAAiC,GAC5C,cAAc,MAAM,sBAwBrB,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAU,cAAc,MAAM;;;EAW/D,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,UAAU,UAAU,EACpB,YAAY,SAAS,MAAM,EAAE,oBAW9B,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,mBAAmB,MAAM,EACzB,cAAc,MAAM,yCAkBrB,CAAC"}
@@ -0,0 +1,75 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { dirname } from "node:path";
3
+ import { armor, Decrypter, Encrypter, generateIdentity, identityToRecipient, } from "age-encryption";
4
+ import { ensureTrailingNewline } from "#app/lib/string.js";
5
+ import { DevsyncError, wrapUnknownError } from "#app/services/error.js";
6
+ export const readAgeIdentityLines = async (identityFile) => {
7
+ const contents = await readFile(identityFile, "utf8");
8
+ const identities = contents
9
+ .split(/\r?\n/u)
10
+ .map((line) => line.trim())
11
+ .filter((line) => {
12
+ return line !== "" && !line.startsWith("#");
13
+ });
14
+ if (identities.length === 0) {
15
+ throw new DevsyncError("No age identities were found in the configured identity file.", {
16
+ code: "AGE_IDENTITY_EMPTY",
17
+ details: [`Identity file: ${identityFile}`],
18
+ hint: "Add at least one age private key to the identity file, or run 'devsync init' to generate one.",
19
+ });
20
+ }
21
+ return identities;
22
+ };
23
+ export const readAgeRecipientsFromIdentityFile = async (identityFile) => {
24
+ const identities = await readAgeIdentityLines(identityFile);
25
+ let recipients;
26
+ try {
27
+ recipients = await Promise.all(identities.map(async (identity) => {
28
+ return await identityToRecipient(identity);
29
+ }));
30
+ }
31
+ catch (error) {
32
+ throw wrapUnknownError("Failed to read age recipients from the configured identity file.", error, {
33
+ code: "AGE_RECIPIENT_READ_FAILED",
34
+ details: [`Identity file: ${identityFile}`],
35
+ hint: "Check that the identity file contains valid age private keys.",
36
+ });
37
+ }
38
+ return [...new Set(recipients)];
39
+ };
40
+ export const createAgeIdentityFile = async (identityFile) => {
41
+ const identity = await generateIdentity();
42
+ const recipient = await identityToRecipient(identity);
43
+ await mkdir(dirname(identityFile), { recursive: true });
44
+ await writeFile(identityFile, ensureTrailingNewline(identity), "utf8");
45
+ return {
46
+ identity,
47
+ recipient,
48
+ };
49
+ };
50
+ export const encryptSecretFile = async (contents, recipients) => {
51
+ const encrypter = new Encrypter();
52
+ for (const recipient of recipients) {
53
+ encrypter.addRecipient(recipient);
54
+ }
55
+ const ciphertext = await encrypter.encrypt(contents);
56
+ return armor.encode(ciphertext);
57
+ };
58
+ export const decryptSecretFile = async (armoredCiphertext, identityFile) => {
59
+ const decrypter = new Decrypter();
60
+ const identities = await readAgeIdentityLines(identityFile);
61
+ for (const identity of identities) {
62
+ decrypter.addIdentity(identity);
63
+ }
64
+ try {
65
+ return await decrypter.decrypt(armor.decode(armoredCiphertext));
66
+ }
67
+ catch (error) {
68
+ throw wrapUnknownError("Failed to decrypt a secret artifact.", error, {
69
+ code: "AGE_DECRYPT_FAILED",
70
+ details: [`Identity file: ${identityFile}`],
71
+ hint: "Check that the artifact is valid age data and that the configured identity file matches one of its recipients.",
72
+ });
73
+ }
74
+ };
75
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/services/crypto.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type SyncContext } from "./runtime.js";
2
+ export type DoctorCheckLevel = "fail" | "ok" | "warn";
3
+ export type DoctorCheck = Readonly<{
4
+ detail: string;
5
+ level: DoctorCheckLevel;
6
+ name: string;
7
+ }>;
8
+ export type SyncDoctorResult = Readonly<{
9
+ checks: readonly DoctorCheck[];
10
+ configPath: string;
11
+ hasFailures: boolean;
12
+ hasWarnings: boolean;
13
+ syncDirectory: string;
14
+ }>;
15
+ export declare const runSyncDoctor: (context: SyncContext) => Promise<SyncDoctorResult>;
16
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/services/doctor.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;AAEtD,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,gBAAgB,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AAoBH,eAAO,MAAM,aAAa,GACxB,SAAS,WAAW,KACnB,OAAO,CAAC,gBAAgB,CAyG1B,CAAC"}
@@ -0,0 +1,84 @@
1
+ import { pathExists } from "./filesystem.js";
2
+ import { ensureRepository } from "./git.js";
3
+ import { loadSyncConfig, } from "./runtime.js";
4
+ const ok = (name, detail) => ({
5
+ detail,
6
+ level: "ok",
7
+ name,
8
+ });
9
+ const warn = (name, detail) => ({
10
+ detail,
11
+ level: "warn",
12
+ name,
13
+ });
14
+ const fail = (name, detail) => ({
15
+ detail,
16
+ level: "fail",
17
+ name,
18
+ });
19
+ export const runSyncDoctor = async (context) => {
20
+ const checks = [];
21
+ try {
22
+ await ensureRepository(context.paths.syncDirectory);
23
+ checks.push(ok("git", "Sync directory is a git repository."));
24
+ }
25
+ catch (error) {
26
+ checks.push(fail("git", error instanceof Error ? error.message : "Git repository check failed."));
27
+ return {
28
+ checks,
29
+ configPath: context.paths.configPath,
30
+ hasFailures: true,
31
+ hasWarnings: false,
32
+ syncDirectory: context.paths.syncDirectory,
33
+ };
34
+ }
35
+ let config;
36
+ try {
37
+ const { effectiveConfig, fullConfig } = await loadSyncConfig(context);
38
+ config = effectiveConfig;
39
+ checks.push(ok("config", `Loaded config with ${fullConfig.entries.length} entries and ${effectiveConfig.age.recipients.length} recipients.`));
40
+ checks.push(ok("machines", effectiveConfig.activeMachine === undefined
41
+ ? "No active machine configured."
42
+ : `Active machine: ${effectiveConfig.activeMachine}.`));
43
+ }
44
+ catch (error) {
45
+ checks.push(fail("config", error instanceof Error
46
+ ? error.message
47
+ : "Sync configuration could not be read."));
48
+ return {
49
+ checks,
50
+ configPath: context.paths.configPath,
51
+ hasFailures: true,
52
+ hasWarnings: false,
53
+ syncDirectory: context.paths.syncDirectory,
54
+ };
55
+ }
56
+ checks.push((await pathExists(config.age.identityFile))
57
+ ? ok("age", `Age identity file exists at ${config.age.identityFile}.`)
58
+ : fail("age", `Age identity file is missing: ${config.age.identityFile}`));
59
+ checks.push(config.entries.length === 0
60
+ ? warn("entries", "No sync entries are configured yet.")
61
+ : ok("entries", `Tracked ${config.entries.length} sync entries.`));
62
+ const missingEntries = config.entries.filter((entry) => {
63
+ return !context.environment || entry.localPath.length > 0;
64
+ });
65
+ let missingCount = 0;
66
+ for (const entry of missingEntries) {
67
+ if (!(await pathExists(entry.localPath))) {
68
+ missingCount += 1;
69
+ }
70
+ }
71
+ checks.push(missingCount === 0
72
+ ? ok("local-paths", "All tracked local paths currently exist.")
73
+ : warn("local-paths", `${missingCount} tracked local path${missingCount === 1 ? " is" : "s are"} missing.`));
74
+ const hasFailures = checks.some((check) => check.level === "fail");
75
+ const hasWarnings = checks.some((check) => check.level === "warn");
76
+ return {
77
+ checks,
78
+ configPath: context.paths.configPath,
79
+ hasFailures,
80
+ hasWarnings,
81
+ syncDirectory: context.paths.syncDirectory,
82
+ };
83
+ };
84
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/services/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export type DevsyncErrorOptions = Readonly<{
2
+ code?: string;
3
+ details?: readonly string[];
4
+ hint?: string;
5
+ }>;
6
+ export declare class DevsyncError extends Error {
7
+ readonly code?: string;
8
+ readonly details: readonly string[];
9
+ readonly hint?: string;
10
+ constructor(message: string, options?: DevsyncErrorOptions);
11
+ }
12
+ export declare const formatDevsyncError: (error: DevsyncError | Error | string) => string;
13
+ export declare const wrapUnknownError: (message: string, error: unknown, options?: DevsyncErrorOptions) => DevsyncError;
14
+ //# sourceMappingURL=error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/services/error.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAQH,qBAAa,YAAa,SAAQ,KAAK;IACrC,SAAgB,IAAI,CAAC,EAAE,MAAM,CAAC;IAC9B,SAAgB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,SAAgB,IAAI,CAAC,EAAE,MAAM,CAAC;gBAEX,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB;CAOtE;AAED,eAAO,MAAM,kBAAkB,GAAI,OAAO,YAAY,GAAG,KAAK,GAAG,MAAM,WActE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,SAAS,MAAM,EACf,OAAO,OAAO,EACd,UAAS,mBAAwB,iBAQlC,CAAC"}
@@ -0,0 +1,38 @@
1
+ const compactLines = (lines) => {
2
+ return lines.filter((line) => {
3
+ return typeof line === "string" && line.trim().length > 0;
4
+ });
5
+ };
6
+ export class DevsyncError extends Error {
7
+ code;
8
+ details;
9
+ hint;
10
+ constructor(message, options = {}) {
11
+ super(message);
12
+ this.name = "DevsyncError";
13
+ this.code = options.code;
14
+ this.details = options.details ?? [];
15
+ this.hint = options.hint;
16
+ }
17
+ }
18
+ export const formatDevsyncError = (error) => {
19
+ if (typeof error === "string") {
20
+ return error;
21
+ }
22
+ if (!(error instanceof DevsyncError)) {
23
+ return error.message;
24
+ }
25
+ return compactLines([
26
+ error.message,
27
+ ...error.details,
28
+ error.hint === undefined ? undefined : `Hint: ${error.hint}`,
29
+ ]).join("\n");
30
+ };
31
+ export const wrapUnknownError = (message, error, options = {}) => {
32
+ const detail = error instanceof Error ? error.message.trim() : String(error);
33
+ return new DevsyncError(message, {
34
+ ...options,
35
+ details: compactLines([...(options.details ?? []), detail]),
36
+ });
37
+ };
38
+ //# sourceMappingURL=error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/services/error.ts"],"names":[],"mappings":"AAMA,MAAM,YAAY,GAAG,CAAC,KAAsC,EAAE,EAAE;IAC9D,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE;QAC3C,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrB,IAAI,CAAU;IACd,OAAO,CAAoB;IAC3B,IAAI,CAAU;IAE9B,YAAmB,OAAe,EAAE,UAA+B,EAAE;QACnE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;QACrC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAoC,EAAE,EAAE;IACzE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,CAAC,KAAK,YAAY,YAAY,CAAC,EAAE,CAAC;QACrC,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IAED,OAAO,YAAY,CAAC;QAClB,KAAK,CAAC,OAAO;QACb,GAAG,KAAK,CAAC,OAAO;QAChB,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,IAAI,EAAE;KAC7D,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,OAAe,EACf,KAAc,EACd,UAA+B,EAAE,EACjC,EAAE;IACF,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE7E,OAAO,IAAI,YAAY,CAAC,OAAO,EAAE;QAC/B,GAAG,OAAO;QACV,OAAO,EAAE,YAAY,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;KAC5D,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { lstat } from "node:fs/promises";
2
+ export { buildExecutableMode, isExecutableMode } from "#app/lib/file-mode.js";
3
+ export declare const pathExists: (path: string) => Promise<boolean>;
4
+ export declare const getPathStats: (path: string) => Promise<import("node:fs").Stats | undefined>;
5
+ export declare const listDirectoryEntries: (path: string) => Promise<import("node:fs").Dirent<string>[]>;
6
+ export declare const writeFileNode: (path: string, node: Readonly<{
7
+ contents: string | Uint8Array;
8
+ executable: boolean;
9
+ }>) => Promise<void>;
10
+ export declare const writeSymlinkNode: (path: string, linkTarget: string) => Promise<void>;
11
+ export declare const copyFilesystemNode: (sourcePath: string, targetPath: string, stats?: Awaited<ReturnType<typeof lstat>>) => Promise<void>;
12
+ export declare const replacePathAtomically: (targetPath: string, nextPath: string) => Promise<void>;
13
+ export declare const removePathAtomically: (targetPath: string) => Promise<void>;
14
+ export declare const writeTextFileAtomically: (targetPath: string, contents: string) => Promise<void>;
15
+ //# sourceMappingURL=filesystem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../src/services/filesystem.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,EAUN,MAAM,kBAAkB,CAAC;AAK1B,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAI9E,eAAO,MAAM,UAAU,GAAU,MAAM,MAAM,qBAY5C,CAAC;AAEF,eAAO,MAAM,YAAY,GAAU,MAAM,MAAM,iDAU9C,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAU,MAAM,MAAM,gDAMtD,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EACZ,MAAM,QAAQ,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,UAAU,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC,kBAKH,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAU,MAAM,MAAM,EAAE,YAAY,MAAM,kBAItE,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,YAAY,MAAM,EAClB,YAAY,MAAM,EAClB,QAAQ,OAAO,CAAC,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC,kBAiC1C,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,YAAY,MAAM,EAClB,UAAU,MAAM,kBA6BjB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAU,YAAY,MAAM,kBAc5D,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,YAAY,MAAM,EAClB,UAAU,MAAM,kBAcjB,CAAC"}