@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.
- package/LICENSE +21 -0
- package/README.md +146 -0
- package/dist/capabilities/analytics.d.ts +3 -0
- package/dist/capabilities/analytics.d.ts.map +1 -0
- package/dist/capabilities/analytics.js +91 -0
- package/dist/capabilities/analytics.js.map +1 -0
- package/dist/capabilities/api-keys.d.ts +3 -0
- package/dist/capabilities/api-keys.d.ts.map +1 -0
- package/dist/capabilities/api-keys.js +90 -0
- package/dist/capabilities/api-keys.js.map +1 -0
- package/dist/capabilities/audit.d.ts +3 -0
- package/dist/capabilities/audit.d.ts.map +1 -0
- package/dist/capabilities/audit.js +74 -0
- package/dist/capabilities/audit.js.map +1 -0
- package/dist/capabilities/entitlements.d.ts +3 -0
- package/dist/capabilities/entitlements.d.ts.map +1 -0
- package/dist/capabilities/entitlements.js +94 -0
- package/dist/capabilities/entitlements.js.map +1 -0
- package/dist/capabilities/events.d.ts +3 -0
- package/dist/capabilities/events.d.ts.map +1 -0
- package/dist/capabilities/events.js +107 -0
- package/dist/capabilities/events.js.map +1 -0
- package/dist/capabilities/files.d.ts +3 -0
- package/dist/capabilities/files.d.ts.map +1 -0
- package/dist/capabilities/files.js +100 -0
- package/dist/capabilities/files.js.map +1 -0
- package/dist/capabilities/helpers.d.ts +27 -0
- package/dist/capabilities/helpers.d.ts.map +1 -0
- package/dist/capabilities/helpers.js +63 -0
- package/dist/capabilities/helpers.js.map +1 -0
- package/dist/capabilities/import-export.d.ts +3 -0
- package/dist/capabilities/import-export.d.ts.map +1 -0
- package/dist/capabilities/import-export.js +267 -0
- package/dist/capabilities/import-export.js.map +1 -0
- package/dist/capabilities/index.d.ts +16 -0
- package/dist/capabilities/index.d.ts.map +1 -0
- package/dist/capabilities/index.js +71 -0
- package/dist/capabilities/index.js.map +1 -0
- package/dist/capabilities/jobs.d.ts +3 -0
- package/dist/capabilities/jobs.d.ts.map +1 -0
- package/dist/capabilities/jobs.js +117 -0
- package/dist/capabilities/jobs.js.map +1 -0
- package/dist/capabilities/notifications.d.ts +3 -0
- package/dist/capabilities/notifications.d.ts.map +1 -0
- package/dist/capabilities/notifications.js +113 -0
- package/dist/capabilities/notifications.js.map +1 -0
- package/dist/capabilities/search.d.ts +3 -0
- package/dist/capabilities/search.d.ts.map +1 -0
- package/dist/capabilities/search.js +121 -0
- package/dist/capabilities/search.js.map +1 -0
- package/dist/capabilities/settings.d.ts +3 -0
- package/dist/capabilities/settings.d.ts.map +1 -0
- package/dist/capabilities/settings.js +75 -0
- package/dist/capabilities/settings.js.map +1 -0
- package/dist/capabilities/types.d.ts +16 -0
- package/dist/capabilities/types.d.ts.map +1 -0
- package/dist/capabilities/types.js +3 -0
- package/dist/capabilities/types.js.map +1 -0
- package/dist/capabilities/webhooks.d.ts +3 -0
- package/dist/capabilities/webhooks.d.ts.map +1 -0
- package/dist/capabilities/webhooks.js +117 -0
- package/dist/capabilities/webhooks.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +60 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/add.d.ts +3 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +88 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/doctor.d.ts +3 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +94 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/generate.d.ts +3 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +41 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/inspect.d.ts +3 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +64 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/new.d.ts +18 -0
- package/dist/commands/new.d.ts.map +1 -0
- package/dist/commands/new.js +149 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/shared.d.ts +14 -0
- package/dist/commands/shared.d.ts.map +1 -0
- package/dist/commands/shared.js +36 -0
- package/dist/commands/shared.js.map +1 -0
- package/dist/commands/skill.d.ts +3 -0
- package/dist/commands/skill.d.ts.map +1 -0
- package/dist/commands/skill.js +59 -0
- package/dist/commands/skill.js.map +1 -0
- package/dist/commands/stack.d.ts +13 -0
- package/dist/commands/stack.d.ts.map +1 -0
- package/dist/commands/stack.js +192 -0
- package/dist/commands/stack.js.map +1 -0
- package/dist/generators/api.d.ts +16 -0
- package/dist/generators/api.d.ts.map +1 -0
- package/dist/generators/api.js +375 -0
- package/dist/generators/api.js.map +1 -0
- package/dist/generators/lwd.d.ts +12 -0
- package/dist/generators/lwd.d.ts.map +1 -0
- package/dist/generators/lwd.js +143 -0
- package/dist/generators/lwd.js.map +1 -0
- package/dist/generators/mobile.d.ts +16 -0
- package/dist/generators/mobile.d.ts.map +1 -0
- package/dist/generators/mobile.js +180 -0
- package/dist/generators/mobile.js.map +1 -0
- package/dist/generators/platform-package.d.ts +18 -0
- package/dist/generators/platform-package.d.ts.map +1 -0
- package/dist/generators/platform-package.js +568 -0
- package/dist/generators/platform-package.js.map +1 -0
- package/dist/generators/root.d.ts +15 -0
- package/dist/generators/root.d.ts.map +1 -0
- package/dist/generators/root.js +249 -0
- package/dist/generators/root.js.map +1 -0
- package/dist/generators/sdk.d.ts +14 -0
- package/dist/generators/sdk.d.ts.map +1 -0
- package/dist/generators/sdk.js +137 -0
- package/dist/generators/sdk.js.map +1 -0
- package/dist/generators/web.d.ts +15 -0
- package/dist/generators/web.d.ts.map +1 -0
- package/dist/generators/web.js +203 -0
- package/dist/generators/web.js.map +1 -0
- package/dist/generators/worker.d.ts +13 -0
- package/dist/generators/worker.d.ts.map +1 -0
- package/dist/generators/worker.js +148 -0
- package/dist/generators/worker.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/project/context.d.ts +24 -0
- package/dist/project/context.d.ts.map +1 -0
- package/dist/project/context.js +63 -0
- package/dist/project/context.js.map +1 -0
- package/dist/project/manifest.d.ts +26 -0
- package/dist/project/manifest.d.ts.map +1 -0
- package/dist/project/manifest.js +73 -0
- package/dist/project/manifest.js.map +1 -0
- package/dist/project/paths.d.ts +25 -0
- package/dist/project/paths.d.ts.map +1 -0
- package/dist/project/paths.js +51 -0
- package/dist/project/paths.js.map +1 -0
- package/dist/project/plan.d.ts +42 -0
- package/dist/project/plan.d.ts.map +1 -0
- package/dist/project/plan.js +251 -0
- package/dist/project/plan.js.map +1 -0
- package/dist/prompts/index.d.ts +24 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +111 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/recipes/index.d.ts +25 -0
- package/dist/recipes/index.d.ts.map +1 -0
- package/dist/recipes/index.js +77 -0
- package/dist/recipes/index.js.map +1 -0
- package/dist/stack/infer.d.ts +4 -0
- package/dist/stack/infer.d.ts.map +1 -0
- package/dist/stack/infer.js +165 -0
- package/dist/stack/infer.js.map +1 -0
- package/dist/stack/lwd.d.ts +24 -0
- package/dist/stack/lwd.d.ts.map +1 -0
- package/dist/stack/lwd.js +62 -0
- package/dist/stack/lwd.js.map +1 -0
- package/dist/stack/lwdtoml.d.ts +38 -0
- package/dist/stack/lwdtoml.d.ts.map +1 -0
- package/dist/stack/lwdtoml.js +57 -0
- package/dist/stack/lwdtoml.js.map +1 -0
- package/dist/stack/manifest.d.ts +15 -0
- package/dist/stack/manifest.d.ts.map +1 -0
- package/dist/stack/manifest.js +86 -0
- package/dist/stack/manifest.js.map +1 -0
- package/dist/stack/types.d.ts +48 -0
- package/dist/stack/types.d.ts.map +1 -0
- package/dist/stack/types.js +5 -0
- package/dist/stack/types.js.map +1 -0
- package/dist/stack/wire.d.ts +40 -0
- package/dist/stack/wire.d.ts.map +1 -0
- package/dist/stack/wire.js +192 -0
- package/dist/stack/wire.js.map +1 -0
- package/dist/types.d.ts +114 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/fs.d.ts +13 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +64 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/git.d.ts +17 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +49 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +21 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/shell.d.ts +21 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +40 -0
- package/dist/utils/shell.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +6 -0
- package/dist/version.js.map +1 -0
- package/package.json +40 -0
- package/skills/obh-add-events/SKILL.md +26 -0
- package/skills/obh-generate-audit-rules/SKILL.md +26 -0
- package/skills/obh-inspect-project/SKILL.md +26 -0
- package/skills/obh-lwd-manifest/SKILL.md +26 -0
- package/skills/obh-retrofit-files/SKILL.md +24 -0
- package/skills/obh-retrofit-jobs/SKILL.md +26 -0
- package/skills/obh-sdk-extraction/SKILL.md +24 -0
- package/skills/obh-settings-migration/SKILL.md +24 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.addWorkerApp = addWorkerApp;
|
|
4
|
+
/**
|
|
5
|
+
* Generates a worker app. Consumers live in src/consumers.d/*.ts, each exporting
|
|
6
|
+
* an optional `init(ctx)` and a `tick(ctx)`. The worker loads them by convention
|
|
7
|
+
* and drives them on an interval — capabilities add background work by dropping
|
|
8
|
+
* a file, never by editing the loop. Includes a plain-HTTP health port because
|
|
9
|
+
* lwd surfaces (including workers) require one.
|
|
10
|
+
*/
|
|
11
|
+
function addWorkerApp(plan, opts) {
|
|
12
|
+
const dir = "apps/worker";
|
|
13
|
+
plan.create(`${dir}/package.json`, JSON.stringify({
|
|
14
|
+
name: `${opts.scope}/worker`,
|
|
15
|
+
version: "0.1.0",
|
|
16
|
+
private: true,
|
|
17
|
+
scripts: {
|
|
18
|
+
dev: "tsx watch src/main.ts",
|
|
19
|
+
build: "tsc -p tsconfig.json",
|
|
20
|
+
typecheck: "tsc -p tsconfig.json --noEmit",
|
|
21
|
+
start: "node dist/main.js",
|
|
22
|
+
test: "vitest run --passWithNoTests",
|
|
23
|
+
},
|
|
24
|
+
dependencies: { pg: "^8.12.0" },
|
|
25
|
+
devDependencies: {
|
|
26
|
+
"@types/node": "^20.14.0",
|
|
27
|
+
"@types/pg": "^8.11.6",
|
|
28
|
+
tsx: "^4.16.0",
|
|
29
|
+
typescript: "^5.5.4",
|
|
30
|
+
vitest: "^2.0.5",
|
|
31
|
+
},
|
|
32
|
+
}, null, 2) + "\n", "worker app package.json");
|
|
33
|
+
plan.create(`${dir}/tsconfig.json`, JSON.stringify({
|
|
34
|
+
extends: "../../tsconfig.base.json",
|
|
35
|
+
compilerOptions: { rootDir: "src", outDir: "dist" },
|
|
36
|
+
include: ["src"],
|
|
37
|
+
exclude: ["dist", "node_modules", "src/**/*.test.ts"],
|
|
38
|
+
}, null, 2) + "\n", "worker tsconfig");
|
|
39
|
+
plan.create(`${dir}/src/context.ts`, CONTEXT, "worker context (pool + logger)");
|
|
40
|
+
plan.create(`${dir}/src/main.ts`, MAIN, "worker loop (auto-loads src/consumers.d/*)");
|
|
41
|
+
plan.create(`${dir}/src/consumers.d/.gitkeep`, "", "worker consumers directory");
|
|
42
|
+
plan.create(`${dir}/Dockerfile`, DOCKERFILE, "worker Dockerfile");
|
|
43
|
+
}
|
|
44
|
+
const CONTEXT = `import { Pool } from "pg"
|
|
45
|
+
|
|
46
|
+
export interface WorkerContext {
|
|
47
|
+
pool: Pool
|
|
48
|
+
log: (msg: string, fields?: Record<string, unknown>) => void
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function createContext(): WorkerContext {
|
|
52
|
+
const databaseUrl = process.env.DATABASE_URL
|
|
53
|
+
if (!databaseUrl) throw new Error("DATABASE_URL is not set")
|
|
54
|
+
const pool = new Pool({ connectionString: databaseUrl })
|
|
55
|
+
return {
|
|
56
|
+
pool,
|
|
57
|
+
log: (msg, fields) => console.log(JSON.stringify({ msg, ...fields })),
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
const MAIN = `import { createServer } from "node:http"
|
|
62
|
+
import { readdirSync } from "node:fs"
|
|
63
|
+
import path from "node:path"
|
|
64
|
+
import { createContext, type WorkerContext } from "./context"
|
|
65
|
+
|
|
66
|
+
interface Consumer {
|
|
67
|
+
name: string
|
|
68
|
+
init?: (ctx: WorkerContext) => Promise<void> | void
|
|
69
|
+
tick: (ctx: WorkerContext) => Promise<void> | void
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function loadConsumers(): Consumer[] {
|
|
73
|
+
const dir = path.join(__dirname, "consumers.d")
|
|
74
|
+
const out: Consumer[] = []
|
|
75
|
+
for (const file of readdirSync(dir).sort()) {
|
|
76
|
+
if (!/\\.(ts|js)$/.test(file) || file.endsWith(".d.ts")) continue
|
|
77
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
78
|
+
const mod = require(path.join(dir, file))
|
|
79
|
+
if (typeof mod.tick === "function") {
|
|
80
|
+
out.push({ name: file.replace(/\\.(ts|js)$/, ""), init: mod.init, tick: mod.tick })
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return out
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function main(): Promise<void> {
|
|
87
|
+
const ctx = createContext()
|
|
88
|
+
const consumers = loadConsumers()
|
|
89
|
+
const pollMs = Number(process.env.POLL_INTERVAL_MS) || 1000
|
|
90
|
+
|
|
91
|
+
for (const c of consumers) {
|
|
92
|
+
if (c.init) await c.init(ctx)
|
|
93
|
+
ctx.log("consumer registered", { consumer: c.name })
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// lwd requires a health port even for a worker surface.
|
|
97
|
+
const port = Number(process.env.PORT) || 8080
|
|
98
|
+
createServer((_req, res) => {
|
|
99
|
+
res.writeHead(200, { "content-type": "application/json" })
|
|
100
|
+
res.end(JSON.stringify({ status: "ok" }))
|
|
101
|
+
}).listen(port, () => ctx.log("worker health listening", { port }))
|
|
102
|
+
|
|
103
|
+
let ticking = false
|
|
104
|
+
const timer = setInterval(async () => {
|
|
105
|
+
if (ticking) return
|
|
106
|
+
ticking = true
|
|
107
|
+
try {
|
|
108
|
+
for (const c of consumers) await c.tick(ctx)
|
|
109
|
+
} catch (err) {
|
|
110
|
+
ctx.log("tick failed", { error: err instanceof Error ? err.message : String(err) })
|
|
111
|
+
} finally {
|
|
112
|
+
ticking = false
|
|
113
|
+
}
|
|
114
|
+
}, pollMs)
|
|
115
|
+
|
|
116
|
+
const shutdown = async (): Promise<void> => {
|
|
117
|
+
clearInterval(timer)
|
|
118
|
+
await ctx.pool.end()
|
|
119
|
+
process.exit(0)
|
|
120
|
+
}
|
|
121
|
+
process.on("SIGTERM", () => void shutdown())
|
|
122
|
+
process.on("SIGINT", () => void shutdown())
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
main().catch((err) => {
|
|
126
|
+
console.error(err)
|
|
127
|
+
process.exit(1)
|
|
128
|
+
})
|
|
129
|
+
`;
|
|
130
|
+
const DOCKERFILE = `# Built by lwd from apps/worker (git.path = "apps/worker").
|
|
131
|
+
FROM node:20-alpine AS builder
|
|
132
|
+
WORKDIR /app
|
|
133
|
+
RUN npm install -g pnpm@9
|
|
134
|
+
COPY package.json ./
|
|
135
|
+
RUN pnpm install --no-frozen-lockfile
|
|
136
|
+
COPY . .
|
|
137
|
+
RUN pnpm build
|
|
138
|
+
|
|
139
|
+
FROM node:20-alpine
|
|
140
|
+
WORKDIR /app
|
|
141
|
+
RUN npm install -g pnpm@9
|
|
142
|
+
COPY package.json ./
|
|
143
|
+
RUN pnpm install --prod --no-frozen-lockfile
|
|
144
|
+
COPY --from=builder /app/dist ./dist
|
|
145
|
+
EXPOSE 8080
|
|
146
|
+
CMD ["node", "dist/main.js"]
|
|
147
|
+
`;
|
|
148
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/generators/worker.ts"],"names":[],"mappings":";;AAaA,oCAmDC;AA1DD;;;;;;GAMG;AACH,SAAgB,YAAY,CAAC,IAAU,EAAE,IAAmB;IAC1D,MAAM,GAAG,GAAG,aAAa,CAAA;IAEzB,IAAI,CAAC,MAAM,CACT,GAAG,GAAG,eAAe,EACrB,IAAI,CAAC,SAAS,CACZ;QACE,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,SAAS;QAC5B,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,IAAI;QACb,OAAO,EAAE;YACP,GAAG,EAAE,uBAAuB;YAC5B,KAAK,EAAE,sBAAsB;YAC7B,SAAS,EAAE,+BAA+B;YAC1C,KAAK,EAAE,mBAAmB;YAC1B,IAAI,EAAE,8BAA8B;SACrC;QACD,YAAY,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE;QAC/B,eAAe,EAAE;YACf,aAAa,EAAE,UAAU;YACzB,WAAW,EAAE,SAAS;YACtB,GAAG,EAAE,SAAS;YACd,UAAU,EAAE,QAAQ;YACpB,MAAM,EAAE,QAAQ;SACjB;KACF,EACD,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,EACR,yBAAyB,CAC1B,CAAA;IAED,IAAI,CAAC,MAAM,CACT,GAAG,GAAG,gBAAgB,EACtB,IAAI,CAAC,SAAS,CACZ;QACE,OAAO,EAAE,0BAA0B;QACnC,eAAe,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE;QACnD,OAAO,EAAE,CAAC,KAAK,CAAC;QAChB,OAAO,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,kBAAkB,CAAC;KACtD,EACD,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,EACR,iBAAiB,CAClB,CAAA;IAED,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,iBAAiB,EAAE,OAAO,EAAE,gCAAgC,CAAC,CAAA;IAC/E,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,cAAc,EAAE,IAAI,EAAE,4CAA4C,CAAC,CAAA;IACrF,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,2BAA2B,EAAE,EAAE,EAAE,4BAA4B,CAAC,CAAA;IAChF,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,aAAa,EAAE,UAAU,EAAE,mBAAmB,CAAC,CAAA;AACnE,CAAC;AAED,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;CAgBf,CAAA;AAED,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoEZ,CAAA;AAED,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;CAiBlB,CAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { FORGE_VERSION } from "./version";
|
|
2
|
+
export * from "./types";
|
|
3
|
+
export { Plan } from "./project/plan";
|
|
4
|
+
export { ProjectContext } from "./project/context";
|
|
5
|
+
export { loadManifest, saveManifest, newManifest, mergeManifest } from "./project/manifest";
|
|
6
|
+
export { CAPABILITIES, getCapability, isImplemented, resolveOrder, missingPrerequisites } from "./capabilities";
|
|
7
|
+
export type { Capability } from "./capabilities";
|
|
8
|
+
export { RECIPES, getRecipe } from "./recipes";
|
|
9
|
+
export { addLwdManifests, computeSecrets } from "./generators/lwd";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,cAAc,SAAS,CAAA;AAEvB,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAE3F,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAC/G,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAEhD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Programmatic surface of @obh/forge. The CLI (src/cli.ts) is the primary entry;
|
|
3
|
+
// these exports let scripts and Claude skills drive Forge in-process.
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
16
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.computeSecrets = exports.addLwdManifests = exports.getRecipe = exports.RECIPES = exports.missingPrerequisites = exports.resolveOrder = exports.isImplemented = exports.getCapability = exports.CAPABILITIES = exports.mergeManifest = exports.newManifest = exports.saveManifest = exports.loadManifest = exports.ProjectContext = exports.Plan = exports.FORGE_VERSION = void 0;
|
|
20
|
+
var version_1 = require("./version");
|
|
21
|
+
Object.defineProperty(exports, "FORGE_VERSION", { enumerable: true, get: function () { return version_1.FORGE_VERSION; } });
|
|
22
|
+
__exportStar(require("./types"), exports);
|
|
23
|
+
var plan_1 = require("./project/plan");
|
|
24
|
+
Object.defineProperty(exports, "Plan", { enumerable: true, get: function () { return plan_1.Plan; } });
|
|
25
|
+
var context_1 = require("./project/context");
|
|
26
|
+
Object.defineProperty(exports, "ProjectContext", { enumerable: true, get: function () { return context_1.ProjectContext; } });
|
|
27
|
+
var manifest_1 = require("./project/manifest");
|
|
28
|
+
Object.defineProperty(exports, "loadManifest", { enumerable: true, get: function () { return manifest_1.loadManifest; } });
|
|
29
|
+
Object.defineProperty(exports, "saveManifest", { enumerable: true, get: function () { return manifest_1.saveManifest; } });
|
|
30
|
+
Object.defineProperty(exports, "newManifest", { enumerable: true, get: function () { return manifest_1.newManifest; } });
|
|
31
|
+
Object.defineProperty(exports, "mergeManifest", { enumerable: true, get: function () { return manifest_1.mergeManifest; } });
|
|
32
|
+
var capabilities_1 = require("./capabilities");
|
|
33
|
+
Object.defineProperty(exports, "CAPABILITIES", { enumerable: true, get: function () { return capabilities_1.CAPABILITIES; } });
|
|
34
|
+
Object.defineProperty(exports, "getCapability", { enumerable: true, get: function () { return capabilities_1.getCapability; } });
|
|
35
|
+
Object.defineProperty(exports, "isImplemented", { enumerable: true, get: function () { return capabilities_1.isImplemented; } });
|
|
36
|
+
Object.defineProperty(exports, "resolveOrder", { enumerable: true, get: function () { return capabilities_1.resolveOrder; } });
|
|
37
|
+
Object.defineProperty(exports, "missingPrerequisites", { enumerable: true, get: function () { return capabilities_1.missingPrerequisites; } });
|
|
38
|
+
var recipes_1 = require("./recipes");
|
|
39
|
+
Object.defineProperty(exports, "RECIPES", { enumerable: true, get: function () { return recipes_1.RECIPES; } });
|
|
40
|
+
Object.defineProperty(exports, "getRecipe", { enumerable: true, get: function () { return recipes_1.getRecipe; } });
|
|
41
|
+
var lwd_1 = require("./generators/lwd");
|
|
42
|
+
Object.defineProperty(exports, "addLwdManifests", { enumerable: true, get: function () { return lwd_1.addLwdManifests; } });
|
|
43
|
+
Object.defineProperty(exports, "computeSecrets", { enumerable: true, get: function () { return lwd_1.computeSecrets; } });
|
|
44
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,iFAAiF;AACjF,sEAAsE;;;;;;;;;;;;;;;;;AAEtE,qCAAyC;AAAhC,wGAAA,aAAa,OAAA;AACtB,0CAAuB;AAEvB,uCAAqC;AAA5B,4FAAA,IAAI,OAAA;AACb,6CAAkD;AAAzC,yGAAA,cAAc,OAAA;AACvB,+CAA2F;AAAlF,wGAAA,YAAY,OAAA;AAAE,wGAAA,YAAY,OAAA;AAAE,uGAAA,WAAW,OAAA;AAAE,yGAAA,aAAa,OAAA;AAE/D,+CAA+G;AAAtG,4GAAA,YAAY,OAAA;AAAE,6GAAA,aAAa,OAAA;AAAE,6GAAA,aAAa,OAAA;AAAE,4GAAA,YAAY,OAAA;AAAE,oHAAA,oBAAoB,OAAA;AAGvF,qCAA8C;AAArC,kGAAA,OAAO,OAAA;AAAE,oGAAA,SAAS,OAAA;AAC3B,wCAAkE;AAAzD,sGAAA,eAAe,OAAA;AAAE,qGAAA,cAAc,OAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { AppRecord, CapabilityName, ForgeManifest } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* A read model of the project Forge is operating on. Commands load one of these,
|
|
4
|
+
* build a Plan against it, and apply. It never mutates anything itself.
|
|
5
|
+
*/
|
|
6
|
+
export declare class ProjectContext {
|
|
7
|
+
readonly root: string;
|
|
8
|
+
readonly manifest: ForgeManifest | undefined;
|
|
9
|
+
readonly rootPkg: Record<string, any> | undefined;
|
|
10
|
+
readonly appDirs: string[];
|
|
11
|
+
readonly packageDirs: string[];
|
|
12
|
+
constructor(root: string, manifest: ForgeManifest | undefined, rootPkg: Record<string, any> | undefined, appDirs: string[], packageDirs: string[]);
|
|
13
|
+
static load(cwd: string): Promise<ProjectContext>;
|
|
14
|
+
hasManifest(): boolean;
|
|
15
|
+
requireManifest(): ForgeManifest;
|
|
16
|
+
hasCapability(name: CapabilityName): boolean;
|
|
17
|
+
/** True if an app directory of this name exists on disk. */
|
|
18
|
+
hasApp(name: string): boolean;
|
|
19
|
+
/** The first app with the given role recorded in the manifest, if any. */
|
|
20
|
+
appByRole(role: AppRecord["role"]): AppRecord | undefined;
|
|
21
|
+
/** True if a worker app exists (on disk or in the manifest). */
|
|
22
|
+
hasWorker(): boolean;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/project/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAKxE;;;GAGG;AACH,qBAAa,cAAc;IAEvB,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,QAAQ,EAAE,aAAa,GAAG,SAAS;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS;IACjD,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE;gBAJrB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,aAAa,GAAG,SAAS,EACnC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EACxC,OAAO,EAAE,MAAM,EAAE,EACjB,WAAW,EAAE,MAAM,EAAE;WAGnB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IASvD,WAAW,IAAI,OAAO;IAItB,eAAe,IAAI,aAAa;IAShC,aAAa,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO;IAI5C,4DAA4D;IAC5D,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI7B,0EAA0E;IAC1E,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,SAAS,GAAG,SAAS;IAKzD,gEAAgE;IAChE,SAAS,IAAI,OAAO;CAGrB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
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.ProjectContext = void 0;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const fs_1 = require("../utils/fs");
|
|
9
|
+
const manifest_1 = require("./manifest");
|
|
10
|
+
const paths_1 = require("./paths");
|
|
11
|
+
/**
|
|
12
|
+
* A read model of the project Forge is operating on. Commands load one of these,
|
|
13
|
+
* build a Plan against it, and apply. It never mutates anything itself.
|
|
14
|
+
*/
|
|
15
|
+
class ProjectContext {
|
|
16
|
+
root;
|
|
17
|
+
manifest;
|
|
18
|
+
rootPkg;
|
|
19
|
+
appDirs;
|
|
20
|
+
packageDirs;
|
|
21
|
+
constructor(root, manifest, rootPkg, appDirs, packageDirs) {
|
|
22
|
+
this.root = root;
|
|
23
|
+
this.manifest = manifest;
|
|
24
|
+
this.rootPkg = rootPkg;
|
|
25
|
+
this.appDirs = appDirs;
|
|
26
|
+
this.packageDirs = packageDirs;
|
|
27
|
+
}
|
|
28
|
+
static async load(cwd) {
|
|
29
|
+
const root = await (0, paths_1.findProjectRoot)(cwd);
|
|
30
|
+
const manifest = await (0, manifest_1.loadManifest)(root);
|
|
31
|
+
const rootPkg = await (0, fs_1.readJson)(node_path_1.default.join(root, "package.json"));
|
|
32
|
+
const appDirs = await (0, fs_1.listDirs)(node_path_1.default.join(root, "apps"));
|
|
33
|
+
const packageDirs = await (0, fs_1.listDirs)(node_path_1.default.join(root, "packages"));
|
|
34
|
+
return new ProjectContext(root, manifest, rootPkg, appDirs, packageDirs);
|
|
35
|
+
}
|
|
36
|
+
hasManifest() {
|
|
37
|
+
return this.manifest !== undefined;
|
|
38
|
+
}
|
|
39
|
+
requireManifest() {
|
|
40
|
+
if (!this.manifest) {
|
|
41
|
+
throw new Error("No forge.json found. Run this inside a Forge project, or create one with `forge new app <name>`.");
|
|
42
|
+
}
|
|
43
|
+
return this.manifest;
|
|
44
|
+
}
|
|
45
|
+
hasCapability(name) {
|
|
46
|
+
return this.manifest?.platform?.[name] === true;
|
|
47
|
+
}
|
|
48
|
+
/** True if an app directory of this name exists on disk. */
|
|
49
|
+
hasApp(name) {
|
|
50
|
+
return this.appDirs.includes(name);
|
|
51
|
+
}
|
|
52
|
+
/** The first app with the given role recorded in the manifest, if any. */
|
|
53
|
+
appByRole(role) {
|
|
54
|
+
const apps = this.manifest?.apps ?? {};
|
|
55
|
+
return Object.values(apps).find((a) => a.role === role);
|
|
56
|
+
}
|
|
57
|
+
/** True if a worker app exists (on disk or in the manifest). */
|
|
58
|
+
hasWorker() {
|
|
59
|
+
return this.hasApp("worker") || this.appByRole("worker") !== undefined;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.ProjectContext = ProjectContext;
|
|
63
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/project/context.ts"],"names":[],"mappings":";;;;;;AAAA,0DAA4B;AAE5B,oCAAgD;AAChD,yCAAyC;AACzC,mCAAyC;AAEzC;;;GAGG;AACH,MAAa,cAAc;IAEd;IACA;IACA;IACA;IACA;IALX,YACW,IAAY,EACZ,QAAmC,EACnC,OAAwC,EACxC,OAAiB,EACjB,WAAqB;QAJrB,SAAI,GAAJ,IAAI,CAAQ;QACZ,aAAQ,GAAR,QAAQ,CAA2B;QACnC,YAAO,GAAP,OAAO,CAAiC;QACxC,YAAO,GAAP,OAAO,CAAU;QACjB,gBAAW,GAAX,WAAW,CAAU;IAC7B,CAAC;IAEJ,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAW;QAC3B,MAAM,IAAI,GAAG,MAAM,IAAA,uBAAe,EAAC,GAAG,CAAC,CAAA;QACvC,MAAM,QAAQ,GAAG,MAAM,IAAA,uBAAY,EAAC,IAAI,CAAC,CAAA;QACzC,MAAM,OAAO,GAAG,MAAM,IAAA,aAAQ,EAAsB,mBAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAA;QACpF,MAAM,OAAO,GAAG,MAAM,IAAA,aAAQ,EAAC,mBAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;QACvD,MAAM,WAAW,GAAG,MAAM,IAAA,aAAQ,EAAC,mBAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAA;QAC/D,OAAO,IAAI,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,CAAA;IAC1E,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAA;IACpC,CAAC;IAED,eAAe;QACb,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,kGAAkG,CACnG,CAAA;QACH,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAED,aAAa,CAAC,IAAoB;QAChC,OAAO,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,CAAA;IACjD,CAAC;IAED,4DAA4D;IAC5D,MAAM,CAAC,IAAY;QACjB,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC;IAED,0EAA0E;IAC1E,SAAS,CAAC,IAAuB;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAA;QACtC,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;IACzD,CAAC;IAED,gEAAgE;IAChE,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,SAAS,CAAA;IACxE,CAAC;CACF;AAlDD,wCAkDC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ApiFramework, ExampleDomain, ForgeConfig, ForgeManifest, Topology } from "../types";
|
|
2
|
+
/** Default convention directories generated apps auto-load from. */
|
|
3
|
+
export declare function defaultConventions(): ForgeConfig["conventions"];
|
|
4
|
+
export interface NewManifestOptions {
|
|
5
|
+
topology: Topology;
|
|
6
|
+
apiFramework?: ApiFramework;
|
|
7
|
+
sdk?: boolean;
|
|
8
|
+
example?: ExampleDomain;
|
|
9
|
+
repo?: string;
|
|
10
|
+
}
|
|
11
|
+
/** Build a fresh manifest for a brand-new project. */
|
|
12
|
+
export declare function newManifest(name: string, createdAt: string, opts: NewManifestOptions): ForgeManifest;
|
|
13
|
+
/** Load forge.json from a project root, or undefined if absent/invalid. */
|
|
14
|
+
export declare function loadManifest(root: string): Promise<ForgeManifest | undefined>;
|
|
15
|
+
/** Persist forge.json. */
|
|
16
|
+
export declare function saveManifest(root: string, manifest: ForgeManifest): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Merge a partial manifest patch into a base manifest. Shallow-merges the
|
|
19
|
+
* top-level records (apps/packages/platform) so capabilities can add entries
|
|
20
|
+
* without clobbering existing ones.
|
|
21
|
+
*/
|
|
22
|
+
export declare function mergeManifest(base: ForgeManifest, patch: DeepPartial<ForgeManifest>): ForgeManifest;
|
|
23
|
+
export type DeepPartial<T> = {
|
|
24
|
+
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/project/manifest.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAKjG,oEAAoE;AACpE,wBAAgB,kBAAkB,IAAI,WAAW,CAAC,aAAa,CAAC,CAO/D;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,QAAQ,CAAA;IAClB,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,sDAAsD;AACtD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,GAAG,aAAa,CAmBpG;AAED,2EAA2E;AAC3E,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAEnF;AAED,0BAA0B;AAC1B,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvF;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,WAAW,CAAC,aAAa,CAAC,GAAG,aAAa,CAUnG;AAOD,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;KAC1B,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAChE,CAAA"}
|
|
@@ -0,0 +1,73 @@
|
|
|
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.defaultConventions = defaultConventions;
|
|
7
|
+
exports.newManifest = newManifest;
|
|
8
|
+
exports.loadManifest = loadManifest;
|
|
9
|
+
exports.saveManifest = saveManifest;
|
|
10
|
+
exports.mergeManifest = mergeManifest;
|
|
11
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
+
const version_1 = require("../version");
|
|
13
|
+
const fs_1 = require("../utils/fs");
|
|
14
|
+
const paths_1 = require("./paths");
|
|
15
|
+
/** Default convention directories generated apps auto-load from. */
|
|
16
|
+
function defaultConventions() {
|
|
17
|
+
return {
|
|
18
|
+
routesDir: "src/routes",
|
|
19
|
+
consumersDir: "src/consumers.d",
|
|
20
|
+
busDir: "src/bus.d",
|
|
21
|
+
migrationsDir: "scripts/migrations.d",
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** Build a fresh manifest for a brand-new project. */
|
|
25
|
+
function newManifest(name, createdAt, opts) {
|
|
26
|
+
return {
|
|
27
|
+
name,
|
|
28
|
+
forgeVersion: version_1.FORGE_VERSION,
|
|
29
|
+
createdAt,
|
|
30
|
+
packageManager: "pnpm",
|
|
31
|
+
runtime: "node20",
|
|
32
|
+
apps: {},
|
|
33
|
+
packages: {},
|
|
34
|
+
platform: {},
|
|
35
|
+
config: {
|
|
36
|
+
apiFramework: opts.apiFramework ?? "hono",
|
|
37
|
+
sdk: opts.sdk ?? true,
|
|
38
|
+
// example can be legitimately null (--no-example), so don't use ??.
|
|
39
|
+
example: opts.example === undefined ? "notes" : opts.example,
|
|
40
|
+
conventions: defaultConventions(),
|
|
41
|
+
},
|
|
42
|
+
deploy: { target: "lwd", topology: opts.topology, repo: opts.repo },
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** Load forge.json from a project root, or undefined if absent/invalid. */
|
|
46
|
+
async function loadManifest(root) {
|
|
47
|
+
return (0, fs_1.readJson)(node_path_1.default.join(root, paths_1.paths.forgeManifest));
|
|
48
|
+
}
|
|
49
|
+
/** Persist forge.json. */
|
|
50
|
+
async function saveManifest(root, manifest) {
|
|
51
|
+
await (0, fs_1.writeJson)(node_path_1.default.join(root, paths_1.paths.forgeManifest), manifest);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Merge a partial manifest patch into a base manifest. Shallow-merges the
|
|
55
|
+
* top-level records (apps/packages/platform) so capabilities can add entries
|
|
56
|
+
* without clobbering existing ones.
|
|
57
|
+
*/
|
|
58
|
+
function mergeManifest(base, patch) {
|
|
59
|
+
return {
|
|
60
|
+
...base,
|
|
61
|
+
...stripRecords(patch),
|
|
62
|
+
apps: { ...base.apps, ...patch.apps },
|
|
63
|
+
packages: { ...base.packages, ...patch.packages },
|
|
64
|
+
platform: { ...base.platform, ...patch.platform },
|
|
65
|
+
config: { ...base.config, ...patch.config },
|
|
66
|
+
deploy: { ...base.deploy, ...patch.deploy },
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function stripRecords(patch) {
|
|
70
|
+
const { apps, packages, platform, config, deploy, ...rest } = patch;
|
|
71
|
+
return rest;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/project/manifest.ts"],"names":[],"mappings":";;;;;AAOA,gDAOC;AAWD,kCAmBC;AAGD,oCAEC;AAGD,oCAEC;AAOD,sCAUC;AAvED,0DAA4B;AAE5B,wCAA0C;AAC1C,oCAAiD;AACjD,mCAA+B;AAE/B,oEAAoE;AACpE,SAAgB,kBAAkB;IAChC,OAAO;QACL,SAAS,EAAE,YAAY;QACvB,YAAY,EAAE,iBAAiB;QAC/B,MAAM,EAAE,WAAW;QACnB,aAAa,EAAE,sBAAsB;KACtC,CAAA;AACH,CAAC;AAUD,sDAAsD;AACtD,SAAgB,WAAW,CAAC,IAAY,EAAE,SAAiB,EAAE,IAAwB;IACnF,OAAO;QACL,IAAI;QACJ,YAAY,EAAE,uBAAa;QAC3B,SAAS;QACT,cAAc,EAAE,MAAM;QACtB,OAAO,EAAE,QAAQ;QACjB,IAAI,EAAE,EAAE;QACR,QAAQ,EAAE,EAAE;QACZ,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE;YACN,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,MAAM;YACzC,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,IAAI;YACrB,oEAAoE;YACpE,OAAO,EAAE,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO;YAC5D,WAAW,EAAE,kBAAkB,EAAE;SAClC;QACD,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;KACpE,CAAA;AACH,CAAC;AAED,2EAA2E;AACpE,KAAK,UAAU,YAAY,CAAC,IAAY;IAC7C,OAAO,IAAA,aAAQ,EAAgB,mBAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAK,CAAC,aAAa,CAAC,CAAC,CAAA;AACtE,CAAC;AAED,0BAA0B;AACnB,KAAK,UAAU,YAAY,CAAC,IAAY,EAAE,QAAuB;IACtE,MAAM,IAAA,cAAS,EAAC,mBAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAK,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,CAAA;AACjE,CAAC;AAED;;;;GAIG;AACH,SAAgB,aAAa,CAAC,IAAmB,EAAE,KAAiC;IAClF,OAAO;QACL,GAAG,IAAI;QACP,GAAG,YAAY,CAAC,KAAK,CAAC;QACtB,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,GAAI,KAAK,CAAC,IAA8B,EAAE;QAChE,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAI,KAAK,CAAC,QAAsC,EAAE;QAChF,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAI,KAAK,CAAC,QAAsC,EAAE;QAChF,MAAM,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,GAAI,KAAK,CAAC,MAAkC,EAAE;QACxE,MAAM,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,GAAI,KAAK,CAAC,MAAkC,EAAE;KACzE,CAAA;AACH,CAAC;AAED,SAAS,YAAY,CAAC,KAAiC;IACrD,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAA;IACnE,OAAO,IAA8B,CAAA;AACvC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the project root by walking up from `start` looking for forge.json,
|
|
3
|
+
* then pnpm-workspace.yaml, then package.json. Falls back to `start`.
|
|
4
|
+
*/
|
|
5
|
+
export declare function findProjectRoot(start: string): Promise<string>;
|
|
6
|
+
/** Absolute path for a repo-relative path within the project. */
|
|
7
|
+
export declare function abs(root: string, relative: string): string;
|
|
8
|
+
export declare const paths: {
|
|
9
|
+
readonly forgeManifest: "forge.json";
|
|
10
|
+
readonly stackManifest: "deploy/stack.json";
|
|
11
|
+
readonly rootPackageJson: "package.json";
|
|
12
|
+
readonly pnpmWorkspace: "pnpm-workspace.yaml";
|
|
13
|
+
readonly tsconfigBase: "tsconfig.base.json";
|
|
14
|
+
readonly envExample: ".env.example";
|
|
15
|
+
readonly ci: ".github/workflows/ci.yml";
|
|
16
|
+
readonly readme: "README.md";
|
|
17
|
+
readonly agents: "AGENTS.md";
|
|
18
|
+
readonly migrationsDir: "migrations";
|
|
19
|
+
readonly migrateScript: "scripts/migrate.ts";
|
|
20
|
+
readonly app: (name: string) => string;
|
|
21
|
+
readonly pkg: (name: string) => string;
|
|
22
|
+
readonly deploy: (name: string) => string;
|
|
23
|
+
readonly dockerfile: (name: string) => string;
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/project/paths.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAWpE;AAED,iEAAiE;AACjE,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,eAAO,MAAM,KAAK;;;;;;;;;;;;yBAYJ,MAAM;yBACN,MAAM;4BACH,MAAM;gCACF,MAAM;CACjB,CAAA"}
|
|
@@ -0,0 +1,51 @@
|
|
|
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.paths = void 0;
|
|
7
|
+
exports.findProjectRoot = findProjectRoot;
|
|
8
|
+
exports.abs = abs;
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const fs_1 = require("../utils/fs");
|
|
11
|
+
/**
|
|
12
|
+
* Resolve the project root by walking up from `start` looking for forge.json,
|
|
13
|
+
* then pnpm-workspace.yaml, then package.json. Falls back to `start`.
|
|
14
|
+
*/
|
|
15
|
+
async function findProjectRoot(start) {
|
|
16
|
+
let dir = node_path_1.default.resolve(start);
|
|
17
|
+
// Walk upward a bounded number of levels.
|
|
18
|
+
for (let i = 0; i < 20; i++) {
|
|
19
|
+
if (await (0, fs_1.exists)(node_path_1.default.join(dir, "forge.json")))
|
|
20
|
+
return dir;
|
|
21
|
+
if (await (0, fs_1.exists)(node_path_1.default.join(dir, "pnpm-workspace.yaml")))
|
|
22
|
+
return dir;
|
|
23
|
+
const parent = node_path_1.default.dirname(dir);
|
|
24
|
+
if (parent === dir)
|
|
25
|
+
break;
|
|
26
|
+
dir = parent;
|
|
27
|
+
}
|
|
28
|
+
return node_path_1.default.resolve(start);
|
|
29
|
+
}
|
|
30
|
+
/** Absolute path for a repo-relative path within the project. */
|
|
31
|
+
function abs(root, relative) {
|
|
32
|
+
return node_path_1.default.join(root, relative);
|
|
33
|
+
}
|
|
34
|
+
exports.paths = {
|
|
35
|
+
forgeManifest: "forge.json",
|
|
36
|
+
stackManifest: "deploy/stack.json",
|
|
37
|
+
rootPackageJson: "package.json",
|
|
38
|
+
pnpmWorkspace: "pnpm-workspace.yaml",
|
|
39
|
+
tsconfigBase: "tsconfig.base.json",
|
|
40
|
+
envExample: ".env.example",
|
|
41
|
+
ci: ".github/workflows/ci.yml",
|
|
42
|
+
readme: "README.md",
|
|
43
|
+
agents: "AGENTS.md",
|
|
44
|
+
migrationsDir: "migrations",
|
|
45
|
+
migrateScript: "scripts/migrate.ts",
|
|
46
|
+
app: (name) => `apps/${name}`,
|
|
47
|
+
pkg: (name) => `packages/${name}`,
|
|
48
|
+
deploy: (name) => `deploy/${name}.lwd.toml`,
|
|
49
|
+
dockerfile: (name) => `docker/${name}.Dockerfile`,
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/project/paths.ts"],"names":[],"mappings":";;;;;;AAOA,0CAWC;AAGD,kBAEC;AAvBD,0DAA4B;AAC5B,oCAAoC;AAEpC;;;GAGG;AACI,KAAK,UAAU,eAAe,CAAC,KAAa;IACjD,IAAI,GAAG,GAAG,mBAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC7B,0CAA0C;IAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,IAAI,MAAM,IAAA,WAAM,EAAC,mBAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;YAAE,OAAO,GAAG,CAAA;QAC1D,IAAI,MAAM,IAAA,WAAM,EAAC,mBAAI,CAAC,IAAI,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;YAAE,OAAO,GAAG,CAAA;QACnE,MAAM,MAAM,GAAG,mBAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAChC,IAAI,MAAM,KAAK,GAAG;YAAE,MAAK;QACzB,GAAG,GAAG,MAAM,CAAA;IACd,CAAC;IACD,OAAO,mBAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAC5B,CAAC;AAED,iEAAiE;AACjE,SAAgB,GAAG,CAAC,IAAY,EAAE,QAAgB;IAChD,OAAO,mBAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;AAClC,CAAC;AAEY,QAAA,KAAK,GAAG;IACnB,aAAa,EAAE,YAAY;IAC3B,aAAa,EAAE,mBAAmB;IAClC,eAAe,EAAE,cAAc;IAC/B,aAAa,EAAE,qBAAqB;IACpC,YAAY,EAAE,oBAAoB;IAClC,UAAU,EAAE,cAAc;IAC1B,EAAE,EAAE,0BAA0B;IAC9B,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,WAAW;IACnB,aAAa,EAAE,YAAY;IAC3B,aAAa,EAAE,oBAAoB;IACnC,GAAG,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,QAAQ,IAAI,EAAE;IACrC,GAAG,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,YAAY,IAAI,EAAE;IACzC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,UAAU,IAAI,WAAW;IACnD,UAAU,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,UAAU,IAAI,aAAa;CACjD,CAAA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { EnvVar, ForgeManifest } from "../types";
|
|
2
|
+
import { type DeepPartial } from "./manifest";
|
|
3
|
+
export interface ApplyOptions {
|
|
4
|
+
dryRun: boolean;
|
|
5
|
+
/** Allow overwriting existing files whose contents differ. */
|
|
6
|
+
force: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A Plan accumulates every change a command wants to make, then applies them in
|
|
10
|
+
* one pass. This is what gives every Forge command uniform dry-run, idempotency,
|
|
11
|
+
* and safety (see spec §21). Commands never touch the filesystem directly.
|
|
12
|
+
*/
|
|
13
|
+
export declare class Plan {
|
|
14
|
+
private fileOps;
|
|
15
|
+
private deps;
|
|
16
|
+
private envVars;
|
|
17
|
+
private scripts;
|
|
18
|
+
private manifestPatch;
|
|
19
|
+
private nextSteps;
|
|
20
|
+
/** Create a file only if it does not already exist. */
|
|
21
|
+
create(p: string, content: string, describe: string): this;
|
|
22
|
+
/** Replace a file's contents (needs --force / confirmation if it differs). */
|
|
23
|
+
overwrite(p: string, content: string, describe: string): this;
|
|
24
|
+
/** Insert a clearly-marked, idempotent section into a file (creating it if absent). */
|
|
25
|
+
append(p: string, marker: string, section: string, describe: string): this;
|
|
26
|
+
addDependency(target: string, name: string, version: string, dev?: boolean): this;
|
|
27
|
+
addEnvVar(v: EnvVar): this;
|
|
28
|
+
addScript(name: string, command: string): this;
|
|
29
|
+
patchManifest(patch: DeepPartial<ForgeManifest>): this;
|
|
30
|
+
nextStep(msg: string): this;
|
|
31
|
+
isEmpty(): boolean;
|
|
32
|
+
/** Human-readable preview of everything this plan would do. */
|
|
33
|
+
render(root: string): Promise<string>;
|
|
34
|
+
/** Apply the plan. Returns whether anything was written. */
|
|
35
|
+
apply(root: string, opts: ApplyOptions): Promise<boolean>;
|
|
36
|
+
private classify;
|
|
37
|
+
private applyAppend;
|
|
38
|
+
private applyDeps;
|
|
39
|
+
private applyScripts;
|
|
40
|
+
private applyEnv;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/project/plan.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGV,MAAM,EAEN,aAAa,EAEd,MAAM,UAAU,CAAA;AAGjB,OAAO,EAA6C,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AAExF,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,OAAO,CAAA;IACf,8DAA8D;IAC9D,KAAK,EAAE,OAAO,CAAA;CACf;AAOD;;;;GAIG;AACH,qBAAa,IAAI;IACf,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,SAAS,CAAe;IAEhC,uDAAuD;IACvD,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK1D,8EAA8E;IAC9E,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK7D,uFAAuF;IACvF,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK1E,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,UAAQ,GAAG,IAAI;IAK/E,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAK1B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAK9C,aAAa,CAAC,KAAK,EAAE,WAAW,CAAC,aAAa,CAAC,GAAG,IAAI;IAKtD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK3B,OAAO,IAAI,OAAO;IAUlB,+DAA+D;IACzD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAqB3C,4DAA4D;IACtD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;YA0DjD,QAAQ;YAYR,WAAW;YAQX,SAAS;YAoBT,YAAY;YAWZ,QAAQ;CAevB"}
|