@cat-factory/cli 0.2.1
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 +139 -0
- package/dist/args.d.ts +40 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +153 -0
- package/dist/args.js.map +1 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +42 -0
- package/dist/bin.js.map +1 -0
- package/dist/bootstrap.d.ts +23 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +171 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/env.d.ts +38 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +150 -0
- package/dist/env.js.map +1 -0
- package/dist/gitignore.d.ts +15 -0
- package/dist/gitignore.d.ts.map +1 -0
- package/dist/gitignore.js +46 -0
- package/dist/gitignore.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/io.d.ts +25 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/io.js +74 -0
- package/dist/io.js.map +1 -0
- package/dist/plan.d.ts +29 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +144 -0
- package/dist/plan.js.map +1 -0
- package/dist/secrets.d.ts +25 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +9 -0
- package/dist/secrets.js.map +1 -0
- package/dist/slug.d.ts +3 -0
- package/dist/slug.d.ts.map +1 -0
- package/dist/slug.js +19 -0
- package/dist/slug.js.map +1 -0
- package/dist/templates.d.ts +29 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/templates.js +189 -0
- package/dist/templates.js.map +1 -0
- package/dist/vcs.d.ts +20 -0
- package/dist/vcs.d.ts.map +1 -0
- package/dist/vcs.js +52 -0
- package/dist/vcs.js.map +1 -0
- package/package.json +51 -0
package/dist/secrets.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { randomBytes as nodeRandomBytes } from 'node:crypto';
|
|
2
|
+
/** Generate a fresh {@link GeneratedSecrets} pair in the server's required formats. */
|
|
3
|
+
export function generateSecrets(randomBytes = nodeRandomBytes) {
|
|
4
|
+
return {
|
|
5
|
+
authSessionSecret: randomBytes(32).toString('hex'),
|
|
6
|
+
encryptionKey: randomBytes(32).toString('base64'),
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=secrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,aAAa,CAAA;AA0B5D,uFAAuF;AACvF,MAAM,UAAU,eAAe,CAAC,WAAW,GAAgB,eAAe;IACxE,OAAO;QACL,iBAAiB,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QAClD,aAAa,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;KAClD,CAAA;AACH,CAAC"}
|
package/dist/slug.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug.d.ts","sourceRoot":"","sources":["../src/slug.ts"],"names":[],"mappings":"AAMA,sGAAsG;AACtG,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAgB,GAAG,MAAM,CAWlF"}
|
package/dist/slug.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// The project name is interpolated verbatim into the generated `local/`/`frontend/` package
|
|
2
|
+
// `name` fields (`<name>-local` / `<name>-frontend`), so it has to be a valid npm package name:
|
|
3
|
+
// lowercase, no spaces, and not starting with `.`/`_`. A free-text answer like "My Cats" would
|
|
4
|
+
// otherwise produce `"My Cats-local"`, which `npm install` rejects. This coerces any input into a
|
|
5
|
+
// safe slug, falling back to a default when nothing usable survives.
|
|
6
|
+
/** Coerce arbitrary text into a valid npm-name slug. Returns `fallback` if nothing usable remains. */
|
|
7
|
+
export function slugifyProjectName(input, fallback = 'cat-factory') {
|
|
8
|
+
const slug = input
|
|
9
|
+
.trim()
|
|
10
|
+
.toLowerCase()
|
|
11
|
+
// Anything not a safe npm-name char becomes a hyphen.
|
|
12
|
+
.replace(/[^a-z0-9._-]+/g, '-')
|
|
13
|
+
// Collapse runs of separators, then strip leading/trailing separators and leading `.`/`_`.
|
|
14
|
+
.replace(/-+/g, '-')
|
|
15
|
+
.replace(/^[._-]+/, '')
|
|
16
|
+
.replace(/[._-]+$/, '');
|
|
17
|
+
return slug.length > 0 ? slug : fallback;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=slug.js.map
|
package/dist/slug.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug.js","sourceRoot":"","sources":["../src/slug.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,gGAAgG;AAChG,+FAA+F;AAC/F,kGAAkG;AAClG,qEAAqE;AAErE,sGAAsG;AACtG,MAAM,UAAU,kBAAkB,CAAC,KAAa,EAAE,QAAQ,GAAG,aAAa;IACxE,MAAM,IAAI,GAAG,KAAK;SACf,IAAI,EAAE;SACN,WAAW,EAAE;QACd,sDAAsD;SACrD,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC;QAC/B,2FAA2F;SAC1F,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;SACtB,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;IACzB,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAA;AAC1C,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const LOCAL_SERVER_VERSION = "^0.19.5";
|
|
2
|
+
export declare const APP_VERSION = "^0.47.7";
|
|
3
|
+
export declare const NUXT_VERSION = "^4.4.8";
|
|
4
|
+
export declare const TYPES_NODE_VERSION = "^26.0.1";
|
|
5
|
+
export declare const TYPESCRIPT_VERSION = "7.0.1-rc";
|
|
6
|
+
export declare const WRANGLER_VERSION = "^4.105.0";
|
|
7
|
+
/** Default executor-harness image agent jobs run as per-run containers. */
|
|
8
|
+
export declare const DEFAULT_HARNESS_IMAGE = "ghcr.io/kibertoad/cat-factory-executor:latest";
|
|
9
|
+
/** The container runtimes the local facade understands (`LOCAL_CONTAINER_RUNTIME`). */
|
|
10
|
+
export declare const CONTAINER_RUNTIMES: readonly ['docker', 'podman', 'orbstack', 'colima', 'apple'];
|
|
11
|
+
export type ContainerRuntime = (typeof CONTAINER_RUNTIMES)[number];
|
|
12
|
+
export declare const localPackageJson: (projectName: string) => string;
|
|
13
|
+
export declare const localMainTs = "// Local-mode backend entry point.\n//\n// Calls the reusable @cat-factory/local-server library's startLocal(): connect to the local\n// Postgres (DATABASE_URL), run the schema migration, boot pg-boss + the durable execution\n// worker, and serve the shared Hono app. Agent jobs run as per-run local containers and GitHub\n// is reached via the PAT in .env. Node 24+ runs this TypeScript directly via type stripping\n// (npm start = `node --env-file-if-exists=.env src/main.ts`), so edits here take effect with no\n// build step.\nimport { startLocal } from '@cat-factory/local-server'\n\nstartLocal().catch((err: unknown) => {\n console.error('failed to start cat-factory local server:', err)\n process.exit(1)\n})\n";
|
|
14
|
+
export declare const dockerCompose: (dbUrl: string) => string;
|
|
15
|
+
/** Non-secret inputs shown in `local/.env.example`, kept in sync with the populated `.env`. */
|
|
16
|
+
export interface LocalEnvExampleInput {
|
|
17
|
+
provider?: 'github' | 'gitlab';
|
|
18
|
+
containerRuntime?: ContainerRuntime;
|
|
19
|
+
databaseUrl?: string;
|
|
20
|
+
port?: number;
|
|
21
|
+
harnessImage?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare const localEnvExample: (input?: LocalEnvExampleInput) => string;
|
|
24
|
+
export declare const frontendPackageJson: (projectName: string) => string;
|
|
25
|
+
export declare const frontendNuxtConfig: (title: string) => string;
|
|
26
|
+
export declare const frontendWranglerToml: (projectName: string) => string;
|
|
27
|
+
export declare const frontendEnvExample: (apiBase?: string) => string;
|
|
28
|
+
export declare const tsconfigJson = "{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"Bundler\",\n \"strict\": true,\n \"skipLibCheck\": true,\n \"noEmit\": true\n }\n}\n";
|
|
29
|
+
//# sourceMappingURL=templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,oBAAoB,YAAY,CAAA;AAC7C,eAAO,MAAM,WAAW,YAAY,CAAA;AACpC,eAAO,MAAM,YAAY,WAAW,CAAA;AACpC,eAAO,MAAM,kBAAkB,YAAY,CAAA;AAC3C,eAAO,MAAM,kBAAkB,aAAa,CAAA;AAC5C,eAAO,MAAM,gBAAgB,aAAa,CAAA;AAE1C,2EAA2E;AAC3E,eAAO,MAAM,qBAAqB,kDAAkD,CAAA;AAEpF,uFAAuF;AACvF,eAAO,MAAM,kBAAkB,YAAI,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAU,CAAA;AAC9F,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAA;AAElE,eAAO,MAAM,gBAAgB,gBAAiB,MAAM,KAAG,MA6BhD,CAAA;AAEP,eAAO,MAAM,WAAW,otBAcvB,CAAA;AAED,eAAO,MAAM,aAAa,UAAW,MAAM,KAAG,MAuC7C,CAAA;AAED,+FAA+F;AAC/F,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC9B,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,eAAO,MAAM,eAAe,WAAW,oBAAoB,KAAQ,MAmClE,CAAA;AAED,eAAO,MAAM,mBAAmB,gBAAiB,MAAM,KAAG,MA4BnD,CAAA;AAEP,eAAO,MAAM,kBAAkB,UAAW,MAAM,KAAG,MAalD,CAAA;AAED,eAAO,MAAM,oBAAoB,gBAAiB,MAAM,KAAG,MAS1D,CAAA;AAED,eAAO,MAAM,kBAAkB,wBAAwC,MAItE,CAAA;AAED,eAAO,MAAM,YAAY,sNAUxB,CAAA"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
// Static file templates for the scaffolded deployment. These mirror `deploy/local` and
|
|
2
|
+
// `deploy/frontend` in this repo, but depend on the PUBLISHED libraries (not `workspace:*`) so
|
|
3
|
+
// the generated project works standalone outside the monorepo.
|
|
4
|
+
// Pinned library versions the scaffolded project depends on. Pinned (not the `latest` dist-tag)
|
|
5
|
+
// so a scaffold is reproducible and the backend/frontend can't resolve to skewed releases; the
|
|
6
|
+
// caret allows in-range patch/minor pickups. Bump these when cutting a CLI release against newer
|
|
7
|
+
// libraries. (`@cat-factory/local-server` and `@cat-factory/app` version independently.)
|
|
8
|
+
export const LOCAL_SERVER_VERSION = '^0.19.5';
|
|
9
|
+
export const APP_VERSION = '^0.47.7';
|
|
10
|
+
export const NUXT_VERSION = '^4.4.8';
|
|
11
|
+
export const TYPES_NODE_VERSION = '^26.0.1';
|
|
12
|
+
export const TYPESCRIPT_VERSION = '7.0.1-rc';
|
|
13
|
+
export const WRANGLER_VERSION = '^4.105.0';
|
|
14
|
+
/** Default executor-harness image agent jobs run as per-run containers. */
|
|
15
|
+
export const DEFAULT_HARNESS_IMAGE = 'ghcr.io/kibertoad/cat-factory-executor:latest';
|
|
16
|
+
/** The container runtimes the local facade understands (`LOCAL_CONTAINER_RUNTIME`). */
|
|
17
|
+
export const CONTAINER_RUNTIMES = ['docker', 'podman', 'orbstack', 'colima', 'apple'];
|
|
18
|
+
export const localPackageJson = (projectName) => `${JSON.stringify({
|
|
19
|
+
name: `${projectName}-local`,
|
|
20
|
+
version: '0.1.0',
|
|
21
|
+
private: true,
|
|
22
|
+
description: 'Local-mode backend deployment of @cat-factory/local-server.',
|
|
23
|
+
type: 'module',
|
|
24
|
+
engines: {
|
|
25
|
+
// The entry (src/main.ts) runs via Node's TypeScript type stripping; --env-file-if-exists
|
|
26
|
+
// also needs a recent Node. 24+ covers both.
|
|
27
|
+
node: '>=24',
|
|
28
|
+
},
|
|
29
|
+
scripts: {
|
|
30
|
+
start: 'node --env-file-if-exists=.env src/main.ts',
|
|
31
|
+
dev: 'node --watch --env-file-if-exists=.env src/main.ts',
|
|
32
|
+
'db:up': 'docker compose up -d postgres',
|
|
33
|
+
'db:down': 'docker compose down',
|
|
34
|
+
},
|
|
35
|
+
dependencies: {
|
|
36
|
+
'@cat-factory/local-server': LOCAL_SERVER_VERSION,
|
|
37
|
+
},
|
|
38
|
+
devDependencies: {
|
|
39
|
+
'@types/node': TYPES_NODE_VERSION,
|
|
40
|
+
typescript: TYPESCRIPT_VERSION,
|
|
41
|
+
},
|
|
42
|
+
}, null, 2)}\n`;
|
|
43
|
+
export const localMainTs = `// Local-mode backend entry point.
|
|
44
|
+
//
|
|
45
|
+
// Calls the reusable @cat-factory/local-server library's startLocal(): connect to the local
|
|
46
|
+
// Postgres (DATABASE_URL), run the schema migration, boot pg-boss + the durable execution
|
|
47
|
+
// worker, and serve the shared Hono app. Agent jobs run as per-run local containers and GitHub
|
|
48
|
+
// is reached via the PAT in .env. Node 24+ runs this TypeScript directly via type stripping
|
|
49
|
+
// (npm start = \`node --env-file-if-exists=.env src/main.ts\`), so edits here take effect with no
|
|
50
|
+
// build step.
|
|
51
|
+
import { startLocal } from '@cat-factory/local-server'
|
|
52
|
+
|
|
53
|
+
startLocal().catch((err: unknown) => {
|
|
54
|
+
console.error('failed to start cat-factory local server:', err)
|
|
55
|
+
process.exit(1)
|
|
56
|
+
})
|
|
57
|
+
`;
|
|
58
|
+
export const dockerCompose = (dbUrl) => {
|
|
59
|
+
// Derive the compose credentials/db from the DATABASE_URL so the two always agree.
|
|
60
|
+
let user = 'cat';
|
|
61
|
+
let password = 'cat';
|
|
62
|
+
let db = 'catfactory';
|
|
63
|
+
let port = '5432';
|
|
64
|
+
try {
|
|
65
|
+
const u = new URL(dbUrl);
|
|
66
|
+
user = decodeURIComponent(u.username) || user;
|
|
67
|
+
password = decodeURIComponent(u.password) || password;
|
|
68
|
+
db = u.pathname.replace(/^\//, '') || db;
|
|
69
|
+
port = u.port || port;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Keep the defaults if the URL doesn't parse.
|
|
73
|
+
}
|
|
74
|
+
return `# Local Postgres for the cat-factory backend. The orchestrator itself runs on the host
|
|
75
|
+
# (so it can drive the container runtime to spawn agent containers), so only Postgres lives here.
|
|
76
|
+
#
|
|
77
|
+
# docker compose up -d postgres # or: pnpm db:up
|
|
78
|
+
services:
|
|
79
|
+
postgres:
|
|
80
|
+
image: postgres:18
|
|
81
|
+
environment:
|
|
82
|
+
POSTGRES_USER: ${user}
|
|
83
|
+
POSTGRES_PASSWORD: ${password}
|
|
84
|
+
POSTGRES_DB: ${db}
|
|
85
|
+
ports:
|
|
86
|
+
- '${port}:5432'
|
|
87
|
+
volumes:
|
|
88
|
+
- cat-factory-pg:/var/lib/postgresql
|
|
89
|
+
healthcheck:
|
|
90
|
+
test: ['CMD-SHELL', 'pg_isready -U ${user} -d ${db}']
|
|
91
|
+
interval: 5s
|
|
92
|
+
timeout: 5s
|
|
93
|
+
retries: 10
|
|
94
|
+
|
|
95
|
+
volumes:
|
|
96
|
+
cat-factory-pg:
|
|
97
|
+
`;
|
|
98
|
+
};
|
|
99
|
+
export const localEnvExample = (input = {}) => {
|
|
100
|
+
const { provider = 'github', containerRuntime = 'docker', databaseUrl = 'postgres://cat:cat@localhost:5432/catfactory', port = 8787, harnessImage = DEFAULT_HARNESS_IMAGE, } = input;
|
|
101
|
+
// Show the chosen provider's PAT var active and the other commented, so the example matches
|
|
102
|
+
// the populated `.env` the CLI writes for that provider.
|
|
103
|
+
const tokenLines = provider === 'gitlab' ? ['# GITHUB_PAT=', 'GITLAB_PAT='] : ['GITHUB_PAT=', '# GITLAB_PAT='];
|
|
104
|
+
return `# Example env for the local-mode backend. Copy to \`.env\` (gitignored) and fill in.
|
|
105
|
+
# \`cat-factory init\` generates a populated \`.env\` for you; this is the documented template
|
|
106
|
+
# (the non-secret values below mirror the ones you chose at scaffold time).
|
|
107
|
+
DATABASE_URL=${databaseUrl}
|
|
108
|
+
PORT=${port}
|
|
109
|
+
CORS_ALLOWED_ORIGINS=http://localhost:3000
|
|
110
|
+
# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
|
111
|
+
AUTH_SESSION_SECRET=
|
|
112
|
+
# Generate with: openssl rand -base64 32
|
|
113
|
+
ENCRYPTION_KEY=
|
|
114
|
+
# A GitHub (classic, scopes: repo,workflow) or GitLab (scope: api,read_user) personal access token.
|
|
115
|
+
${tokenLines.join('\n')}
|
|
116
|
+
# For a self-managed GitLab instance, also set GITLAB_API_BASE (e.g. https://gitlab.example.com/api/v4).
|
|
117
|
+
# GITLAB_API_BASE=
|
|
118
|
+
LOCAL_HARNESS_IMAGE=${harnessImage}
|
|
119
|
+
# Container runtime that spawns agent jobs: ${CONTAINER_RUNTIMES.join(' | ')}.
|
|
120
|
+
LOCAL_CONTAINER_RUNTIME=${containerRuntime}
|
|
121
|
+
# At least one model provider (Cloudflare Workers AI over REST shown; or a direct vendor key):
|
|
122
|
+
# CLOUDFLARE_ACCOUNT_ID=
|
|
123
|
+
# CLOUDFLARE_API_TOKEN=
|
|
124
|
+
# ANTHROPIC_API_KEY=
|
|
125
|
+
# OPENAI_API_KEY=
|
|
126
|
+
`;
|
|
127
|
+
};
|
|
128
|
+
export const frontendPackageJson = (projectName) => `${JSON.stringify({
|
|
129
|
+
name: `${projectName}-frontend`,
|
|
130
|
+
version: '0.1.0',
|
|
131
|
+
private: true,
|
|
132
|
+
description: 'Frontend SPA deployment — extends the @cat-factory/app Nuxt layer.',
|
|
133
|
+
type: 'module',
|
|
134
|
+
scripts: {
|
|
135
|
+
postinstall: 'nuxt prepare',
|
|
136
|
+
dev: 'nuxt dev',
|
|
137
|
+
build: 'nuxt build',
|
|
138
|
+
generate: 'nuxt generate',
|
|
139
|
+
preview: 'nuxt preview',
|
|
140
|
+
deploy: 'wrangler pages deploy',
|
|
141
|
+
},
|
|
142
|
+
dependencies: {
|
|
143
|
+
'@cat-factory/app': APP_VERSION,
|
|
144
|
+
nuxt: NUXT_VERSION,
|
|
145
|
+
},
|
|
146
|
+
devDependencies: {
|
|
147
|
+
typescript: '^6.0.3',
|
|
148
|
+
'vue-tsc': '^3.3.5',
|
|
149
|
+
wrangler: WRANGLER_VERSION,
|
|
150
|
+
},
|
|
151
|
+
}, null, 2)}\n`;
|
|
152
|
+
export const frontendNuxtConfig = (title) => `// Frontend deployment — a thin Nuxt app that consumes the @cat-factory/app layer.
|
|
153
|
+
// All SPA logic lives in the layer; this app only \`extends\` it and applies branding.
|
|
154
|
+
// The backend URL is baked in at BUILD time from NUXT_PUBLIC_API_BASE (the SPA is ssr: false).
|
|
155
|
+
export default defineNuxtConfig({
|
|
156
|
+
extends: ['@cat-factory/app'],
|
|
157
|
+
|
|
158
|
+
app: {
|
|
159
|
+
head: {
|
|
160
|
+
title: ${JSON.stringify(title)},
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
})
|
|
164
|
+
`;
|
|
165
|
+
export const frontendWranglerToml = (projectName) => `# Cloudflare Pages config for the frontend SPA.
|
|
166
|
+
#
|
|
167
|
+
# The SPA's backend URL is baked in at BUILD time (NUXT_PUBLIC_API_BASE), NOT here — Pages
|
|
168
|
+
# [vars] only reach Functions at runtime and this is a pure static SPA. Change \`name\` to your
|
|
169
|
+
# own Pages project.
|
|
170
|
+
name = "${projectName}-frontend"
|
|
171
|
+
pages_build_output_dir = ".output/public"
|
|
172
|
+
compatibility_date = "2025-06-01"
|
|
173
|
+
`;
|
|
174
|
+
export const frontendEnvExample = (apiBase = 'http://localhost:8787') => `# Example env for the frontend SPA. Copy to \`.env\` (gitignored).
|
|
175
|
+
# Base URL of the backend API, baked in at build time (mirrors your chosen --api-base/--port).
|
|
176
|
+
NUXT_PUBLIC_API_BASE=${apiBase}
|
|
177
|
+
`;
|
|
178
|
+
export const tsconfigJson = `{
|
|
179
|
+
"compilerOptions": {
|
|
180
|
+
"target": "ES2022",
|
|
181
|
+
"module": "ESNext",
|
|
182
|
+
"moduleResolution": "Bundler",
|
|
183
|
+
"strict": true,
|
|
184
|
+
"skipLibCheck": true,
|
|
185
|
+
"noEmit": true
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
`;
|
|
189
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"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"}
|
package/dist/vcs.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type VcsProvider = 'github' | 'gitlab';
|
|
2
|
+
export declare const VCS_PROVIDERS: readonly VcsProvider[];
|
|
3
|
+
/**
|
|
4
|
+
* A GitHub "new personal access token (classic)" URL with the local-mode scopes pre-selected.
|
|
5
|
+
* Classic tokens (not fine-grained) are used because only the classic form accepts the `scopes`
|
|
6
|
+
* query param for pre-selection.
|
|
7
|
+
*/
|
|
8
|
+
export declare function githubPatCreationUrl(): string;
|
|
9
|
+
/**
|
|
10
|
+
* A GitLab "new personal access token" URL with the `api` scope pre-selected, so a developer
|
|
11
|
+
* without a GitLab PAT can click straight through to create one.
|
|
12
|
+
*/
|
|
13
|
+
export declare function gitlabPatCreationUrl(): string;
|
|
14
|
+
/** The pre-scoped token-creation URL for a provider. */
|
|
15
|
+
export declare function patCreationUrl(provider: VcsProvider): string;
|
|
16
|
+
/** The `.env` variable name a provider's PAT is written under (read by the local-mode facade). */
|
|
17
|
+
export declare function patEnvVar(provider: VcsProvider): 'GITHUB_PAT' | 'GITLAB_PAT';
|
|
18
|
+
/** Human label for prompts/output. */
|
|
19
|
+
export declare function providerLabel(provider: VcsProvider): string;
|
|
20
|
+
//# sourceMappingURL=vcs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vcs.d.ts","sourceRoot":"","sources":["../src/vcs.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE7C,eAAO,MAAM,aAAa,EAAE,SAAS,WAAW,EAAyB,CAAA;AAYzE;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAM7C;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAM7C;AAED,wDAAwD;AACxD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAE5D;AAED,kGAAkG;AAClG,wBAAgB,SAAS,CAAC,QAAQ,EAAE,WAAW,GAAG,YAAY,GAAG,YAAY,CAE5E;AAED,sCAAsC;AACtC,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAE3D"}
|
package/dist/vcs.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Source-control provider helpers: the pre-scoped "create a personal access token" URLs the
|
|
2
|
+
// CLI opens in the browser, and the env-var name each provider's token is written under.
|
|
3
|
+
//
|
|
4
|
+
// These mirror `@cat-factory/local-server`'s `githubPatCreationUrl` / `gitlabPatCreationUrl`
|
|
5
|
+
// (backend/runtimes/local/src/github.ts) so the token the developer mints here carries exactly
|
|
6
|
+
// the scopes the local-mode agent containers need. They are duplicated rather than imported to
|
|
7
|
+
// keep the backend stack out of a scaffolder (the CLI's only runtime dep is @clack/prompts).
|
|
8
|
+
export const VCS_PROVIDERS = ['github', 'gitlab'];
|
|
9
|
+
/**
|
|
10
|
+
* The classic-token scopes local mode needs: agent containers clone/push branches and open PRs
|
|
11
|
+
* (`repo`, which also covers reading the PR head's Actions check runs for the CI gate and
|
|
12
|
+
* merging the PR), and the coder/ci-fixer may touch `.github/workflows/*` files (`workflow`).
|
|
13
|
+
*/
|
|
14
|
+
const GITHUB_PAT_SCOPES = ['repo', 'workflow'];
|
|
15
|
+
/** The GitLab scope a coding agent needs: `api` covers repo read/write + merge. */
|
|
16
|
+
const GITLAB_PAT_SCOPES = ['api'];
|
|
17
|
+
/**
|
|
18
|
+
* A GitHub "new personal access token (classic)" URL with the local-mode scopes pre-selected.
|
|
19
|
+
* Classic tokens (not fine-grained) are used because only the classic form accepts the `scopes`
|
|
20
|
+
* query param for pre-selection.
|
|
21
|
+
*/
|
|
22
|
+
export function githubPatCreationUrl() {
|
|
23
|
+
const params = new URLSearchParams({
|
|
24
|
+
description: 'cat-factory local mode',
|
|
25
|
+
scopes: GITHUB_PAT_SCOPES.join(','),
|
|
26
|
+
});
|
|
27
|
+
return `https://github.com/settings/tokens/new?${params.toString()}`;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A GitLab "new personal access token" URL with the `api` scope pre-selected, so a developer
|
|
31
|
+
* without a GitLab PAT can click straight through to create one.
|
|
32
|
+
*/
|
|
33
|
+
export function gitlabPatCreationUrl() {
|
|
34
|
+
const params = new URLSearchParams({
|
|
35
|
+
name: 'cat-factory local mode',
|
|
36
|
+
'scopes[]': GITLAB_PAT_SCOPES.join(','),
|
|
37
|
+
});
|
|
38
|
+
return `https://gitlab.com/-/user_settings/personal_access_tokens?${params.toString()}`;
|
|
39
|
+
}
|
|
40
|
+
/** The pre-scoped token-creation URL for a provider. */
|
|
41
|
+
export function patCreationUrl(provider) {
|
|
42
|
+
return provider === 'github' ? githubPatCreationUrl() : gitlabPatCreationUrl();
|
|
43
|
+
}
|
|
44
|
+
/** The `.env` variable name a provider's PAT is written under (read by the local-mode facade). */
|
|
45
|
+
export function patEnvVar(provider) {
|
|
46
|
+
return provider === 'github' ? 'GITHUB_PAT' : 'GITLAB_PAT';
|
|
47
|
+
}
|
|
48
|
+
/** Human label for prompts/output. */
|
|
49
|
+
export function providerLabel(provider) {
|
|
50
|
+
return provider === 'github' ? 'GitHub' : 'GitLab';
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=vcs.js.map
|
package/dist/vcs.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vcs.js","sourceRoot":"","sources":["../src/vcs.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,yFAAyF;AACzF,EAAE;AACF,6FAA6F;AAC7F,+FAA+F;AAC/F,+FAA+F;AAC/F,6FAA6F;AAI7F,MAAM,CAAC,MAAM,aAAa,GAA2B,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;AAEzE;;;;GAIG;AACH,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,UAAU,CAAU,CAAA;AAEvD,mFAAmF;AACnF,MAAM,iBAAiB,GAAG,CAAC,KAAK,CAAU,CAAA;AAE1C;;;;GAIG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,WAAW,EAAE,wBAAwB;QACrC,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC;KACpC,CAAC,CAAA;IACF,OAAO,0CAA0C,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAA;AACtE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,IAAI,EAAE,wBAAwB;QAC9B,UAAU,EAAE,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC;KACxC,CAAC,CAAA;IACF,OAAO,6DAA6D,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAA;AACzF,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,cAAc,CAAC,QAAqB;IAClD,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,oBAAoB,EAAE,CAAC,CAAC,CAAC,oBAAoB,EAAE,CAAA;AAChF,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,SAAS,CAAC,QAAqB;IAC7C,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAA;AAC5D,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,aAAa,CAAC,QAAqB;IACjD,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAA;AACpD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cat-factory/cli",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Bootstrap CLI for the Agent Architecture Board: scaffold a local-mode deployment (Node/local backend + frontend SPA) on your own machine — generates the crypto secrets, populates and gitignores the .env files, and mints a GitHub/GitLab personal access token by opening the browser at the right pre-scoped URL.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"bootstrap",
|
|
7
|
+
"cat-factory",
|
|
8
|
+
"cli",
|
|
9
|
+
"scaffold",
|
|
10
|
+
"self-host"
|
|
11
|
+
],
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/kibertoad/cat-factory.git",
|
|
15
|
+
"directory": "backend/packages/cli"
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"cat-factory": "./dist/bin.js"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"default": "./dist/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./package.json": "./package.json"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@clack/prompts": "^1.6.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^26.0.1",
|
|
41
|
+
"typescript": "7.0.1-rc",
|
|
42
|
+
"vitest": "^4.1.9"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsc -b tsconfig.build.json",
|
|
46
|
+
"start": "node dist/bin.js",
|
|
47
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
48
|
+
"test": "vitest",
|
|
49
|
+
"test:run": "vitest run"
|
|
50
|
+
}
|
|
51
|
+
}
|