@obh/forge 0.2.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 (215) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +146 -0
  3. package/dist/capabilities/analytics.d.ts +3 -0
  4. package/dist/capabilities/analytics.d.ts.map +1 -0
  5. package/dist/capabilities/analytics.js +91 -0
  6. package/dist/capabilities/analytics.js.map +1 -0
  7. package/dist/capabilities/api-keys.d.ts +3 -0
  8. package/dist/capabilities/api-keys.d.ts.map +1 -0
  9. package/dist/capabilities/api-keys.js +90 -0
  10. package/dist/capabilities/api-keys.js.map +1 -0
  11. package/dist/capabilities/audit.d.ts +3 -0
  12. package/dist/capabilities/audit.d.ts.map +1 -0
  13. package/dist/capabilities/audit.js +74 -0
  14. package/dist/capabilities/audit.js.map +1 -0
  15. package/dist/capabilities/entitlements.d.ts +3 -0
  16. package/dist/capabilities/entitlements.d.ts.map +1 -0
  17. package/dist/capabilities/entitlements.js +94 -0
  18. package/dist/capabilities/entitlements.js.map +1 -0
  19. package/dist/capabilities/events.d.ts +3 -0
  20. package/dist/capabilities/events.d.ts.map +1 -0
  21. package/dist/capabilities/events.js +107 -0
  22. package/dist/capabilities/events.js.map +1 -0
  23. package/dist/capabilities/files.d.ts +3 -0
  24. package/dist/capabilities/files.d.ts.map +1 -0
  25. package/dist/capabilities/files.js +100 -0
  26. package/dist/capabilities/files.js.map +1 -0
  27. package/dist/capabilities/helpers.d.ts +27 -0
  28. package/dist/capabilities/helpers.d.ts.map +1 -0
  29. package/dist/capabilities/helpers.js +63 -0
  30. package/dist/capabilities/helpers.js.map +1 -0
  31. package/dist/capabilities/import-export.d.ts +3 -0
  32. package/dist/capabilities/import-export.d.ts.map +1 -0
  33. package/dist/capabilities/import-export.js +267 -0
  34. package/dist/capabilities/import-export.js.map +1 -0
  35. package/dist/capabilities/index.d.ts +16 -0
  36. package/dist/capabilities/index.d.ts.map +1 -0
  37. package/dist/capabilities/index.js +71 -0
  38. package/dist/capabilities/index.js.map +1 -0
  39. package/dist/capabilities/jobs.d.ts +3 -0
  40. package/dist/capabilities/jobs.d.ts.map +1 -0
  41. package/dist/capabilities/jobs.js +117 -0
  42. package/dist/capabilities/jobs.js.map +1 -0
  43. package/dist/capabilities/notifications.d.ts +3 -0
  44. package/dist/capabilities/notifications.d.ts.map +1 -0
  45. package/dist/capabilities/notifications.js +113 -0
  46. package/dist/capabilities/notifications.js.map +1 -0
  47. package/dist/capabilities/search.d.ts +3 -0
  48. package/dist/capabilities/search.d.ts.map +1 -0
  49. package/dist/capabilities/search.js +121 -0
  50. package/dist/capabilities/search.js.map +1 -0
  51. package/dist/capabilities/settings.d.ts +3 -0
  52. package/dist/capabilities/settings.d.ts.map +1 -0
  53. package/dist/capabilities/settings.js +75 -0
  54. package/dist/capabilities/settings.js.map +1 -0
  55. package/dist/capabilities/types.d.ts +16 -0
  56. package/dist/capabilities/types.d.ts.map +1 -0
  57. package/dist/capabilities/types.js +3 -0
  58. package/dist/capabilities/types.js.map +1 -0
  59. package/dist/capabilities/webhooks.d.ts +3 -0
  60. package/dist/capabilities/webhooks.d.ts.map +1 -0
  61. package/dist/capabilities/webhooks.js +117 -0
  62. package/dist/capabilities/webhooks.js.map +1 -0
  63. package/dist/cli.d.ts +3 -0
  64. package/dist/cli.d.ts.map +1 -0
  65. package/dist/cli.js +60 -0
  66. package/dist/cli.js.map +1 -0
  67. package/dist/commands/add.d.ts +3 -0
  68. package/dist/commands/add.d.ts.map +1 -0
  69. package/dist/commands/add.js +88 -0
  70. package/dist/commands/add.js.map +1 -0
  71. package/dist/commands/doctor.d.ts +3 -0
  72. package/dist/commands/doctor.d.ts.map +1 -0
  73. package/dist/commands/doctor.js +94 -0
  74. package/dist/commands/doctor.js.map +1 -0
  75. package/dist/commands/generate.d.ts +3 -0
  76. package/dist/commands/generate.d.ts.map +1 -0
  77. package/dist/commands/generate.js +41 -0
  78. package/dist/commands/generate.js.map +1 -0
  79. package/dist/commands/inspect.d.ts +3 -0
  80. package/dist/commands/inspect.d.ts.map +1 -0
  81. package/dist/commands/inspect.js +64 -0
  82. package/dist/commands/inspect.js.map +1 -0
  83. package/dist/commands/new.d.ts +18 -0
  84. package/dist/commands/new.d.ts.map +1 -0
  85. package/dist/commands/new.js +149 -0
  86. package/dist/commands/new.js.map +1 -0
  87. package/dist/commands/shared.d.ts +14 -0
  88. package/dist/commands/shared.d.ts.map +1 -0
  89. package/dist/commands/shared.js +36 -0
  90. package/dist/commands/shared.js.map +1 -0
  91. package/dist/commands/skill.d.ts +3 -0
  92. package/dist/commands/skill.d.ts.map +1 -0
  93. package/dist/commands/skill.js +59 -0
  94. package/dist/commands/skill.js.map +1 -0
  95. package/dist/commands/stack.d.ts +13 -0
  96. package/dist/commands/stack.d.ts.map +1 -0
  97. package/dist/commands/stack.js +192 -0
  98. package/dist/commands/stack.js.map +1 -0
  99. package/dist/generators/api.d.ts +16 -0
  100. package/dist/generators/api.d.ts.map +1 -0
  101. package/dist/generators/api.js +375 -0
  102. package/dist/generators/api.js.map +1 -0
  103. package/dist/generators/lwd.d.ts +12 -0
  104. package/dist/generators/lwd.d.ts.map +1 -0
  105. package/dist/generators/lwd.js +143 -0
  106. package/dist/generators/lwd.js.map +1 -0
  107. package/dist/generators/mobile.d.ts +16 -0
  108. package/dist/generators/mobile.d.ts.map +1 -0
  109. package/dist/generators/mobile.js +180 -0
  110. package/dist/generators/mobile.js.map +1 -0
  111. package/dist/generators/platform-package.d.ts +18 -0
  112. package/dist/generators/platform-package.d.ts.map +1 -0
  113. package/dist/generators/platform-package.js +568 -0
  114. package/dist/generators/platform-package.js.map +1 -0
  115. package/dist/generators/root.d.ts +15 -0
  116. package/dist/generators/root.d.ts.map +1 -0
  117. package/dist/generators/root.js +249 -0
  118. package/dist/generators/root.js.map +1 -0
  119. package/dist/generators/sdk.d.ts +14 -0
  120. package/dist/generators/sdk.d.ts.map +1 -0
  121. package/dist/generators/sdk.js +137 -0
  122. package/dist/generators/sdk.js.map +1 -0
  123. package/dist/generators/web.d.ts +15 -0
  124. package/dist/generators/web.d.ts.map +1 -0
  125. package/dist/generators/web.js +203 -0
  126. package/dist/generators/web.js.map +1 -0
  127. package/dist/generators/worker.d.ts +13 -0
  128. package/dist/generators/worker.d.ts.map +1 -0
  129. package/dist/generators/worker.js +148 -0
  130. package/dist/generators/worker.js.map +1 -0
  131. package/dist/index.d.ts +10 -0
  132. package/dist/index.d.ts.map +1 -0
  133. package/dist/index.js +44 -0
  134. package/dist/index.js.map +1 -0
  135. package/dist/project/context.d.ts +24 -0
  136. package/dist/project/context.d.ts.map +1 -0
  137. package/dist/project/context.js +63 -0
  138. package/dist/project/context.js.map +1 -0
  139. package/dist/project/manifest.d.ts +26 -0
  140. package/dist/project/manifest.d.ts.map +1 -0
  141. package/dist/project/manifest.js +73 -0
  142. package/dist/project/manifest.js.map +1 -0
  143. package/dist/project/paths.d.ts +25 -0
  144. package/dist/project/paths.d.ts.map +1 -0
  145. package/dist/project/paths.js +51 -0
  146. package/dist/project/paths.js.map +1 -0
  147. package/dist/project/plan.d.ts +42 -0
  148. package/dist/project/plan.d.ts.map +1 -0
  149. package/dist/project/plan.js +251 -0
  150. package/dist/project/plan.js.map +1 -0
  151. package/dist/prompts/index.d.ts +24 -0
  152. package/dist/prompts/index.d.ts.map +1 -0
  153. package/dist/prompts/index.js +111 -0
  154. package/dist/prompts/index.js.map +1 -0
  155. package/dist/recipes/index.d.ts +25 -0
  156. package/dist/recipes/index.d.ts.map +1 -0
  157. package/dist/recipes/index.js +77 -0
  158. package/dist/recipes/index.js.map +1 -0
  159. package/dist/stack/infer.d.ts +4 -0
  160. package/dist/stack/infer.d.ts.map +1 -0
  161. package/dist/stack/infer.js +165 -0
  162. package/dist/stack/infer.js.map +1 -0
  163. package/dist/stack/lwd.d.ts +24 -0
  164. package/dist/stack/lwd.d.ts.map +1 -0
  165. package/dist/stack/lwd.js +62 -0
  166. package/dist/stack/lwd.js.map +1 -0
  167. package/dist/stack/lwdtoml.d.ts +38 -0
  168. package/dist/stack/lwdtoml.d.ts.map +1 -0
  169. package/dist/stack/lwdtoml.js +57 -0
  170. package/dist/stack/lwdtoml.js.map +1 -0
  171. package/dist/stack/manifest.d.ts +15 -0
  172. package/dist/stack/manifest.d.ts.map +1 -0
  173. package/dist/stack/manifest.js +86 -0
  174. package/dist/stack/manifest.js.map +1 -0
  175. package/dist/stack/types.d.ts +48 -0
  176. package/dist/stack/types.d.ts.map +1 -0
  177. package/dist/stack/types.js +5 -0
  178. package/dist/stack/types.js.map +1 -0
  179. package/dist/stack/wire.d.ts +40 -0
  180. package/dist/stack/wire.d.ts.map +1 -0
  181. package/dist/stack/wire.js +192 -0
  182. package/dist/stack/wire.js.map +1 -0
  183. package/dist/types.d.ts +114 -0
  184. package/dist/types.d.ts.map +1 -0
  185. package/dist/types.js +5 -0
  186. package/dist/types.js.map +1 -0
  187. package/dist/utils/fs.d.ts +13 -0
  188. package/dist/utils/fs.d.ts.map +1 -0
  189. package/dist/utils/fs.js +64 -0
  190. package/dist/utils/fs.js.map +1 -0
  191. package/dist/utils/git.d.ts +17 -0
  192. package/dist/utils/git.d.ts.map +1 -0
  193. package/dist/utils/git.js +49 -0
  194. package/dist/utils/git.js.map +1 -0
  195. package/dist/utils/logger.d.ts +16 -0
  196. package/dist/utils/logger.d.ts.map +1 -0
  197. package/dist/utils/logger.js +21 -0
  198. package/dist/utils/logger.js.map +1 -0
  199. package/dist/utils/shell.d.ts +21 -0
  200. package/dist/utils/shell.d.ts.map +1 -0
  201. package/dist/utils/shell.js +40 -0
  202. package/dist/utils/shell.js.map +1 -0
  203. package/dist/version.d.ts +2 -0
  204. package/dist/version.d.ts.map +1 -0
  205. package/dist/version.js +6 -0
  206. package/dist/version.js.map +1 -0
  207. package/package.json +40 -0
  208. package/skills/obh-add-events/SKILL.md +26 -0
  209. package/skills/obh-generate-audit-rules/SKILL.md +26 -0
  210. package/skills/obh-inspect-project/SKILL.md +26 -0
  211. package/skills/obh-lwd-manifest/SKILL.md +26 -0
  212. package/skills/obh-retrofit-files/SKILL.md +24 -0
  213. package/skills/obh-retrofit-jobs/SKILL.md +26 -0
  214. package/skills/obh-sdk-extraction/SKILL.md +24 -0
  215. package/skills/obh-settings-migration/SKILL.md +24 -0
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.planSecrets = planSecrets;
7
+ exports.computeStackDeploy = computeStackDeploy;
8
+ exports.printStackPlan = printStackPlan;
9
+ exports.executeStackDeploy = executeStackDeploy;
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const node_crypto_1 = require("node:crypto");
12
+ const manifest_1 = require("./manifest");
13
+ const lwdtoml_1 = require("./lwdtoml");
14
+ const logger_1 = require("../utils/logger");
15
+ function genValue(type, bytes) {
16
+ const buf = (0, node_crypto_1.randomBytes)(bytes);
17
+ return type === "hex" ? buf.toString("hex") : buf.toString("base64url");
18
+ }
19
+ /** Owner reaches a co-located service; a dedicated resource app is reachable cross-app; co-located [[services]] is not. */
20
+ function isReachable(serviceApp, consumer, manifest) {
21
+ if (consumer === serviceApp)
22
+ return true;
23
+ return manifest.apps.find((a) => a.name === serviceApp)?.role === "resource";
24
+ }
25
+ /**
26
+ * Pure planning: given the manifest, each app's lwd.toml, and the secret names
27
+ * lwd already holds per app, decide what to skip / generate / derive / block.
28
+ * No IO, no execution — this is what the tests exercise.
29
+ */
30
+ function planSecrets(manifest, tomlByApp, existingByApp, opts = {}) {
31
+ const rotate = new Set(opts.rotate ?? []);
32
+ const items = [];
33
+ const flags = [];
34
+ const runValues = {};
35
+ const inScope = (app) => !opts.onlyApp || app === opts.onlyApp;
36
+ // 1. Generated component secrets.
37
+ for (const [name, g] of Object.entries(manifest.secrets.generate)) {
38
+ const willRotate = rotate.has(name);
39
+ let value;
40
+ const ensure = () => {
41
+ if (!value) {
42
+ value = genValue(g.type, g.bytes);
43
+ runValues[name] = value;
44
+ }
45
+ return value;
46
+ };
47
+ for (const app of g.apps) {
48
+ if (!inScope(app))
49
+ continue;
50
+ const has = (existingByApp[app] ?? []).includes(name);
51
+ if (has && !willRotate)
52
+ items.push({ app, key: name, action: "skip" });
53
+ else
54
+ items.push({ app, key: name, action: "generate", value: ensure() });
55
+ }
56
+ }
57
+ // 2. Derived connection secrets.
58
+ for (const [name, c] of Object.entries(manifest.secrets.connections)) {
59
+ const consumers = [...c.apps, ...(c.sharedWith ?? [])];
60
+ const refs = (0, manifest_1.templateRefs)(c.template);
61
+ const rotatedRef = refs.some((r) => rotate.has(r));
62
+ for (const app of consumers) {
63
+ if (!inScope(app))
64
+ continue;
65
+ if (!isReachable(c.service.app, app, manifest)) {
66
+ const msg = `${app} can't reach "${c.service.name}" co-located in ${c.service.app}: move it to a dedicated app (split topology) so ${name} is reachable across apps, or drop ${app} as a consumer.`;
67
+ flags.push(msg);
68
+ items.push({ app, key: name, action: "blocked", reason: msg });
69
+ continue;
70
+ }
71
+ const has = (existingByApp[app] ?? []).includes(name);
72
+ if (has && !rotatedRef) {
73
+ items.push({ app, key: name, action: "skip" });
74
+ continue;
75
+ }
76
+ const missingRef = refs.find((r) => runValues[r] === undefined);
77
+ if (missingRef) {
78
+ const msg = `cannot derive ${name} for ${app}: ${missingRef} is already set and its value is not retrievable. Re-run with \`--rotate ${missingRef}\` to re-establish it and all derived connections, or set ${name} manually.`;
79
+ flags.push(msg);
80
+ items.push({ app, key: name, action: "blocked", reason: msg });
81
+ continue;
82
+ }
83
+ items.push({ app, key: name, action: "derive", value: (0, manifest_1.resolveTemplate)(c.template, runValues) });
84
+ }
85
+ }
86
+ // 3. Manual secrets: block the apps that declare them but don't have them set.
87
+ const manual = new Set(manifest.secrets.manual);
88
+ for (const app of manifest.apps) {
89
+ if (!inScope(app.name))
90
+ continue;
91
+ const toml = tomlByApp[app.name];
92
+ if (!toml)
93
+ continue;
94
+ const needed = new Set([...toml.secrets, ...toml.services.flatMap((s) => s.secrets)]);
95
+ for (const m of manual) {
96
+ if (!needed.has(m))
97
+ continue;
98
+ if (!(existingByApp[app.name] ?? []).includes(m)) {
99
+ items.push({ app: app.name, key: m, action: "manual-missing", reason: `set it: lwd secret set ${app.name} ${m}` });
100
+ }
101
+ }
102
+ }
103
+ return { order: manifest.order.filter(inScope), items, flags };
104
+ }
105
+ /** Read each app's lwd.toml and the secret names lwd already holds, then plan. */
106
+ async function computeStackDeploy(root, manifest, adapter, opts = {}) {
107
+ const tomlByApp = {};
108
+ const existingByApp = {};
109
+ for (const app of manifest.apps) {
110
+ if (opts.onlyApp && app.name !== opts.onlyApp)
111
+ continue;
112
+ const toml = await (0, lwdtoml_1.readLwdToml)(node_path_1.default.join(root, app.manifest));
113
+ if (toml)
114
+ tomlByApp[app.name] = toml;
115
+ existingByApp[app.name] = await adapter.secretLs(app.name);
116
+ }
117
+ return { plan: planSecrets(manifest, tomlByApp, existingByApp, opts), tomlByApp };
118
+ }
119
+ /** Log the plan, masking every value (a generated value never appears in output). */
120
+ function printStackPlan(manifest, plan) {
121
+ const byApp = new Map();
122
+ for (const it of plan.items) {
123
+ const list = byApp.get(it.app) ?? [];
124
+ list.push(it);
125
+ byApp.set(it.app, list);
126
+ }
127
+ logger_1.log.info(`Stack "${manifest.name}" — apply order: ${plan.order.join(" → ")}`);
128
+ for (const appName of plan.order) {
129
+ const items = byApp.get(appName) ?? [];
130
+ logger_1.log.plain(` ${appName}`);
131
+ if (items.length === 0)
132
+ logger_1.log.dim(" (no secrets)");
133
+ for (const it of items) {
134
+ if (it.action === "generate")
135
+ logger_1.log.plain(` generate ${it.key} (hidden)`);
136
+ else if (it.action === "derive")
137
+ logger_1.log.plain(` derive ${it.key} (hidden)`);
138
+ else if (it.action === "skip")
139
+ logger_1.log.dim(` skip ${it.key} (already set)`);
140
+ else if (it.action === "manual-missing")
141
+ logger_1.log.warn(` MANUAL ${it.key} — ${it.reason}`);
142
+ else
143
+ logger_1.log.error(` BLOCKED ${it.key} — ${it.reason}`);
144
+ }
145
+ }
146
+ if (plan.flags.length > 0) {
147
+ logger_1.log.plain("");
148
+ logger_1.log.error("Connectivity / derivation problems:");
149
+ for (const f of plan.flags)
150
+ logger_1.log.plain(" - " + f);
151
+ }
152
+ }
153
+ /** Execute the plan: set missing secrets per app in order, apply, gate on health. */
154
+ async function executeStackDeploy(root, manifest, adapter, plan, opts = {}) {
155
+ const appByName = new Map(manifest.apps.map((a) => [a.name, a]));
156
+ for (const appName of plan.order) {
157
+ const app = appByName.get(appName);
158
+ if (!app)
159
+ continue;
160
+ const items = plan.items.filter((i) => i.app === appName);
161
+ const missingManual = items.filter((i) => i.action === "manual-missing");
162
+ if (missingManual.length > 0) {
163
+ logger_1.log.error(`${appName}: unset required secrets — ${missingManual.map((m) => m.key).join(", ")}. Set them and re-run.`);
164
+ throw new Error(`${appName} has unset manual secrets`);
165
+ }
166
+ for (const it of items) {
167
+ if ((it.action === "generate" || it.action === "derive") && it.value !== undefined) {
168
+ await adapter.secretSet(appName, it.key, it.value);
169
+ logger_1.log.success(`${appName}: set ${it.key}`);
170
+ }
171
+ }
172
+ await adapter.apply(app.manifest);
173
+ logger_1.log.success(`${appName}: applied ${app.manifest}`);
174
+ if (!opts.noWait) {
175
+ const ok = await waitHealthy(adapter, appName);
176
+ if (!ok)
177
+ logger_1.log.warn(`${appName}: not healthy yet — continuing (use lwd status ${appName} to check)`);
178
+ }
179
+ }
180
+ }
181
+ async function waitHealthy(adapter, app, tries = 30, delayMs = 2000) {
182
+ for (let i = 0; i < tries; i++) {
183
+ const s = await adapter.status(app);
184
+ if (s.healthy)
185
+ return true;
186
+ if (/failed|error|crash/.test(s.state))
187
+ return false;
188
+ await new Promise((r) => setTimeout(r, delayMs));
189
+ }
190
+ return false;
191
+ }
192
+ //# sourceMappingURL=wire.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire.js","sourceRoot":"","sources":["../../src/stack/wire.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ /** Backend framework for a generated API app. */
2
+ export type ApiFramework = "hono" | "express";
3
+ /** How an app is built/served. */
4
+ export type WebFramework = "vite-react";
5
+ /** Deployment target. Only lwd is first-class today. */
6
+ export type DeployTarget = "lwd";
7
+ /** The example domain a project is scaffolded with (or none). */
8
+ export type ExampleDomain = "notes" | null;
9
+ /**
10
+ * Project-level choices Forge records so it (and Claude skills) stay flexible
11
+ * instead of assuming a fixed structure. Overridable via forge.json.
12
+ */
13
+ export interface ForgeConfig {
14
+ /** Backend framework for the API app. */
15
+ apiFramework: ApiFramework;
16
+ /** Whether a shared SDK package exists. */
17
+ sdk: boolean;
18
+ /** The example domain generated (or null for a bare health-only app). */
19
+ example: ExampleDomain;
20
+ /** Convention directories generated apps auto-load from (recorded, not hard-coded). */
21
+ conventions: {
22
+ routesDir: string;
23
+ consumersDir: string;
24
+ busDir: string;
25
+ migrationsDir: string;
26
+ };
27
+ }
28
+ /** lwd deployment topology (see §14 of the spec). */
29
+ export type Topology = "small" | "split";
30
+ /** The OBH platform primitives Forge can install. */
31
+ export type CapabilityName = "events" | "jobs" | "files" | "audit" | "settings" | "api-keys" | "webhooks" | "import-export" | "entitlements" | "search" | "analytics" | "notifications";
32
+ /** Recipes are ordered bundles of scaffolding operations. */
33
+ export type RecipeName = "full-saas" | "api-web-worker" | "api-only" | "worker" | "platform-package";
34
+ /** A deployable application inside a project. */
35
+ export interface AppRecord {
36
+ /** Directory name under apps/, e.g. "api". */
37
+ name: string;
38
+ /** Repo-relative path, e.g. "apps/api". */
39
+ path: string;
40
+ /** Present for API apps. */
41
+ framework?: ApiFramework | WebFramework;
42
+ /** Role hint used by generators and doctor. */
43
+ role: "api" | "web" | "worker" | "mobile";
44
+ }
45
+ /** A shared internal package inside a project. */
46
+ export interface PackageRecord {
47
+ name: string;
48
+ path: string;
49
+ }
50
+ /** The forge.json project manifest (see §18). A record and aid — never a reconciler contract. */
51
+ export interface ForgeManifest {
52
+ name: string;
53
+ forgeVersion: string;
54
+ createdAt: string;
55
+ packageManager: "pnpm";
56
+ runtime: "node20";
57
+ apps: Record<string, AppRecord>;
58
+ packages: Record<string, PackageRecord>;
59
+ platform: Partial<Record<CapabilityName, boolean>>;
60
+ config: ForgeConfig;
61
+ deploy: {
62
+ target: DeployTarget;
63
+ topology: Topology;
64
+ /** "owner/repo" (or a full git URL) the lwd manifests deploy from. */
65
+ repo?: string;
66
+ };
67
+ }
68
+ /** How a file operation is classified for safety (see §21). */
69
+ export type FileOpKind =
70
+ /** Write only if the file does not already exist. */
71
+ "create"
72
+ /** Insert a clearly-marked section; idempotent via its marker. */
73
+ | "append"
74
+ /** Replace an existing file's contents (requires --force / confirmation). */
75
+ | "overwrite";
76
+ /** A single planned change to a file. */
77
+ export interface FileOp {
78
+ kind: FileOpKind;
79
+ /** Repo-relative path. */
80
+ path: string;
81
+ /** Full contents for create/overwrite. */
82
+ content?: string;
83
+ /** For append: a unique marker so re-runs are idempotent. */
84
+ marker?: string;
85
+ /** For append: the section body inserted after the marker. */
86
+ section?: string;
87
+ /** Human-readable one-liner shown in dry-run output. */
88
+ describe: string;
89
+ }
90
+ /** A dependency to add to the target app/package package.json. */
91
+ export interface DepAdd {
92
+ /** Repo-relative dir whose package.json gets the dependency (default: project root). */
93
+ target: string;
94
+ name: string;
95
+ version: string;
96
+ dev?: boolean;
97
+ }
98
+ /** An environment variable to document in .env.example. */
99
+ export interface EnvVar {
100
+ name: string;
101
+ /** Example / placeholder value; never a real secret. */
102
+ example: string;
103
+ comment?: string;
104
+ /** If true, listed as an lwd secret name (value set out-of-band). */
105
+ secret?: boolean;
106
+ }
107
+ /** A script to add to the root package.json. */
108
+ export interface ScriptAdd {
109
+ name: string;
110
+ command: string;
111
+ }
112
+ /** The outcome of applying a plan, per op. */
113
+ export type ApplyResult = "created" | "appended" | "overwritten" | "skipped" | "conflict";
114
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ // Central type contracts for OBH Forge.
3
+ // Keep this file the single source of truth for shapes that cross module boundaries.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,wCAAwC;AACxC,qFAAqF"}
@@ -0,0 +1,13 @@
1
+ /** Does a path exist? */
2
+ export declare function exists(p: string): Promise<boolean>;
3
+ /** Read a file as UTF-8, or return undefined if it does not exist. */
4
+ export declare function readFileSafe(p: string): Promise<string | undefined>;
5
+ /** Read + parse JSON, or undefined if missing/invalid. */
6
+ export declare function readJson<T>(p: string): Promise<T | undefined>;
7
+ /** Write a file, creating parent directories as needed. */
8
+ export declare function writeFile(p: string, content: string): Promise<void>;
9
+ /** Write pretty JSON with a trailing newline. */
10
+ export declare function writeJson(p: string, value: unknown): Promise<void>;
11
+ /** List immediate subdirectory names of a directory (empty if it does not exist). */
12
+ export declare function listDirs(p: string): Promise<string[]>;
13
+ //# sourceMappingURL=fs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":"AAGA,yBAAyB;AACzB,wBAAsB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOxD;AAED,sEAAsE;AACtE,wBAAsB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAMzE;AAED,0DAA0D;AAC1D,wBAAsB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAQnE;AAED,2DAA2D;AAC3D,wBAAsB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGzE;AAED,iDAAiD;AACjD,wBAAsB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAExE;AAED,qFAAqF;AACrF,wBAAsB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAO3D"}
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.exists = exists;
7
+ exports.readFileSafe = readFileSafe;
8
+ exports.readJson = readJson;
9
+ exports.writeFile = writeFile;
10
+ exports.writeJson = writeJson;
11
+ exports.listDirs = listDirs;
12
+ const node_fs_1 = require("node:fs");
13
+ const node_path_1 = __importDefault(require("node:path"));
14
+ /** Does a path exist? */
15
+ async function exists(p) {
16
+ try {
17
+ await node_fs_1.promises.stat(p);
18
+ return true;
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ /** Read a file as UTF-8, or return undefined if it does not exist. */
25
+ async function readFileSafe(p) {
26
+ try {
27
+ return await node_fs_1.promises.readFile(p, "utf8");
28
+ }
29
+ catch {
30
+ return undefined;
31
+ }
32
+ }
33
+ /** Read + parse JSON, or undefined if missing/invalid. */
34
+ async function readJson(p) {
35
+ const raw = await readFileSafe(p);
36
+ if (raw === undefined)
37
+ return undefined;
38
+ try {
39
+ return JSON.parse(raw);
40
+ }
41
+ catch {
42
+ return undefined;
43
+ }
44
+ }
45
+ /** Write a file, creating parent directories as needed. */
46
+ async function writeFile(p, content) {
47
+ await node_fs_1.promises.mkdir(node_path_1.default.dirname(p), { recursive: true });
48
+ await node_fs_1.promises.writeFile(p, content, "utf8");
49
+ }
50
+ /** Write pretty JSON with a trailing newline. */
51
+ async function writeJson(p, value) {
52
+ await writeFile(p, JSON.stringify(value, null, 2) + "\n");
53
+ }
54
+ /** List immediate subdirectory names of a directory (empty if it does not exist). */
55
+ async function listDirs(p) {
56
+ try {
57
+ const entries = await node_fs_1.promises.readdir(p, { withFileTypes: true });
58
+ return entries.filter((e) => e.isDirectory()).map((e) => e.name);
59
+ }
60
+ catch {
61
+ return [];
62
+ }
63
+ }
64
+ //# sourceMappingURL=fs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":";;;;;AAIA,wBAOC;AAGD,oCAMC;AAGD,4BAQC;AAGD,8BAGC;AAGD,8BAEC;AAGD,4BAOC;AApDD,qCAAwC;AACxC,0DAA4B;AAE5B,yBAAyB;AAClB,KAAK,UAAU,MAAM,CAAC,CAAS;IACpC,IAAI,CAAC;QACH,MAAM,kBAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAChB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,sEAAsE;AAC/D,KAAK,UAAU,YAAY,CAAC,CAAS;IAC1C,IAAI,CAAC;QACH,OAAO,MAAM,kBAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,0DAA0D;AACnD,KAAK,UAAU,QAAQ,CAAI,CAAS;IACzC,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,CAAC,CAAC,CAAA;IACjC,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IACvC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAM,CAAA;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,2DAA2D;AACpD,KAAK,UAAU,SAAS,CAAC,CAAS,EAAE,OAAe;IACxD,MAAM,kBAAE,CAAC,KAAK,CAAC,mBAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACpD,MAAM,kBAAE,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;AACxC,CAAC;AAED,iDAAiD;AAC1C,KAAK,UAAU,SAAS,CAAC,CAAS,EAAE,KAAc;IACvD,MAAM,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;AAC3D,CAAC;AAED,qFAAqF;AAC9E,KAAK,UAAU,QAAQ,CAAC,CAAS;IACtC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,kBAAE,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAA;QAC5D,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ export interface GitRepo {
2
+ /** "owner/repo" */
3
+ slug: string;
4
+ /** Normalised https URL. */
5
+ url: string;
6
+ }
7
+ /**
8
+ * Detect the GitHub repo from a directory's `origin` remote. Handles both
9
+ * https and ssh forms. Returns undefined if the dir is not a git repo or has no
10
+ * usable origin.
11
+ */
12
+ export declare function detectGitRepo(cwd: string): Promise<GitRepo | undefined>;
13
+ /** Parse a git remote URL (https or ssh) into a GitHub slug + https URL. */
14
+ export declare function parseRemote(raw: string): GitRepo | undefined;
15
+ /** Normalise an "owner/repo" slug (or full URL) into a GitRepo. */
16
+ export declare function slugToRepo(input: string): GitRepo | undefined;
17
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,OAAO;IACtB,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,4BAA4B;IAC5B,GAAG,EAAE,MAAM,CAAA;CACZ;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAS7E;AAED,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAS5D;AAED,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAO7D"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectGitRepo = detectGitRepo;
4
+ exports.parseRemote = parseRemote;
5
+ exports.slugToRepo = slugToRepo;
6
+ const node_child_process_1 = require("node:child_process");
7
+ const node_util_1 = require("node:util");
8
+ const exec = (0, node_util_1.promisify)(node_child_process_1.execFile);
9
+ /**
10
+ * Detect the GitHub repo from a directory's `origin` remote. Handles both
11
+ * https and ssh forms. Returns undefined if the dir is not a git repo or has no
12
+ * usable origin.
13
+ */
14
+ async function detectGitRepo(cwd) {
15
+ let raw;
16
+ try {
17
+ const { stdout } = await exec("git", ["remote", "get-url", "origin"], { cwd });
18
+ raw = stdout.trim();
19
+ }
20
+ catch {
21
+ return undefined;
22
+ }
23
+ return parseRemote(raw);
24
+ }
25
+ /** Parse a git remote URL (https or ssh) into a GitHub slug + https URL. */
26
+ function parseRemote(raw) {
27
+ const trimmed = raw.replace(/\.git$/, "").trim();
28
+ // git@github.com:owner/repo or ssh://git@github.com/owner/repo
29
+ const ssh = trimmed.match(/git@[^:]+:(.+)$/) ?? trimmed.match(/ssh:\/\/git@[^/]+\/(.+)$/);
30
+ if (ssh?.[1])
31
+ return slugToRepo(ssh[1]);
32
+ // https://github.com/owner/repo
33
+ const https = trimmed.match(/https?:\/\/[^/]+\/(.+)$/);
34
+ if (https?.[1])
35
+ return slugToRepo(https[1]);
36
+ return undefined;
37
+ }
38
+ /** Normalise an "owner/repo" slug (or full URL) into a GitRepo. */
39
+ function slugToRepo(input) {
40
+ const parsed = input.startsWith("http") || input.startsWith("git@") ? parseRemote(input) : undefined;
41
+ if (parsed)
42
+ return parsed;
43
+ const parts = input.split("/").filter(Boolean);
44
+ if (parts.length < 2)
45
+ return undefined;
46
+ const slug = `${parts[parts.length - 2]}/${parts[parts.length - 1]}`;
47
+ return { slug, url: `https://github.com/${slug}` };
48
+ }
49
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":";;AAiBA,sCASC;AAGD,kCASC;AAGD,gCAOC;AAhDD,2DAA6C;AAC7C,yCAAqC;AAErC,MAAM,IAAI,GAAG,IAAA,qBAAS,EAAC,6BAAQ,CAAC,CAAA;AAShC;;;;GAIG;AACI,KAAK,UAAU,aAAa,CAAC,GAAW;IAC7C,IAAI,GAAW,CAAA;IACf,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;QAC9E,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,OAAO,WAAW,CAAC,GAAG,CAAC,CAAA;AACzB,CAAC;AAED,4EAA4E;AAC5E,SAAgB,WAAW,CAAC,GAAW;IACrC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAChD,iEAAiE;IACjE,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAA;IACzF,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IACvC,gCAAgC;IAChC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAA;IACtD,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAC3C,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,mEAAmE;AACnE,SAAgB,UAAU,CAAC,KAAa;IACtC,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACpG,IAAI,MAAM;QAAE,OAAO,MAAM,CAAA;IACzB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAC9C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAA;IACtC,MAAM,IAAI,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAA;IACpE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,sBAAsB,IAAI,EAAE,EAAE,CAAA;AACpD,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Tiny leveled logger. Boring on purpose: writes plain lines to stdout/stderr.
3
+ * Forge is a CLI, so this is the whole logging story.
4
+ */
5
+ export interface Logger {
6
+ info(msg: string): void;
7
+ step(msg: string): void;
8
+ success(msg: string): void;
9
+ warn(msg: string): void;
10
+ error(msg: string): void;
11
+ dim(msg: string): void;
12
+ plain(msg: string): void;
13
+ }
14
+ export declare function createLogger(): Logger;
15
+ export declare const log: Logger;
16
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,wBAAgB,YAAY,IAAI,MAAM,CAUrC;AAED,eAAO,MAAM,GAAG,QAAiB,CAAA"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.log = void 0;
7
+ exports.createLogger = createLogger;
8
+ const picocolors_1 = __importDefault(require("picocolors"));
9
+ function createLogger() {
10
+ return {
11
+ info: (m) => console.log(picocolors_1.default.blue("·") + " " + m),
12
+ step: (m) => console.log(picocolors_1.default.cyan("→") + " " + m),
13
+ success: (m) => console.log(picocolors_1.default.green("✓") + " " + m),
14
+ warn: (m) => console.warn(picocolors_1.default.yellow("!") + " " + m),
15
+ error: (m) => console.error(picocolors_1.default.red("✗") + " " + m),
16
+ dim: (m) => console.log(picocolors_1.default.dim(m)),
17
+ plain: (m) => console.log(m),
18
+ };
19
+ }
20
+ exports.log = createLogger();
21
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":";;;;;;AAgBA,oCAUC;AA1BD,4DAA2B;AAgB3B,SAAgB,YAAY;IAC1B,OAAO;QACL,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QAChD,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QAChD,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QACpD,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,oBAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QACnD,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,oBAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QAClD,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAClC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;KAC7B,CAAA;AACH,CAAC;AAEY,QAAA,GAAG,GAAG,YAAY,EAAE,CAAA"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Run a command, streaming stdio to the terminal. Used sparingly — Forge is a
3
+ * file generator, not a task runner. Returns the exit code.
4
+ */
5
+ export declare function run(cmd: string, args: string[], cwd: string): Promise<number>;
6
+ export interface CaptureResult {
7
+ code: number;
8
+ stdout: string;
9
+ stderr: string;
10
+ }
11
+ export interface CaptureOptions {
12
+ cwd?: string;
13
+ /** Written to the child's stdin then closed (e.g. a secret value). */
14
+ stdin?: string;
15
+ }
16
+ /**
17
+ * Run a command with piped stdio and capture its output. Used by the lwd CLI
18
+ * adapter (secret values go in via `stdin`, never argv). `run()` is untouched.
19
+ */
20
+ export declare function capture(cmd: string, args: string[], opts?: CaptureOptions): Promise<CaptureResult>;
21
+ //# sourceMappingURL=shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/utils/shell.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM7E;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAkBtG"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.run = run;
4
+ exports.capture = capture;
5
+ const node_child_process_1 = require("node:child_process");
6
+ /**
7
+ * Run a command, streaming stdio to the terminal. Used sparingly — Forge is a
8
+ * file generator, not a task runner. Returns the exit code.
9
+ */
10
+ function run(cmd, args, cwd) {
11
+ return new Promise((resolve, reject) => {
12
+ const child = (0, node_child_process_1.spawn)(cmd, args, { cwd, stdio: "inherit", shell: process.platform === "win32" });
13
+ child.on("error", reject);
14
+ child.on("close", (code) => resolve(code ?? 0));
15
+ });
16
+ }
17
+ /**
18
+ * Run a command with piped stdio and capture its output. Used by the lwd CLI
19
+ * adapter (secret values go in via `stdin`, never argv). `run()` is untouched.
20
+ */
21
+ function capture(cmd, args, opts = {}) {
22
+ return new Promise((resolve, reject) => {
23
+ const child = (0, node_child_process_1.spawn)(cmd, args, {
24
+ cwd: opts.cwd,
25
+ stdio: ["pipe", "pipe", "pipe"],
26
+ shell: process.platform === "win32",
27
+ });
28
+ let stdout = "";
29
+ let stderr = "";
30
+ child.stdout.on("data", (d) => (stdout += d.toString()));
31
+ child.stderr.on("data", (d) => (stderr += d.toString()));
32
+ child.on("error", reject);
33
+ child.on("close", (code) => resolve({ code: code ?? 0, stdout, stderr }));
34
+ if (opts.stdin !== undefined) {
35
+ child.stdin.write(opts.stdin);
36
+ }
37
+ child.stdin.end();
38
+ });
39
+ }
40
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/utils/shell.ts"],"names":[],"mappings":";;AAMA,kBAMC;AAkBD,0BAkBC;AAhDD,2DAA0C;AAE1C;;;GAGG;AACH,SAAgB,GAAG,CAAC,GAAW,EAAE,IAAc,EAAE,GAAW;IAC1D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,IAAA,0BAAK,EAAC,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC,CAAA;QAC9F,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACzB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAA;IACjD,CAAC,CAAC,CAAA;AACJ,CAAC;AAcD;;;GAGG;AACH,SAAgB,OAAO,CAAC,GAAW,EAAE,IAAc,EAAE,OAAuB,EAAE;IAC5E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,IAAA,0BAAK,EAAC,GAAG,EAAE,IAAI,EAAE;YAC7B,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;SACpC,CAAC,CAAA;QACF,IAAI,MAAM,GAAG,EAAE,CAAA;QACf,IAAI,MAAM,GAAG,EAAE,CAAA;QACf,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;QACxD,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;QACxD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACzB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;QACzE,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC7B,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC/B,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAA;IACnB,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const FORGE_VERSION = "0.2.0";
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,aAAa,UAAU,CAAA"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FORGE_VERSION = void 0;
4
+ // Single source of truth for the Forge version stamped into forge.json.
5
+ exports.FORGE_VERSION = "0.2.0";
6
+ //# sourceMappingURL=version.js.map