@launchfile/macos-dev 0.1.3

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 (158) hide show
  1. package/CLAUDE.md +37 -0
  2. package/dist/__tests__/dry-run.test.d.ts +2 -0
  3. package/dist/__tests__/dry-run.test.d.ts.map +1 -0
  4. package/dist/__tests__/dry-run.test.js +129 -0
  5. package/dist/__tests__/dry-run.test.js.map +1 -0
  6. package/dist/__tests__/env-writer.test.d.ts +2 -0
  7. package/dist/__tests__/env-writer.test.d.ts.map +1 -0
  8. package/dist/__tests__/env-writer.test.js +127 -0
  9. package/dist/__tests__/env-writer.test.js.map +1 -0
  10. package/dist/__tests__/lockfile-detect.test.d.ts +2 -0
  11. package/dist/__tests__/lockfile-detect.test.d.ts.map +1 -0
  12. package/dist/__tests__/lockfile-detect.test.js +75 -0
  13. package/dist/__tests__/lockfile-detect.test.js.map +1 -0
  14. package/dist/__tests__/port-allocator.test.d.ts +2 -0
  15. package/dist/__tests__/port-allocator.test.d.ts.map +1 -0
  16. package/dist/__tests__/port-allocator.test.js +53 -0
  17. package/dist/__tests__/port-allocator.test.js.map +1 -0
  18. package/dist/__tests__/secret-generator.test.d.ts +2 -0
  19. package/dist/__tests__/secret-generator.test.d.ts.map +1 -0
  20. package/dist/__tests__/secret-generator.test.js +26 -0
  21. package/dist/__tests__/secret-generator.test.js.map +1 -0
  22. package/dist/__tests__/state.test.d.ts +2 -0
  23. package/dist/__tests__/state.test.d.ts.map +1 -0
  24. package/dist/__tests__/state.test.js +30 -0
  25. package/dist/__tests__/state.test.js.map +1 -0
  26. package/dist/cli.d.ts +12 -0
  27. package/dist/cli.d.ts.map +1 -0
  28. package/dist/cli.js +69 -0
  29. package/dist/cli.js.map +1 -0
  30. package/dist/env-writer.d.ts +46 -0
  31. package/dist/env-writer.d.ts.map +1 -0
  32. package/dist/env-writer.js +175 -0
  33. package/dist/env-writer.js.map +1 -0
  34. package/dist/health.d.ts +12 -0
  35. package/dist/health.d.ts.map +1 -0
  36. package/dist/health.js +72 -0
  37. package/dist/health.js.map +1 -0
  38. package/dist/index.d.ts +9 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +8 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/lockfile-detect.d.ts +14 -0
  43. package/dist/lockfile-detect.d.ts.map +1 -0
  44. package/dist/lockfile-detect.js +40 -0
  45. package/dist/lockfile-detect.js.map +1 -0
  46. package/dist/port-allocator.d.ts +21 -0
  47. package/dist/port-allocator.d.ts.map +1 -0
  48. package/dist/port-allocator.js +78 -0
  49. package/dist/port-allocator.js.map +1 -0
  50. package/dist/prereqs.d.ts +10 -0
  51. package/dist/prereqs.d.ts.map +1 -0
  52. package/dist/prereqs.js +22 -0
  53. package/dist/prereqs.js.map +1 -0
  54. package/dist/process-manager.d.ts +43 -0
  55. package/dist/process-manager.d.ts.map +1 -0
  56. package/dist/process-manager.js +188 -0
  57. package/dist/process-manager.js.map +1 -0
  58. package/dist/provider.d.ts +26 -0
  59. package/dist/provider.d.ts.map +1 -0
  60. package/dist/provider.js +342 -0
  61. package/dist/provider.js.map +1 -0
  62. package/dist/resources/index.d.ts +10 -0
  63. package/dist/resources/index.d.ts.map +1 -0
  64. package/dist/resources/index.js +23 -0
  65. package/dist/resources/index.js.map +1 -0
  66. package/dist/resources/mysql.d.ts +16 -0
  67. package/dist/resources/mysql.d.ts.map +1 -0
  68. package/dist/resources/mysql.js +64 -0
  69. package/dist/resources/mysql.js.map +1 -0
  70. package/dist/resources/postgres.d.ts +22 -0
  71. package/dist/resources/postgres.d.ts.map +1 -0
  72. package/dist/resources/postgres.js +98 -0
  73. package/dist/resources/postgres.js.map +1 -0
  74. package/dist/resources/redis.d.ts +16 -0
  75. package/dist/resources/redis.d.ts.map +1 -0
  76. package/dist/resources/redis.js +42 -0
  77. package/dist/resources/redis.js.map +1 -0
  78. package/dist/resources/sqlite.d.ts +16 -0
  79. package/dist/resources/sqlite.d.ts.map +1 -0
  80. package/dist/resources/sqlite.js +38 -0
  81. package/dist/resources/sqlite.js.map +1 -0
  82. package/dist/resources/types.d.ts +40 -0
  83. package/dist/resources/types.d.ts.map +1 -0
  84. package/dist/resources/types.js +8 -0
  85. package/dist/resources/types.js.map +1 -0
  86. package/dist/runtimes/bun.d.ts +11 -0
  87. package/dist/runtimes/bun.d.ts.map +1 -0
  88. package/dist/runtimes/bun.js +20 -0
  89. package/dist/runtimes/bun.js.map +1 -0
  90. package/dist/runtimes/index.d.ts +8 -0
  91. package/dist/runtimes/index.d.ts.map +1 -0
  92. package/dist/runtimes/index.js +18 -0
  93. package/dist/runtimes/index.js.map +1 -0
  94. package/dist/runtimes/node.d.ts +11 -0
  95. package/dist/runtimes/node.d.ts.map +1 -0
  96. package/dist/runtimes/node.js +70 -0
  97. package/dist/runtimes/node.js.map +1 -0
  98. package/dist/runtimes/python.d.ts +11 -0
  99. package/dist/runtimes/python.d.ts.map +1 -0
  100. package/dist/runtimes/python.js +38 -0
  101. package/dist/runtimes/python.js.map +1 -0
  102. package/dist/runtimes/ruby.d.ts +11 -0
  103. package/dist/runtimes/ruby.d.ts.map +1 -0
  104. package/dist/runtimes/ruby.js +51 -0
  105. package/dist/runtimes/ruby.js.map +1 -0
  106. package/dist/runtimes/types.d.ts +13 -0
  107. package/dist/runtimes/types.d.ts.map +1 -0
  108. package/dist/runtimes/types.js +5 -0
  109. package/dist/runtimes/types.js.map +1 -0
  110. package/dist/secret-generator.d.ts +11 -0
  111. package/dist/secret-generator.d.ts.map +1 -0
  112. package/dist/secret-generator.js +26 -0
  113. package/dist/secret-generator.js.map +1 -0
  114. package/dist/shell.d.ts +25 -0
  115. package/dist/shell.d.ts.map +1 -0
  116. package/dist/shell.js +46 -0
  117. package/dist/shell.js.map +1 -0
  118. package/dist/state.d.ts +35 -0
  119. package/dist/state.d.ts.map +1 -0
  120. package/dist/state.js +62 -0
  121. package/dist/state.js.map +1 -0
  122. package/dist/storage.d.ts +16 -0
  123. package/dist/storage.d.ts.map +1 -0
  124. package/dist/storage.js +48 -0
  125. package/dist/storage.js.map +1 -0
  126. package/package.json +41 -0
  127. package/src/__tests__/dry-run.test.ts +157 -0
  128. package/src/__tests__/env-writer.test.ts +156 -0
  129. package/src/__tests__/lockfile-detect.test.ts +74 -0
  130. package/src/__tests__/port-allocator.test.ts +59 -0
  131. package/src/__tests__/secret-generator.test.ts +31 -0
  132. package/src/__tests__/state.test.ts +33 -0
  133. package/src/cli.ts +78 -0
  134. package/src/env-writer.ts +231 -0
  135. package/src/health.ts +80 -0
  136. package/src/index.ts +9 -0
  137. package/src/lockfile-detect.ts +48 -0
  138. package/src/port-allocator.ts +97 -0
  139. package/src/prereqs.ts +32 -0
  140. package/src/process-manager.ts +242 -0
  141. package/src/provider.ts +415 -0
  142. package/src/resources/index.ts +29 -0
  143. package/src/resources/mysql.ts +98 -0
  144. package/src/resources/postgres.ts +133 -0
  145. package/src/resources/redis.ts +58 -0
  146. package/src/resources/sqlite.ts +52 -0
  147. package/src/resources/types.ts +47 -0
  148. package/src/runtimes/bun.ts +25 -0
  149. package/src/runtimes/index.ts +24 -0
  150. package/src/runtimes/node.ts +71 -0
  151. package/src/runtimes/python.ts +42 -0
  152. package/src/runtimes/ruby.ts +55 -0
  153. package/src/runtimes/types.ts +16 -0
  154. package/src/secret-generator.ts +32 -0
  155. package/src/shell.ts +70 -0
  156. package/src/state.ts +92 -0
  157. package/src/storage.ts +67 -0
  158. package/tsconfig.json +18 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../src/runtimes/python.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,qBAAa,eAAgB,YAAW,gBAAgB;IACvD,QAAQ,CAAC,OAAO,YAAY;IAEtB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAS9D,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAUjE"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Python runtime installer via pyenv.
3
+ */
4
+ import { readFile } from "node:fs/promises";
5
+ import { join } from "node:path";
6
+ import { shell, shellOk } from "../shell.js";
7
+ export class PythonInstaller {
8
+ runtime = "python";
9
+ async detectVersion(projectDir) {
10
+ try {
11
+ const content = await readFile(join(projectDir, ".python-version"), "utf8");
12
+ return content.trim() || undefined;
13
+ }
14
+ catch {
15
+ return undefined;
16
+ }
17
+ }
18
+ async install(version) {
19
+ if (!(await shellOk("which pyenv"))) {
20
+ await shell("brew install pyenv");
21
+ }
22
+ if (!(await shellOk(`pyenv versions --bare | grep -q "^${version}$"`))) {
23
+ await shell(`pyenv install ${version}`);
24
+ }
25
+ await shell(`pyenv local ${version}`);
26
+ }
27
+ async shellEnv(_version) {
28
+ if (await shellOk("which pyenv")) {
29
+ const result = await shell("pyenv root", { silent: true, allowFailure: true });
30
+ if (result.exitCode === 0) {
31
+ const root = result.stdout.trim();
32
+ return { PATH: `${root}/shims:${process.env.PATH ?? ""}` };
33
+ }
34
+ }
35
+ return {};
36
+ }
37
+ }
38
+ //# sourceMappingURL=python.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python.js","sourceRoot":"","sources":["../../src/runtimes/python.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAG7C,MAAM,OAAO,eAAe;IAClB,OAAO,GAAG,QAAQ,CAAC;IAE5B,KAAK,CAAC,aAAa,CAAC,UAAkB;QACrC,IAAI,CAAC;YACJ,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAC;YAC5E,OAAO,OAAO,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,SAAS,CAAC;QAClB,CAAC;IACF,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAe;QAC5B,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;YACrC,MAAM,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,qCAAqC,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC;YACxE,MAAM,KAAK,CAAC,iBAAiB,OAAO,EAAE,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,KAAK,CAAC,eAAe,OAAO,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB;QAC9B,IAAI,MAAM,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;YAClC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/E,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBAClC,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,UAAU,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,EAAE,CAAC;YAC5D,CAAC;QACF,CAAC;QACD,OAAO,EAAE,CAAC;IACX,CAAC;CACD"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Ruby runtime installer via rbenv.
3
+ */
4
+ import type { RuntimeInstaller } from "./types.js";
5
+ export declare class RubyInstaller implements RuntimeInstaller {
6
+ readonly runtime = "ruby";
7
+ detectVersion(projectDir: string): Promise<string | undefined>;
8
+ install(version: string): Promise<void>;
9
+ shellEnv(_version: string): Promise<Record<string, string>>;
10
+ }
11
+ //# sourceMappingURL=ruby.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ruby.d.ts","sourceRoot":"","sources":["../../src/runtimes/ruby.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,qBAAa,aAAc,YAAW,gBAAgB;IACrD,QAAQ,CAAC,OAAO,UAAU;IAEpB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAS9D,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAWjE"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Ruby runtime installer via rbenv.
3
+ */
4
+ import { readFile } from "node:fs/promises";
5
+ import { join } from "node:path";
6
+ import { shell, shellOk } from "../shell.js";
7
+ export class RubyInstaller {
8
+ runtime = "ruby";
9
+ async detectVersion(projectDir) {
10
+ try {
11
+ const content = await readFile(join(projectDir, ".ruby-version"), "utf8");
12
+ return content.trim() || undefined;
13
+ }
14
+ catch {
15
+ return undefined;
16
+ }
17
+ }
18
+ async install(version) {
19
+ if (!(await shellOk("which rbenv"))) {
20
+ await shell("brew install rbenv ruby-build");
21
+ }
22
+ const installed = await shellOk(`rbenv versions --bare | grep -q "^${version}$"`);
23
+ if (!installed) {
24
+ await shell(`rbenv install ${version}`);
25
+ }
26
+ await shell(`rbenv local ${version}`);
27
+ }
28
+ async shellEnv(_version) {
29
+ if (await shellOk("which rbenv")) {
30
+ try {
31
+ const result = await shell("rbenv init - bash", { silent: true });
32
+ return parseRbenvEnv(result.stdout);
33
+ }
34
+ catch {
35
+ return {};
36
+ }
37
+ }
38
+ return {};
39
+ }
40
+ }
41
+ function parseRbenvEnv(output) {
42
+ const env = {};
43
+ for (const line of output.split("\n")) {
44
+ const match = /^export\s+(\w+)="?([^"]*)"?/.exec(line);
45
+ if (match) {
46
+ env[match[1]] = match[2];
47
+ }
48
+ }
49
+ return env;
50
+ }
51
+ //# sourceMappingURL=ruby.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ruby.js","sourceRoot":"","sources":["../../src/runtimes/ruby.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAG7C,MAAM,OAAO,aAAa;IAChB,OAAO,GAAG,MAAM,CAAC;IAE1B,KAAK,CAAC,aAAa,CAAC,UAAkB;QACrC,IAAI,CAAC;YACJ,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAC;YAC1E,OAAO,OAAO,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,SAAS,CAAC;QAClB,CAAC;IACF,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAe;QAC5B,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;YACrC,MAAM,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC9C,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,qCAAqC,OAAO,IAAI,CAAC,CAAC;QAClF,IAAI,CAAC,SAAS,EAAE,CAAC;YAChB,MAAM,KAAK,CAAC,iBAAiB,OAAO,EAAE,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,KAAK,CAAC,eAAe,OAAO,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB;QAC9B,IAAI,MAAM,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;YAClC,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClE,OAAO,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACrC,CAAC;YAAC,MAAM,CAAC;gBACR,OAAO,EAAE,CAAC;YACX,CAAC;QACF,CAAC;QACD,OAAO,EAAE,CAAC;IACX,CAAC;CACD;AAED,SAAS,aAAa,CAAC,MAAc;IACpC,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,6BAA6B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,KAAK,EAAE,CAAC;YACX,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QAC5B,CAAC;IACF,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Runtime installer interface.
3
+ */
4
+ export interface RuntimeInstaller {
5
+ readonly runtime: string;
6
+ /** Detect the version from project files (.nvmrc, .ruby-version, etc.) */
7
+ detectVersion(projectDir: string): Promise<string | undefined>;
8
+ /** Ensure the runtime version is installed */
9
+ install(version: string): Promise<void>;
10
+ /** Get any shell env modifications needed (PATH, etc.) */
11
+ shellEnv(version: string): Promise<Record<string, string>>;
12
+ }
13
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtimes/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,0EAA0E;IAC1E,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAE/D,8CAA8C;IAC9C,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExC,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC3D"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Runtime installer interface.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/runtimes/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Secret and value generators for Launchfile env vars.
3
+ */
4
+ import type { Generator } from "@launchfile/sdk";
5
+ /**
6
+ * Generate a value based on the generator type.
7
+ */
8
+ export declare function generateValue(generator: Generator, existingPorts?: Set<number>): Promise<string>;
9
+ /** Generate a password suitable for database users */
10
+ export declare function generatePassword(): string;
11
+ //# sourceMappingURL=secret-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-generator.d.ts","sourceRoot":"","sources":["../src/secret-generator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD;;GAEG;AACH,wBAAsB,aAAa,CAClC,SAAS,EAAE,SAAS,EACpB,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACzB,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED,sDAAsD;AACtD,wBAAgB,gBAAgB,IAAI,MAAM,CAGzC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Secret and value generators for Launchfile env vars.
3
+ */
4
+ import { randomBytes, randomUUID } from "node:crypto";
5
+ import { allocatePort } from "./port-allocator.js";
6
+ /**
7
+ * Generate a value based on the generator type.
8
+ */
9
+ export async function generateValue(generator, existingPorts) {
10
+ switch (generator) {
11
+ case "secret":
12
+ return randomBytes(32).toString("base64url");
13
+ case "uuid":
14
+ return randomUUID();
15
+ case "port": {
16
+ const port = await allocatePort(`generated-${Date.now()}`, existingPorts ?? new Set());
17
+ return String(port);
18
+ }
19
+ }
20
+ }
21
+ /** Generate a password suitable for database users */
22
+ export function generatePassword() {
23
+ // URL-safe so it can go in connection strings without encoding
24
+ return randomBytes(24).toString("base64url");
25
+ }
26
+ //# sourceMappingURL=secret-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-generator.js","sourceRoot":"","sources":["../src/secret-generator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAClC,SAAoB,EACpB,aAA2B;IAE3B,QAAQ,SAAS,EAAE,CAAC;QACnB,KAAK,QAAQ;YACZ,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC9C,KAAK,MAAM;YACV,OAAO,UAAU,EAAE,CAAC;QACrB,KAAK,MAAM,CAAC,CAAC,CAAC;YACb,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,aAAa,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,aAAa,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;YACvF,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;IACF,CAAC;AACF,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,gBAAgB;IAC/B,+DAA+D;IAC/D,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Shell execution helper with timeout, logging, and structured results.
3
+ */
4
+ export interface ShellResult {
5
+ exitCode: number;
6
+ stdout: string;
7
+ stderr: string;
8
+ }
9
+ export interface ShellOpts {
10
+ cwd?: string;
11
+ env?: Record<string, string>;
12
+ timeout?: number;
13
+ /** If true, don't log the command being run */
14
+ silent?: boolean;
15
+ }
16
+ /**
17
+ * Run a shell command and return structured output.
18
+ * Throws on non-zero exit code unless `allowFailure` is set.
19
+ */
20
+ export declare function shell(command: string, opts?: ShellOpts & {
21
+ allowFailure?: boolean;
22
+ }): Promise<ShellResult>;
23
+ /** Run a command, return true if exit code is 0 */
24
+ export declare function shellOk(command: string, opts?: ShellOpts): Promise<boolean>;
25
+ //# sourceMappingURL=shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,WAAW,WAAW;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,KAAK,CAC1B,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,SAAS,GAAG;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/C,OAAO,CAAC,WAAW,CAAC,CAoCtB;AAED,mDAAmD;AACnD,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAGjF"}
package/dist/shell.js ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Shell execution helper with timeout, logging, and structured results.
3
+ */
4
+ import { exec as cpExec } from "node:child_process";
5
+ /**
6
+ * Run a shell command and return structured output.
7
+ * Throws on non-zero exit code unless `allowFailure` is set.
8
+ */
9
+ export async function shell(command, opts = {}) {
10
+ if (!opts.silent) {
11
+ console.log(` $ ${command}`);
12
+ }
13
+ const execOpts = {
14
+ cwd: opts.cwd,
15
+ env: opts.env ? { ...process.env, ...opts.env } : undefined,
16
+ timeout: opts.timeout ?? 120_000,
17
+ maxBuffer: 10 * 1024 * 1024,
18
+ };
19
+ return new Promise((resolve, reject) => {
20
+ cpExec(command, execOpts, (error, stdout, stderr) => {
21
+ const result = {
22
+ exitCode: error?.code ?? (typeof error?.code === "number" ? error.code : 0),
23
+ stdout: typeof stdout === "string" ? stdout : "",
24
+ stderr: typeof stderr === "string" ? stderr : "",
25
+ };
26
+ // Node's exec sets error.code to the exit code on non-zero
27
+ if (error && result.exitCode === 0) {
28
+ result.exitCode = 1;
29
+ }
30
+ if (error && !opts.allowFailure) {
31
+ reject(Object.assign(new Error(`Command failed: ${command}\n${result.stderr}`), {
32
+ result,
33
+ }));
34
+ }
35
+ else {
36
+ resolve(result);
37
+ }
38
+ });
39
+ });
40
+ }
41
+ /** Run a command, return true if exit code is 0 */
42
+ export async function shellOk(command, opts) {
43
+ const result = await shell(command, { ...opts, allowFailure: true, silent: true });
44
+ return result.exitCode === 0;
45
+ }
46
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,IAAI,MAAM,EAAoB,MAAM,oBAAoB,CAAC;AAgBtE;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAC1B,OAAe,EACf,OAA+C,EAAE;IAEjD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,OAAO,OAAO,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM,QAAQ,GAAgB;QAC7B,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS;QAC3D,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,OAAO;QAChC,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;KAC3B,CAAC;IAEF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACtC,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACnD,MAAM,MAAM,GAAgB;gBAC3B,QAAQ,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC,OAAO,KAAK,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC3E,MAAM,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;gBAChD,MAAM,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;aAChD,CAAC;YAEF,2DAA2D;YAC3D,IAAI,KAAK,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBACpC,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,CAAC;YAED,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;gBACjC,MAAM,CACL,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,OAAO,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE;oBACxE,MAAM;iBACN,CAAC,CACF,CAAC;YACH,CAAC;iBAAM,CAAC;gBACP,OAAO,CAAC,MAAM,CAAC,CAAC;YACjB,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,mDAAmD;AACnD,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAe,EAAE,IAAgB;IAC9D,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACnF,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * State management for the macOS dev provider.
3
+ *
4
+ * Persists secrets, ports, and resource state in .launchfile/state.json
5
+ * so credentials and ports are stable across restarts.
6
+ */
7
+ export interface ResourceState {
8
+ type: string;
9
+ name: string;
10
+ brewService?: string;
11
+ port: number;
12
+ dbName?: string;
13
+ user?: string;
14
+ password?: string;
15
+ }
16
+ export interface LaunchState {
17
+ version: 1;
18
+ appName: string;
19
+ launchfileHash: string;
20
+ createdAt: string;
21
+ updatedAt: string;
22
+ resources: Record<string, ResourceState>;
23
+ secrets: Record<string, string>;
24
+ ports: Record<string, number>;
25
+ }
26
+ export declare function hashLaunchfile(content: string): string;
27
+ /** Load state from disk, or return null if none exists */
28
+ export declare function loadState(projectDir: string): Promise<LaunchState | null>;
29
+ /** Create a fresh state object */
30
+ export declare function initState(appName: string, launchfileContent: string): LaunchState;
31
+ /** Save state to disk */
32
+ export declare function saveState(projectDir: string, state: LaunchState): Promise<void>;
33
+ /** Ensure .launchfile directories exist */
34
+ export declare function ensureDirs(projectDir: string): Promise<void>;
35
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACzC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAaD,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,0DAA0D;AAC1D,wBAAsB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAO/E;AAED,kCAAkC;AAClC,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,WAAW,CAYjF;AAED,yBAAyB;AACzB,wBAAsB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAMrF;AAED,2CAA2C;AAC3C,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASlE"}
package/dist/state.js ADDED
@@ -0,0 +1,62 @@
1
+ /**
2
+ * State management for the macOS dev provider.
3
+ *
4
+ * Persists secrets, ports, and resource state in .launchfile/state.json
5
+ * so credentials and ports are stable across restarts.
6
+ */
7
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
8
+ import { join } from "node:path";
9
+ import { createHash } from "node:crypto";
10
+ const STATE_DIR = ".launchfile";
11
+ const STATE_FILE = "state.json";
12
+ function stateDir(projectDir) {
13
+ return join(projectDir, STATE_DIR);
14
+ }
15
+ function statePath(projectDir) {
16
+ return join(stateDir(projectDir), STATE_FILE);
17
+ }
18
+ export function hashLaunchfile(content) {
19
+ return createHash("sha256").update(content).digest("hex").slice(0, 16);
20
+ }
21
+ /** Load state from disk, or return null if none exists */
22
+ export async function loadState(projectDir) {
23
+ try {
24
+ const raw = await readFile(statePath(projectDir), "utf8");
25
+ return JSON.parse(raw);
26
+ }
27
+ catch {
28
+ return null;
29
+ }
30
+ }
31
+ /** Create a fresh state object */
32
+ export function initState(appName, launchfileContent) {
33
+ const now = new Date().toISOString();
34
+ return {
35
+ version: 1,
36
+ appName,
37
+ launchfileHash: hashLaunchfile(launchfileContent),
38
+ createdAt: now,
39
+ updatedAt: now,
40
+ resources: {},
41
+ secrets: {},
42
+ ports: {},
43
+ };
44
+ }
45
+ /** Save state to disk */
46
+ export async function saveState(projectDir, state) {
47
+ state.updatedAt = new Date().toISOString();
48
+ // Security: restrict directory/file permissions — state.json contains
49
+ // database passwords and generated secrets in plaintext.
50
+ await mkdir(stateDir(projectDir), { recursive: true, mode: 0o700 });
51
+ await writeFile(statePath(projectDir), JSON.stringify(state, null, 2) + "\n", { mode: 0o600 });
52
+ }
53
+ /** Ensure .launchfile directories exist */
54
+ export async function ensureDirs(projectDir) {
55
+ const dirs = ["storage", "tmp", "logs", "data", "env"];
56
+ // Security: restrict permissions — these dirs contain secrets, logs, env files
57
+ await Promise.all(dirs.map((d) => mkdir(join(projectDir, STATE_DIR, d), { recursive: true, mode: 0o700 })));
58
+ // Safety net: write a .gitignore inside .launchfile/ so secrets aren't
59
+ // accidentally committed even if the project's .gitignore doesn't exclude it.
60
+ await writeFile(join(projectDir, STATE_DIR, ".gitignore"), "*\n", { mode: 0o644 });
61
+ }
62
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Local storage provisioning for Launchfile volumes.
3
+ *
4
+ * Maps container paths to local directories under .launchfile/.
5
+ */
6
+ import type { StorageVolume } from "@launchfile/sdk";
7
+ /**
8
+ * Create local directories for a component's storage volumes.
9
+ * Returns a map of container path → local path.
10
+ */
11
+ export declare function provisionStorage(storage: Record<string, StorageVolume> | undefined, componentName: string, projectDir: string): Promise<Record<string, string>>;
12
+ /** Clean up ephemeral (non-persistent) storage for a component */
13
+ export declare function cleanEphemeralStorage(storage: Record<string, StorageVolume> | undefined, componentName: string, projectDir: string): Promise<void>;
14
+ /** Clean up all storage (persistent + ephemeral) for a component */
15
+ export declare function destroyStorage(componentName: string, projectDir: string): Promise<void>;
16
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIrD;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,SAAS,EAClD,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAejC;AAED,kEAAkE;AAClE,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,SAAS,EAClD,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CASf;AAED,oEAAoE;AACpE,wBAAsB,cAAc,CACnC,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CASf"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Local storage provisioning for Launchfile volumes.
3
+ *
4
+ * Maps container paths to local directories under .launchfile/.
5
+ */
6
+ import { mkdir, rm } from "node:fs/promises";
7
+ import { join } from "node:path";
8
+ const STATE_DIR = ".launchfile";
9
+ /**
10
+ * Create local directories for a component's storage volumes.
11
+ * Returns a map of container path → local path.
12
+ */
13
+ export async function provisionStorage(storage, componentName, projectDir) {
14
+ if (!storage)
15
+ return {};
16
+ const volumeMap = {};
17
+ for (const [name, volume] of Object.entries(storage)) {
18
+ const persistent = volume.persistent !== false; // default true
19
+ const subdir = persistent ? "storage" : "tmp";
20
+ const localPath = join(projectDir, STATE_DIR, subdir, componentName, name);
21
+ await mkdir(localPath, { recursive: true });
22
+ volumeMap[volume.path] = localPath;
23
+ }
24
+ return volumeMap;
25
+ }
26
+ /** Clean up ephemeral (non-persistent) storage for a component */
27
+ export async function cleanEphemeralStorage(storage, componentName, projectDir) {
28
+ if (!storage)
29
+ return;
30
+ for (const [name, volume] of Object.entries(storage)) {
31
+ if (volume.persistent === false) {
32
+ const localPath = join(projectDir, STATE_DIR, "tmp", componentName, name);
33
+ await rm(localPath, { recursive: true, force: true });
34
+ }
35
+ }
36
+ }
37
+ /** Clean up all storage (persistent + ephemeral) for a component */
38
+ export async function destroyStorage(componentName, projectDir) {
39
+ await rm(join(projectDir, STATE_DIR, "storage", componentName), {
40
+ recursive: true,
41
+ force: true,
42
+ });
43
+ await rm(join(projectDir, STATE_DIR, "tmp", componentName), {
44
+ recursive: true,
45
+ force: true,
46
+ });
47
+ }
48
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,MAAM,SAAS,GAAG,aAAa,CAAC;AAEhC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACrC,OAAkD,EAClD,aAAqB,EACrB,UAAkB;IAElB,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAExB,MAAM,SAAS,GAA2B,EAAE,CAAC;IAE7C,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACtD,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,KAAK,KAAK,CAAC,CAAC,eAAe;QAC/D,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;QAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;QAE3E,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IACpC,CAAC;IAED,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAC1C,OAAkD,EAClD,aAAqB,EACrB,UAAkB;IAElB,IAAI,CAAC,OAAO;QAAE,OAAO;IAErB,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACtD,IAAI,MAAM,CAAC,UAAU,KAAK,KAAK,EAAE,CAAC;YACjC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;YAC1E,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,CAAC;IACF,CAAC;AACF,CAAC;AAED,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,aAAqB,EACrB,UAAkB;IAElB,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,CAAC,EAAE;QAC/D,SAAS,EAAE,IAAI;QACf,KAAK,EAAE,IAAI;KACX,CAAC,CAAC;IACH,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,CAAC,EAAE;QAC3D,SAAS,EAAE,IAAI;QACf,KAAK,EAAE,IAAI;KACX,CAAC,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@launchfile/macos-dev",
3
+ "version": "0.1.3",
4
+ "description": "macOS dev provider for Launchfile — run apps locally via brew services and native runtimes",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "test": "vitest run",
11
+ "test:watch": "vitest",
12
+ "typecheck": "tsc --noEmit",
13
+ "lint": "biome check src/",
14
+ "lint:fix": "biome check --write src/",
15
+ "dev": "bun run src/cli.ts"
16
+ },
17
+ "keywords": [
18
+ "launchfile",
19
+ "macos",
20
+ "dev",
21
+ "provider",
22
+ "brew"
23
+ ],
24
+ "license": "MIT",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/launchfile/launchfile",
28
+ "directory": "providers/macos-dev"
29
+ },
30
+ "dependencies": {
31
+ "@launchfile/sdk": "0.1.2",
32
+ "semver": "^7.7.4"
33
+ },
34
+ "devDependencies": {
35
+ "@biomejs/biome": "^2.4.10",
36
+ "@types/bun": "^1.3.11",
37
+ "@types/semver": "^7.7.1",
38
+ "typescript": "^6.0.0",
39
+ "vitest": "^4.1.3"
40
+ }
41
+ }