@stackwright-pro/launch-stackwright-pro 0.4.0-alpha.13 → 0.4.0-alpha.133
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 +11 -20
- package/dist/index.js +229 -122
- package/dist/index.js.map +1 -1
- package/package.json +17 -17
- package/templates/pro/_app.tsx +14 -4
- package/templates/pro/app/slug-page/page.tsx +32 -0
- package/templates/pro/content.yml +1 -1
- package/templates/pro/next.config.js +3 -0
- package/templates/pro/prebuild.js +23 -95
- package/templates/pro/pro-providers.tsx +46 -0
- package/templates/pro/scripts/pro-content-plugin.js +103 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
PROPRIETARY SOFTWARE LICENSE
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 Per Aspera LLC. All Rights Reserved.
|
|
4
|
+
|
|
5
|
+
This software and associated documentation files (the "Software") are the
|
|
6
|
+
proprietary and confidential property of Per Aspera LLC ("Company").
|
|
7
|
+
|
|
8
|
+
RESTRICTIONS: You may not use, copy, modify, merge, publish, distribute,
|
|
9
|
+
sublicense, sell, or otherwise exploit this Software or any portion thereof
|
|
10
|
+
without the express prior written consent of the Company.
|
|
11
|
+
|
|
12
|
+
GOVERNMENT USE: Use, duplication, or disclosure by the U.S. Government is
|
|
13
|
+
subject to restrictions as set forth in FAR 52.227-19 (Commercial Computer
|
|
14
|
+
Software - Restricted Rights) and DFARS 252.227-7013 (Rights in Technical
|
|
15
|
+
Data and Computer Software), as applicable.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED. IN NO EVENT SHALL THE COMPANY BE LIABLE FOR ANY CLAIM, DAMAGES, OR
|
|
19
|
+
OTHER LIABILITY ARISING FROM THE USE OF THE SOFTWARE.
|
|
20
|
+
|
|
21
|
+
For licensing inquiries: legal@peraspera.com
|
package/README.md
CHANGED
|
@@ -21,10 +21,14 @@ to automatically wire up Pro features:
|
|
|
21
21
|
## Quick Start
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
|
|
24
|
+
# Works — project created in $cwd/my-app
|
|
25
|
+
pnpx @stackwright-pro/launch-stackwright-pro --name my-app -y
|
|
25
26
|
# Dependencies install automatically (~7s)
|
|
26
27
|
cd my-app
|
|
27
|
-
|
|
28
|
+
npx @stackwright-pro/raft # Start the otter raft
|
|
29
|
+
|
|
30
|
+
# Equivalent explicit form
|
|
31
|
+
pnpx @stackwright-pro/launch-stackwright-pro my-app --name my-app -y
|
|
28
32
|
```
|
|
29
33
|
|
|
30
34
|
### With an OpenAPI Spec
|
|
@@ -72,7 +76,7 @@ Options:
|
|
|
72
76
|
--force Overwrite existing directory
|
|
73
77
|
--skip-otters Skip otter raft setup
|
|
74
78
|
-y, --yes Skip prompts, use defaults
|
|
75
|
-
--spec <
|
|
79
|
+
--spec <paths...> Paths to OpenAPI specs (can be specified multiple times)
|
|
76
80
|
--spec-name <name> Name for the API integration (default: derived from filename)
|
|
77
81
|
-V, --version Output the version number
|
|
78
82
|
-h, --help Display help
|
|
@@ -120,24 +124,11 @@ for architecture details, auth deep-dives, and deployment guides.
|
|
|
120
124
|
|
|
121
125
|
## Starting the Otter Raft
|
|
122
126
|
|
|
123
|
-
The otter raft runs in two modes:
|
|
124
|
-
|
|
125
|
-
### Interactive Mode (Default)
|
|
126
|
-
|
|
127
127
|
```bash
|
|
128
|
-
|
|
128
|
+
cd my-app
|
|
129
|
+
npx @stackwright-pro/raft
|
|
129
130
|
```
|
|
130
131
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
- Asks questions about your project via TUI
|
|
134
|
-
- Coordinates specialist otters (brand, theme, api, auth, page)
|
|
135
|
-
- Uses certificate pinning to ensure only approved otters are invoked
|
|
136
|
-
|
|
137
|
-
### Phases Mode (Debugging)
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
python -m stackwright_pro.raft.cli_adapter foreman --phases
|
|
141
|
-
```
|
|
132
|
+
The raft verifies otter integrity, loads project context from `.stackwright/init-context.json`, and spawns code-puppy in foreman mode. Tell the foreman about your specs in natural language — it coordinates the API, auth, data, and page otters to build your app.
|
|
142
133
|
|
|
143
|
-
|
|
134
|
+
All state lives in `.stackwright/` — you can interrupt and resume at any time.
|
package/dist/index.js
CHANGED
|
@@ -31,9 +31,9 @@ var require_package = __commonJS({
|
|
|
31
31
|
"package.json"(exports2, module2) {
|
|
32
32
|
module2.exports = {
|
|
33
33
|
name: "@stackwright-pro/launch-stackwright-pro",
|
|
34
|
-
version: "0.4.0-alpha.
|
|
34
|
+
version: "0.4.0-alpha.133",
|
|
35
35
|
description: "Launch a new Stackwright Pro project with OpenAPI integration, auth, and the otter raft",
|
|
36
|
-
license: "
|
|
36
|
+
license: "SEE LICENSE IN LICENSE",
|
|
37
37
|
publishConfig: {
|
|
38
38
|
access: "public"
|
|
39
39
|
},
|
|
@@ -69,21 +69,21 @@ var require_package = __commonJS({
|
|
|
69
69
|
"@stackwright-pro/mcp": "workspace:*",
|
|
70
70
|
"@stackwright-pro/openapi": "workspace:*",
|
|
71
71
|
"@stackwright-pro/otters": "workspace:*",
|
|
72
|
-
"@stackwright-pro/scaffold-hooks": "
|
|
73
|
-
"@stackwright/cli": "^0.
|
|
74
|
-
"@stackwright/scaffold-core": "^0.
|
|
72
|
+
"@stackwright-pro/scaffold-hooks": "workspace:*",
|
|
73
|
+
"@stackwright/cli": "^0.9.0",
|
|
74
|
+
"@stackwright/scaffold-core": "^0.3.3",
|
|
75
75
|
chalk: "^5.6.2",
|
|
76
|
-
commander: "^
|
|
77
|
-
"fs-extra": "^11.3",
|
|
78
|
-
"js-yaml": "^4.
|
|
76
|
+
commander: "^15.0.0",
|
|
77
|
+
"fs-extra": "^11.3.5",
|
|
78
|
+
"js-yaml": "^4.2.0"
|
|
79
79
|
},
|
|
80
80
|
devDependencies: {
|
|
81
81
|
"@types/fs-extra": "^11.0",
|
|
82
82
|
"@types/js-yaml": "^4.0.9",
|
|
83
|
-
"@types/node": "
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
vitest: "
|
|
83
|
+
"@types/node": "catalog:",
|
|
84
|
+
tsup: "catalog:",
|
|
85
|
+
typescript: "catalog:",
|
|
86
|
+
vitest: "catalog:"
|
|
87
87
|
}
|
|
88
88
|
};
|
|
89
89
|
}
|
|
@@ -91,84 +91,77 @@ var require_package = __commonJS({
|
|
|
91
91
|
|
|
92
92
|
// src/index.ts
|
|
93
93
|
var import_commander = require("commander");
|
|
94
|
-
var
|
|
94
|
+
var import_path2 = __toESM(require("path"));
|
|
95
95
|
var import_os = __toESM(require("os"));
|
|
96
|
-
var
|
|
96
|
+
var import_fs_extra2 = __toESM(require("fs-extra"));
|
|
97
97
|
var import_chalk = __toESM(require("chalk"));
|
|
98
|
-
var import_js_yaml = __toESM(require("js-yaml"));
|
|
99
98
|
var import_child_process = require("child_process");
|
|
100
99
|
var import_cli = require("@stackwright/cli");
|
|
101
100
|
var import_scaffold_core = require("@stackwright/scaffold-core");
|
|
102
101
|
var import_scaffold_hooks = require("@stackwright-pro/scaffold-hooks");
|
|
103
102
|
|
|
103
|
+
// src/scaffold.ts
|
|
104
|
+
var import_fs_extra = __toESM(require("fs-extra"));
|
|
105
|
+
var import_js_yaml = __toESM(require("js-yaml"));
|
|
106
|
+
var import_path = __toESM(require("path"));
|
|
107
|
+
|
|
104
108
|
// src/generated/workspace-versions.ts
|
|
105
109
|
var PRO_VERSIONS = {
|
|
106
|
-
"@stackwright-pro/auth": "0.
|
|
107
|
-
"@stackwright-pro/auth-nextjs": "0.
|
|
108
|
-
"@stackwright-pro/
|
|
109
|
-
"@stackwright-pro/
|
|
110
|
-
"@stackwright-pro/
|
|
110
|
+
"@stackwright-pro/auth": "0.2.0-alpha.21",
|
|
111
|
+
"@stackwright-pro/auth-nextjs": "0.3.0-alpha.10",
|
|
112
|
+
"@stackwright-pro/build-scripts-plugins": "0.1.0-alpha.3",
|
|
113
|
+
"@stackwright-pro/display-components": "0.2.0-alpha.11",
|
|
114
|
+
"@stackwright-pro/mcp": "0.2.0-alpha.95",
|
|
115
|
+
"@stackwright-pro/openapi": "0.3.0-alpha.34",
|
|
116
|
+
"@stackwright-pro/otters": "1.0.0-alpha.62",
|
|
117
|
+
"@stackwright-pro/pulse": "0.3.0-alpha.29",
|
|
118
|
+
"@stackwright-pro/workflow": "0.1.0-alpha.24",
|
|
119
|
+
"@stackwright-pro/workflow-components": "0.1.0-alpha.26"
|
|
111
120
|
};
|
|
112
121
|
var OSS_VERSIONS = {
|
|
113
|
-
"@stackwright/build-scripts": "
|
|
114
|
-
"@stackwright/
|
|
115
|
-
"@stackwright/
|
|
116
|
-
"@stackwright/
|
|
117
|
-
"@stackwright/
|
|
118
|
-
"@stackwright/
|
|
119
|
-
"@stackwright/
|
|
122
|
+
"@stackwright/build-scripts": "0.10.0-alpha.0",
|
|
123
|
+
"@stackwright/collections": "^0.1.2",
|
|
124
|
+
"@stackwright/core": "^0.10.0",
|
|
125
|
+
"@stackwright/icons": "^0.5.2",
|
|
126
|
+
"@stackwright/mcp": "^0.5.0",
|
|
127
|
+
"@stackwright/nextjs": "^0.6.0",
|
|
128
|
+
"@stackwright/otters": "^0.2.2",
|
|
129
|
+
"@stackwright/types": "^1.7.0",
|
|
130
|
+
"@stackwright/ui-shadcn": "^0.1.3"
|
|
120
131
|
};
|
|
121
132
|
|
|
122
|
-
// src/
|
|
123
|
-
(0, import_scaffold_hooks.registerProScaffoldHooks)();
|
|
124
|
-
var { version } = require_package();
|
|
125
|
-
async function copyProTemplate(templateName, destPath) {
|
|
126
|
-
const src = import_path.default.resolve(__dirname, "..", "templates", "pro", templateName);
|
|
127
|
-
await import_fs_extra.default.copy(src, destPath);
|
|
128
|
-
}
|
|
129
|
-
async function addAuthToStackwrightYml(targetDir) {
|
|
130
|
-
const ymlPath = import_path.default.join(targetDir, "stackwright.yml");
|
|
131
|
-
const content = await import_fs_extra.default.readFile(ymlPath, "utf-8");
|
|
132
|
-
const config = import_js_yaml.default.load(content, { schema: import_js_yaml.default.CORE_SCHEMA });
|
|
133
|
-
config.auth = {
|
|
134
|
-
type: "pki",
|
|
135
|
-
profile: "dod_cac",
|
|
136
|
-
source: "gateway_headers",
|
|
137
|
-
roles: [
|
|
138
|
-
{ name: "ADMIN", permissions: ["*"] },
|
|
139
|
-
{ name: "ANALYST", permissions: ["data:read", "data:write"] },
|
|
140
|
-
{ name: "VIEWER", permissions: ["data:read"] }
|
|
141
|
-
],
|
|
142
|
-
protected_routes: [{ path: "/*", roles: ["VIEWER", "ANALYST", "ADMIN"] }],
|
|
143
|
-
public_routes: ["/", "/getting-started"]
|
|
144
|
-
};
|
|
145
|
-
await import_fs_extra.default.writeFile(ymlPath, import_js_yaml.default.dump(config, { lineWidth: 120 }));
|
|
146
|
-
}
|
|
133
|
+
// src/scaffold.ts
|
|
147
134
|
async function addProDepsToPackageJson(targetDir) {
|
|
148
135
|
const pkgPath = import_path.default.join(targetDir, "package.json");
|
|
149
136
|
const content = await import_fs_extra.default.readFile(pkgPath, "utf-8");
|
|
150
137
|
const pkg = JSON.parse(content);
|
|
151
|
-
const dependencies = pkg.dependencies
|
|
152
|
-
const devDependencies = pkg.devDependencies
|
|
153
|
-
const scripts = pkg.scripts
|
|
138
|
+
const dependencies = typeof pkg.dependencies === "object" && pkg.dependencies !== null ? { ...pkg.dependencies } : {};
|
|
139
|
+
const devDependencies = typeof pkg.devDependencies === "object" && pkg.devDependencies !== null ? { ...pkg.devDependencies } : {};
|
|
140
|
+
const scripts = typeof pkg.scripts === "object" && pkg.scripts !== null ? { ...pkg.scripts } : {};
|
|
154
141
|
for (const [pkgName, pinnedVersion] of Object.entries(OSS_VERSIONS)) {
|
|
155
|
-
if (
|
|
142
|
+
if (pkgName in dependencies) {
|
|
156
143
|
dependencies[pkgName] = pinnedVersion;
|
|
157
144
|
}
|
|
158
|
-
if (
|
|
145
|
+
if (pkgName in devDependencies) {
|
|
159
146
|
devDependencies[pkgName] = pinnedVersion;
|
|
160
147
|
}
|
|
161
148
|
}
|
|
162
149
|
Object.assign(dependencies, {
|
|
163
|
-
"@stackwright-pro/mcp": PRO_VERSIONS["@stackwright-pro/mcp"],
|
|
164
|
-
"@stackwright-pro/otters": PRO_VERSIONS["@stackwright-pro/otters"],
|
|
165
|
-
"@stackwright-pro/openapi": PRO_VERSIONS["@stackwright-pro/openapi"],
|
|
166
150
|
"@stackwright-pro/auth": PRO_VERSIONS["@stackwright-pro/auth"],
|
|
167
151
|
"@stackwright-pro/auth-nextjs": PRO_VERSIONS["@stackwright-pro/auth-nextjs"],
|
|
168
|
-
|
|
152
|
+
"@stackwright-pro/build-scripts-plugins": PRO_VERSIONS["@stackwright-pro/build-scripts-plugins"],
|
|
153
|
+
"@stackwright-pro/display-components": PRO_VERSIONS["@stackwright-pro/display-components"],
|
|
154
|
+
"@stackwright-pro/mcp": PRO_VERSIONS["@stackwright-pro/mcp"],
|
|
155
|
+
"@stackwright-pro/openapi": PRO_VERSIONS["@stackwright-pro/openapi"],
|
|
156
|
+
"@stackwright-pro/otters": PRO_VERSIONS["@stackwright-pro/otters"],
|
|
157
|
+
"@stackwright-pro/pulse": PRO_VERSIONS["@stackwright-pro/pulse"],
|
|
158
|
+
"@stackwright-pro/workflow": PRO_VERSIONS["@stackwright-pro/workflow"],
|
|
159
|
+
"@stackwright-pro/workflow-components": PRO_VERSIONS["@stackwright-pro/workflow-components"],
|
|
160
|
+
"@stackwright/build-scripts": OSS_VERSIONS["@stackwright/build-scripts"],
|
|
161
|
+
zod: "^4.0.0"
|
|
169
162
|
});
|
|
170
163
|
Object.assign(devDependencies, {
|
|
171
|
-
"@stoplight/prism-cli": "^5.
|
|
164
|
+
"@stoplight/prism-cli": "^5.15.10"
|
|
172
165
|
});
|
|
173
166
|
Object.assign(scripts, {
|
|
174
167
|
"dev:admin": "MOCK_USER=admin next dev",
|
|
@@ -182,6 +175,13 @@ async function addProDepsToPackageJson(targetDir) {
|
|
|
182
175
|
pkg.scripts = scripts;
|
|
183
176
|
await import_fs_extra.default.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
184
177
|
}
|
|
178
|
+
async function addAuthToStackwrightYml(targetDir) {
|
|
179
|
+
const ymlPath = import_path.default.join(targetDir, "stackwright.yml");
|
|
180
|
+
const content = await import_fs_extra.default.readFile(ymlPath, "utf-8");
|
|
181
|
+
const config = import_js_yaml.default.load(content, { schema: import_js_yaml.default.CORE_SCHEMA });
|
|
182
|
+
config.auth = {};
|
|
183
|
+
await import_fs_extra.default.writeFile(ymlPath, import_js_yaml.default.dump(config, { lineWidth: 120 }));
|
|
184
|
+
}
|
|
185
185
|
async function addIntegrationToStackwrightYml(targetDir, specName, specFilename, mockUrl) {
|
|
186
186
|
const ymlPath = import_path.default.join(targetDir, "stackwright.yml");
|
|
187
187
|
const content = await import_fs_extra.default.readFile(ymlPath, "utf-8");
|
|
@@ -195,20 +195,71 @@ async function addIntegrationToStackwrightYml(targetDir, specName, specFilename,
|
|
|
195
195
|
if (mockUrl) {
|
|
196
196
|
integration.mockUrl = mockUrl;
|
|
197
197
|
}
|
|
198
|
-
config.integrations = [
|
|
198
|
+
config.integrations = [
|
|
199
|
+
...Array.isArray(config.integrations) ? config.integrations : [],
|
|
200
|
+
integration
|
|
201
|
+
];
|
|
199
202
|
await import_fs_extra.default.writeFile(ymlPath, import_js_yaml.default.dump(config, { lineWidth: 120 }));
|
|
200
203
|
}
|
|
201
|
-
async function
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
204
|
+
async function scaffoldWorkspaceConfig(targetDir) {
|
|
205
|
+
const workspaceDir = import_path.default.join(targetDir, ".code_puppy");
|
|
206
|
+
await import_fs_extra.default.ensureDir(workspaceDir);
|
|
207
|
+
const workspaceStats = await import_fs_extra.default.lstat(workspaceDir);
|
|
208
|
+
if (workspaceStats.isSymbolicLink()) {
|
|
209
|
+
throw new Error(".code_puppy/ is a symlink \u2014 refusing to write. Check for tampering.");
|
|
210
|
+
}
|
|
211
|
+
const agentsDir = import_path.default.join(workspaceDir, "agents");
|
|
212
|
+
await import_fs_extra.default.ensureDir(agentsDir);
|
|
213
|
+
if (await import_fs_extra.default.pathExists(agentsDir)) {
|
|
214
|
+
const agentsStats = await import_fs_extra.default.lstat(agentsDir);
|
|
215
|
+
if (agentsStats.isSymbolicLink()) {
|
|
216
|
+
throw new Error(".code_puppy/agents is a symlink \u2014 refusing to write. Check for tampering.");
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const configPath = import_path.default.join(workspaceDir, "config.json");
|
|
220
|
+
let existingConfig = {};
|
|
221
|
+
if (import_fs_extra.default.existsSync(configPath)) {
|
|
222
|
+
try {
|
|
223
|
+
existingConfig = JSON.parse(await import_fs_extra.default.readFile(configPath, "utf-8"));
|
|
224
|
+
} catch {
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (await import_fs_extra.default.pathExists(configPath)) {
|
|
228
|
+
const configStats = await import_fs_extra.default.lstat(configPath);
|
|
229
|
+
if (configStats.isSymbolicLink()) {
|
|
230
|
+
throw new Error(
|
|
231
|
+
".code_puppy/config.json is a symlink \u2014 refusing to write. Check for tampering."
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
await import_fs_extra.default.writeFile(
|
|
236
|
+
configPath,
|
|
237
|
+
JSON.stringify({ ...existingConfig, projectOnly: true }, null, 2) + "\n",
|
|
238
|
+
"utf-8"
|
|
239
|
+
);
|
|
240
|
+
const mcpServersPath = import_path.default.join(workspaceDir, "mcp_servers.json");
|
|
241
|
+
if (await import_fs_extra.default.pathExists(mcpServersPath)) {
|
|
242
|
+
const mcpStats = await import_fs_extra.default.lstat(mcpServersPath);
|
|
243
|
+
if (mcpStats.isSymbolicLink()) {
|
|
244
|
+
throw new Error(
|
|
245
|
+
".code_puppy/mcp_servers.json is a symlink \u2014 refusing to write. Check for tampering."
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (!import_fs_extra.default.existsSync(mcpServersPath)) {
|
|
250
|
+
const mcpConfig = {
|
|
251
|
+
mcp_servers: {
|
|
252
|
+
"stackwright-pro-mcp": {
|
|
253
|
+
type: "stdio",
|
|
254
|
+
command: "pnpm",
|
|
255
|
+
args: ["exec", "stackwright-pro-mcp"],
|
|
256
|
+
enabled: true,
|
|
257
|
+
cwd: "${PROJECT_ROOT}"
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
await import_fs_extra.default.writeFile(mcpServersPath, JSON.stringify(mcpConfig, null, 2) + "\n", "utf-8");
|
|
205
262
|
}
|
|
206
|
-
const specFilename = import_path.default.basename(resolvedSpec);
|
|
207
|
-
const derivedName = specName || import_path.default.basename(specFilename, import_path.default.extname(specFilename));
|
|
208
|
-
const specsDir = import_path.default.join(targetDir, "specs");
|
|
209
|
-
await import_fs_extra.default.ensureDir(specsDir);
|
|
210
|
-
await import_fs_extra.default.copy(resolvedSpec, import_path.default.join(specsDir, specFilename));
|
|
211
|
-
return { specFilename, derivedName };
|
|
212
263
|
}
|
|
213
264
|
function generateReadme(options) {
|
|
214
265
|
const { projectName, hasSpec, specName, specFilename, hasOtters, hasMock } = options;
|
|
@@ -231,7 +282,7 @@ export const EquipmentSchema = z.object({
|
|
|
231
282
|
export type Equipment = z.infer<typeof EquipmentSchema>;
|
|
232
283
|
|
|
233
284
|
// src/generated/${specName}/client.ts
|
|
234
|
-
export class ${specName.charAt(0).toUpperCase() + specName.slice(1)}Client {
|
|
285
|
+
export class ${(specName ?? "api").charAt(0).toUpperCase() + (specName ?? "api").slice(1)}Client {
|
|
235
286
|
async getEquipment(id: string): Promise<Equipment> {
|
|
236
287
|
// Auto-wired with auth, validation, error handling
|
|
237
288
|
}
|
|
@@ -244,10 +295,10 @@ export class ${specName.charAt(0).toUpperCase() + specName.slice(1)}Client {
|
|
|
244
295
|
3. You import and use it:
|
|
245
296
|
|
|
246
297
|
\`\`\`typescript
|
|
247
|
-
import { ${specName.charAt(0).toUpperCase() + specName.slice(1)}Client } from '@/generated/${specName}/client';
|
|
298
|
+
import { ${(specName ?? "api").charAt(0).toUpperCase() + (specName ?? "api").slice(1)}Client } from '@/generated/${specName}/client';
|
|
248
299
|
import type { Equipment } from '@/generated/${specName}/types';
|
|
249
300
|
|
|
250
|
-
const client = new ${specName.charAt(0).toUpperCase() + specName.slice(1)}Client();
|
|
301
|
+
const client = new ${(specName ?? "api").charAt(0).toUpperCase() + (specName ?? "api").slice(1)}Client();
|
|
251
302
|
const gear: Equipment = await client.getEquipment('123');
|
|
252
303
|
\`\`\`
|
|
253
304
|
|
|
@@ -283,12 +334,10 @@ Your project includes **SIX specialized AI agents** in \`node_modules/@stackwrig
|
|
|
283
334
|
**Start the otter raft:**
|
|
284
335
|
|
|
285
336
|
\`\`\`bash
|
|
286
|
-
|
|
337
|
+
npx @stackwright-pro/raft
|
|
287
338
|
\`\`\`
|
|
288
339
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
The raft is a Python state machine with a Rich terminal UI \u2014 it asks questions about your brand, auth, and data preferences, then coordinates specialist otters to build your app. All user interaction happens in the terminal; code-puppy is called as a one-shot subprocess for creative tasks only.
|
|
340
|
+
The raft verifies otter integrity, writes project context, and spawns code-puppy in foreman mode. The foreman asks questions about your brand, auth, and data preferences, then coordinates specialist otters to build your app. All state lives in \`.stackwright/\` \u2014 interrupt and resume anytime.
|
|
292
341
|
|
|
293
342
|
**Example session prompt:**
|
|
294
343
|
|
|
@@ -331,12 +380,16 @@ ${mockSection}## \u{1F4C1} Project Structure
|
|
|
331
380
|
|
|
332
381
|
\`\`\`
|
|
333
382
|
.
|
|
383
|
+
\u251C\u2500\u2500 app/
|
|
384
|
+
\u2502 \u251C\u2500\u2500 layout.tsx # Root layout (StackwrightLayout + Providers)
|
|
385
|
+
\u2502 \u251C\u2500\u2500 page.tsx # Home page (renders root content)
|
|
386
|
+
\u2502 \u251C\u2500\u2500 [...slug]/
|
|
387
|
+
\u2502 \u2502 \u2514\u2500\u2500 page.tsx # Dynamic pages from YAML content
|
|
388
|
+
\u2502 \u2514\u2500\u2500 _components/
|
|
389
|
+
\u2502 \u251C\u2500\u2500 providers.tsx # Pro: AuthProvider + component registration
|
|
390
|
+
\u2502 \u2514\u2500\u2500 page-client.tsx # Client-side page renderer
|
|
334
391
|
\u251C\u2500\u2500 pages/
|
|
335
|
-
\u2502 \
|
|
336
|
-
\u2502 \u251C\u2500\u2500 index.tsx # Home page (auto-generated by Stackwright)
|
|
337
|
-
\u2502 \u251C\u2500\u2500 about/
|
|
338
|
-
\u2502 \u2502 \u2514\u2500\u2500 content.yml # Page content in YAML
|
|
339
|
-
\u2502 \u2514\u2500\u2500 ...
|
|
392
|
+
\u2502 \u2514\u2500\u2500 content.yml # Root page content in YAML
|
|
340
393
|
\u251C\u2500\u2500 lib/
|
|
341
394
|
\u2502 \u2514\u2500\u2500 mock-auth.ts # Dev-only auth mocking (no backend needed)
|
|
342
395
|
\u251C\u2500\u2500 scripts/
|
|
@@ -356,7 +409,7 @@ ${mockSection}## \u{1F4C1} Project Structure
|
|
|
356
409
|
\`\`\`
|
|
357
410
|
|
|
358
411
|
**Key Files:**
|
|
359
|
-
- \`
|
|
412
|
+
- \`app/_components/providers.tsx\` - Wraps your app with \`AuthProvider\` for RBAC
|
|
360
413
|
- \`stackwright.yml\` - Single source of truth for theme, auth roles, and API wiring
|
|
361
414
|
- \`lib/mock-auth.ts\` - Mocks CAC/PIV headers locally so you can test auth flows
|
|
362
415
|
- \`scripts/prebuild.js\` - Runs before dev/build to generate types from your OpenAPI spec
|
|
@@ -466,8 +519,28 @@ ${aiAgentsSection}## \u{1F4DA} Learn More
|
|
|
466
519
|
**Questions?** File an issue or ping us in the discussions. We're here to help you ship faster.
|
|
467
520
|
`;
|
|
468
521
|
}
|
|
522
|
+
|
|
523
|
+
// src/index.ts
|
|
524
|
+
(0, import_scaffold_hooks.registerProScaffoldHooks)();
|
|
525
|
+
var { version } = require_package();
|
|
526
|
+
async function copyProTemplate(templateName, destPath) {
|
|
527
|
+
const src = import_path2.default.resolve(__dirname, "..", "templates", "pro", templateName);
|
|
528
|
+
await import_fs_extra2.default.copy(src, destPath);
|
|
529
|
+
}
|
|
530
|
+
async function handleSpec(targetDir, specPath, specName) {
|
|
531
|
+
const resolvedSpec = import_path2.default.resolve(specPath);
|
|
532
|
+
if (!import_fs_extra2.default.existsSync(resolvedSpec)) {
|
|
533
|
+
throw new Error(`Spec file not found: ${resolvedSpec}`);
|
|
534
|
+
}
|
|
535
|
+
const specFilename = import_path2.default.basename(resolvedSpec);
|
|
536
|
+
const derivedName = specName || import_path2.default.basename(specFilename, import_path2.default.extname(specFilename));
|
|
537
|
+
const specsDir = import_path2.default.join(targetDir, "specs");
|
|
538
|
+
await import_fs_extra2.default.ensureDir(specsDir);
|
|
539
|
+
await import_fs_extra2.default.copy(resolvedSpec, import_path2.default.join(specsDir, specFilename));
|
|
540
|
+
return { specFilename, derivedName };
|
|
541
|
+
}
|
|
469
542
|
async function launch(targetDir, options) {
|
|
470
|
-
const dirName =
|
|
543
|
+
const dirName = import_path2.default.basename(targetDir);
|
|
471
544
|
console.log(import_chalk.default.cyan.bold("\n\u{1F6A2} Launching Stackwright Pro...\n"));
|
|
472
545
|
const scaffoldOpts = {
|
|
473
546
|
name: options.name || dirName,
|
|
@@ -483,11 +556,11 @@ async function launch(targetDir, options) {
|
|
|
483
556
|
await addProDepsToPackageJson(targetDir);
|
|
484
557
|
console.log(import_chalk.default.green("\u{1F9A6} Pro packages added to package.json"));
|
|
485
558
|
const verifyPkg = JSON.parse(
|
|
486
|
-
await
|
|
559
|
+
await import_fs_extra2.default.readFile(import_path2.default.join(targetDir, "package.json"), "utf-8")
|
|
487
560
|
);
|
|
488
|
-
const proDepCount = Object.keys(
|
|
489
|
-
|
|
490
|
-
).length;
|
|
561
|
+
const proDepCount = Object.keys(
|
|
562
|
+
typeof verifyPkg.dependencies === "object" && verifyPkg.dependencies !== null ? verifyPkg.dependencies : {}
|
|
563
|
+
).filter((k) => k.startsWith("@stackwright-pro")).length;
|
|
491
564
|
console.log(import_chalk.default.dim(` \u2192 package.json verified: ${proDepCount} @stackwright-pro/* deps ready`));
|
|
492
565
|
console.log(import_chalk.default.cyan("\n\u{1F4E6} Installing dependencies (this takes a moment)..."));
|
|
493
566
|
if (!options.skipInstall) {
|
|
@@ -522,33 +595,47 @@ async function launch(targetDir, options) {
|
|
|
522
595
|
const dependencyMode = "standalone";
|
|
523
596
|
await (0, import_scaffold_core.runScaffoldHooks)("postInstall", {
|
|
524
597
|
targetDir,
|
|
525
|
-
projectName: options.name ||
|
|
526
|
-
siteTitle: options.title || options.name ||
|
|
598
|
+
projectName: options.name || import_path2.default.basename(targetDir),
|
|
599
|
+
siteTitle: options.title || options.name || import_path2.default.basename(targetDir),
|
|
527
600
|
themeId: options.theme || "corporate",
|
|
528
601
|
packageJson: {},
|
|
529
602
|
dependencyMode
|
|
530
603
|
});
|
|
531
|
-
await copyProTemplate(
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
await copyProTemplate("
|
|
536
|
-
await copyProTemplate("
|
|
537
|
-
await
|
|
538
|
-
await copyProTemplate("
|
|
539
|
-
|
|
604
|
+
await copyProTemplate(
|
|
605
|
+
"pro-providers.tsx",
|
|
606
|
+
import_path2.default.join(targetDir, "app", "_components", "providers.tsx")
|
|
607
|
+
);
|
|
608
|
+
await copyProTemplate("content.yml", import_path2.default.join(targetDir, "pages", "content.yml"));
|
|
609
|
+
await copyProTemplate("next.config.js", import_path2.default.join(targetDir, "next.config.js"));
|
|
610
|
+
await import_fs_extra2.default.ensureDir(import_path2.default.join(targetDir, "lib"));
|
|
611
|
+
await copyProTemplate("mock-auth.ts", import_path2.default.join(targetDir, "lib", "mock-auth.ts"));
|
|
612
|
+
await copyProTemplate("yaml.d.ts", import_path2.default.join(targetDir, "yaml.d.ts"));
|
|
613
|
+
await import_fs_extra2.default.ensureDir(import_path2.default.join(targetDir, "scripts"));
|
|
614
|
+
await copyProTemplate("prebuild.js", import_path2.default.join(targetDir, "scripts", "prebuild.js"));
|
|
615
|
+
await copyProTemplate(
|
|
616
|
+
"scripts/pro-content-plugin.js",
|
|
617
|
+
import_path2.default.join(targetDir, "scripts", "pro-content-plugin.js")
|
|
618
|
+
);
|
|
619
|
+
await import_fs_extra2.default.ensureDir(import_path2.default.join(targetDir, "app", "[...slug]"));
|
|
620
|
+
await copyProTemplate(
|
|
621
|
+
"app/slug-page/page.tsx",
|
|
622
|
+
import_path2.default.join(targetDir, "app", "[...slug]", "page.tsx")
|
|
623
|
+
);
|
|
624
|
+
console.log(import_chalk.default.green(" Auth integration added (App Router providers + RBAC)"));
|
|
540
625
|
await addAuthToStackwrightYml(targetDir);
|
|
541
626
|
let specInfo = null;
|
|
542
627
|
const MOCK_URL = "http://localhost:4010";
|
|
543
|
-
if (options.spec) {
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
628
|
+
if (options.spec && options.spec.length > 0) {
|
|
629
|
+
for (const specPath of options.spec) {
|
|
630
|
+
specInfo = await handleSpec(targetDir, specPath, options.specName);
|
|
631
|
+
await addIntegrationToStackwrightYml(
|
|
632
|
+
targetDir,
|
|
633
|
+
specInfo.derivedName,
|
|
634
|
+
specInfo.specFilename,
|
|
635
|
+
options.mock ? MOCK_URL : void 0
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
console.log(import_chalk.default.green(`\u{1F4E1} ${options.spec.length} OpenAPI integration(s) wired up`));
|
|
552
639
|
if (options.mock) {
|
|
553
640
|
console.log(import_chalk.default.green("\u{1F3AD} Prism mock server configured"));
|
|
554
641
|
}
|
|
@@ -558,9 +645,9 @@ async function launch(targetDir, options) {
|
|
|
558
645
|
"\u26A0\uFE0F No spec provided with --mock. Using sample Petstore spec for demo. Replace with your API spec."
|
|
559
646
|
)
|
|
560
647
|
);
|
|
561
|
-
const specsDir =
|
|
562
|
-
await
|
|
563
|
-
await copyProTemplate("petstore.yaml",
|
|
648
|
+
const specsDir = import_path2.default.join(targetDir, "specs");
|
|
649
|
+
await import_fs_extra2.default.ensureDir(specsDir);
|
|
650
|
+
await copyProTemplate("petstore.yaml", import_path2.default.join(specsDir, "petstore.yaml"));
|
|
564
651
|
specInfo = { specFilename: "petstore.yaml", derivedName: "petstore" };
|
|
565
652
|
await addIntegrationToStackwrightYml(
|
|
566
653
|
targetDir,
|
|
@@ -579,13 +666,33 @@ async function launch(targetDir, options) {
|
|
|
579
666
|
hasOtters: !options.skipOtters,
|
|
580
667
|
hasMock: !!options.mock
|
|
581
668
|
});
|
|
582
|
-
await
|
|
669
|
+
await import_fs_extra2.default.writeFile(import_path2.default.join(targetDir, "README.md"), readmeContent);
|
|
583
670
|
console.log(import_chalk.default.green("\u{1F4C4} README.md created"));
|
|
584
|
-
const
|
|
671
|
+
const initContext = {
|
|
672
|
+
projectRoot: targetDir,
|
|
673
|
+
projectName: options.name || dirName,
|
|
674
|
+
generatedBy: "launch-stackwright-pro",
|
|
675
|
+
version: "1.0"
|
|
676
|
+
};
|
|
677
|
+
if (specInfo) {
|
|
678
|
+
initContext.specPath = `specs/${specInfo.specFilename}`;
|
|
679
|
+
initContext.specName = specInfo.derivedName;
|
|
680
|
+
}
|
|
681
|
+
initContext.theme = options.theme || "corporate";
|
|
682
|
+
const stackwrightDir = import_path2.default.join(targetDir, ".stackwright");
|
|
683
|
+
await import_fs_extra2.default.ensureDir(stackwrightDir);
|
|
684
|
+
await import_fs_extra2.default.writeFile(
|
|
685
|
+
import_path2.default.join(stackwrightDir, "init-context.json"),
|
|
686
|
+
JSON.stringify(initContext, null, 2) + "\n",
|
|
687
|
+
"utf-8"
|
|
688
|
+
);
|
|
689
|
+
await scaffoldWorkspaceConfig(targetDir);
|
|
690
|
+
console.log(import_chalk.default.green("\u{1F43E} .code_puppy/ workspace scaffolded (projectOnly: true)"));
|
|
691
|
+
const relDir = import_path2.default.relative(process.cwd(), targetDir) || ".";
|
|
585
692
|
console.log(import_chalk.default.cyan.bold("\n\u{1F389} All set! Here's what to do next:\n"));
|
|
586
693
|
console.log(import_chalk.default.white(` 1. cd ${relDir}`));
|
|
587
|
-
console.log(import_chalk.default.white(" 2.
|
|
588
|
-
console.log(import_chalk.default.dim(" (
|
|
694
|
+
console.log(import_chalk.default.white(" 2. npx @stackwright-pro/raft"));
|
|
695
|
+
console.log(import_chalk.default.dim(" (use --verbose for troubleshooting)"));
|
|
589
696
|
if (specInfo) {
|
|
590
697
|
console.log(import_chalk.default.cyan(`
|
|
591
698
|
\u{1F4E1} Your API spec was copied to specs/${specInfo.specFilename}`));
|
|
@@ -603,8 +710,8 @@ async function launch(targetDir, options) {
|
|
|
603
710
|
async function main() {
|
|
604
711
|
const program = new import_commander.Command();
|
|
605
712
|
program.name("launch-stackwright-pro").description("\u{1F6A2} Launch a new Stackwright Pro project with auth, OpenAPI, and the otter raft").version(version).argument("[directory]", "Project directory", ".").option("--name <name>", "Project name (used in package.json)").option("--title <title>", "Site title shown in the app bar and browser tab").option("--theme <themeId>", "Theme ID (e.g., corporate, creative, minimal)").option("--force", "Launch even if the target directory is not empty").option("--skip-otters", "Skip copying otter raft configs").option("-y, --yes", "Skip all prompts, use defaults").option("--mock", "Configure Prism mock server for API development (runs on port 4010)").option(
|
|
606
|
-
"--spec <
|
|
607
|
-
"
|
|
713
|
+
"--spec <paths...>",
|
|
714
|
+
"Paths to OpenAPI specs (YAML or JSON) \u2014 copies into project and wires up integrations (can be specified multiple times)"
|
|
608
715
|
).option(
|
|
609
716
|
"--spec-name <name>",
|
|
610
717
|
"Name for the API integration (default: derived from spec filename)"
|
|
@@ -613,8 +720,8 @@ async function main() {
|
|
|
613
720
|
"Skip automatic pnpm install (useful in CI or when using a different package manager)"
|
|
614
721
|
).action(async (directory, options) => {
|
|
615
722
|
const homeDir = import_os.default.homedir();
|
|
616
|
-
const targetDir =
|
|
617
|
-
if (!targetDir.startsWith(homeDir +
|
|
723
|
+
const targetDir = directory !== "." ? import_path2.default.resolve(process.cwd(), directory) : options.name ? import_path2.default.resolve(process.cwd(), options.name) : process.cwd();
|
|
724
|
+
if (!targetDir.startsWith(homeDir + import_path2.default.sep) && targetDir !== homeDir) {
|
|
618
725
|
console.warn(import_chalk.default.yellow(`\u26A0\uFE0F Scaffolding outside your home directory: ${targetDir}`));
|
|
619
726
|
}
|
|
620
727
|
await launch(targetDir, options);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../package.json","../src/index.ts","../src/generated/workspace-versions.ts"],"sourcesContent":["{\n \"name\": \"@stackwright-pro/launch-stackwright-pro\",\n \"version\": \"0.4.0-alpha.13\",\n \"description\": \"Launch a new Stackwright Pro project with OpenAPI integration, auth, and the otter raft\",\n \"license\": \"MIT\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/Per-Aspera-LLC/stackwright-pro\"\n },\n \"keywords\": [\n \"stackwright\",\n \"stackwright-pro\",\n \"scaffolding\",\n \"openapi\",\n \"government\",\n \"hackathon\"\n ],\n \"files\": [\n \"dist\",\n \"templates\"\n ],\n \"bin\": {\n \"launch-stackwright-pro\": \"dist/index.js\"\n },\n \"scripts\": {\n \"build\": \"node ../../scripts/sync-versions.mjs && tsup\",\n \"sync-versions\": \"node ../../scripts/sync-versions.mjs\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"dependencies\": {\n \"@stackwright-pro/auth\": \"workspace:*\",\n \"@stackwright-pro/auth-nextjs\": \"workspace:*\",\n \"@stackwright-pro/mcp\": \"workspace:*\",\n \"@stackwright-pro/openapi\": \"workspace:*\",\n \"@stackwright-pro/otters\": \"workspace:*\",\n \"@stackwright-pro/scaffold-hooks\": \"latest\",\n \"@stackwright/cli\": \"^0.7.1-alpha.0\",\n \"@stackwright/scaffold-core\": \"^0.1.0\",\n \"chalk\": \"^5.6.2\",\n \"commander\": \"^14.0.3\",\n \"fs-extra\": \"^11.3\",\n \"js-yaml\": \"^4.1.0\"\n },\n \"devDependencies\": {\n \"@types/fs-extra\": \"^11.0\",\n \"@types/js-yaml\": \"^4.0.9\",\n \"@types/node\": \"^24.0.0\",\n \"typescript\": \"^5.0\",\n \"tsup\": \"^8.5\",\n \"vitest\": \"^4.0.18\"\n }\n}\n","import { Command } from 'commander';\nimport path from 'path';\nimport os from 'os';\nimport fs from 'fs-extra';\nimport chalk from 'chalk';\nimport yaml from 'js-yaml';\nimport { execSync } from 'child_process';\n\nimport { scaffold, ScaffoldOptions } from '@stackwright/cli';\nimport { runScaffoldHooks } from '@stackwright/scaffold-core';\nimport { registerProScaffoldHooks } from '@stackwright-pro/scaffold-hooks';\nimport { PRO_VERSIONS, OSS_VERSIONS } from './generated/workspace-versions';\n// Register Pro hooks (adds deps, MCP config, etc.)\n// Must be called before scaffold() to ensure hooks run in the CLI's scaffold-core context\nregisterProScaffoldHooks();\n\nconst { version } = require('../package.json') as { version: string };\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface LaunchProOptions {\n name?: string;\n title?: string;\n theme?: string;\n force?: boolean;\n skipOtters?: boolean;\n skipInstall?: boolean;\n yes?: boolean;\n spec?: string;\n specName?: string;\n mock?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Template copying (Pro-specific - hooks can't handle these)\n// ---------------------------------------------------------------------------\n\nasync function copyProTemplate(templateName: string, destPath: string): Promise<void> {\n const src = path.resolve(__dirname, '..', 'templates', 'pro', templateName);\n await fs.copy(src, destPath);\n}\n\n// ---------------------------------------------------------------------------\n// Auth config (Pro-specific - hooks can't handle these)\n// ---------------------------------------------------------------------------\n\nasync function addAuthToStackwrightYml(targetDir: string): Promise<void> {\n const ymlPath = path.join(targetDir, 'stackwright.yml');\n const content = await fs.readFile(ymlPath, 'utf-8');\n const config = yaml.load(content, { schema: yaml.CORE_SCHEMA }) as Record<string, unknown>;\n\n config.auth = {\n type: 'pki',\n profile: 'dod_cac',\n source: 'gateway_headers',\n roles: [\n { name: 'ADMIN', permissions: ['*'] },\n { name: 'ANALYST', permissions: ['data:read', 'data:write'] },\n { name: 'VIEWER', permissions: ['data:read'] },\n ],\n protected_routes: [{ path: '/*', roles: ['VIEWER', 'ANALYST', 'ADMIN'] }],\n public_routes: ['/', '/getting-started'],\n };\n\n await fs.writeFile(ymlPath, yaml.dump(config, { lineWidth: 120 }));\n}\n\nasync function addProDepsToPackageJson(targetDir: string): Promise<void> {\n const pkgPath = path.join(targetDir, 'package.json');\n const content = await fs.readFile(pkgPath, 'utf-8');\n const pkg = JSON.parse(content) as Record<string, any>;\n\n const dependencies = (pkg.dependencies as Record<string, string>) || {};\n const devDependencies = (pkg.devDependencies as Record<string, string>) || {};\n const scripts = (pkg.scripts as Record<string, string>) || {};\n\n // Fix any workspace:* references that scaffold may have written\n // (happens when running from inside a pnpm workspace)\n for (const [pkgName, pinnedVersion] of Object.entries(OSS_VERSIONS)) {\n if (dependencies[pkgName] === 'workspace:*') {\n dependencies[pkgName] = pinnedVersion;\n }\n if (devDependencies[pkgName] === 'workspace:*') {\n devDependencies[pkgName] = pinnedVersion;\n }\n }\n\n // Pro runtime dependencies — exact versions from workspace at build time\n Object.assign(dependencies, {\n '@stackwright-pro/mcp': PRO_VERSIONS['@stackwright-pro/mcp'],\n '@stackwright-pro/otters': PRO_VERSIONS['@stackwright-pro/otters'],\n '@stackwright-pro/openapi': PRO_VERSIONS['@stackwright-pro/openapi'],\n '@stackwright-pro/auth': PRO_VERSIONS['@stackwright-pro/auth'],\n '@stackwright-pro/auth-nextjs': PRO_VERSIONS['@stackwright-pro/auth-nextjs'],\n zod: '^3.23.0',\n });\n\n // Pro dev dependencies\n Object.assign(devDependencies, {\n '@stoplight/prism-cli': '^5.14.2',\n });\n\n // Role-based dev scripts\n Object.assign(scripts, {\n 'dev:admin': 'MOCK_USER=admin next dev',\n 'dev:analyst': 'MOCK_USER=analyst next dev',\n 'dev:viewer': 'MOCK_USER=viewer next dev',\n prebuild: 'node scripts/prebuild.js',\n predev: 'node scripts/prebuild.js',\n });\n\n pkg.dependencies = dependencies;\n pkg.devDependencies = devDependencies;\n pkg.scripts = scripts;\n\n await fs.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\\n', 'utf-8');\n}\n\nasync function addIntegrationToStackwrightYml(\n targetDir: string,\n specName: string,\n specFilename: string,\n mockUrl?: string\n): Promise<void> {\n const ymlPath = path.join(targetDir, 'stackwright.yml');\n const content = await fs.readFile(ymlPath, 'utf-8');\n const config = yaml.load(content, { schema: yaml.CORE_SCHEMA }) as Record<string, unknown>;\n\n const integration: Record<string, unknown> = {\n type: 'openapi',\n name: specName,\n spec: `./specs/${specFilename}`,\n collections: [],\n };\n\n if (mockUrl) {\n integration.mockUrl = mockUrl;\n }\n\n config.integrations = [integration];\n\n await fs.writeFile(ymlPath, yaml.dump(config, { lineWidth: 120 }));\n}\n\n// ---------------------------------------------------------------------------\n// Spec handling (Pro-specific - hooks can't handle these)\n// ---------------------------------------------------------------------------\n\nasync function handleSpec(\n targetDir: string,\n specPath: string,\n specName?: string\n): Promise<{ specFilename: string; derivedName: string }> {\n const resolvedSpec = path.resolve(specPath);\n\n if (!fs.existsSync(resolvedSpec)) {\n throw new Error(`Spec file not found: ${resolvedSpec}`);\n }\n\n const specFilename = path.basename(resolvedSpec);\n const derivedName = specName || path.basename(specFilename, path.extname(specFilename));\n\n const specsDir = path.join(targetDir, 'specs');\n await fs.ensureDir(specsDir);\n await fs.copy(resolvedSpec, path.join(specsDir, specFilename));\n\n return { specFilename, derivedName };\n}\n\n// ---------------------------------------------------------------------------\n// README generator (Pro-specific - hooks can't handle these)\n// ---------------------------------------------------------------------------\n\nfunction generateReadme(options: {\n projectName: string;\n hasSpec: boolean;\n specName?: string;\n specFilename?: string;\n hasOtters: boolean;\n hasMock: boolean;\n}): string {\n const { projectName, hasSpec, specName, specFilename, hasOtters, hasMock } = options;\n\n // Build API Integration section if spec is present\n const apiIntegrationSection = hasSpec\n ? `## 📡 API Integration\n\nYour OpenAPI spec was copied to \\`specs/${specFilename}\\` and wired up in \\`stackwright.yml\\`.\n\n**What gets generated:**\n\n\\`\\`\\`typescript\n// src/generated/${specName}/schemas.ts\nexport const EquipmentSchema = z.object({\n id: z.string(),\n name: z.string(),\n status: z.enum(['operational', 'maintenance', 'retired']),\n // ... Zod validation for runtime safety\n});\n\n// src/generated/${specName}/types.ts\nexport type Equipment = z.infer<typeof EquipmentSchema>;\n\n// src/generated/${specName}/client.ts\nexport class ${specName!.charAt(0).toUpperCase() + specName!.slice(1)}Client {\n async getEquipment(id: string): Promise<Equipment> {\n // Auto-wired with auth, validation, error handling\n }\n}\n\\`\\`\\`\n\n**How it works:**\n1. The \\`predev\\` script in \\`package.json\\` runs \\`prebuild.js\\` before every \\`pnpm dev\\`\n2. Prebuild reads your spec and generates type-safe code\n3. You import and use it:\n\n\\`\\`\\`typescript\nimport { ${specName!.charAt(0).toUpperCase() + specName!.slice(1)}Client } from '@/generated/${specName}/client';\nimport type { Equipment } from '@/generated/${specName}/types';\n\nconst client = new ${specName!.charAt(0).toUpperCase() + specName!.slice(1)}Client();\nconst gear: Equipment = await client.getEquipment('123');\n\\`\\`\\`\n\nNo manual typing. No drift. No runtime surprises.\n\n`\n : '';\n\n // Build mock server section if enabled\n const mockSection = hasMock\n ? `## 🎭 Mock Server\n\nPrism mock server is configured to serve your API at **http://localhost:4010**.\n\n\\`\\`\\`bash\npnpm dev:mock # Starts Prism + Next.js together\n\\`\\`\\`\n\nThis starts:\n1. Prism mock server on port 4010 (serves your OpenAPI spec)\n2. Next.js dev server on port 3000\n\nThe generated API client is automatically configured to use the mock server.\n\n`\n : '';\n\n // Build AI Agents section if otters are present\n const aiAgentsSection = hasOtters\n ? `## 🦦 AI Agents (The Otter Raft)\n\nYour project includes **SIX specialized AI agents** in \\`node_modules/@stackwright-pro/otters/\\`:\n\n- \\`stackwright-pro-foreman-otter\\` - Master coordinator that orchestrates all specialist otters\n- \\`stackwright-pro-api-otter\\` - Discovers entities from OpenAPI specs\n- \\`stackwright-pro-auth-otter\\` - Configures CAC/OIDC auth, RBAC rules, and audit middleware\n- \\`stackwright-pro-data-otter\\` - Configures endpoint filters & ISR revalidation\n- \\`stackwright-pro-page-otter\\` - Generates pages auto-wired with data, theme, and auth\n- \\`stackwright-pro-dashboard-otter\\` - Builds live data dashboards\n\n**Start the otter raft:**\n\n\\`\\`\\`bash\nuvx stackwright-pro-raft\n\\`\\`\\`\n\n> **Local dev (before PyPI publish):** \\`python -m stackwright_pro.raft.cli_adapter foreman\\`\n\nThe raft is a Python state machine with a Rich terminal UI — it asks questions about your brand, auth, and data preferences, then coordinates specialist otters to build your app. All user interaction happens in the terminal; code-puppy is called as a one-shot subprocess for creative tasks only.\n\n**Example session prompt:**\n\n\"Build me a logistics dashboard from our OpenAPI spec. Connect to /equipment and /supplies endpoints.\"\n\n`\n : '';\n\n return `# ${projectName}\n\nA Stackwright Pro application with role-based auth, OpenAPI integration, and intelligent AI agents.\n\n## 🚀 Quick Start\n\n\\`\\`\\`bash\n# Start development server\npnpm dev\n\n# Open your browser\nopen http://localhost:3000\n\\`\\`\\`\n\n## 👥 Role-Based Development\n\nStackwright Pro includes **mock authentication** for local development with three pre-configured roles:\n\n\\`\\`\\`bash\npnpm dev:admin # Full permissions (*)\npnpm dev:analyst # Read & write data\npnpm dev:viewer # Read-only access\n\\`\\`\\`\n\n**How it works:**\n- Each script sets the \\`MOCK_USER\\` environment variable\n- \\`lib/mock-auth.ts\\` intercepts requests and injects the appropriate user context\n- Your pages & API routes respect the RBAC rules in \\`stackwright.yml\\`\n- No backend required for testing auth flows! 🎉\n\n**Pro tip:** Test your UI for all three roles to ensure proper permissions enforcement.\n\n${mockSection}## 📁 Project Structure\n\n\\`\\`\\`\n.\n├── pages/\n│ ├── _app.tsx # Pro version with AuthProvider + shadcn\n│ ├── index.tsx # Home page (auto-generated by Stackwright)\n│ ├── about/\n│ │ └── content.yml # Page content in YAML\n│ └── ...\n├── lib/\n│ └── mock-auth.ts # Dev-only auth mocking (no backend needed)\n├── scripts/\n│ └── prebuild.js # Auto-generates code from OpenAPI specs\n├── specs/ # OpenAPI spec files (if --spec was used)\n├── src/\n│ └── generated/ # Auto-generated types & clients\n│ └── {specName}/\n│ ├── schemas.ts # Zod schemas for runtime validation\n│ ├── types.ts # TypeScript types\n│ ├── client.ts # API client with auth\n│ └── provider.ts # CollectionProvider for Stackwright\n├── .stackwright/\n│ └── otters/ # AI agent configs (4 specialized otters)\n├── stackwright.yml # Theme, auth, API integrations\n└── package.json\n\\`\\`\\`\n\n**Key Files:**\n- \\`pages/_app.tsx\\` - Wraps your app with \\`AuthProvider\\` for RBAC\n- \\`stackwright.yml\\` - Single source of truth for theme, auth roles, and API wiring\n- \\`lib/mock-auth.ts\\` - Mocks CAC/PIV headers locally so you can test auth flows\n- \\`scripts/prebuild.js\\` - Runs before dev/build to generate types from your OpenAPI spec\n\n## 📄 Adding Pages\n\nStackwright uses **YAML for content**, so you never touch JSX unless you want to.\n\n**Example:** Create \\`pages/about/content.yml\\`:\n\n\\`\\`\\`yaml\ntitle: About Us\ndescription: Learn more about our mission\n\nsections:\n - type: main\n heading: Who We Are\n body: |\n We build mission-critical logistics systems for the Marine Corps.\n\n - type: feature_list\n title: Our Capabilities\n features:\n - icon: Security\n title: Zero Trust\n description: PKI-based auth with CAC/PIV\n - icon: Api\n title: Real-time Data\n description: OpenAPI-backed, Zod-validated\n\\`\\`\\`\n\nThat's it. Navigate to \\`/about\\` and it just works. No routing config, no React components.\n\n${apiIntegrationSection}## 🎨 Customizing Theme\n\nEdit \\`stackwright.yml\\` to change colors, fonts, spacing — applies everywhere instantly.\n\n\\`\\`\\`yaml\ntheme:\n id: my-theme\n name: My Custom Theme\n colors:\n primary: \"#C41E3A\" # Marine Corps red\n background: \"#FFFFFF\"\n text: \"#1A1A1A\"\n accent: \"#FFD700\" # Gold\n typography:\n fontFamily: \"'Inter', sans-serif\"\n h1Size: \"2.5rem\"\n spacing:\n unit: 8\n\\`\\`\\`\n\nNo CSS files. No theme provider boilerplate. Just YAML. Stackwright handles the rest.\n\n## 🔐 Auth Configuration\n\nStackwright Pro comes with **3 pre-configured roles** in \\`stackwright.yml\\`:\n\n\\`\\`\\`yaml\nauth:\n roles:\n - name: ADMIN\n permissions: ['*'] # Full access\n - name: ANALYST \n permissions: ['data:read', 'data:write'] # Read/write data\n - name: VIEWER\n permissions: ['data:read'] # Read-only\n\\`\\`\\`\n\n**Gate content in your YAML:**\n\n\\`\\`\\`yaml\nsections:\n - type: button\n label: Delete Equipment\n action: /api/equipment/delete\n auth:\n required_roles: [ADMIN]\n fallback: hide # Options: hide, disable, show_message\n\\`\\`\\`\n\nOnly admins see the button. Analysts and viewers? Button doesn't exist in the DOM.\n\n**Route protection:**\n\n\\`\\`\\`yaml\nauth:\n protected_routes:\n - path: /admin/*\n roles: [ADMIN]\n - path: /equipment/* \n roles: [ANALYST, ADMIN]\n public_routes:\n - /\n - /about\n\\`\\`\\`\n\nNo middleware to write. No useAuth hooks to remember. RBAC is declarative.\n\n${aiAgentsSection}## 📚 Learn More\n\n- **Stackwright Docs:** [https://stackwright.dev](https://stackwright.dev)\n- **OSS Repo:** [https://github.com/Per-Aspera-LLC/stackwright](https://github.com/Per-Aspera-LLC/stackwright)\n- **Pro Repo:** [https://github.com/Per-Aspera-LLC/stackwright-pro](https://github.com/Per-Aspera-LLC/stackwright-pro)\n\n**Questions?** File an issue or ping us in the discussions. We're here to help you ship faster.\n`;\n}\n\n// ---------------------------------------------------------------------------\n// Main launch flow\n// ---------------------------------------------------------------------------\n\nasync function launch(targetDir: string, options: LaunchProOptions): Promise<void> {\n const dirName = path.basename(targetDir);\n\n console.log(chalk.cyan.bold('\\n🚢 Launching Stackwright Pro...\\n'));\n\n // ------------------------------------------------------------------\n // 1. Scaffold base OSS project via @stackwright/cli\n // Hooks auto-handle: Pro deps, MCP config, role-based scripts\n // ------------------------------------------------------------------\n\n const scaffoldOpts: ScaffoldOptions = {\n name: options.name || dirName,\n standalone: true, // prevents `workspace:*` refs when CLI runs inside the Pro monorepo\n ...(options.title !== undefined && { title: options.title }),\n ...(options.theme !== undefined && { theme: options.theme }),\n ...(options.force !== undefined && { force: options.force }),\n ...(options.yes !== undefined && { noInteractive: options.yes }),\n };\n\n await scaffold(targetDir, scaffoldOpts);\n console.log(chalk.green('✅ Base project scaffolded (hooks added Pro deps + MCP config)'));\n\n // ------------------------------------------------------------------\n // 1b. Run pnpm install — citizen devs shouldn't need to know this step exists\n // ------------------------------------------------------------------\n\n // Patch Pro packages directly into package.json before install.\n // This bypasses the scaffold hooks system (which has a known version-resolution\n // issue) and guarantees pro deps land regardless of hook execution order.\n await addProDepsToPackageJson(targetDir);\n console.log(chalk.green('🦦 Pro packages added to package.json'));\n\n // Verify package.json has Pro deps before installing\n const verifyPkg = JSON.parse(\n await fs.readFile(path.join(targetDir, 'package.json'), 'utf-8')\n ) as Record<string, any>;\n const proDepCount = Object.keys((verifyPkg.dependencies as Record<string, string>) || {}).filter(\n (k) => k.startsWith('@stackwright-pro')\n ).length;\n console.log(chalk.dim(` → package.json verified: ${proDepCount} @stackwright-pro/* deps ready`));\n\n console.log(chalk.cyan('\\n📦 Installing dependencies (this takes a moment)...'));\n if (!options.skipInstall) {\n try {\n execSync('pnpm install --ignore-workspace', {\n cwd: targetDir,\n stdio: 'inherit',\n timeout: 120_000,\n });\n console.log(chalk.green('✅ Dependencies installed'));\n } catch (err: unknown) {\n const isTimeout =\n err instanceof Error &&\n (err.message.includes('ETIMEDOUT') || err.message.includes('timeout'));\n console.error(\n chalk.red('\\n❌ pnpm install failed. Auth and Pro packages are NOT installed.')\n );\n console.error(\n chalk.red(' Your project is in an incomplete state — do NOT run or deploy it.')\n );\n if (isTimeout) {\n console.error(\n chalk.yellow(' The install timed out (>2 min). Check your network connection.')\n );\n }\n console.error(\n chalk.yellow(` Fix the error above, then run: pnpm install --ignore-workspace`)\n );\n process.exit(1);\n }\n } else {\n console.log(chalk.dim('ℹ️ Skipping install (--skip-install). Run: pnpm install'));\n }\n\n // Fire postInstall hooks now that install has run\n const dependencyMode: 'workspace' | 'standalone' = 'standalone';\n await runScaffoldHooks('postInstall', {\n targetDir,\n projectName: options.name || path.basename(targetDir),\n siteTitle: options.title || options.name || path.basename(targetDir),\n themeId: options.theme || 'corporate',\n packageJson: {},\n dependencyMode,\n });\n\n // ------------------------------------------------------------------\n // 2. Copy Pro templates (hooks can't handle these)\n // ------------------------------------------------------------------\n\n // Replace _app.tsx with Pro version (AuthProvider, shadcn, etc.)\n await copyProTemplate('_app.tsx', path.join(targetDir, 'pages', '_app.tsx'));\n\n // Add root content.yml for the home page\n await copyProTemplate('content.yml', path.join(targetDir, 'pages', 'content.yml'));\n\n // Replace next.config.js with Pro version (transpile pro pkgs)\n await copyProTemplate('next.config.js', path.join(targetDir, 'next.config.js'));\n\n // Add lib/mock-auth.ts\n await fs.ensureDir(path.join(targetDir, 'lib'));\n await copyProTemplate('mock-auth.ts', path.join(targetDir, 'lib', 'mock-auth.ts'));\n\n // Add yaml.d.ts for TypeScript support\n await copyProTemplate('yaml.d.ts', path.join(targetDir, 'yaml.d.ts'));\n\n // Add scripts/prebuild.js\n await fs.ensureDir(path.join(targetDir, 'scripts'));\n await copyProTemplate('prebuild.js', path.join(targetDir, 'scripts', 'prebuild.js'));\n\n console.log(chalk.green('🔐 Auth integration added (RBAC with 3 roles)'));\n\n // ------------------------------------------------------------------\n // 3. Add auth section to stackwright.yml\n // ------------------------------------------------------------------\n\n await addAuthToStackwrightYml(targetDir);\n\n // ------------------------------------------------------------------\n // 4. Handle --spec if provided\n // ------------------------------------------------------------------\n\n let specInfo: { specFilename: string; derivedName: string } | null = null;\n const MOCK_URL = 'http://localhost:4010';\n\n if (options.spec) {\n specInfo = await handleSpec(targetDir, options.spec, options.specName);\n\n // Pass mockUrl if --mock flag is set\n await addIntegrationToStackwrightYml(\n targetDir,\n specInfo.derivedName,\n specInfo.specFilename,\n options.mock ? MOCK_URL : undefined\n );\n console.log(chalk.green('📡 OpenAPI integration wired up'));\n\n if (options.mock) {\n console.log(chalk.green('🎭 Prism mock server configured'));\n }\n } else if (options.mock) {\n // --mock without --spec: use sample Petstore spec for demo\n console.log(\n chalk.yellow(\n '⚠️ No spec provided with --mock. Using sample Petstore spec for demo. Replace with your API spec.'\n )\n );\n\n const specsDir = path.join(targetDir, 'specs');\n await fs.ensureDir(specsDir);\n await copyProTemplate('petstore.yaml', path.join(specsDir, 'petstore.yaml'));\n\n specInfo = { specFilename: 'petstore.yaml', derivedName: 'petstore' };\n\n await addIntegrationToStackwrightYml(\n targetDir,\n specInfo.derivedName,\n specInfo.specFilename,\n MOCK_URL\n );\n console.log(chalk.green('📡 Sample Petstore spec wired up'));\n console.log(chalk.green('🎭 Prism mock server configured'));\n }\n\n // ------------------------------------------------------------------\n // 5. Generate README\n // ------------------------------------------------------------------\n\n const readmeContent = generateReadme({\n projectName: options.name || dirName,\n hasSpec: !!specInfo,\n ...(specInfo?.derivedName !== undefined && { specName: specInfo.derivedName }),\n ...(specInfo?.specFilename !== undefined && { specFilename: specInfo.specFilename }),\n hasOtters: !options.skipOtters,\n hasMock: !!options.mock,\n });\n\n await fs.writeFile(path.join(targetDir, 'README.md'), readmeContent);\n console.log(chalk.green('📄 README.md created'));\n\n // ------------------------------------------------------------------\n // 6. Print next steps\n // ------------------------------------------------------------------\n\n const relDir = path.relative(process.cwd(), targetDir) || '.';\n\n console.log(chalk.cyan.bold(\"\\n🎉 All set! Here's what to do next:\\n\"));\n console.log(chalk.white(` 1. cd ${relDir}`));\n console.log(chalk.white(' 2. uvx stackwright-pro-raft'));\n console.log(chalk.dim(' (local dev: python -m stackwright_pro.raft.cli_adapter foreman)'));\n\n if (specInfo) {\n console.log(chalk.cyan(`\\n📡 Your API spec was copied to specs/${specInfo.specFilename}`));\n console.log(chalk.dim(' The prebuild will generate types & client on first `pnpm dev`.'));\n }\n\n if (options.mock) {\n console.log(chalk.cyan('\\n🎭 Run with mock server:'));\n console.log(chalk.white(' pnpm dev:mock # Starts Prism + Next.js'));\n }\n\n if (!options.skipOtters) {\n console.log(chalk.cyan.bold('\\n🦦 The otter raft is ready to build your site!'));\n console.log(chalk.dim(' Run the command above to get started.\\n'));\n }\n}\n\n// ---------------------------------------------------------------------------\n// CLI definition\n// ---------------------------------------------------------------------------\n\nasync function main(): Promise<void> {\n const program = new Command();\n\n program\n .name('launch-stackwright-pro')\n .description('🚢 Launch a new Stackwright Pro project with auth, OpenAPI, and the otter raft')\n .version(version)\n .argument('[directory]', 'Project directory', '.')\n .option('--name <name>', 'Project name (used in package.json)')\n .option('--title <title>', 'Site title shown in the app bar and browser tab')\n .option('--theme <themeId>', 'Theme ID (e.g., corporate, creative, minimal)')\n .option('--force', 'Launch even if the target directory is not empty')\n .option('--skip-otters', 'Skip copying otter raft configs')\n .option('-y, --yes', 'Skip all prompts, use defaults')\n .option('--mock', 'Configure Prism mock server for API development (runs on port 4010)')\n .option(\n '--spec <path>',\n 'Path to an OpenAPI spec (YAML or JSON) — copies into project and wires up integration'\n )\n .option(\n '--spec-name <name>',\n 'Name for the API integration (default: derived from spec filename)'\n )\n .option(\n '--skip-install',\n 'Skip automatic pnpm install (useful in CI or when using a different package manager)'\n )\n .action(async (directory: string, options: LaunchProOptions) => {\n const homeDir = os.homedir();\n const targetDir = path.resolve(directory);\n\n // Warn (don't block) when scaffolding outside home dir — unusual for a user-facing CLI\n if (!targetDir.startsWith(homeDir + path.sep) && targetDir !== homeDir) {\n console.warn(chalk.yellow(`⚠️ Scaffolding outside your home directory: ${targetDir}`));\n }\n\n await launch(targetDir, options);\n });\n\n await program.parseAsync(process.argv);\n}\n\nmain().catch((err: unknown) => {\n console.error(chalk.red('\\n❌ Launch failed:'), err);\n process.exit(1);\n});\n","// AUTO-GENERATED — do not edit manually.\n// Run `pnpm sync-versions` or `pnpm build` to regenerate.\n// Generated: 2026-04-21T13:35:30.893Z\n//\n// PRO_VERSIONS: exact versions of @stackwright-pro/* packages in this workspace.\n// OSS_VERSIONS: minimum tested versions of @stackwright/* OSS packages (caret range).\n\n/**\n * Exact versions of every @stackwright-pro/* package currently in the workspace.\n * Used by launch-stackwright-pro and scaffold-hooks to pin deps in scaffolded projects.\n * Updated automatically on every build — never edit this file by hand.\n */\nexport const PRO_VERSIONS = {\n '@stackwright-pro/auth': '0.1.1-alpha.0',\n '@stackwright-pro/auth-nextjs': '0.1.1-alpha.0',\n '@stackwright-pro/mcp': '0.2.0-alpha.3',\n '@stackwright-pro/openapi': '0.2.2-alpha.2',\n '@stackwright-pro/otters': '1.0.0-alpha.11',\n} as const satisfies Record<string, string>;\n\n/**\n * Minimum tested versions of @stackwright/* OSS packages.\n * Caret ranges anchored to the last version resolved in pnpm-lock.yaml.\n * Updated automatically on every build.\n */\nexport const OSS_VERSIONS = {\n '@stackwright/build-scripts': '^0.4.0',\n '@stackwright/core': '^0.7.0',\n '@stackwright/icons': '^0.3.0',\n '@stackwright/mcp': '^0.2.0',\n '@stackwright/nextjs': '^0.3.1',\n '@stackwright/otters': '^0.2.0',\n '@stackwright/ui-shadcn': '^0.1.0',\n} as const satisfies Record<string, string>;\n"],"mappings":"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","names":["exports","module","path","fs","yaml","chalk","os"]}
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/index.ts","../src/scaffold.ts","../src/generated/workspace-versions.ts"],"sourcesContent":["{\n \"name\": \"@stackwright-pro/launch-stackwright-pro\",\n \"version\": \"0.4.0-alpha.133\",\n \"description\": \"Launch a new Stackwright Pro project with OpenAPI integration, auth, and the otter raft\",\n \"license\": \"SEE LICENSE IN LICENSE\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/Per-Aspera-LLC/stackwright-pro\"\n },\n \"keywords\": [\n \"stackwright\",\n \"stackwright-pro\",\n \"scaffolding\",\n \"openapi\",\n \"government\",\n \"hackathon\"\n ],\n \"files\": [\n \"dist\",\n \"templates\"\n ],\n \"bin\": {\n \"launch-stackwright-pro\": \"dist/index.js\"\n },\n \"scripts\": {\n \"build\": \"node ../../scripts/sync-versions.mjs && tsup\",\n \"sync-versions\": \"node ../../scripts/sync-versions.mjs\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"dependencies\": {\n \"@stackwright-pro/auth\": \"workspace:*\",\n \"@stackwright-pro/auth-nextjs\": \"workspace:*\",\n \"@stackwright-pro/mcp\": \"workspace:*\",\n \"@stackwright-pro/openapi\": \"workspace:*\",\n \"@stackwright-pro/otters\": \"workspace:*\",\n \"@stackwright-pro/scaffold-hooks\": \"workspace:*\",\n \"@stackwright/cli\": \"^0.9.0\",\n \"@stackwright/scaffold-core\": \"^0.3.3\",\n \"chalk\": \"^5.6.2\",\n \"commander\": \"^15.0.0\",\n \"fs-extra\": \"^11.3.5\",\n \"js-yaml\": \"^4.2.0\"\n },\n \"devDependencies\": {\n \"@types/fs-extra\": \"^11.0\",\n \"@types/js-yaml\": \"^4.0.9\",\n \"@types/node\": \"catalog:\",\n \"tsup\": \"catalog:\",\n \"typescript\": \"catalog:\",\n \"vitest\": \"catalog:\"\n }\n}\n","import { Command } from 'commander';\nimport path from 'path';\nimport os from 'os';\nimport fs from 'fs-extra';\nimport chalk from 'chalk';\nimport { execSync } from 'child_process';\n\nimport { scaffold, ScaffoldOptions } from '@stackwright/cli';\nimport { runScaffoldHooks } from '@stackwright/scaffold-core';\nimport { registerProScaffoldHooks } from '@stackwright-pro/scaffold-hooks';\nimport {\n addProDepsToPackageJson,\n addAuthToStackwrightYml,\n scaffoldWorkspaceConfig,\n addIntegrationToStackwrightYml,\n generateReadme,\n} from './scaffold.js';\n// Register Pro hooks (adds deps, MCP config, etc.)\n// Must be called before scaffold() to ensure hooks run in the CLI's scaffold-core context\nregisterProScaffoldHooks();\n\nconst { version } = require('../package.json') as { version: string };\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface LaunchProOptions {\n name?: string;\n title?: string;\n theme?: string;\n force?: boolean;\n skipOtters?: boolean;\n skipInstall?: boolean;\n yes?: boolean;\n spec?: string[];\n specName?: string;\n mock?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Template copying (Pro-specific - hooks can't handle these)\n// ---------------------------------------------------------------------------\n\nasync function copyProTemplate(templateName: string, destPath: string): Promise<void> {\n const src = path.resolve(__dirname, '..', 'templates', 'pro', templateName);\n await fs.copy(src, destPath);\n}\n\n// ---------------------------------------------------------------------------\n// Spec handling (Pro-specific - hooks can't handle these)\n// ---------------------------------------------------------------------------\n\nasync function handleSpec(\n targetDir: string,\n specPath: string,\n specName?: string\n): Promise<{ specFilename: string; derivedName: string }> {\n const resolvedSpec = path.resolve(specPath);\n\n if (!fs.existsSync(resolvedSpec)) {\n throw new Error(`Spec file not found: ${resolvedSpec}`);\n }\n\n const specFilename = path.basename(resolvedSpec);\n const derivedName = specName || path.basename(specFilename, path.extname(specFilename));\n\n const specsDir = path.join(targetDir, 'specs');\n await fs.ensureDir(specsDir);\n await fs.copy(resolvedSpec, path.join(specsDir, specFilename));\n\n return { specFilename, derivedName };\n}\n\n// ---------------------------------------------------------------------------\n// Main launch flow\n// ---------------------------------------------------------------------------\n\nasync function launch(targetDir: string, options: LaunchProOptions): Promise<void> {\n const dirName = path.basename(targetDir);\n\n console.log(chalk.cyan.bold('\\n🚢 Launching Stackwright Pro...\\n'));\n\n // ------------------------------------------------------------------\n // 1. Scaffold base OSS project via @stackwright/cli\n // Hooks auto-handle: Pro deps, MCP config, role-based scripts\n // ------------------------------------------------------------------\n\n const scaffoldOpts: ScaffoldOptions = {\n name: options.name || dirName,\n standalone: true, // prevents `workspace:*` refs when CLI runs inside the Pro monorepo\n ...(options.title !== undefined && { title: options.title }),\n ...(options.theme !== undefined && { theme: options.theme }),\n ...(options.force !== undefined && { force: options.force }),\n ...(options.yes !== undefined && { noInteractive: options.yes }),\n };\n\n await scaffold(targetDir, scaffoldOpts);\n console.log(chalk.green('✅ Base project scaffolded (hooks added Pro deps + MCP config)'));\n\n // ------------------------------------------------------------------\n // 1b. Run pnpm install — citizen devs shouldn't need to know this step exists\n // ------------------------------------------------------------------\n\n // Patch Pro packages directly into package.json before install.\n // This bypasses the scaffold hooks system (which has a known version-resolution\n // issue) and guarantees pro deps land regardless of hook execution order.\n await addProDepsToPackageJson(targetDir);\n console.log(chalk.green('🦦 Pro packages added to package.json'));\n\n // Verify package.json has Pro deps before installing\n const verifyPkg = JSON.parse(\n await fs.readFile(path.join(targetDir, 'package.json'), 'utf-8')\n ) as Record<string, unknown>;\n const proDepCount = Object.keys(\n typeof verifyPkg.dependencies === 'object' && verifyPkg.dependencies !== null\n ? (verifyPkg.dependencies as Record<string, string>)\n : {}\n ).filter((k) => k.startsWith('@stackwright-pro')).length;\n console.log(chalk.dim(` → package.json verified: ${proDepCount} @stackwright-pro/* deps ready`));\n\n console.log(chalk.cyan('\\n📦 Installing dependencies (this takes a moment)...'));\n if (!options.skipInstall) {\n try {\n execSync('pnpm install --ignore-workspace', {\n cwd: targetDir,\n stdio: 'inherit',\n timeout: 120_000,\n });\n console.log(chalk.green('✅ Dependencies installed'));\n } catch (err: unknown) {\n const isTimeout =\n err instanceof Error &&\n (err.message.includes('ETIMEDOUT') || err.message.includes('timeout'));\n console.error(\n chalk.red('\\n❌ pnpm install failed. Auth and Pro packages are NOT installed.')\n );\n console.error(\n chalk.red(' Your project is in an incomplete state — do NOT run or deploy it.')\n );\n if (isTimeout) {\n console.error(\n chalk.yellow(' The install timed out (>2 min). Check your network connection.')\n );\n }\n console.error(\n chalk.yellow(` Fix the error above, then run: pnpm install --ignore-workspace`)\n );\n process.exit(1);\n }\n } else {\n console.log(chalk.dim('ℹ️ Skipping install (--skip-install). Run: pnpm install'));\n }\n\n // Fire postInstall hooks now that install has run\n const dependencyMode: 'workspace' | 'standalone' = 'standalone';\n await runScaffoldHooks('postInstall', {\n targetDir,\n projectName: options.name || path.basename(targetDir),\n siteTitle: options.title || options.name || path.basename(targetDir),\n themeId: options.theme || 'corporate',\n packageJson: {},\n dependencyMode,\n });\n\n // ------------------------------------------------------------------\n // 2. Copy Pro templates (hooks can't handle these)\n // ------------------------------------------------------------------\n\n // Replace providers.tsx with Pro version (AuthProvider, Pro component registration)\n // Pro integrates into the App Router layout — NOT the Pages Router _app.tsx.\n // Putting _app.tsx in pages/ triggers Next.js 16 Pages Router mode which fails\n // on missing _document (see swp-srp / GH scaffold smoke test).\n await copyProTemplate(\n 'pro-providers.tsx',\n path.join(targetDir, 'app', '_components', 'providers.tsx')\n );\n\n // Add root content.yml for the home page\n // Goes in pages/ for Stackwright's content system — this is a YAML data file,\n // not a Next.js page module, so it does NOT trigger Pages Router mode.\n await copyProTemplate('content.yml', path.join(targetDir, 'pages', 'content.yml'));\n\n // Replace next.config.js with Pro version (transpile pro pkgs)\n await copyProTemplate('next.config.js', path.join(targetDir, 'next.config.js'));\n\n // Add lib/mock-auth.ts\n await fs.ensureDir(path.join(targetDir, 'lib'));\n await copyProTemplate('mock-auth.ts', path.join(targetDir, 'lib', 'mock-auth.ts'));\n\n // Add yaml.d.ts for TypeScript support\n await copyProTemplate('yaml.d.ts', path.join(targetDir, 'yaml.d.ts'));\n\n // Add scripts/prebuild.js + scripts/pro-content-plugin.js\n await fs.ensureDir(path.join(targetDir, 'scripts'));\n await copyProTemplate('prebuild.js', path.join(targetDir, 'scripts', 'prebuild.js'));\n await copyProTemplate(\n 'scripts/pro-content-plugin.js',\n path.join(targetDir, 'scripts', 'pro-content-plugin.js')\n );\n\n // Override app/[...slug]/page.tsx with Pro version that filters _-prefixed data-sink slugs.\n // The OSS scaffold's generateStackwrightStaticParams returns _auth.json, _collections.json,\n // etc. as routes (they're in public/stackwright-content/ but not in RESERVED_FILES).\n // The Pro version wraps that function to filter them out.\n await fs.ensureDir(path.join(targetDir, 'app', '[...slug]'));\n await copyProTemplate(\n 'app/slug-page/page.tsx',\n path.join(targetDir, 'app', '[...slug]', 'page.tsx')\n );\n\n console.log(chalk.green(' Auth integration added (App Router providers + RBAC)'));\n\n // ------------------------------------------------------------------\n // 3. Add auth section to stackwright.yml\n // ------------------------------------------------------------------\n\n await addAuthToStackwrightYml(targetDir);\n\n // ------------------------------------------------------------------\n // 4. Handle --spec if provided\n // ------------------------------------------------------------------\n\n let specInfo: { specFilename: string; derivedName: string } | null = null;\n const MOCK_URL = 'http://localhost:4010';\n\n if (options.spec && options.spec.length > 0) {\n for (const specPath of options.spec) {\n specInfo = await handleSpec(targetDir, specPath, options.specName);\n await addIntegrationToStackwrightYml(\n targetDir,\n specInfo.derivedName,\n specInfo.specFilename,\n options.mock ? MOCK_URL : undefined\n );\n }\n console.log(chalk.green(`📡 ${options.spec.length} OpenAPI integration(s) wired up`));\n if (options.mock) {\n console.log(chalk.green('🎭 Prism mock server configured'));\n }\n } else if (options.mock) {\n // --mock without --spec: use sample Petstore spec for demo\n console.log(\n chalk.yellow(\n '⚠️ No spec provided with --mock. Using sample Petstore spec for demo. Replace with your API spec.'\n )\n );\n\n const specsDir = path.join(targetDir, 'specs');\n await fs.ensureDir(specsDir);\n await copyProTemplate('petstore.yaml', path.join(specsDir, 'petstore.yaml'));\n\n specInfo = { specFilename: 'petstore.yaml', derivedName: 'petstore' };\n\n await addIntegrationToStackwrightYml(\n targetDir,\n specInfo.derivedName,\n specInfo.specFilename,\n MOCK_URL\n );\n console.log(chalk.green('📡 Sample Petstore spec wired up'));\n console.log(chalk.green('🎭 Prism mock server configured'));\n }\n\n // ------------------------------------------------------------------\n // 5. Generate README\n // ------------------------------------------------------------------\n\n const readmeContent = generateReadme({\n projectName: options.name || dirName,\n hasSpec: !!specInfo,\n ...(specInfo?.derivedName !== undefined && { specName: specInfo.derivedName }),\n ...(specInfo?.specFilename !== undefined && { specFilename: specInfo.specFilename }),\n hasOtters: !options.skipOtters,\n hasMock: !!options.mock,\n });\n\n await fs.writeFile(path.join(targetDir, 'README.md'), readmeContent);\n console.log(chalk.green('📄 README.md created'));\n\n // ------------------------------------------------------------------\n // 5b. Write init-context.json for raft launcher\n // ------------------------------------------------------------------\n\n const initContext: Record<string, unknown> = {\n projectRoot: targetDir,\n projectName: options.name || dirName,\n generatedBy: 'launch-stackwright-pro',\n version: '1.0',\n };\n\n if (specInfo) {\n initContext.specPath = `specs/${specInfo.specFilename}`;\n initContext.specName = specInfo.derivedName;\n }\n\n initContext.theme = options.theme || 'corporate';\n\n const stackwrightDir = path.join(targetDir, '.stackwright');\n await fs.ensureDir(stackwrightDir);\n await fs.writeFile(\n path.join(stackwrightDir, 'init-context.json'),\n JSON.stringify(initContext, null, 2) + '\\n',\n 'utf-8'\n );\n\n // ------------------------------------------------------------------\n // 5c. Scaffold .code_puppy/ workspace directory\n // Creates config.json (projectOnly: true), mcp_servers.json,\n // and agents/ dir. raft-puppy discovers this via walk-up from cwd\n // on first startup — no CLI flags needed.\n // ------------------------------------------------------------------\n\n await scaffoldWorkspaceConfig(targetDir);\n console.log(chalk.green('🐾 .code_puppy/ workspace scaffolded (projectOnly: true)'));\n\n // ------------------------------------------------------------------\n // 6. Print next steps\n // ------------------------------------------------------------------\n\n const relDir = path.relative(process.cwd(), targetDir) || '.';\n\n console.log(chalk.cyan.bold(\"\\n🎉 All set! Here's what to do next:\\n\"));\n console.log(chalk.white(` 1. cd ${relDir}`));\n console.log(chalk.white(' 2. npx @stackwright-pro/raft'));\n console.log(chalk.dim(' (use --verbose for troubleshooting)'));\n\n if (specInfo) {\n console.log(chalk.cyan(`\\n📡 Your API spec was copied to specs/${specInfo.specFilename}`));\n console.log(chalk.dim(' The prebuild will generate types & client on first `pnpm dev`.'));\n }\n\n if (options.mock) {\n console.log(chalk.cyan('\\n🎭 Run with mock server:'));\n console.log(chalk.white(' pnpm dev:mock # Starts Prism + Next.js'));\n }\n\n if (!options.skipOtters) {\n console.log(chalk.cyan.bold('\\n🦦 The otter raft is ready to build your site!'));\n console.log(chalk.dim(' Run the command above to get started.\\n'));\n }\n}\n\n// ---------------------------------------------------------------------------\n// CLI definition\n// ---------------------------------------------------------------------------\n\nasync function main(): Promise<void> {\n const program = new Command();\n\n program\n .name('launch-stackwright-pro')\n .description('🚢 Launch a new Stackwright Pro project with auth, OpenAPI, and the otter raft')\n .version(version)\n .argument('[directory]', 'Project directory', '.')\n .option('--name <name>', 'Project name (used in package.json)')\n .option('--title <title>', 'Site title shown in the app bar and browser tab')\n .option('--theme <themeId>', 'Theme ID (e.g., corporate, creative, minimal)')\n .option('--force', 'Launch even if the target directory is not empty')\n .option('--skip-otters', 'Skip copying otter raft configs')\n .option('-y, --yes', 'Skip all prompts, use defaults')\n .option('--mock', 'Configure Prism mock server for API development (runs on port 4010)')\n .option(\n '--spec <paths...>',\n 'Paths to OpenAPI specs (YAML or JSON) — copies into project and wires up integrations (can be specified multiple times)'\n )\n .option(\n '--spec-name <name>',\n 'Name for the API integration (default: derived from spec filename)'\n )\n .option(\n '--skip-install',\n 'Skip automatic pnpm install (useful in CI or when using a different package manager)'\n )\n .action(async (directory: string, options: LaunchProOptions) => {\n const homeDir = os.homedir();\n const targetDir =\n directory !== '.'\n ? path.resolve(process.cwd(), directory)\n : options.name\n ? path.resolve(process.cwd(), options.name)\n : process.cwd(); // last resort — same as old behaviour, only hit if neither arg nor --name\n\n // Warn (don't block) when scaffolding outside home dir — unusual for a user-facing CLI\n if (!targetDir.startsWith(homeDir + path.sep) && targetDir !== homeDir) {\n console.warn(chalk.yellow(`⚠️ Scaffolding outside your home directory: ${targetDir}`));\n }\n\n await launch(targetDir, options);\n });\n\n await program.parseAsync(process.argv);\n}\n\nmain().catch((err: unknown) => {\n console.error(chalk.red('\\n❌ Launch failed:'), err);\n process.exit(1);\n});\n","/**\n * scaffold.ts — Pro-specific scaffold mutation helpers\n *\n * Extracted from src/index.ts so these pure filesystem transforms can be\n * imported and tested independently (no __dirname, no fs.copy, no chalk).\n *\n * Every function here:\n * - Accepts a targetDir and operates on real files\n * - Is async/await throughout\n * - Has no side effects beyond writing to targetDir\n * - Is fully unit-testable with a real temp filesystem\n */\n\nimport fs from 'fs-extra';\nimport yaml from 'js-yaml';\nimport path from 'path';\nimport { PRO_VERSIONS, OSS_VERSIONS } from './generated/workspace-versions.js';\n\n// ---------------------------------------------------------------------------\n// Package.json mutations\n// ---------------------------------------------------------------------------\n\n/**\n * Inject Pro runtime dependencies and scripts into an existing package.json.\n * Enforces OSS version floors and adds Pro-specific dev scripts (prebuild/predev).\n * Safe to call multiple times — idempotent for dep keys.\n */\nexport async function addProDepsToPackageJson(targetDir: string): Promise<void> {\n const pkgPath = path.join(targetDir, 'package.json');\n const content = await fs.readFile(pkgPath, 'utf-8');\n const pkg = JSON.parse(content) as Record<string, unknown>;\n\n const dependencies: Record<string, string> =\n typeof pkg.dependencies === 'object' && pkg.dependencies !== null\n ? { ...(pkg.dependencies as Record<string, string>) }\n : {};\n const devDependencies: Record<string, string> =\n typeof pkg.devDependencies === 'object' && pkg.devDependencies !== null\n ? { ...(pkg.devDependencies as Record<string, string>) }\n : {};\n const scripts: Record<string, string> =\n typeof pkg.scripts === 'object' && pkg.scripts !== null\n ? { ...(pkg.scripts as Record<string, string>) }\n : {};\n\n // Enforce OSS version floors — replace workspace:* refs AND upgrade any stale version\n // pinned by the OSS scaffold template to our tested minimum.\n // OSS_VERSIONS = \"minimum tested versions\" — we always want them to win.\n for (const [pkgName, pinnedVersion] of Object.entries(OSS_VERSIONS)) {\n if (pkgName in dependencies) {\n dependencies[pkgName] = pinnedVersion;\n }\n if (pkgName in devDependencies) {\n devDependencies[pkgName] = pinnedVersion;\n }\n }\n\n // Pro runtime dependencies — exact versions from workspace at build time\n Object.assign(dependencies, {\n '@stackwright-pro/auth': PRO_VERSIONS['@stackwright-pro/auth'],\n '@stackwright-pro/auth-nextjs': PRO_VERSIONS['@stackwright-pro/auth-nextjs'],\n '@stackwright-pro/build-scripts-plugins':\n PRO_VERSIONS['@stackwright-pro/build-scripts-plugins'],\n '@stackwright-pro/display-components': PRO_VERSIONS['@stackwright-pro/display-components'],\n '@stackwright-pro/mcp': PRO_VERSIONS['@stackwright-pro/mcp'],\n '@stackwright-pro/openapi': PRO_VERSIONS['@stackwright-pro/openapi'],\n '@stackwright-pro/otters': PRO_VERSIONS['@stackwright-pro/otters'],\n '@stackwright-pro/pulse': PRO_VERSIONS['@stackwright-pro/pulse'],\n '@stackwright-pro/workflow': PRO_VERSIONS['@stackwright-pro/workflow'],\n '@stackwright-pro/workflow-components': PRO_VERSIONS['@stackwright-pro/workflow-components'],\n '@stackwright/build-scripts': OSS_VERSIONS['@stackwright/build-scripts'],\n zod: '^4.0.0',\n });\n\n // Pro dev dependencies\n Object.assign(devDependencies, {\n '@stoplight/prism-cli': '^5.15.10',\n });\n\n // Role-based dev scripts\n Object.assign(scripts, {\n 'dev:admin': 'MOCK_USER=admin next dev',\n 'dev:analyst': 'MOCK_USER=analyst next dev',\n 'dev:viewer': 'MOCK_USER=viewer next dev',\n prebuild: 'node scripts/prebuild.js',\n predev: 'node scripts/prebuild.js',\n });\n\n pkg.dependencies = dependencies;\n pkg.devDependencies = devDependencies;\n pkg.scripts = scripts;\n\n await fs.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\\n', 'utf-8');\n}\n\n// ---------------------------------------------------------------------------\n// stackwright.yml mutations\n// ---------------------------------------------------------------------------\n\n/**\n * Add an empty `auth:` key to an existing stackwright.yml.\n * The auth key is the hook point for Pro RBAC configuration.\n */\nexport async function addAuthToStackwrightYml(targetDir: string): Promise<void> {\n const ymlPath = path.join(targetDir, 'stackwright.yml');\n const content = await fs.readFile(ymlPath, 'utf-8');\n const config = yaml.load(content, { schema: yaml.CORE_SCHEMA }) as Record<string, unknown>;\n\n config.auth = {};\n\n await fs.writeFile(ymlPath, yaml.dump(config, { lineWidth: 120 }));\n}\n\n/**\n * Append an OpenAPI integration entry to the `integrations:` array in stackwright.yml.\n * Creates the array if it does not exist. Safe to call multiple times for different specs.\n */\nexport async function addIntegrationToStackwrightYml(\n targetDir: string,\n specName: string,\n specFilename: string,\n mockUrl?: string\n): Promise<void> {\n const ymlPath = path.join(targetDir, 'stackwright.yml');\n const content = await fs.readFile(ymlPath, 'utf-8');\n const config = yaml.load(content, { schema: yaml.CORE_SCHEMA }) as Record<string, unknown>;\n\n const integration: Record<string, unknown> = {\n type: 'openapi',\n name: specName,\n spec: `./specs/${specFilename}`,\n collections: [],\n };\n\n if (mockUrl) {\n integration.mockUrl = mockUrl;\n }\n\n config.integrations = [\n ...(Array.isArray(config.integrations) ? config.integrations : []),\n integration,\n ];\n\n await fs.writeFile(ymlPath, yaml.dump(config, { lineWidth: 120 }));\n}\n\n// ---------------------------------------------------------------------------\n// .code_puppy/ workspace config scaffolding\n// ---------------------------------------------------------------------------\n\n/**\n * Create (or idempotently update) the .code_puppy/ workspace directory.\n *\n * Creates:\n * - .code_puppy/config.json { projectOnly: true } (merges with existing)\n * - .code_puppy/mcp_servers.json stackwright-pro-mcp stdio server entry\n * - .code_puppy/agents/ empty directory for future agent configs\n *\n * Symlink guard: refuses to write if any of the managed paths is a symlink,\n * consistent with raft/src/lib.ts ensureWorkspaceConfig.\n */\nexport async function scaffoldWorkspaceConfig(targetDir: string): Promise<void> {\n const workspaceDir = path.join(targetDir, '.code_puppy');\n await fs.ensureDir(workspaceDir);\n // Symlink guard — consistent with raft/src/lib.ts ensureWorkspaceConfig\n const workspaceStats = await fs.lstat(workspaceDir);\n if (workspaceStats.isSymbolicLink()) {\n throw new Error('.code_puppy/ is a symlink — refusing to write. Check for tampering.');\n }\n\n const agentsDir = path.join(workspaceDir, 'agents');\n await fs.ensureDir(agentsDir);\n if (await fs.pathExists(agentsDir)) {\n const agentsStats = await fs.lstat(agentsDir);\n if (agentsStats.isSymbolicLink()) {\n throw new Error('.code_puppy/agents is a symlink — refusing to write. Check for tampering.');\n }\n }\n\n // config.json — projectOnly: true\n // Merge with existing so we don't clobber user customizations on re-scaffold\n const configPath = path.join(workspaceDir, 'config.json');\n let existingConfig: Record<string, unknown> = {};\n if (fs.existsSync(configPath)) {\n try {\n existingConfig = JSON.parse(await fs.readFile(configPath, 'utf-8')) as Record<\n string,\n unknown\n >;\n } catch {\n // Malformed — start fresh\n }\n }\n if (await fs.pathExists(configPath)) {\n const configStats = await fs.lstat(configPath);\n if (configStats.isSymbolicLink()) {\n throw new Error(\n '.code_puppy/config.json is a symlink — refusing to write. Check for tampering.'\n );\n }\n }\n await fs.writeFile(\n configPath,\n JSON.stringify({ ...existingConfig, projectOnly: true }, null, 2) + '\\n',\n 'utf-8'\n );\n\n // mcp_servers.json — pnpm-based stackwright-pro-mcp server\n // ${PROJECT_ROOT} is a literal — raft-puppy expands it at runtime to the\n // directory containing .code_puppy/ (walk-up discovery root).\n const mcpServersPath = path.join(workspaceDir, 'mcp_servers.json');\n if (await fs.pathExists(mcpServersPath)) {\n const mcpStats = await fs.lstat(mcpServersPath);\n if (mcpStats.isSymbolicLink()) {\n throw new Error(\n '.code_puppy/mcp_servers.json is a symlink — refusing to write. Check for tampering.'\n );\n }\n }\n if (!fs.existsSync(mcpServersPath)) {\n const mcpConfig = {\n mcp_servers: {\n 'stackwright-pro-mcp': {\n type: 'stdio',\n command: 'pnpm',\n args: ['exec', 'stackwright-pro-mcp'],\n enabled: true,\n cwd: '${PROJECT_ROOT}',\n },\n },\n };\n await fs.writeFile(mcpServersPath, JSON.stringify(mcpConfig, null, 2) + '\\n', 'utf-8');\n }\n}\n\n// ---------------------------------------------------------------------------\n// README generation\n// ---------------------------------------------------------------------------\n\nexport interface GenerateReadmeOptions {\n projectName: string;\n hasSpec: boolean;\n specName?: string;\n specFilename?: string;\n hasOtters: boolean;\n hasMock: boolean;\n}\n\n/**\n * Generate a project README.md with conditional sections based on which\n * Pro features are enabled (spec, mock server, otter raft).\n */\nexport function generateReadme(options: GenerateReadmeOptions): string {\n const { projectName, hasSpec, specName, specFilename, hasOtters, hasMock } = options;\n\n // Build API Integration section if spec is present\n const apiIntegrationSection = hasSpec\n ? `## 📡 API Integration\\n\\nYour OpenAPI spec was copied to \\`specs/${specFilename}\\` and wired up in \\`stackwright.yml\\`.\\n\\n**What gets generated:**\\n\\n\\`\\`\\`typescript\\n// src/generated/${specName}/schemas.ts\\nexport const EquipmentSchema = z.object({\\n id: z.string(),\\n name: z.string(),\\n status: z.enum(['operational', 'maintenance', 'retired']),\\n // ... Zod validation for runtime safety\\n});\\n\\n// src/generated/${specName}/types.ts\\nexport type Equipment = z.infer<typeof EquipmentSchema>;\\n\\n// src/generated/${specName}/client.ts\\nexport class ${(specName ?? 'api').charAt(0).toUpperCase() + (specName ?? 'api').slice(1)}Client {\\n async getEquipment(id: string): Promise<Equipment> {\\n // Auto-wired with auth, validation, error handling\\n }\\n}\\n\\`\\`\\`\\n\\n**How it works:**\\n1. The \\`predev\\` script in \\`package.json\\` runs \\`prebuild.js\\` before every \\`pnpm dev\\`\\n2. Prebuild reads your spec and generates type-safe code\\n3. You import and use it:\\n\\n\\`\\`\\`typescript\\nimport { ${(specName ?? 'api').charAt(0).toUpperCase() + (specName ?? 'api').slice(1)}Client } from '@/generated/${specName}/client';\\nimport type { Equipment } from '@/generated/${specName}/types';\\n\\nconst client = new ${(specName ?? 'api').charAt(0).toUpperCase() + (specName ?? 'api').slice(1)}Client();\\nconst gear: Equipment = await client.getEquipment('123');\\n\\`\\`\\`\\n\\nNo manual typing. No drift. No runtime surprises.\\n\\n`\n : '';\n\n // Build mock server section if enabled\n const mockSection = hasMock\n ? `## 🎭 Mock Server\\n\\nPrism mock server is configured to serve your API at **http://localhost:4010**.\\n\\n\\`\\`\\`bash\\npnpm dev:mock # Starts Prism + Next.js together\\n\\`\\`\\`\\n\\nThis starts:\\n1. Prism mock server on port 4010 (serves your OpenAPI spec)\\n2. Next.js dev server on port 3000\\n\\nThe generated API client is automatically configured to use the mock server.\\n\\n`\n : '';\n\n // Build AI Agents section if otters are present\n const aiAgentsSection = hasOtters\n ? `## 🦦 AI Agents (The Otter Raft)\\n\\nYour project includes **SIX specialized AI agents** in \\`node_modules/@stackwright-pro/otters/\\`:\\n\\n- \\`stackwright-pro-foreman-otter\\` - Master coordinator that orchestrates all specialist otters\\n- \\`stackwright-pro-api-otter\\` - Discovers entities from OpenAPI specs\\n- \\`stackwright-pro-auth-otter\\` - Configures CAC/OIDC auth, RBAC rules, and audit middleware\\n- \\`stackwright-pro-data-otter\\` - Configures endpoint filters & ISR revalidation\\n- \\`stackwright-pro-page-otter\\` - Generates pages auto-wired with data, theme, and auth\\n- \\`stackwright-pro-dashboard-otter\\` - Builds live data dashboards\\n\\n**Start the otter raft:**\\n\\n\\`\\`\\`bash\\nnpx @stackwright-pro/raft\\n\\`\\`\\`\\n\\nThe raft verifies otter integrity, writes project context, and spawns code-puppy in foreman mode. The foreman asks questions about your brand, auth, and data preferences, then coordinates specialist otters to build your app. All state lives in \\`.stackwright/\\` — interrupt and resume anytime.\\n\\n**Example session prompt:**\\n\\n\"Build me a logistics dashboard from our OpenAPI spec. Connect to /equipment and /supplies endpoints.\"\\n\\n`\n : '';\n\n return `# ${projectName}\\n\\nA Stackwright Pro application with role-based auth, OpenAPI integration, and intelligent AI agents.\\n\\n## 🚀 Quick Start\\n\\n\\`\\`\\`bash\\n# Start development server\\npnpm dev\\n\\n# Open your browser\\nopen http://localhost:3000\\n\\`\\`\\`\\n\\n## 👥 Role-Based Development\\n\\nStackwright Pro includes **mock authentication** for local development with three pre-configured roles:\\n\\n\\`\\`\\`bash\\npnpm dev:admin # Full permissions (*)\\npnpm dev:analyst # Read & write data\\npnpm dev:viewer # Read-only access\\n\\`\\`\\`\\n\\n**How it works:**\\n- Each script sets the \\`MOCK_USER\\` environment variable\\n- \\`lib/mock-auth.ts\\` intercepts requests and injects the appropriate user context\\n- Your pages & API routes respect the RBAC rules in \\`stackwright.yml\\`\\n- No backend required for testing auth flows! 🎉\\n\\n**Pro tip:** Test your UI for all three roles to ensure proper permissions enforcement.\\n\\n${mockSection}## 📁 Project Structure\\n\\n\\`\\`\\`\\n.\\n├── app/\\n│ ├── layout.tsx # Root layout (StackwrightLayout + Providers)\\n│ ├── page.tsx # Home page (renders root content)\\n│ ├── [...slug]/\\n│ │ └── page.tsx # Dynamic pages from YAML content\\n│ └── _components/\\n│ ├── providers.tsx # Pro: AuthProvider + component registration\\n│ └── page-client.tsx # Client-side page renderer\\n├── pages/\\n│ └── content.yml # Root page content in YAML\\n├── lib/\\n│ └── mock-auth.ts # Dev-only auth mocking (no backend needed)\\n├── scripts/\\n│ └── prebuild.js # Auto-generates code from OpenAPI specs\\n├── specs/ # OpenAPI spec files (if --spec was used)\\n├── src/\\n│ └── generated/ # Auto-generated types & clients\\n│ └── {specName}/\\n│ ├── schemas.ts # Zod schemas for runtime validation\\n│ ├── types.ts # TypeScript types\\n│ ├── client.ts # API client with auth\\n│ └── provider.ts # CollectionProvider for Stackwright\\n├── .stackwright/\\n│ └── otters/ # AI agent configs (4 specialized otters)\\n├── stackwright.yml # Theme, auth, API integrations\\n└── package.json\\n\\`\\`\\`\\n\\n**Key Files:**\\n- \\`app/_components/providers.tsx\\` - Wraps your app with \\`AuthProvider\\` for RBAC\\n- \\`stackwright.yml\\` - Single source of truth for theme, auth roles, and API wiring\\n- \\`lib/mock-auth.ts\\` - Mocks CAC/PIV headers locally so you can test auth flows\\n- \\`scripts/prebuild.js\\` - Runs before dev/build to generate types from your OpenAPI spec\\n\\n## 📄 Adding Pages\\n\\nStackwright uses **YAML for content**, so you never touch JSX unless you want to.\\n\\n**Example:** Create \\`pages/about/content.yml\\`:\\n\\n\\`\\`\\`yaml\\ntitle: About Us\\ndescription: Learn more about our mission\\n\\nsections:\\n - type: main\\n heading: Who We Are\\n body: |\\n We build mission-critical logistics systems for the Marine Corps.\\n\\n - type: feature_list\\n title: Our Capabilities\\n features:\\n - icon: Security\\n title: Zero Trust\\n description: PKI-based auth with CAC/PIV\\n - icon: Api\\n title: Real-time Data\\n description: OpenAPI-backed, Zod-validated\\n\\`\\`\\`\\n\\nThat's it. Navigate to \\`/about\\` and it just works. No routing config, no React components.\\n\\n${apiIntegrationSection}## 🎨 Customizing Theme\\n\\nEdit \\`stackwright.yml\\` to change colors, fonts, spacing — applies everywhere instantly.\\n\\n\\`\\`\\`yaml\\ntheme:\\n id: my-theme\\n name: My Custom Theme\\n colors:\\n primary: \"#C41E3A\" # Marine Corps red\\n background: \"#FFFFFF\"\\n text: \"#1A1A1A\"\\n accent: \"#FFD700\" # Gold\\n typography:\\n fontFamily: \"'Inter', sans-serif\"\\n h1Size: \"2.5rem\"\\n spacing:\\n unit: 8\\n\\`\\`\\`\\n\\nNo CSS files. No theme provider boilerplate. Just YAML. Stackwright handles the rest.\\n\\n## 🔐 Auth Configuration\\n\\nStackwright Pro comes with **3 pre-configured roles** in \\`stackwright.yml\\`:\\n\\n\\`\\`\\`yaml\\nauth:\\n roles:\\n - name: ADMIN\\n permissions: ['*'] # Full access\\n - name: ANALYST \\n permissions: ['data:read', 'data:write'] # Read/write data\\n - name: VIEWER\\n permissions: ['data:read'] # Read-only\\n\\`\\`\\`\\n\\n**Gate content in your YAML:**\\n\\n\\`\\`\\`yaml\\nsections:\\n - type: button\\n label: Delete Equipment\\n action: /api/equipment/delete\\n auth:\\n required_roles: [ADMIN]\\n fallback: hide # Options: hide, disable, show_message\\n\\`\\`\\`\\n\\nOnly admins see the button. Analysts and viewers? Button doesn't exist in the DOM.\\n\\n**Route protection:**\\n\\n\\`\\`\\`yaml\\nauth:\\n protected_routes:\\n - path: /admin/*\\n roles: [ADMIN]\\n - path: /equipment/* \\n roles: [ANALYST, ADMIN]\\n public_routes:\\n - /\\n - /about\\n\\`\\`\\`\\n\\nNo middleware to write. No useAuth hooks to remember. RBAC is declarative.\\n\\n${aiAgentsSection}## 📚 Learn More\\n\\n- **Stackwright Docs:** [https://stackwright.dev](https://stackwright.dev)\\n- **OSS Repo:** [https://github.com/Per-Aspera-LLC/stackwright](https://github.com/Per-Aspera-LLC/stackwright)\\n- **Pro Repo:** [https://github.com/Per-Aspera-LLC/stackwright-pro](https://github.com/Per-Aspera-LLC/stackwright-pro)\\n\\n**Questions?** File an issue or ping us in the discussions. We're here to help you ship faster.\\n`;\n}\n","// AUTO-GENERATED — do not edit manually.\n// Run `pnpm sync-versions` or `pnpm build` to regenerate.\n//\n// PRO_VERSIONS: exact versions of @stackwright-pro/* packages in this workspace.\n// OSS_VERSIONS: minimum tested versions of @stackwright/* OSS packages (caret range).\n\n/**\n * Exact versions of every @stackwright-pro/* package currently in the workspace.\n * Used by launch-stackwright-pro and scaffold-hooks to pin deps in scaffolded projects.\n * Updated automatically on every build — never edit this file by hand.\n */\nexport const PRO_VERSIONS = {\n '@stackwright-pro/auth': '0.2.0-alpha.21',\n '@stackwright-pro/auth-nextjs': '0.3.0-alpha.10',\n '@stackwright-pro/build-scripts-plugins': '0.1.0-alpha.3',\n '@stackwright-pro/display-components': '0.2.0-alpha.11',\n '@stackwright-pro/mcp': '0.2.0-alpha.95',\n '@stackwright-pro/openapi': '0.3.0-alpha.34',\n '@stackwright-pro/otters': '1.0.0-alpha.62',\n '@stackwright-pro/pulse': '0.3.0-alpha.29',\n '@stackwright-pro/workflow': '0.1.0-alpha.24',\n '@stackwright-pro/workflow-components': '0.1.0-alpha.26',\n} as const satisfies Record<string, string>;\n\n/**\n * Minimum tested versions of @stackwright/* OSS packages.\n * Caret ranges anchored to the last version resolved in pnpm-lock.yaml.\n * Updated automatically on every build.\n */\nexport const OSS_VERSIONS = {\n '@stackwright/build-scripts': '0.10.0-alpha.0',\n '@stackwright/collections': '^0.1.2',\n '@stackwright/core': '^0.10.0',\n '@stackwright/icons': '^0.5.2',\n '@stackwright/mcp': '^0.5.0',\n '@stackwright/nextjs': '^0.6.0',\n '@stackwright/otters': '^0.2.2',\n '@stackwright/types': '^1.7.0',\n '@stackwright/ui-shadcn': '^0.1.3',\n} as const satisfies Record<string, string>;\n"],"mappings":"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","names":["exports","module","import_path","import_fs_extra","path","fs","yaml","path","fs","chalk","os"]}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackwright-pro/launch-stackwright-pro",
|
|
3
|
-
"version": "0.4.0-alpha.
|
|
3
|
+
"version": "0.4.0-alpha.133",
|
|
4
4
|
"description": "Launch a new Stackwright Pro project with OpenAPI integration, auth, and the otter raft",
|
|
5
|
-
"license": "
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
@@ -26,26 +26,26 @@
|
|
|
26
26
|
"launch-stackwright-pro": "dist/index.js"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@stackwright
|
|
30
|
-
"@stackwright/
|
|
31
|
-
"@stackwright/scaffold-core": "^0.1.0",
|
|
29
|
+
"@stackwright/cli": "^0.9.0",
|
|
30
|
+
"@stackwright/scaffold-core": "^0.3.3",
|
|
32
31
|
"chalk": "^5.6.2",
|
|
33
|
-
"commander": "^
|
|
34
|
-
"fs-extra": "^11.3",
|
|
35
|
-
"js-yaml": "^4.
|
|
36
|
-
"@stackwright-pro/auth": "0.
|
|
37
|
-
"@stackwright-pro/auth-nextjs": "0.
|
|
38
|
-
"@stackwright-pro/mcp": "0.2.0-alpha.
|
|
39
|
-
"@stackwright-pro/openapi": "0.
|
|
40
|
-
"@stackwright-pro/otters": "1.0.0-alpha.
|
|
32
|
+
"commander": "^15.0.0",
|
|
33
|
+
"fs-extra": "^11.3.5",
|
|
34
|
+
"js-yaml": "^4.2.0",
|
|
35
|
+
"@stackwright-pro/auth": "0.2.0-alpha.21",
|
|
36
|
+
"@stackwright-pro/auth-nextjs": "0.3.0-alpha.10",
|
|
37
|
+
"@stackwright-pro/mcp": "0.2.0-alpha.95",
|
|
38
|
+
"@stackwright-pro/openapi": "0.3.0-alpha.34",
|
|
39
|
+
"@stackwright-pro/otters": "1.0.0-alpha.62",
|
|
40
|
+
"@stackwright-pro/scaffold-hooks": "1.0.0-alpha.16"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/fs-extra": "^11.0",
|
|
44
44
|
"@types/js-yaml": "^4.0.9",
|
|
45
|
-
"@types/node": "^
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"vitest": "^4.
|
|
45
|
+
"@types/node": "^25.9.2",
|
|
46
|
+
"tsup": "^8.5.1",
|
|
47
|
+
"typescript": "^6.0.3",
|
|
48
|
+
"vitest": "^4.1.8"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "node ../../scripts/sync-versions.mjs && tsup",
|
package/templates/pro/_app.tsx
CHANGED
|
@@ -6,7 +6,17 @@ import { registerDisplayComponents } from '@stackwright-pro/display-components';
|
|
|
6
6
|
import { registerPulseComponents } from '@stackwright-pro/pulse';
|
|
7
7
|
import { AuthProvider } from '@stackwright-pro/auth';
|
|
8
8
|
import '@stackwright/ui-shadcn/styles.css';
|
|
9
|
-
import
|
|
9
|
+
import authConfigRaw from '../src/auth-config.json'; // Generated at build time by prebuild.js
|
|
10
|
+
|
|
11
|
+
// auth-config.json is written from stackwright.yml `auth:` section — it may be
|
|
12
|
+
// sparse (e.g. `{}`) when roles haven't been configured yet, so we cast to the
|
|
13
|
+
// full shape and use || fallbacks below.
|
|
14
|
+
type AuthConfigShape = {
|
|
15
|
+
roles?: Array<{ name: string; permissions?: string[] }>;
|
|
16
|
+
protected_routes?: Array<{ path: string; roles: string[] }>;
|
|
17
|
+
public_routes?: string[];
|
|
18
|
+
};
|
|
19
|
+
const authConfig = authConfigRaw as AuthConfigShape;
|
|
10
20
|
|
|
11
21
|
// Register Stackwright components
|
|
12
22
|
registerNextJSComponents();
|
|
@@ -24,9 +34,9 @@ export default function App({ Component, pageProps }: AppProps) {
|
|
|
24
34
|
user={user}
|
|
25
35
|
session={session}
|
|
26
36
|
rbacConfig={{
|
|
27
|
-
roles: authConfig.roles
|
|
28
|
-
protected_routes: authConfig.protected_routes
|
|
29
|
-
public_routes: authConfig.public_routes
|
|
37
|
+
roles: authConfig.roles ?? [],
|
|
38
|
+
protected_routes: authConfig.protected_routes ?? [],
|
|
39
|
+
public_routes: authConfig.public_routes ?? [],
|
|
30
40
|
}}
|
|
31
41
|
>
|
|
32
42
|
<Component {...pageProps} />
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
generateStackwrightStaticParams,
|
|
3
|
+
getStackwrightPageData,
|
|
4
|
+
} from '@stackwright/nextjs/server';
|
|
5
|
+
import { notFound } from 'next/navigation';
|
|
6
|
+
import { StackwrightPageClient } from '../_components/page-client';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Filter out data-sink slugs produced by Pro prebuild plugins (_auth, _collections,
|
|
10
|
+
* _integrations, etc.). These files live in public/stackwright-content/ but are NOT
|
|
11
|
+
* page content — they are runtime data consumed by middleware and providers.
|
|
12
|
+
*
|
|
13
|
+
* The OSS generateStackwrightStaticParams() returns them because the RESERVED_FILES
|
|
14
|
+
* list in @stackwright/nextjs predates Pro's additionalSinks (swp-xyia / OSS #509).
|
|
15
|
+
* Filtering here keeps the Pro scaffold correct until the OSS package syncs its list.
|
|
16
|
+
*/
|
|
17
|
+
function filterProDataSinks(params: Array<{ slug: string[] }>): Array<{ slug: string[] }> {
|
|
18
|
+
return params.filter(({ slug }) => {
|
|
19
|
+
// Top-level _ prefixed slugs are always internal data files, never pages
|
|
20
|
+
if (slug.length === 1 && slug[0] !== undefined && slug[0].startsWith('_')) return false;
|
|
21
|
+
return true;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const generateStaticParams = () => filterProDataSinks(generateStackwrightStaticParams());
|
|
26
|
+
|
|
27
|
+
export default async function SlugPage({ params }: { params: Promise<{ slug: string[] }> }) {
|
|
28
|
+
const { slug } = await params;
|
|
29
|
+
const pageData = await getStackwrightPageData(slug);
|
|
30
|
+
if (!pageData) notFound();
|
|
31
|
+
return <StackwrightPageClient content={pageData} />;
|
|
32
|
+
}
|
|
@@ -7,5 +7,5 @@ content:
|
|
|
7
7
|
textSize: h1
|
|
8
8
|
textColor: secondary
|
|
9
9
|
textBlocks:
|
|
10
|
-
- text: Welcome to your new Stackwright Pro project.
|
|
10
|
+
- text: Welcome to your new Stackwright Pro project. Run the otter raft to build your pages.
|
|
11
11
|
textSize: h6
|
|
@@ -13,6 +13,9 @@ module.exports = createStackwrightNextConfig({
|
|
|
13
13
|
'@stackwright-pro/auth',
|
|
14
14
|
'@stackwright-pro/auth-nextjs',
|
|
15
15
|
'@stackwright-pro/display-components',
|
|
16
|
+
'@stackwright-pro/pulse',
|
|
17
|
+
'@stackwright-pro/workflow',
|
|
18
|
+
'@stackwright-pro/workflow-components',
|
|
16
19
|
],
|
|
17
20
|
// YAML is parsed server-side at build time - no loader needed in browser
|
|
18
21
|
});
|
|
@@ -1,105 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Stackwright Pro prebuild script
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Thin wrapper around @stackwright/build-scripts runPrebuild() with the
|
|
5
|
+
* Pro plugin bundle. All theme/auth/collections/integrations data flows
|
|
6
|
+
* through the per-otter sibling YAML files (stackwright.theme.yml,
|
|
7
|
+
* stackwright.auth.yml, stackwright.collections.yml, stackwright.integrations.yml).
|
|
8
|
+
*
|
|
9
|
+
* Each domain otter calls its own `stackwright_pro_compile_*` MCP tool
|
|
10
|
+
* immediately after writing its source YAML — this script is the
|
|
11
|
+
* "compile everything from scratch" entry point invoked by predev/prebuild.
|
|
7
12
|
*/
|
|
13
|
+
'use strict';
|
|
8
14
|
|
|
9
|
-
const { spawn } = require('child_process');
|
|
10
|
-
const fs = require('fs');
|
|
11
15
|
const path = require('path');
|
|
12
|
-
const
|
|
13
|
-
const {
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Run stackwright-prebuild to generate _root.json, _site.json, etc.
|
|
17
|
-
*/
|
|
18
|
-
async function runStackwrightPrebuild(projectRoot) {
|
|
19
|
-
return new Promise((resolve, reject) => {
|
|
20
|
-
// Use pnpm exec to ensure we use the correct package manager
|
|
21
|
-
const proc = spawn(process.platform === 'win32' ? 'pnpm.cmd' : 'pnpm', ['exec', 'stackwright-prebuild'], {
|
|
22
|
-
cwd: projectRoot,
|
|
23
|
-
stdio: 'inherit',
|
|
24
|
-
shell: true,
|
|
25
|
-
});
|
|
26
|
-
proc.on('close', (code) => {
|
|
27
|
-
if (code === 0) {
|
|
28
|
-
resolve();
|
|
29
|
-
} else {
|
|
30
|
-
reject(new Error(`stackwright-prebuild exited with code ${code}`));
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
proc.on('error', reject);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Parse full stackwright.yml using js-yaml for complete config parsing
|
|
39
|
-
*/
|
|
40
|
-
function parseStackwrightYml(content) {
|
|
41
|
-
return yaml.load(content, { schema: yaml.CORE_SCHEMA });
|
|
42
|
-
}
|
|
16
|
+
const { runPrebuild } = require('@stackwright/build-scripts');
|
|
17
|
+
const { proPlugins } = require('@stackwright-pro/build-scripts-plugins');
|
|
43
18
|
|
|
44
19
|
async function main() {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Run stackwright-prebuild first to generate content JSON files
|
|
55
|
-
console.log('Generating content files...');
|
|
56
|
-
await runStackwrightPrebuild(projectRoot);
|
|
57
|
-
|
|
58
|
-
const configContent = fs.readFileSync(configPath, 'utf-8');
|
|
59
|
-
const fullConfig = parseStackwrightYml(configContent);
|
|
60
|
-
|
|
61
|
-
// Extract auth config and write as JSON for client-side use
|
|
62
|
-
if (fullConfig.auth) {
|
|
63
|
-
const authConfig = fullConfig.auth;
|
|
64
|
-
const srcDir = path.join(projectRoot, 'src');
|
|
65
|
-
|
|
66
|
-
if (!fs.existsSync(srcDir)) {
|
|
67
|
-
fs.mkdirSync(srcDir, { recursive: true });
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
fs.writeFileSync(
|
|
71
|
-
path.join(srcDir, 'auth-config.json'),
|
|
72
|
-
JSON.stringify(authConfig, null, 2)
|
|
73
|
-
);
|
|
74
|
-
console.log('✓ Generated src/auth-config.json');
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Extract integrations for OpenAPI plugin
|
|
78
|
-
const siteConfig = { integrations: fullConfig.integrations || [] };
|
|
79
|
-
|
|
80
|
-
if (!siteConfig.integrations.length) {
|
|
81
|
-
console.log('No integrations in stackwright.yml — skipping OpenAPI plugin.');
|
|
82
|
-
console.log('✓ Prebuild complete!');
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
console.log(`Found ${siteConfig.integrations.length} integration(s). Running OpenAPI plugin...`);
|
|
87
|
-
|
|
88
|
-
const plugin = createOpenAPIPlugin();
|
|
89
|
-
|
|
90
|
-
if (plugin.beforeBuild) {
|
|
91
|
-
await plugin.beforeBuild({
|
|
92
|
-
siteConfig,
|
|
93
|
-
projectRoot,
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
console.log('✓ Prebuild complete!');
|
|
98
|
-
} catch (error) {
|
|
99
|
-
console.error('Prebuild failed:', error.message);
|
|
100
|
-
console.error(error.stack);
|
|
101
|
-
process.exit(1);
|
|
102
|
-
}
|
|
20
|
+
const projectRoot = path.resolve(__dirname, '..');
|
|
21
|
+
await runPrebuild({
|
|
22
|
+
projectRoot,
|
|
23
|
+
plugins: proPlugins,
|
|
24
|
+
unknownContentTypes: 'warn',
|
|
25
|
+
});
|
|
26
|
+
console.log(' Prebuild complete!');
|
|
103
27
|
}
|
|
104
28
|
|
|
105
|
-
main()
|
|
29
|
+
main().catch((err) => {
|
|
30
|
+
console.error('Prebuild failed:', err.message);
|
|
31
|
+
console.error(err.stack);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { registerAppRouterComponents } from '@stackwright/nextjs/app-router';
|
|
3
|
+
import { registerShadcnComponents } from '@stackwright/ui-shadcn';
|
|
4
|
+
import { registerDefaultIcons } from '@stackwright/icons';
|
|
5
|
+
import { registerDisplayComponents } from '@stackwright-pro/display-components';
|
|
6
|
+
import { registerPulseComponents } from '@stackwright-pro/pulse';
|
|
7
|
+
import { AuthProvider } from '@stackwright-pro/auth/client';
|
|
8
|
+
import '@stackwright/ui-shadcn/styles.css';
|
|
9
|
+
// Generated by stackwright-prebuild. Run `pnpm predev` to regenerate when icons change.
|
|
10
|
+
// This file is safe to commit — it is updated deterministically from your YAML content.
|
|
11
|
+
import { registerSiteIcons } from '../../stackwright-generated/icons';
|
|
12
|
+
import authConfigRaw from '../../src/auth-config.json';
|
|
13
|
+
|
|
14
|
+
// auth-config.json is written from stackwright.yml `auth:` section by prebuild.js — it may be
|
|
15
|
+
// sparse (e.g. `{}`) when roles haven't been configured yet, so we cast to the full shape
|
|
16
|
+
// and use ?? fallbacks below.
|
|
17
|
+
type AuthConfigShape = {
|
|
18
|
+
roles?: Array<{ name: string; permissions?: string[] }>;
|
|
19
|
+
protected_routes?: Array<{ path: string; roles: string[] }>;
|
|
20
|
+
public_routes?: string[];
|
|
21
|
+
};
|
|
22
|
+
const authConfig = authConfigRaw as AuthConfigShape;
|
|
23
|
+
|
|
24
|
+
// Register Stackwright components (OSS + Pro)
|
|
25
|
+
registerAppRouterComponents();
|
|
26
|
+
registerSiteIcons();
|
|
27
|
+
registerShadcnComponents();
|
|
28
|
+
registerDefaultIcons();
|
|
29
|
+
registerDisplayComponents();
|
|
30
|
+
registerPulseComponents();
|
|
31
|
+
|
|
32
|
+
export function Providers({ children }: { children: React.ReactNode }) {
|
|
33
|
+
return (
|
|
34
|
+
<AuthProvider
|
|
35
|
+
user={null}
|
|
36
|
+
session={null}
|
|
37
|
+
rbacConfig={{
|
|
38
|
+
roles: authConfig.roles ?? [],
|
|
39
|
+
protected_routes: authConfig.protected_routes ?? [],
|
|
40
|
+
public_routes: authConfig.public_routes ?? [],
|
|
41
|
+
}}
|
|
42
|
+
>
|
|
43
|
+
{children}
|
|
44
|
+
</AuthProvider>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// packages/launch-stackwright-pro/templates/pro/scripts/pro-content-plugin.js
|
|
2
|
+
//
|
|
3
|
+
// Pro content type plugin for @stackwright/build-scripts.
|
|
4
|
+
//
|
|
5
|
+
// CONFIRMED CASE B (@stackwright/build-scripts@0.5.0-alpha.0 / types@1.2.0-alpha.0):
|
|
6
|
+
// The currently shipped version of build-scripts does NOT read
|
|
7
|
+
// `contentItemSchemas` or `knownContentTypeKeys` from plugin objects.
|
|
8
|
+
// Those fields first appear in @stackwright/types@1.4.0+ and will be
|
|
9
|
+
// consumed by build-scripts@0.7.0 when that release ships.
|
|
10
|
+
//
|
|
11
|
+
// CURRENT BEHAVIOUR (pre-0.7.0):
|
|
12
|
+
// `unknownContentTypes: 'warn'` in prebuild.js already prevents hard failures
|
|
13
|
+
// for unrecognised content types. The `beforeBuild` stub below ensures this
|
|
14
|
+
// plugin is a syntactically valid, callable plugin (not silently ignored by
|
|
15
|
+
// the plugin runner) even though there is no side-effect to execute yet.
|
|
16
|
+
//
|
|
17
|
+
// TODO(@stackwright/build-scripts@0.7.0): Once 0.7.0 is the resolved floor,
|
|
18
|
+
// remove the `beforeBuild` stub — `contentItemSchemas` and
|
|
19
|
+
// `knownContentTypeKeys` will be consumed natively by the runtime and the
|
|
20
|
+
// plugin will suppress "unknown content type" warnings automatically.
|
|
21
|
+
|
|
22
|
+
'use strict';
|
|
23
|
+
|
|
24
|
+
const { z } = require('zod');
|
|
25
|
+
|
|
26
|
+
const PRO_CONTENT_TYPE_KEYS = [
|
|
27
|
+
// @stackwright-pro/display-components
|
|
28
|
+
'metric_card',
|
|
29
|
+
'status_badge',
|
|
30
|
+
'stat_bar',
|
|
31
|
+
'sparkline',
|
|
32
|
+
'activity_feed',
|
|
33
|
+
'dashboard_grid',
|
|
34
|
+
'data_table',
|
|
35
|
+
'json_viewer',
|
|
36
|
+
'action_bar',
|
|
37
|
+
'section',
|
|
38
|
+
'collection_listing',
|
|
39
|
+
'detail_field',
|
|
40
|
+
'detail_view',
|
|
41
|
+
// @stackwright-pro/pulse
|
|
42
|
+
'pulse_provider',
|
|
43
|
+
'metric_card_pulse',
|
|
44
|
+
'data_table_pulse',
|
|
45
|
+
'status_badge_pulse',
|
|
46
|
+
'detail_card_pulse',
|
|
47
|
+
'stats_grid',
|
|
48
|
+
'map_pulse',
|
|
49
|
+
'alert_banner',
|
|
50
|
+
// @stackwright-pro/workflow-components
|
|
51
|
+
'workflow_mount',
|
|
52
|
+
// @stackwright-pro/display-components — navigation
|
|
53
|
+
'breadcrumb',
|
|
54
|
+
'page_header_bar',
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
// OSS content types that Pro otters augment with extra fields (e.g. `theme:`,
|
|
58
|
+
// `auth:`). The strict OSS Zod schemas reject unknown properties, so we
|
|
59
|
+
// register passthrough variants here. When build-scripts@0.7.0+ evaluates
|
|
60
|
+
// the union [contentItemSchema, ...extraSchemas], the strict OSS schema
|
|
61
|
+
// fails on the extra field and falls through to our passthrough version.
|
|
62
|
+
const OSS_TYPES_WITH_PRO_EXTENSIONS = [
|
|
63
|
+
'text_block',
|
|
64
|
+
'alert',
|
|
65
|
+
'grid',
|
|
66
|
+
'main',
|
|
67
|
+
'collection_list',
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
const proContentPlugin = {
|
|
71
|
+
name: 'pro-content',
|
|
72
|
+
|
|
73
|
+
// --- Fields read by build-scripts@0.7.0+ (types@1.4.0+) ---
|
|
74
|
+
// Passthrough schemas — let each component handle its own prop validation
|
|
75
|
+
// at runtime. Registered here so the prebuild content-item validator
|
|
76
|
+
// accepts pro types without errors.
|
|
77
|
+
contentItemSchemas: [
|
|
78
|
+
// Pro-only types — fully passthrough (no OSS schema exists)
|
|
79
|
+
...PRO_CONTENT_TYPE_KEYS.map((type) =>
|
|
80
|
+
z.object({ type: z.literal(type) }).passthrough()
|
|
81
|
+
),
|
|
82
|
+
// OSS types with Pro extensions (theme:, auth:, etc.) — passthrough
|
|
83
|
+
// variants so the extra fields don't fail strict OSS validation.
|
|
84
|
+
...OSS_TYPES_WITH_PRO_EXTENSIONS.map((type) =>
|
|
85
|
+
z.object({ type: z.literal(type) }).passthrough()
|
|
86
|
+
),
|
|
87
|
+
],
|
|
88
|
+
// String keys so the prebuild skips "unknown content type" warnings.
|
|
89
|
+
knownContentTypeKeys: [...PRO_CONTENT_TYPE_KEYS, ...OSS_TYPES_WITH_PRO_EXTENSIONS],
|
|
90
|
+
|
|
91
|
+
// --- Stub lifecycle hook (required for build-scripts@0.5.x / types@1.2.x) ---
|
|
92
|
+
// build-scripts@0.5.x only calls plugins that have beforeBuild or afterBuild.
|
|
93
|
+
// Without this stub the plugin object is accepted but never invoked, making
|
|
94
|
+
// the whole registration a silent no-op. The stub has no side-effects; its
|
|
95
|
+
// only purpose is to keep the plugin in the active lifecycle.
|
|
96
|
+
//
|
|
97
|
+
// Remove this stub when build-scripts@0.7.0 is the resolved floor (the
|
|
98
|
+
// 0.7.x runner calls plugins purely for their schema/key registration,
|
|
99
|
+
// not via beforeBuild/afterBuild).
|
|
100
|
+
beforeBuild: () => {},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
module.exports = { proContentPlugin };
|