@tinyrack/dotweave 0.39.4

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 (246) hide show
  1. package/bin/index.js +5 -0
  2. package/dist/application.d.ts +5 -0
  3. package/dist/application.d.ts.map +1 -0
  4. package/dist/application.js +86 -0
  5. package/dist/application.js.map +1 -0
  6. package/dist/cli/autocomplete.d.ts +7 -0
  7. package/dist/cli/autocomplete.d.ts.map +1 -0
  8. package/dist/cli/autocomplete.js +62 -0
  9. package/dist/cli/autocomplete.js.map +1 -0
  10. package/dist/cli/cd.d.ts +4 -0
  11. package/dist/cli/cd.d.ts.map +1 -0
  12. package/dist/cli/cd.js +23 -0
  13. package/dist/cli/cd.js.map +1 -0
  14. package/dist/cli/doctor.d.ts +4 -0
  15. package/dist/cli/doctor.d.ts.map +1 -0
  16. package/dist/cli/doctor.js +92 -0
  17. package/dist/cli/doctor.js.map +1 -0
  18. package/dist/cli/index.d.ts +4 -0
  19. package/dist/cli/index.d.ts.map +1 -0
  20. package/dist/cli/index.js +22 -0
  21. package/dist/cli/index.js.map +1 -0
  22. package/dist/cli/init.d.ts +4 -0
  23. package/dist/cli/init.d.ts.map +1 -0
  24. package/dist/cli/init.js +110 -0
  25. package/dist/cli/init.js.map +1 -0
  26. package/dist/cli/profile/index.d.ts +3 -0
  27. package/dist/cli/profile/index.d.ts.map +1 -0
  28. package/dist/cli/profile/index.js +15 -0
  29. package/dist/cli/profile/index.js.map +1 -0
  30. package/dist/cli/profile/list.d.ts +4 -0
  31. package/dist/cli/profile/list.d.ts.map +1 -0
  32. package/dist/cli/profile/list.js +42 -0
  33. package/dist/cli/profile/list.js.map +1 -0
  34. package/dist/cli/profile/use.d.ts +4 -0
  35. package/dist/cli/profile/use.d.ts.map +1 -0
  36. package/dist/cli/profile/use.js +49 -0
  37. package/dist/cli/profile/use.js.map +1 -0
  38. package/dist/cli/pull.d.ts +4 -0
  39. package/dist/cli/pull.d.ts.map +1 -0
  40. package/dist/cli/pull.js +107 -0
  41. package/dist/cli/pull.js.map +1 -0
  42. package/dist/cli/push.d.ts +4 -0
  43. package/dist/cli/push.d.ts.map +1 -0
  44. package/dist/cli/push.js +49 -0
  45. package/dist/cli/push.js.map +1 -0
  46. package/dist/cli/root-commands.d.ts +13 -0
  47. package/dist/cli/root-commands.d.ts.map +1 -0
  48. package/dist/cli/root-commands.js +25 -0
  49. package/dist/cli/root-commands.js.map +1 -0
  50. package/dist/cli/status.d.ts +4 -0
  51. package/dist/cli/status.d.ts.map +1 -0
  52. package/dist/cli/status.js +132 -0
  53. package/dist/cli/status.js.map +1 -0
  54. package/dist/cli/track.d.ts +4 -0
  55. package/dist/cli/track.d.ts.map +1 -0
  56. package/dist/cli/track.js +133 -0
  57. package/dist/cli/track.js.map +1 -0
  58. package/dist/cli/untrack.d.ts +4 -0
  59. package/dist/cli/untrack.d.ts.map +1 -0
  60. package/dist/cli/untrack.js +40 -0
  61. package/dist/cli/untrack.js.map +1 -0
  62. package/dist/config/constants.d.ts +31 -0
  63. package/dist/config/constants.d.ts.map +1 -0
  64. package/dist/config/constants.js +33 -0
  65. package/dist/config/constants.js.map +1 -0
  66. package/dist/config/global-config.d.ts +21 -0
  67. package/dist/config/global-config.d.ts.map +1 -0
  68. package/dist/config/global-config.js +89 -0
  69. package/dist/config/global-config.js.map +1 -0
  70. package/dist/config/identity-file.d.ts +9 -0
  71. package/dist/config/identity-file.d.ts.map +1 -0
  72. package/dist/config/identity-file.js +48 -0
  73. package/dist/config/identity-file.js.map +1 -0
  74. package/dist/config/migration.d.ts +9 -0
  75. package/dist/config/migration.d.ts.map +1 -0
  76. package/dist/config/migration.js +61 -0
  77. package/dist/config/migration.js.map +1 -0
  78. package/dist/config/platform.d.ts +12 -0
  79. package/dist/config/platform.d.ts.map +1 -0
  80. package/dist/config/platform.js +25 -0
  81. package/dist/config/platform.js.map +1 -0
  82. package/dist/config/runtime-env.d.ts +7 -0
  83. package/dist/config/runtime-env.d.ts.map +1 -0
  84. package/dist/config/runtime-env.js +31 -0
  85. package/dist/config/runtime-env.js.map +1 -0
  86. package/dist/config/sync-entry.d.ts +14 -0
  87. package/dist/config/sync-entry.d.ts.map +1 -0
  88. package/dist/config/sync-entry.js +99 -0
  89. package/dist/config/sync-entry.js.map +1 -0
  90. package/dist/config/sync-schema.d.ts +146 -0
  91. package/dist/config/sync-schema.d.ts.map +1 -0
  92. package/dist/config/sync-schema.js +392 -0
  93. package/dist/config/sync-schema.js.map +1 -0
  94. package/dist/config/sync.d.ts +8 -0
  95. package/dist/config/sync.d.ts.map +1 -0
  96. package/dist/config/sync.js +53 -0
  97. package/dist/config/sync.js.map +1 -0
  98. package/dist/config/xdg.d.ts +10 -0
  99. package/dist/config/xdg.d.ts.map +1 -0
  100. package/dist/config/xdg.js +90 -0
  101. package/dist/config/xdg.js.map +1 -0
  102. package/dist/index.d.ts +3 -0
  103. package/dist/index.d.ts.map +1 -0
  104. package/dist/index.js +4 -0
  105. package/dist/index.js.map +1 -0
  106. package/dist/lib/content.d.ts +5 -0
  107. package/dist/lib/content.d.ts.map +1 -0
  108. package/dist/lib/content.js +29 -0
  109. package/dist/lib/content.js.map +1 -0
  110. package/dist/lib/crypto.d.ts +45 -0
  111. package/dist/lib/crypto.d.ts.map +1 -0
  112. package/dist/lib/crypto.js +130 -0
  113. package/dist/lib/crypto.js.map +1 -0
  114. package/dist/lib/env.d.ts +13 -0
  115. package/dist/lib/env.d.ts.map +1 -0
  116. package/dist/lib/env.js +50 -0
  117. package/dist/lib/env.js.map +1 -0
  118. package/dist/lib/error.d.ts +22 -0
  119. package/dist/lib/error.d.ts.map +1 -0
  120. package/dist/lib/error.js +50 -0
  121. package/dist/lib/error.js.map +1 -0
  122. package/dist/lib/file-mode.d.ts +36 -0
  123. package/dist/lib/file-mode.d.ts.map +1 -0
  124. package/dist/lib/file-mode.js +55 -0
  125. package/dist/lib/file-mode.js.map +1 -0
  126. package/dist/lib/filesystem.d.ts +60 -0
  127. package/dist/lib/filesystem.d.ts.map +1 -0
  128. package/dist/lib/filesystem.js +190 -0
  129. package/dist/lib/filesystem.js.map +1 -0
  130. package/dist/lib/git.d.ts +23 -0
  131. package/dist/lib/git.d.ts.map +1 -0
  132. package/dist/lib/git.js +162 -0
  133. package/dist/lib/git.js.map +1 -0
  134. package/dist/lib/jsonc.d.ts +8 -0
  135. package/dist/lib/jsonc.d.ts.map +1 -0
  136. package/dist/lib/jsonc.js +78 -0
  137. package/dist/lib/jsonc.js.map +1 -0
  138. package/dist/lib/path.d.ts +21 -0
  139. package/dist/lib/path.d.ts.map +1 -0
  140. package/dist/lib/path.js +44 -0
  141. package/dist/lib/path.js.map +1 -0
  142. package/dist/lib/promise.d.ts +10 -0
  143. package/dist/lib/promise.d.ts.map +1 -0
  144. package/dist/lib/promise.js +25 -0
  145. package/dist/lib/promise.js.map +1 -0
  146. package/dist/lib/string.d.ts +6 -0
  147. package/dist/lib/string.d.ts.map +1 -0
  148. package/dist/lib/string.js +8 -0
  149. package/dist/lib/string.js.map +1 -0
  150. package/dist/lib/validation.d.ts +7 -0
  151. package/dist/lib/validation.d.ts.map +1 -0
  152. package/dist/lib/validation.js +13 -0
  153. package/dist/lib/validation.js.map +1 -0
  154. package/dist/lib/version.d.ts +2 -0
  155. package/dist/lib/version.d.ts.map +1 -0
  156. package/dist/lib/version.js +4 -0
  157. package/dist/lib/version.js.map +1 -0
  158. package/dist/migrations/global-v3.d.ts +3 -0
  159. package/dist/migrations/global-v3.d.ts.map +1 -0
  160. package/dist/migrations/global-v3.js +5 -0
  161. package/dist/migrations/global-v3.js.map +1 -0
  162. package/dist/services/autocomplete.d.ts +5 -0
  163. package/dist/services/autocomplete.d.ts.map +1 -0
  164. package/dist/services/autocomplete.js +185 -0
  165. package/dist/services/autocomplete.js.map +1 -0
  166. package/dist/services/config-file.d.ts +73 -0
  167. package/dist/services/config-file.d.ts.map +1 -0
  168. package/dist/services/config-file.js +40 -0
  169. package/dist/services/config-file.js.map +1 -0
  170. package/dist/services/doctor.d.ts +16 -0
  171. package/dist/services/doctor.d.ts.map +1 -0
  172. package/dist/services/doctor.js +126 -0
  173. package/dist/services/doctor.js.map +1 -0
  174. package/dist/services/init.d.ts +24 -0
  175. package/dist/services/init.d.ts.map +1 -0
  176. package/dist/services/init.js +265 -0
  177. package/dist/services/init.js.map +1 -0
  178. package/dist/services/local-materialization.d.ts +30 -0
  179. package/dist/services/local-materialization.d.ts.map +1 -0
  180. package/dist/services/local-materialization.js +451 -0
  181. package/dist/services/local-materialization.js.map +1 -0
  182. package/dist/services/local-snapshot.d.ts +26 -0
  183. package/dist/services/local-snapshot.d.ts.map +1 -0
  184. package/dist/services/local-snapshot.js +119 -0
  185. package/dist/services/local-snapshot.js.map +1 -0
  186. package/dist/services/paths.d.ts +8 -0
  187. package/dist/services/paths.d.ts.map +1 -0
  188. package/dist/services/paths.js +71 -0
  189. package/dist/services/paths.js.map +1 -0
  190. package/dist/services/profile.d.ts +39 -0
  191. package/dist/services/profile.d.ts.map +1 -0
  192. package/dist/services/profile.js +124 -0
  193. package/dist/services/profile.js.map +1 -0
  194. package/dist/services/pull.d.ts +38 -0
  195. package/dist/services/pull.d.ts.map +1 -0
  196. package/dist/services/pull.js +148 -0
  197. package/dist/services/pull.js.map +1 -0
  198. package/dist/services/push.d.ts +38 -0
  199. package/dist/services/push.d.ts.map +1 -0
  200. package/dist/services/push.js +120 -0
  201. package/dist/services/push.js.map +1 -0
  202. package/dist/services/repo-artifacts.d.ts +52 -0
  203. package/dist/services/repo-artifacts.d.ts.map +1 -0
  204. package/dist/services/repo-artifacts.js +325 -0
  205. package/dist/services/repo-artifacts.js.map +1 -0
  206. package/dist/services/repo-snapshot.d.ts +7 -0
  207. package/dist/services/repo-snapshot.d.ts.map +1 -0
  208. package/dist/services/repo-snapshot.js +181 -0
  209. package/dist/services/repo-snapshot.js.map +1 -0
  210. package/dist/services/runtime.d.ts +30 -0
  211. package/dist/services/runtime.d.ts.map +1 -0
  212. package/dist/services/runtime.js +71 -0
  213. package/dist/services/runtime.js.map +1 -0
  214. package/dist/services/set.d.ts +41 -0
  215. package/dist/services/set.d.ts.map +1 -0
  216. package/dist/services/set.js +288 -0
  217. package/dist/services/set.js.map +1 -0
  218. package/dist/services/status.d.ts +41 -0
  219. package/dist/services/status.d.ts.map +1 -0
  220. package/dist/services/status.js +87 -0
  221. package/dist/services/status.js.map +1 -0
  222. package/dist/services/terminal/cli-runtime.d.ts +18 -0
  223. package/dist/services/terminal/cli-runtime.d.ts.map +1 -0
  224. package/dist/services/terminal/cli-runtime.js +19 -0
  225. package/dist/services/terminal/cli-runtime.js.map +1 -0
  226. package/dist/services/terminal/logger.d.ts +9 -0
  227. package/dist/services/terminal/logger.d.ts.map +1 -0
  228. package/dist/services/terminal/logger.js +15 -0
  229. package/dist/services/terminal/logger.js.map +1 -0
  230. package/dist/services/terminal/path-completion.d.ts +3 -0
  231. package/dist/services/terminal/path-completion.d.ts.map +1 -0
  232. package/dist/services/terminal/path-completion.js +108 -0
  233. package/dist/services/terminal/path-completion.js.map +1 -0
  234. package/dist/services/terminal/shell.d.ts +24 -0
  235. package/dist/services/terminal/shell.d.ts.map +1 -0
  236. package/dist/services/terminal/shell.js +227 -0
  237. package/dist/services/terminal/shell.js.map +1 -0
  238. package/dist/services/track.d.ts +20 -0
  239. package/dist/services/track.d.ts.map +1 -0
  240. package/dist/services/track.js +224 -0
  241. package/dist/services/track.js.map +1 -0
  242. package/dist/services/untrack.d.ts +13 -0
  243. package/dist/services/untrack.d.ts.map +1 -0
  244. package/dist/services/untrack.js +133 -0
  245. package/dist/services/untrack.js.map +1 -0
  246. package/package.json +84 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/services/terminal/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,aAAa,EAAE,MAAM,SAAS,CAAC;AAI9D,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,UAKK,EAAE,EACI,EAAE;IACb,MAAM,MAAM,GAAG,aAAa,CAAC;QAC3B,aAAa,EAAE;YACb,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK;YACpD,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,KAAK;SACZ;QACD,KAAK,EAAE,OAAO,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;QACnE,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;KACpE,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC1E,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { DotweaveCliContext } from "#app/services/terminal/cli-runtime.ts";
2
+ export declare const proposePathCompletions: (this: DotweaveCliContext, partial: string) => Promise<string[]>;
3
+ //# sourceMappingURL=path-completion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-completion.d.ts","sourceRoot":"","sources":["../../../src/services/terminal/path-completion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AA8IhF,eAAO,MAAM,sBAAsB,GACjC,MAAM,kBAAkB,EACxB,SAAS,MAAM,sBA0BhB,CAAC"}
@@ -0,0 +1,108 @@
1
+ const HOME_PREFIX = "~";
2
+ const HIDDEN_ENTRY_PREFIX = ".";
3
+ const RECOVERABLE_ERROR_CODES = new Set([
4
+ "EACCES",
5
+ "ENOENT",
6
+ "ENOTDIR",
7
+ ]);
8
+ const SHELL_PATH_SEPARATOR = "/";
9
+ const isRecoverableCompletionError = (error) => {
10
+ return (error instanceof Error &&
11
+ "code" in error &&
12
+ typeof error.code === "string" &&
13
+ RECOVERABLE_ERROR_CODES.has(error.code));
14
+ };
15
+ const buildRelativeCompletionBase = (partial, context) => {
16
+ const lastSeparatorIndex = partial.lastIndexOf(SHELL_PATH_SEPARATOR);
17
+ const displayPrefix = lastSeparatorIndex < 0 ? "" : partial.slice(0, lastSeparatorIndex + 1);
18
+ const entryPrefix = lastSeparatorIndex < 0 ? partial : partial.slice(lastSeparatorIndex + 1);
19
+ return {
20
+ absoluteDirectory: context.path.resolve(context.process.cwd(), displayPrefix === "" ? "." : displayPrefix),
21
+ displayPrefix,
22
+ entryPrefix,
23
+ };
24
+ };
25
+ const buildAbsoluteCompletionBase = (partial, context) => {
26
+ const lastSeparatorIndex = partial.lastIndexOf(SHELL_PATH_SEPARATOR);
27
+ const displayPrefix = lastSeparatorIndex < 0
28
+ ? SHELL_PATH_SEPARATOR
29
+ : partial.slice(0, lastSeparatorIndex + 1);
30
+ const entryPrefix = lastSeparatorIndex < 0 ? partial : partial.slice(lastSeparatorIndex + 1);
31
+ return {
32
+ absoluteDirectory: context.path.resolve(displayPrefix),
33
+ displayPrefix,
34
+ entryPrefix,
35
+ };
36
+ };
37
+ const buildHomeCompletionBase = (partial, context) => {
38
+ if (partial === HOME_PREFIX) {
39
+ return {
40
+ absoluteDirectory: context.os.homedir(),
41
+ displayPrefix: `${HOME_PREFIX}${SHELL_PATH_SEPARATOR}`,
42
+ entryPrefix: "",
43
+ };
44
+ }
45
+ if (!partial.startsWith(`${HOME_PREFIX}${SHELL_PATH_SEPARATOR}`)) {
46
+ return undefined;
47
+ }
48
+ const homeRelativePath = partial.slice(2);
49
+ const lastSeparatorIndex = homeRelativePath.lastIndexOf(SHELL_PATH_SEPARATOR);
50
+ const directorySuffix = lastSeparatorIndex < 0
51
+ ? ""
52
+ : homeRelativePath.slice(0, lastSeparatorIndex + 1);
53
+ const entryPrefix = lastSeparatorIndex < 0
54
+ ? homeRelativePath
55
+ : homeRelativePath.slice(lastSeparatorIndex + 1);
56
+ return {
57
+ absoluteDirectory: context.path.resolve(context.os.homedir(), directorySuffix === "" ? "." : directorySuffix),
58
+ displayPrefix: `${HOME_PREFIX}${SHELL_PATH_SEPARATOR}${directorySuffix}`,
59
+ entryPrefix,
60
+ };
61
+ };
62
+ const resolveCompletionBase = (partial, context) => {
63
+ if (partial.startsWith(HOME_PREFIX)) {
64
+ return buildHomeCompletionBase(partial, context);
65
+ }
66
+ if (partial.startsWith(SHELL_PATH_SEPARATOR)) {
67
+ return buildAbsoluteCompletionBase(partial, context);
68
+ }
69
+ return buildRelativeCompletionBase(partial, context);
70
+ };
71
+ const shouldIncludeEntry = (name, entryPrefix) => {
72
+ if (!name.startsWith(entryPrefix)) {
73
+ return false;
74
+ }
75
+ if (!entryPrefix.startsWith(HIDDEN_ENTRY_PREFIX) &&
76
+ name.startsWith(HIDDEN_ENTRY_PREFIX)) {
77
+ return false;
78
+ }
79
+ return true;
80
+ };
81
+ const buildCompletionValue = (base, entryName, isDirectory) => {
82
+ const completion = `${base.displayPrefix}${entryName}`;
83
+ return isDirectory ? `${completion}${SHELL_PATH_SEPARATOR}` : completion;
84
+ };
85
+ export const proposePathCompletions = async function (partial) {
86
+ const base = resolveCompletionBase(partial, this);
87
+ if (base === undefined) {
88
+ return [];
89
+ }
90
+ try {
91
+ const entries = await this.fs.promises.readdir(base.absoluteDirectory, {
92
+ withFileTypes: true,
93
+ });
94
+ return entries
95
+ .filter((entry) => shouldIncludeEntry(entry.name, base.entryPrefix))
96
+ .map((entry) => {
97
+ return buildCompletionValue(base, entry.name, entry.isDirectory());
98
+ })
99
+ .sort((left, right) => left.localeCompare(right));
100
+ }
101
+ catch (error) {
102
+ if (isRecoverableCompletionError(error)) {
103
+ return [];
104
+ }
105
+ throw error;
106
+ }
107
+ };
108
+ //# sourceMappingURL=path-completion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-completion.js","sourceRoot":"","sources":["../../../src/services/terminal/path-completion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { PlatformKey } from "#app/config/platform.ts";
2
+ type ShellCommand = Readonly<{
3
+ args: readonly string[];
4
+ command: string;
5
+ }>;
6
+ type WindowsProcessInfo = Readonly<{
7
+ commandLine?: string;
8
+ executablePath?: string;
9
+ name?: string;
10
+ parentProcessId: number;
11
+ processId: number;
12
+ }>;
13
+ type ResolveShellCommandOptions = Readonly<{
14
+ initialWindowsProcessId?: number;
15
+ inspectWindowsProcess?: (processId: number) => Promise<WindowsProcessInfo | undefined>;
16
+ }>;
17
+ export declare const resolveShellCommandForPlatform: (platformKey: PlatformKey, options?: ResolveShellCommandOptions) => Promise<ShellCommand>;
18
+ export declare const resolveShellCommand: () => Promise<Readonly<{
19
+ args: readonly string[];
20
+ command: string;
21
+ }>>;
22
+ export declare const launchShellInDirectory: (directory: string) => Promise<void>;
23
+ export {};
24
+ //# sourceMappingURL=shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../../src/services/terminal/shell.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAK3D,KAAK,YAAY,GAAG,QAAQ,CAAC;IAC3B,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAEH,KAAK,kBAAkB,GAAG,QAAQ,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC,CAAC;AAEH,KAAK,0BAA0B,GAAG,QAAQ,CAAC;IACzC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,qBAAqB,CAAC,EAAE,CACtB,SAAS,EAAE,MAAM,KACd,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAAC;CAC9C,CAAC,CAAC;AA6NH,eAAO,MAAM,8BAA8B,GACzC,aAAa,WAAW,EACxB,UAAS,0BAA+B,KACvC,OAAO,CAAC,YAAY,CAStB,CAAC;AAEF,eAAO,MAAM,mBAAmB;UA5PxB,SAAS,MAAM,EAAE;aACd,MAAM;GA6PhB,CAAC;AA4BF,eAAO,MAAM,sBAAsB,GAAU,WAAW,MAAM,kBA8C7D,CAAC"}
@@ -0,0 +1,227 @@
1
+ import { spawn } from "node:child_process";
2
+ import { resolveCurrentPlatformKey } from "#app/config/runtime-env.ts";
3
+ import { ENV } from "#app/lib/env.ts";
4
+ import { DotweaveError } from "#app/lib/error.ts";
5
+ const windowsShellNames = new Set([
6
+ "bash",
7
+ "cmd",
8
+ "fish",
9
+ "nu",
10
+ "powershell",
11
+ "pwsh",
12
+ "sh",
13
+ "zsh",
14
+ ]);
15
+ const windowsProcessQueryScript = [
16
+ "$processId = [int]$args[0]",
17
+ '$process = Get-CimInstance Win32_Process -Filter ("ProcessId = " + $processId)',
18
+ "if ($null -eq $process) { exit 0 }",
19
+ "$encode = {",
20
+ " param([string]$value)",
21
+ ' if ([string]::IsNullOrEmpty($value)) { return "" }',
22
+ " return [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($value))",
23
+ "}",
24
+ "[Console]::Out.WriteLine($process.ProcessId)",
25
+ "[Console]::Out.WriteLine($process.ParentProcessId)",
26
+ "[Console]::Out.WriteLine((& $encode $process.Name))",
27
+ "[Console]::Out.WriteLine((& $encode $process.ExecutablePath))",
28
+ "[Console]::Out.WriteLine((& $encode $process.CommandLine))",
29
+ ].join(";");
30
+ const trimConfiguredValue = (value) => {
31
+ const trimmed = value?.trim();
32
+ return trimmed === undefined || trimmed === "" ? undefined : trimmed;
33
+ };
34
+ const decodeWindowsProcessField = (value) => {
35
+ const trimmed = trimConfiguredValue(value);
36
+ if (trimmed === undefined) {
37
+ return undefined;
38
+ }
39
+ return Buffer.from(trimmed, "base64").toString("utf8");
40
+ };
41
+ const normalizeProcessName = (value) => {
42
+ const trimmed = trimConfiguredValue(value);
43
+ if (trimmed === undefined) {
44
+ return undefined;
45
+ }
46
+ const filename = trimmed
47
+ .replaceAll("\\", "/")
48
+ .split("/")
49
+ .at(-1)
50
+ ?.toLowerCase();
51
+ if (filename === undefined || filename === "") {
52
+ return undefined;
53
+ }
54
+ return filename.endsWith(".exe") ? filename.slice(0, -4) : filename;
55
+ };
56
+ const stripSingleTrailingLineEnding = (value) => {
57
+ if (value.endsWith("\r\n")) {
58
+ return value.slice(0, -2);
59
+ }
60
+ if (value.endsWith("\n")) {
61
+ return value.slice(0, -1);
62
+ }
63
+ return value;
64
+ };
65
+ const parseWindowsProcessInfo = (output) => {
66
+ const normalized = stripSingleTrailingLineEnding(output);
67
+ if (normalized === "") {
68
+ return undefined;
69
+ }
70
+ const lines = normalized.split(/\r?\n/u);
71
+ if (lines.length < 5) {
72
+ return undefined;
73
+ }
74
+ const [processIdLine, parentProcessIdLine, nameValue, executablePathValue, commandLineValue,] = lines;
75
+ const processId = Number.parseInt(processIdLine ?? "", 10);
76
+ const parentProcessId = Number.parseInt(parentProcessIdLine ?? "", 10);
77
+ if (!Number.isSafeInteger(processId) ||
78
+ processId <= 0 ||
79
+ !Number.isSafeInteger(parentProcessId) ||
80
+ parentProcessId < 0) {
81
+ return undefined;
82
+ }
83
+ return {
84
+ commandLine: decodeWindowsProcessField(commandLineValue),
85
+ executablePath: decodeWindowsProcessField(executablePathValue),
86
+ name: decodeWindowsProcessField(nameValue),
87
+ parentProcessId,
88
+ processId,
89
+ };
90
+ };
91
+ const inspectWindowsProcess = async (processId) => {
92
+ return await new Promise((resolve) => {
93
+ const child = spawn("powershell.exe", [
94
+ "-NoLogo",
95
+ "-NoProfile",
96
+ "-NonInteractive",
97
+ "-Command",
98
+ windowsProcessQueryScript,
99
+ String(processId),
100
+ ], {
101
+ env: process.env,
102
+ stdio: ["ignore", "pipe", "ignore"],
103
+ windowsHide: true,
104
+ });
105
+ let stdout = "";
106
+ child.stdout?.setEncoding("utf8");
107
+ child.stdout?.on("data", (chunk) => {
108
+ stdout += chunk;
109
+ });
110
+ child.on("error", () => {
111
+ resolve(undefined);
112
+ });
113
+ child.on("close", (code) => {
114
+ resolve(code === 0 ? parseWindowsProcessInfo(stdout) : undefined);
115
+ });
116
+ });
117
+ };
118
+ const isWrapperCmdProcess = (processInfo) => {
119
+ return /(?:^|\s)\/c(?:\s|$)/iu.test(processInfo.commandLine ?? "");
120
+ };
121
+ const createShellCommandFromProcess = (processInfo) => {
122
+ const command = trimConfiguredValue(processInfo.executablePath) ??
123
+ trimConfiguredValue(processInfo.name);
124
+ const processName = normalizeProcessName(command);
125
+ if (command === undefined ||
126
+ processName === undefined ||
127
+ !windowsShellNames.has(processName)) {
128
+ return undefined;
129
+ }
130
+ if (processName === "cmd" && isWrapperCmdProcess(processInfo)) {
131
+ return undefined;
132
+ }
133
+ return {
134
+ args: [],
135
+ command,
136
+ };
137
+ };
138
+ const resolveWindowsShellCommand = async (options) => {
139
+ const inspect = options.inspectWindowsProcess ?? inspectWindowsProcess;
140
+ const visited = new Set();
141
+ let processId = options.initialWindowsProcessId ?? process.ppid;
142
+ while (Number.isSafeInteger(processId) &&
143
+ processId > 0 &&
144
+ !visited.has(processId) &&
145
+ visited.size < 16) {
146
+ visited.add(processId);
147
+ const processInfo = await inspect(processId);
148
+ if (processInfo === undefined) {
149
+ break;
150
+ }
151
+ const shellCommand = createShellCommandFromProcess(processInfo);
152
+ if (shellCommand !== undefined) {
153
+ return shellCommand;
154
+ }
155
+ processId = processInfo.parentProcessId;
156
+ }
157
+ return {
158
+ args: [],
159
+ command: trimConfiguredValue(ENV.COMSPEC) ?? "cmd.exe",
160
+ };
161
+ };
162
+ export const resolveShellCommandForPlatform = async (platformKey, options = {}) => {
163
+ if (platformKey === "win") {
164
+ return await resolveWindowsShellCommand(options);
165
+ }
166
+ return {
167
+ args: [],
168
+ command: trimConfiguredValue(ENV.SHELL) ?? "/bin/sh",
169
+ };
170
+ };
171
+ export const resolveShellCommand = async () => {
172
+ return await resolveShellCommandForPlatform(resolveCurrentPlatformKey());
173
+ };
174
+ const createShellFailureHint = () => {
175
+ return resolveCurrentPlatformKey() === "win"
176
+ ? "Set COMSPEC to a valid shell executable."
177
+ : "Set SHELL to a valid shell executable.";
178
+ };
179
+ const createShellExitError = (command, code, signal) => {
180
+ const error = new DotweaveError(signal === null
181
+ ? `Shell exited with code ${code ?? "unknown"}.`
182
+ : `Shell exited due to signal ${signal}.`, {
183
+ details: [`Shell: ${command}`],
184
+ hint: "Exit the spawned shell normally when you're done.",
185
+ });
186
+ error.exitCode = code ?? 1;
187
+ return error;
188
+ };
189
+ export const launchShellInDirectory = async (directory) => {
190
+ const { args, command } = await resolveShellCommand();
191
+ await new Promise((resolve, reject) => {
192
+ const child = spawn(command, [...args], {
193
+ cwd: directory,
194
+ env: process.env,
195
+ stdio: "inherit",
196
+ });
197
+ let settled = false;
198
+ const finish = (handler) => {
199
+ if (settled) {
200
+ return;
201
+ }
202
+ settled = true;
203
+ handler();
204
+ };
205
+ child.on("error", (error) => {
206
+ finish(() => {
207
+ reject(new DotweaveError("Failed to launch shell.", {
208
+ details: [
209
+ `Shell: ${command}`,
210
+ error instanceof Error ? error.message : String(error),
211
+ ],
212
+ hint: createShellFailureHint(),
213
+ }));
214
+ });
215
+ });
216
+ child.on("close", (code, signal) => {
217
+ if (code === 0) {
218
+ finish(resolve);
219
+ return;
220
+ }
221
+ finish(() => {
222
+ reject(createShellExitError(command, code, signal));
223
+ });
224
+ });
225
+ });
226
+ };
227
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../../src/services/terminal/shell.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { type SyncConfigEntryKind, type SyncMode } from "#app/config/sync.ts";
2
+ export type TrackRequest = Readonly<{
3
+ profiles?: readonly string[];
4
+ mode: SyncMode;
5
+ repoPath?: string;
6
+ target: string;
7
+ }>;
8
+ export type TrackResult = Readonly<{
9
+ alreadyTracked: boolean;
10
+ changed: boolean;
11
+ configPath: string;
12
+ kind: SyncConfigEntryKind;
13
+ localPath: string;
14
+ profiles: readonly string[];
15
+ mode: SyncMode;
16
+ repoPath: string;
17
+ syncDirectory: string;
18
+ }>;
19
+ export declare const trackTarget: (request: TrackRequest, cwd: string) => Promise<TrackResult>;
20
+ //# sourceMappingURL=track.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"track.d.ts","sourceRoot":"","sources":["../../src/services/track.ts"],"names":[],"mappings":"AAKA,OAAO,EAML,KAAK,mBAAmB,EACxB,KAAK,QAAQ,EACd,MAAM,qBAAqB,CAAC;AAmB7B,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC;IAClC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;IACjC,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,mBAAmB,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AAiHH,eAAO,MAAM,WAAW,GACtB,SAAS,YAAY,EACrB,KAAK,MAAM,KACV,OAAO,CAAC,WAAW,CAqLrB,CAAC"}
@@ -0,0 +1,224 @@
1
+ import { resolve } from "node:path";
2
+ import { resolveDefaultIdentityFile } from "#app/config/identity-file.ts";
3
+ import { readEnvValue } from "#app/config/runtime-env.ts";
4
+ import { normalizeSyncProfileName, normalizeSyncRepoPath, readSyncConfig, } from "#app/config/sync.ts";
5
+ import { expandHomePath } from "#app/config/xdg.ts";
6
+ import { DotweaveError } from "#app/lib/error.ts";
7
+ import { getPathStats } from "#app/lib/filesystem.ts";
8
+ import { ensureGitRepository } from "#app/lib/git.ts";
9
+ import { doPathsOverlap } from "#app/lib/path.ts";
10
+ import { buildSyncConfigDocument, writeValidatedSyncConfig, } from "./config-file.js";
11
+ import { buildConfiguredHomeLocalPath, buildRepoPathWithinRoot, } from "./paths.js";
12
+ import { resolveSyncConfigResolutionContext, resolveSyncPaths, } from "./runtime.js";
13
+ const buildDefaultPlatformMode = (mode) => ({
14
+ default: mode,
15
+ });
16
+ const hasPlatformSpecificModeOverride = (configuredMode) => {
17
+ return (configuredMode.win !== undefined ||
18
+ configuredMode.mac !== undefined ||
19
+ configuredMode.linux !== undefined ||
20
+ configuredMode.wsl !== undefined);
21
+ };
22
+ const buildDefaultPlatformRepoPath = (repoPath) => ({
23
+ default: normalizeSyncRepoPath(repoPath),
24
+ });
25
+ const buildTrackEntryCandidate = async (targetPath, syncDirectory, homeDirectory, input) => {
26
+ const targetStats = await getPathStats(targetPath);
27
+ if (targetStats === undefined) {
28
+ throw new DotweaveError("Sync target does not exist.", {
29
+ code: "TARGET_NOT_FOUND",
30
+ details: [`Target: ${targetPath}`],
31
+ hint: "Create the file or directory first, then run the command again.",
32
+ });
33
+ }
34
+ const kind = (() => {
35
+ if (targetStats.isDirectory()) {
36
+ return "directory";
37
+ }
38
+ if (targetStats.isFile() || targetStats.isSymbolicLink()) {
39
+ return "file";
40
+ }
41
+ throw new DotweaveError("Sync target type is not supported.", {
42
+ code: "TARGET_UNSUPPORTED_TYPE",
43
+ details: [`Target: ${targetPath}`],
44
+ hint: "Track a regular file, symlink, or directory.",
45
+ });
46
+ })();
47
+ if (doPathsOverlap(targetPath, syncDirectory)) {
48
+ throw new DotweaveError("Sync target overlaps the dotweave sync directory.", {
49
+ code: "TARGET_OVERLAPS_SYNC_DIR",
50
+ details: [`Target: ${targetPath}`, `Sync directory: ${syncDirectory}`],
51
+ hint: "Choose a path outside the dotweave sync directory.",
52
+ });
53
+ }
54
+ if (input.identityFile !== undefined &&
55
+ doPathsOverlap(targetPath, input.identityFile)) {
56
+ throw new DotweaveError("Sync target contains the configured age identity file.", {
57
+ code: "TARGET_OVERLAPS_IDENTITY",
58
+ details: [
59
+ `Target: ${targetPath}`,
60
+ `Age identity file: ${input.identityFile}`,
61
+ ],
62
+ hint: "Store age key material outside tracked sync targets.",
63
+ });
64
+ }
65
+ const localRepoPath = buildRepoPathWithinRoot(targetPath, homeDirectory, "Sync target");
66
+ const configuredLocalPath = buildConfiguredHomeLocalPath(localRepoPath);
67
+ const configuredRepoPath = input.repoPath === undefined
68
+ ? undefined
69
+ : buildDefaultPlatformRepoPath(input.repoPath);
70
+ const repoPath = configuredRepoPath?.default ?? localRepoPath;
71
+ return {
72
+ configuredLocalPath,
73
+ ...(configuredRepoPath === undefined ? {} : { configuredRepoPath }),
74
+ kind,
75
+ localPath: targetPath,
76
+ profiles: input.profiles?.map((m) => normalizeSyncProfileName(m)) ?? [],
77
+ profilesExplicit: input.profiles !== undefined,
78
+ mode: input.mode,
79
+ modeExplicit: true,
80
+ configuredMode: buildDefaultPlatformMode(input.mode),
81
+ permissionExplicit: false,
82
+ repoPath,
83
+ };
84
+ };
85
+ export const trackTarget = async (request, cwd) => {
86
+ const target = request.target.trim();
87
+ if (target.length === 0) {
88
+ throw new DotweaveError("Target path is required.", {
89
+ code: "TARGET_REQUIRED",
90
+ hint: "Pass a file or directory path, for example 'dotweave track ~/.gitconfig'.",
91
+ });
92
+ }
93
+ const { syncDirectory, configPath } = resolveSyncPaths();
94
+ const context = resolveSyncConfigResolutionContext();
95
+ await ensureGitRepository(syncDirectory);
96
+ const config = await readSyncConfig(syncDirectory, context);
97
+ const identityFile = config.age !== undefined
98
+ ? resolveDefaultIdentityFile(readEnvValue("HOME"), readEnvValue("XDG_CONFIG_HOME"))
99
+ : undefined;
100
+ const isProfileClear = request.profiles !== undefined &&
101
+ request.profiles.length === 1 &&
102
+ request.profiles[0] === "";
103
+ const effectiveProfiles = isProfileClear ? [] : request.profiles;
104
+ const candidate = await buildTrackEntryCandidate(resolve(cwd, expandHomePath(target, context.homeDirectory)), syncDirectory, context.homeDirectory, {
105
+ identityFile,
106
+ profiles: effectiveProfiles,
107
+ mode: request.mode,
108
+ repoPath: request.repoPath,
109
+ });
110
+ const existingEntry = config.entries.find((entry) => entry.localPath === candidate.localPath);
111
+ const alreadyTracked = existingEntry !== undefined && existingEntry.kind === candidate.kind;
112
+ if (existingEntry !== undefined && existingEntry.kind !== candidate.kind) {
113
+ throw new DotweaveError("Sync target conflicts with an existing tracked entry.", {
114
+ code: "TARGET_CONFLICT",
115
+ details: [
116
+ `Requested local path: ${candidate.localPath}`,
117
+ `Requested repo path: ${candidate.repoPath}`,
118
+ `Existing entry: ${existingEntry.localPath} -> ${existingEntry.repoPath}`,
119
+ ],
120
+ hint: "Untrack or rename the existing entry before adding this root.",
121
+ });
122
+ }
123
+ const nextEntry = existingEntry !== undefined && request.repoPath === undefined
124
+ ? {
125
+ ...candidate,
126
+ configuredRepoPath: existingEntry.configuredRepoPath,
127
+ repoPath: existingEntry.repoPath,
128
+ }
129
+ : candidate;
130
+ const repoPathConflict = config.entries.find((entry) => {
131
+ return (entry.repoPath === nextEntry.repoPath &&
132
+ entry.localPath !== nextEntry.localPath);
133
+ });
134
+ if (repoPathConflict !== undefined) {
135
+ throw new DotweaveError("Sync target conflicts with an existing tracked entry.", {
136
+ code: "TARGET_CONFLICT",
137
+ details: [
138
+ `Requested local path: ${nextEntry.localPath}`,
139
+ `Requested repo path: ${nextEntry.repoPath}`,
140
+ `Existing entry: ${repoPathConflict.localPath} -> ${repoPathConflict.repoPath}`,
141
+ ],
142
+ hint: "Change --repo-path or untrack the conflicting entry first.",
143
+ });
144
+ }
145
+ if (!alreadyTracked) {
146
+ const nextConfig = buildSyncConfigDocument({
147
+ ...config,
148
+ entries: [...config.entries, nextEntry],
149
+ });
150
+ await writeValidatedSyncConfig(syncDirectory, nextConfig, context);
151
+ return {
152
+ alreadyTracked,
153
+ changed: true,
154
+ configPath,
155
+ kind: nextEntry.kind,
156
+ localPath: nextEntry.localPath,
157
+ profiles: nextEntry.profiles,
158
+ mode: nextEntry.mode,
159
+ repoPath: nextEntry.repoPath,
160
+ syncDirectory,
161
+ };
162
+ }
163
+ const requestedConfiguredMode = buildDefaultPlatformMode(request.mode);
164
+ const modeChanged = existingEntry?.mode !== request.mode ||
165
+ existingEntry?.configuredMode.default !== requestedConfiguredMode.default ||
166
+ (existingEntry !== undefined &&
167
+ hasPlatformSpecificModeOverride(existingEntry.configuredMode));
168
+ const profilesChanged = effectiveProfiles !== undefined &&
169
+ (existingEntry?.profiles.length !== candidate.profiles.length ||
170
+ !candidate.profiles.every((m) => existingEntry?.profiles.includes(m)));
171
+ const repoPathChanged = request.repoPath !== undefined &&
172
+ (existingEntry?.repoPath !== nextEntry.repoPath ||
173
+ JSON.stringify(existingEntry?.configuredRepoPath) !==
174
+ JSON.stringify(nextEntry.configuredRepoPath));
175
+ const changed = modeChanged || profilesChanged || repoPathChanged;
176
+ if (changed) {
177
+ const nextConfig = buildSyncConfigDocument({
178
+ ...config,
179
+ entries: config.entries.map((entry) => {
180
+ if (entry.localPath !== candidate.localPath) {
181
+ return entry;
182
+ }
183
+ return {
184
+ ...entry,
185
+ ...(repoPathChanged
186
+ ? {
187
+ configuredRepoPath: nextEntry.configuredRepoPath,
188
+ repoPath: nextEntry.repoPath,
189
+ }
190
+ : {}),
191
+ ...(modeChanged
192
+ ? {
193
+ configuredMode: requestedConfiguredMode,
194
+ mode: request.mode,
195
+ }
196
+ : {}),
197
+ ...(profilesChanged
198
+ ? {
199
+ profiles: candidate.profiles,
200
+ profilesExplicit: candidate.profilesExplicit,
201
+ }
202
+ : {}),
203
+ };
204
+ }),
205
+ });
206
+ await writeValidatedSyncConfig(syncDirectory, nextConfig, context);
207
+ }
208
+ return {
209
+ alreadyTracked,
210
+ changed,
211
+ configPath,
212
+ kind: nextEntry.kind,
213
+ localPath: nextEntry.localPath,
214
+ profiles: profilesChanged
215
+ ? nextEntry.profiles
216
+ : (existingEntry?.profiles ?? []),
217
+ mode: modeChanged ? request.mode : (existingEntry?.mode ?? request.mode),
218
+ repoPath: repoPathChanged || !alreadyTracked
219
+ ? nextEntry.repoPath
220
+ : (existingEntry?.repoPath ?? nextEntry.repoPath),
221
+ syncDirectory,
222
+ };
223
+ };
224
+ //# sourceMappingURL=track.js.map