@stackwright-pro/launch-stackwright-pro 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -0
- package/dist/index.js +596 -0
- package/dist/index.js.map +1 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# launch-stackwright-pro
|
|
2
|
+
|
|
3
|
+
š¢ Scaffold a new **Stackwright Pro** project in one command ā complete with
|
|
4
|
+
OpenAPI integration, RBAC auth, mock users, and the otter raft ready to build
|
|
5
|
+
your site for you.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx launch-stackwright-pro my-app --yes
|
|
11
|
+
cd my-app
|
|
12
|
+
pnpm install
|
|
13
|
+
pnpm dev
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### With an OpenAPI Spec
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx launch-stackwright-pro my-app --spec ./my-api.yaml --yes
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The spec gets copied into `specs/` and wired into `stackwright.yml`. The
|
|
23
|
+
prebuild script generates types & a client on the first `pnpm dev`.
|
|
24
|
+
|
|
25
|
+
## What Gets Created
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
my-app/
|
|
29
|
+
āāā pages/
|
|
30
|
+
ā āāā _app.tsx # Pro _app with AuthProvider
|
|
31
|
+
ā āāā _document.tsx
|
|
32
|
+
ā āāā index.ts
|
|
33
|
+
ā āāā [...slug].tsx
|
|
34
|
+
āāā lib/
|
|
35
|
+
ā āāā mock-auth.ts # Dev-mode mock users (admin/analyst/viewer)
|
|
36
|
+
āāā scripts/
|
|
37
|
+
ā āāā prebuild.js # Reads stackwright.yml ā runs OpenAPI plugin
|
|
38
|
+
āāā specs/ # Only if --spec was provided
|
|
39
|
+
ā āāā <your-spec>.yaml
|
|
40
|
+
āāā .stackwright/
|
|
41
|
+
ā āāā otters/ # 𦦠Brand, foreman, page, & theme otters
|
|
42
|
+
āāā stackwright.yml # Theme + auth + integrations config
|
|
43
|
+
āāā next.config.js # Pro config (transpile pro pkgs + yaml-loader)
|
|
44
|
+
āāā yaml.d.ts # TS declarations for YAML imports
|
|
45
|
+
āāā .code-puppy.json # MCP auto-configuration
|
|
46
|
+
āāā package.json # OSS + Pro dependencies
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## CLI Options
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
launch-stackwright-pro [directory]
|
|
53
|
+
|
|
54
|
+
Options:
|
|
55
|
+
--name <name> Project name (used in package.json)
|
|
56
|
+
--title <title> Site title shown in the app bar and browser tab
|
|
57
|
+
--theme <themeId> Theme ID (e.g., corporate, creative, minimal)
|
|
58
|
+
--force Overwrite existing directory
|
|
59
|
+
--skip-otters Skip otter raft setup
|
|
60
|
+
-y, --yes Skip prompts, use defaults
|
|
61
|
+
--spec <path> Path to an OpenAPI spec (YAML or JSON)
|
|
62
|
+
--spec-name <name> Name for the API integration (default: derived from filename)
|
|
63
|
+
-V, --version Output the version number
|
|
64
|
+
-h, --help Display help
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Role-Based Dev Scripts
|
|
68
|
+
|
|
69
|
+
The scaffolded project includes convenience scripts for developing against
|
|
70
|
+
different mock roles:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pnpm dev # No mock auth ā unauthenticated
|
|
74
|
+
pnpm dev:admin # MOCK_USER=admin
|
|
75
|
+
pnpm dev:analyst # MOCK_USER=analyst
|
|
76
|
+
pnpm dev:viewer # MOCK_USER=viewer
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## What's Different from OSS `launch-stackwright`?
|
|
80
|
+
|
|
81
|
+
| Feature | OSS | Pro |
|
|
82
|
+
|---------|-----|-----|
|
|
83
|
+
| Base scaffold | ā
| ā
|
|
|
84
|
+
| Otter raft | ā
| ā
|
|
|
85
|
+
| RBAC auth | ā | ā
|
|
|
86
|
+
| Mock users | ā | ā
|
|
|
87
|
+
| OpenAPI integration | ā | ā
|
|
|
88
|
+
| Prebuild code-gen | ā | ā
|
|
|
89
|
+
| YAML config loading | ā | ā
|
|
|
90
|
+
|
|
91
|
+
## Docs
|
|
92
|
+
|
|
93
|
+
See the main [Stackwright Pro documentation](https://github.com/Per-Aspera-LLC/stackwright-pro)
|
|
94
|
+
for architecture details, auth deep-dives, and deployment guides.
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
|
|
29
|
+
// package.json
|
|
30
|
+
var require_package = __commonJS({
|
|
31
|
+
"package.json"(exports2, module2) {
|
|
32
|
+
module2.exports = {
|
|
33
|
+
name: "@stackwright-pro/launch-stackwright-pro",
|
|
34
|
+
version: "0.2.0",
|
|
35
|
+
description: "Launch a new Stackwright Pro project with OpenAPI integration, auth, and the otter raft",
|
|
36
|
+
license: "MIT",
|
|
37
|
+
repository: {
|
|
38
|
+
type: "git",
|
|
39
|
+
url: "https://github.com/Per-Aspera-LLC/stackwright-pro"
|
|
40
|
+
},
|
|
41
|
+
keywords: [
|
|
42
|
+
"stackwright",
|
|
43
|
+
"stackwright-pro",
|
|
44
|
+
"scaffolding",
|
|
45
|
+
"openapi",
|
|
46
|
+
"government",
|
|
47
|
+
"hackathon"
|
|
48
|
+
],
|
|
49
|
+
files: [
|
|
50
|
+
"dist"
|
|
51
|
+
],
|
|
52
|
+
bin: {
|
|
53
|
+
"launch-stackwright-pro": "dist/index.js"
|
|
54
|
+
},
|
|
55
|
+
scripts: {
|
|
56
|
+
build: "tsup",
|
|
57
|
+
dev: "tsup --watch"
|
|
58
|
+
},
|
|
59
|
+
dependencies: {
|
|
60
|
+
"@stackwright/cli": "latest",
|
|
61
|
+
chalk: "^5.6.2",
|
|
62
|
+
commander: "^14.0.3",
|
|
63
|
+
"fs-extra": "^11.3",
|
|
64
|
+
"js-yaml": "^4.1.0"
|
|
65
|
+
},
|
|
66
|
+
devDependencies: {
|
|
67
|
+
"@types/fs-extra": "^11.0",
|
|
68
|
+
"@types/js-yaml": "^4.0.9",
|
|
69
|
+
"@types/node": "^24.0.0",
|
|
70
|
+
typescript: "^5.0",
|
|
71
|
+
tsup: "^8.5"
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// src/index.ts
|
|
78
|
+
var import_commander = require("commander");
|
|
79
|
+
var import_path = __toESM(require("path"));
|
|
80
|
+
var import_fs_extra = __toESM(require("fs-extra"));
|
|
81
|
+
var import_chalk = __toESM(require("chalk"));
|
|
82
|
+
var import_js_yaml = __toESM(require("js-yaml"));
|
|
83
|
+
var import_cli = require("@stackwright/cli");
|
|
84
|
+
var { version } = require_package();
|
|
85
|
+
var STACKWRIGHT_NPM_VERSIONS = {
|
|
86
|
+
"@stackwright/core": "^0.7.0",
|
|
87
|
+
"@stackwright/icons": "^0.3.0",
|
|
88
|
+
"@stackwright/nextjs": "^0.3.1",
|
|
89
|
+
"@stackwright/ui-shadcn": "^0.1.0",
|
|
90
|
+
"@stackwright/build-scripts": "^0.4.0",
|
|
91
|
+
"@stackwright/mcp": "^0.2.0",
|
|
92
|
+
"@stackwright-pro/mcp": "latest"
|
|
93
|
+
};
|
|
94
|
+
var PRO_DEPENDENCIES = {
|
|
95
|
+
"@stackwright/otters": "latest",
|
|
96
|
+
// OSS otters (installed as package)
|
|
97
|
+
"@stackwright-pro/otters": "latest",
|
|
98
|
+
// Pro otters (installed as package)
|
|
99
|
+
"@stackwright-pro/openapi": "latest",
|
|
100
|
+
"@stackwright-pro/auth": "latest",
|
|
101
|
+
"@stackwright-pro/auth-nextjs": "latest",
|
|
102
|
+
zod: "^3.23.0"
|
|
103
|
+
};
|
|
104
|
+
var PRO_DEV_DEPENDENCIES = {
|
|
105
|
+
"@stoplight/prism-cli": "^5.14.2"
|
|
106
|
+
// Mock server for API development
|
|
107
|
+
};
|
|
108
|
+
async function fixWorkspaceRefs(targetDir) {
|
|
109
|
+
const pkgPath = import_path.default.join(targetDir, "package.json");
|
|
110
|
+
const pkg = await import_fs_extra.default.readJSON(pkgPath);
|
|
111
|
+
for (const [pkgName, version2] of Object.entries(STACKWRIGHT_NPM_VERSIONS)) {
|
|
112
|
+
if (pkg.dependencies?.[pkgName] === "workspace:*") {
|
|
113
|
+
pkg.dependencies[pkgName] = version2;
|
|
114
|
+
console.log(import_chalk.default.dim(` Fixed ${pkgName}: workspace:* \u2192 ${version2}`));
|
|
115
|
+
}
|
|
116
|
+
if (pkg.devDependencies?.[pkgName] === "workspace:*") {
|
|
117
|
+
pkg.devDependencies[pkgName] = version2;
|
|
118
|
+
console.log(import_chalk.default.dim(` Fixed ${pkgName} (dev): workspace:* \u2192 ${version2}`));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
await import_fs_extra.default.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
122
|
+
}
|
|
123
|
+
async function addProDependencies(targetDir, specFilename) {
|
|
124
|
+
const pkgPath = import_path.default.join(targetDir, "package.json");
|
|
125
|
+
await fixWorkspaceRefs(targetDir);
|
|
126
|
+
const pkg = await import_fs_extra.default.readJSON(pkgPath);
|
|
127
|
+
pkg.dependencies["@stackwright/mcp"] = STACKWRIGHT_NPM_VERSIONS["@stackwright/mcp"];
|
|
128
|
+
pkg.dependencies["@stackwright-pro/mcp"] = "latest";
|
|
129
|
+
pkg.dependencies = { ...pkg.dependencies, ...PRO_DEPENDENCIES };
|
|
130
|
+
pkg.devDependencies = { ...pkg.devDependencies, ...PRO_DEV_DEPENDENCIES };
|
|
131
|
+
const scripts = { ...pkg.scripts };
|
|
132
|
+
scripts["dev:admin"] = "MOCK_USER=admin next dev";
|
|
133
|
+
scripts["dev:analyst"] = "MOCK_USER=analyst next dev";
|
|
134
|
+
scripts["dev:viewer"] = "MOCK_USER=viewer next dev";
|
|
135
|
+
scripts.prebuild = "node scripts/prebuild.js";
|
|
136
|
+
scripts.predev = "node scripts/prebuild.js";
|
|
137
|
+
if (specFilename) {
|
|
138
|
+
scripts["dev:mock"] = `prism mock ./specs/${specFilename} --port 4010 --dynamic & next dev`;
|
|
139
|
+
}
|
|
140
|
+
pkg.scripts = scripts;
|
|
141
|
+
await import_fs_extra.default.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
142
|
+
}
|
|
143
|
+
async function copyProTemplate(templateName, destPath) {
|
|
144
|
+
const src = import_path.default.resolve(__dirname, "..", "templates", "pro", templateName);
|
|
145
|
+
await import_fs_extra.default.copy(src, destPath);
|
|
146
|
+
}
|
|
147
|
+
async function addAuthToStackwrightYml(targetDir) {
|
|
148
|
+
const ymlPath = import_path.default.join(targetDir, "stackwright.yml");
|
|
149
|
+
const content = await import_fs_extra.default.readFile(ymlPath, "utf-8");
|
|
150
|
+
const config = import_js_yaml.default.load(content);
|
|
151
|
+
config.auth = {
|
|
152
|
+
type: "pki",
|
|
153
|
+
profile: "dod_cac",
|
|
154
|
+
source: "gateway_headers",
|
|
155
|
+
roles: [
|
|
156
|
+
{ name: "ADMIN", permissions: ["*"] },
|
|
157
|
+
{ name: "ANALYST", permissions: ["data:read", "data:write"] },
|
|
158
|
+
{ name: "VIEWER", permissions: ["data:read"] }
|
|
159
|
+
],
|
|
160
|
+
protected_routes: [{ path: "/*", roles: ["VIEWER", "ANALYST", "ADMIN"] }],
|
|
161
|
+
public_routes: ["/", "/getting-started"]
|
|
162
|
+
};
|
|
163
|
+
await import_fs_extra.default.writeFile(ymlPath, import_js_yaml.default.dump(config, { lineWidth: 120 }));
|
|
164
|
+
}
|
|
165
|
+
async function addIntegrationToStackwrightYml(targetDir, specName, specFilename, mockUrl) {
|
|
166
|
+
const ymlPath = import_path.default.join(targetDir, "stackwright.yml");
|
|
167
|
+
const content = await import_fs_extra.default.readFile(ymlPath, "utf-8");
|
|
168
|
+
const config = import_js_yaml.default.load(content);
|
|
169
|
+
const integration = {
|
|
170
|
+
type: "openapi",
|
|
171
|
+
name: specName,
|
|
172
|
+
spec: `./specs/${specFilename}`,
|
|
173
|
+
collections: []
|
|
174
|
+
};
|
|
175
|
+
if (mockUrl) {
|
|
176
|
+
integration.mockUrl = mockUrl;
|
|
177
|
+
}
|
|
178
|
+
config.integrations = [integration];
|
|
179
|
+
await import_fs_extra.default.writeFile(ymlPath, import_js_yaml.default.dump(config, { lineWidth: 120 }));
|
|
180
|
+
}
|
|
181
|
+
async function handleSpec(targetDir, specPath, specName) {
|
|
182
|
+
const resolvedSpec = import_path.default.resolve(specPath);
|
|
183
|
+
if (!import_fs_extra.default.existsSync(resolvedSpec)) {
|
|
184
|
+
throw new Error(`Spec file not found: ${resolvedSpec}`);
|
|
185
|
+
}
|
|
186
|
+
const specFilename = import_path.default.basename(resolvedSpec);
|
|
187
|
+
const derivedName = specName || import_path.default.basename(specFilename, import_path.default.extname(specFilename));
|
|
188
|
+
const specsDir = import_path.default.join(targetDir, "specs");
|
|
189
|
+
await import_fs_extra.default.ensureDir(specsDir);
|
|
190
|
+
await import_fs_extra.default.copy(resolvedSpec, import_path.default.join(specsDir, specFilename));
|
|
191
|
+
return { specFilename, derivedName };
|
|
192
|
+
}
|
|
193
|
+
function writeCodePuppyConfig(targetDir) {
|
|
194
|
+
const config = {
|
|
195
|
+
mcpServers: {
|
|
196
|
+
stackwright: {
|
|
197
|
+
command: "node",
|
|
198
|
+
args: [import_path.default.join(targetDir, "node_modules", "@stackwright", "mcp", "dist", "server.js")],
|
|
199
|
+
env: { NODE_ENV: "development" }
|
|
200
|
+
},
|
|
201
|
+
"stackwright-pro": {
|
|
202
|
+
command: "node",
|
|
203
|
+
args: [import_path.default.join(targetDir, "node_modules", "@stackwright-pro", "mcp", "dist", "server.js")],
|
|
204
|
+
env: { NODE_ENV: "development" }
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
// Both OSS and Pro otters are installed as packages - no file copying!
|
|
208
|
+
agents_path: [
|
|
209
|
+
"node_modules/@stackwright/otters",
|
|
210
|
+
// OSS otters (installed as package)
|
|
211
|
+
"node_modules/@stackwright-pro/otters"
|
|
212
|
+
// Pro otters (installed as package)
|
|
213
|
+
]
|
|
214
|
+
};
|
|
215
|
+
return import_fs_extra.default.writeFile(
|
|
216
|
+
import_path.default.join(targetDir, ".code-puppy.json"),
|
|
217
|
+
JSON.stringify(config, null, 2) + "\n"
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
function generateReadme(options) {
|
|
221
|
+
const { projectName, hasSpec, specName, specFilename, hasOtters, hasMock } = options;
|
|
222
|
+
const apiIntegrationSection = hasSpec ? `## \u{1F4E1} API Integration
|
|
223
|
+
|
|
224
|
+
Your OpenAPI spec was copied to \`specs/${specFilename}\` and wired up in \`stackwright.yml\`.
|
|
225
|
+
|
|
226
|
+
**What gets generated:**
|
|
227
|
+
|
|
228
|
+
\`\`\`typescript
|
|
229
|
+
// src/generated/${specName}/schemas.ts
|
|
230
|
+
export const EquipmentSchema = z.object({
|
|
231
|
+
id: z.string(),
|
|
232
|
+
name: z.string(),
|
|
233
|
+
status: z.enum(['operational', 'maintenance', 'retired']),
|
|
234
|
+
// ... Zod validation for runtime safety
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// src/generated/${specName}/types.ts
|
|
238
|
+
export type Equipment = z.infer<typeof EquipmentSchema>;
|
|
239
|
+
|
|
240
|
+
// src/generated/${specName}/client.ts
|
|
241
|
+
export class ${specName.charAt(0).toUpperCase() + specName.slice(1)}Client {
|
|
242
|
+
async getEquipment(id: string): Promise<Equipment> {
|
|
243
|
+
// Auto-wired with auth, validation, error handling
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
\`\`\`
|
|
247
|
+
|
|
248
|
+
**How it works:**
|
|
249
|
+
1. The \`predev\` script in \`package.json\` runs \`prebuild.js\` before every \`pnpm dev\`
|
|
250
|
+
2. Prebuild reads your spec and generates type-safe code
|
|
251
|
+
3. You import and use it:
|
|
252
|
+
|
|
253
|
+
\`\`\`typescript
|
|
254
|
+
import { ${specName.charAt(0).toUpperCase() + specName.slice(1)}Client } from '@/generated/${specName}/client';
|
|
255
|
+
import type { Equipment } from '@/generated/${specName}/types';
|
|
256
|
+
|
|
257
|
+
const client = new ${specName.charAt(0).toUpperCase() + specName.slice(1)}Client();
|
|
258
|
+
const gear: Equipment = await client.getEquipment('123');
|
|
259
|
+
\`\`\`
|
|
260
|
+
|
|
261
|
+
No manual typing. No drift. No runtime surprises.
|
|
262
|
+
|
|
263
|
+
` : "";
|
|
264
|
+
const mockSection = hasMock ? `## \u{1F3AD} Mock Server
|
|
265
|
+
|
|
266
|
+
Prism mock server is configured to serve your API at **http://localhost:4010**.
|
|
267
|
+
|
|
268
|
+
\`\`\`bash
|
|
269
|
+
pnpm dev:mock # Starts Prism + Next.js together
|
|
270
|
+
\`\`\`
|
|
271
|
+
|
|
272
|
+
This starts:
|
|
273
|
+
1. Prism mock server on port 4010 (serves your OpenAPI spec)
|
|
274
|
+
2. Next.js dev server on port 3000
|
|
275
|
+
|
|
276
|
+
The generated API client is automatically configured to use the mock server.
|
|
277
|
+
|
|
278
|
+
` : "";
|
|
279
|
+
const aiAgentsSection = hasOtters ? `## \u{1F9A6} AI Agents (The Otter Raft)
|
|
280
|
+
|
|
281
|
+
Your project includes **EIGHT specialized AI agents** in \`.stackwright/\`:
|
|
282
|
+
|
|
283
|
+
### OSS Pipeline (Visual Design)
|
|
284
|
+
- \`stackwright-foreman-otter\` - Orchestrates Brand \u2192 Theme \u2192 Pages
|
|
285
|
+
- \`stackwright-brand-otter\` - Brand discovery through conversation
|
|
286
|
+
- \`stackwright-theme-otter\` - Visual design (colors, fonts, spacing)
|
|
287
|
+
- \`stackwright-page-otter\` - Content page building
|
|
288
|
+
|
|
289
|
+
### Pro Pipeline (API Integration)
|
|
290
|
+
- \`stackwright-pro-foreman-otter\` - Master coordinator (installed via @stackwright-pro/otters package)
|
|
291
|
+
- \`stackwright-pro-api-otter\` - Discovers entities from OpenAPI specs
|
|
292
|
+
- \`stackwright-pro-data-otter\` - Configures endpoint filters & ISR
|
|
293
|
+
- \`stackwright-pro-dashboard-otter\` - Builds live data dashboards
|
|
294
|
+
|
|
295
|
+
**Invoke the Foreman to build for you:**
|
|
296
|
+
|
|
297
|
+
\`\`\`bash
|
|
298
|
+
# OSS: Build a branded static site
|
|
299
|
+
code-puppy -i -a stackwright-foreman-otter
|
|
300
|
+
|
|
301
|
+
# Pro: Build a full-stack site with live API data
|
|
302
|
+
code-puppy -i -a stackwright-pro-foreman-otter
|
|
303
|
+
\`\`\`
|
|
304
|
+
|
|
305
|
+
**Example prompts:**
|
|
306
|
+
|
|
307
|
+
OSS Foreman: "Build me a law firm website with navy and gold colors"
|
|
308
|
+
|
|
309
|
+
Pro Foreman: "Build me a logistics dashboard from our OpenAPI spec. Connect to /equipment and /supplies endpoints."
|
|
310
|
+
|
|
311
|
+
The foreman will orchestrate specialist otters, validate outputs, and render previews.
|
|
312
|
+
|
|
313
|
+
` : "";
|
|
314
|
+
return `# ${projectName}
|
|
315
|
+
|
|
316
|
+
A Stackwright Pro application with role-based auth, OpenAPI integration, and intelligent AI agents.
|
|
317
|
+
|
|
318
|
+
## \u{1F680} Quick Start
|
|
319
|
+
|
|
320
|
+
\`\`\`bash
|
|
321
|
+
# Install dependencies
|
|
322
|
+
pnpm install
|
|
323
|
+
|
|
324
|
+
# Start development server (no auth mock)
|
|
325
|
+
pnpm dev
|
|
326
|
+
|
|
327
|
+
# Open your browser
|
|
328
|
+
open http://localhost:3000
|
|
329
|
+
\`\`\`
|
|
330
|
+
|
|
331
|
+
## \u{1F465} Role-Based Development
|
|
332
|
+
|
|
333
|
+
Stackwright Pro includes **mock authentication** for local development with three pre-configured roles:
|
|
334
|
+
|
|
335
|
+
\`\`\`bash
|
|
336
|
+
pnpm dev:admin # Full permissions (*)
|
|
337
|
+
pnpm dev:analyst # Read & write data
|
|
338
|
+
pnpm dev:viewer # Read-only access
|
|
339
|
+
\`\`\`
|
|
340
|
+
|
|
341
|
+
**How it works:**
|
|
342
|
+
- Each script sets the \`MOCK_USER\` environment variable
|
|
343
|
+
- \`lib/mock-auth.ts\` intercepts requests and injects the appropriate user context
|
|
344
|
+
- Your pages & API routes respect the RBAC rules in \`stackwright.yml\`
|
|
345
|
+
- No backend required for testing auth flows! \u{1F389}
|
|
346
|
+
|
|
347
|
+
**Pro tip:** Test your UI for all three roles to ensure proper permissions enforcement.
|
|
348
|
+
|
|
349
|
+
${mockSection}## \u{1F4C1} Project Structure
|
|
350
|
+
|
|
351
|
+
\`\`\`
|
|
352
|
+
.
|
|
353
|
+
\u251C\u2500\u2500 pages/
|
|
354
|
+
\u2502 \u251C\u2500\u2500 _app.tsx # Pro version with AuthProvider + shadcn
|
|
355
|
+
\u2502 \u251C\u2500\u2500 index.tsx # Home page (auto-generated by Stackwright)
|
|
356
|
+
\u2502 \u251C\u2500\u2500 about/
|
|
357
|
+
\u2502 \u2502 \u2514\u2500\u2500 content.yml # Page content in YAML
|
|
358
|
+
\u2502 \u2514\u2500\u2500 ...
|
|
359
|
+
\u251C\u2500\u2500 lib/
|
|
360
|
+
\u2502 \u2514\u2500\u2500 mock-auth.ts # Dev-only auth mocking (no backend needed)
|
|
361
|
+
\u251C\u2500\u2500 scripts/
|
|
362
|
+
\u2502 \u2514\u2500\u2500 prebuild.js # Auto-generates code from OpenAPI specs
|
|
363
|
+
\u251C\u2500\u2500 specs/ # OpenAPI spec files (if --spec was used)
|
|
364
|
+
\u251C\u2500\u2500 src/
|
|
365
|
+
\u2502 \u2514\u2500\u2500 generated/ # Auto-generated types & clients
|
|
366
|
+
\u2502 \u2514\u2500\u2500 {specName}/
|
|
367
|
+
\u2502 \u251C\u2500\u2500 schemas.ts # Zod schemas for runtime validation
|
|
368
|
+
\u2502 \u251C\u2500\u2500 types.ts # TypeScript types
|
|
369
|
+
\u2502 \u251C\u2500\u2500 client.ts # API client with auth
|
|
370
|
+
\u2502 \u2514\u2500\u2500 provider.ts # CollectionProvider for Stackwright
|
|
371
|
+
\u251C\u2500\u2500 .stackwright/
|
|
372
|
+
\u2502 \u2514\u2500\u2500 otters/ # AI agent configs (4 specialized otters)
|
|
373
|
+
\u251C\u2500\u2500 stackwright.yml # Theme, auth, API integrations
|
|
374
|
+
\u2514\u2500\u2500 package.json
|
|
375
|
+
\`\`\`
|
|
376
|
+
|
|
377
|
+
**Key Files:**
|
|
378
|
+
- \`pages/_app.tsx\` - Wraps your app with \`AuthProvider\` for RBAC
|
|
379
|
+
- \`stackwright.yml\` - Single source of truth for theme, auth roles, and API wiring
|
|
380
|
+
- \`lib/mock-auth.ts\` - Mocks CAC/PIV headers locally so you can test auth flows
|
|
381
|
+
- \`scripts/prebuild.js\` - Runs before dev/build to generate types from your OpenAPI spec
|
|
382
|
+
|
|
383
|
+
## \u{1F4C4} Adding Pages
|
|
384
|
+
|
|
385
|
+
Stackwright uses **YAML for content**, so you never touch JSX unless you want to.
|
|
386
|
+
|
|
387
|
+
**Example:** Create \`pages/about/content.yml\`:
|
|
388
|
+
|
|
389
|
+
\`\`\`yaml
|
|
390
|
+
title: About Us
|
|
391
|
+
description: Learn more about our mission
|
|
392
|
+
|
|
393
|
+
sections:
|
|
394
|
+
- type: main
|
|
395
|
+
heading: Who We Are
|
|
396
|
+
body: |
|
|
397
|
+
We build mission-critical logistics systems for the Marine Corps.
|
|
398
|
+
|
|
399
|
+
- type: feature_list
|
|
400
|
+
title: Our Capabilities
|
|
401
|
+
features:
|
|
402
|
+
- icon: Security
|
|
403
|
+
title: Zero Trust
|
|
404
|
+
description: PKI-based auth with CAC/PIV
|
|
405
|
+
- icon: Api
|
|
406
|
+
title: Real-time Data
|
|
407
|
+
description: OpenAPI-backed, Zod-validated
|
|
408
|
+
\`\`\`
|
|
409
|
+
|
|
410
|
+
That's it. Navigate to \`/about\` and it just works. No routing config, no React components.
|
|
411
|
+
|
|
412
|
+
${apiIntegrationSection}## \u{1F3A8} Customizing Theme
|
|
413
|
+
|
|
414
|
+
Edit \`stackwright.yml\` to change colors, fonts, spacing \u2014 applies everywhere instantly.
|
|
415
|
+
|
|
416
|
+
\`\`\`yaml
|
|
417
|
+
theme:
|
|
418
|
+
id: my-theme
|
|
419
|
+
name: My Custom Theme
|
|
420
|
+
colors:
|
|
421
|
+
primary: "#C41E3A" # Marine Corps red
|
|
422
|
+
background: "#FFFFFF"
|
|
423
|
+
text: "#1A1A1A"
|
|
424
|
+
accent: "#FFD700" # Gold
|
|
425
|
+
typography:
|
|
426
|
+
fontFamily: "'Inter', sans-serif"
|
|
427
|
+
h1Size: "2.5rem"
|
|
428
|
+
spacing:
|
|
429
|
+
unit: 8
|
|
430
|
+
\`\`\`
|
|
431
|
+
|
|
432
|
+
No CSS files. No theme provider boilerplate. Just YAML. Stackwright handles the rest.
|
|
433
|
+
|
|
434
|
+
## \u{1F510} Auth Configuration
|
|
435
|
+
|
|
436
|
+
Stackwright Pro comes with **3 pre-configured roles** in \`stackwright.yml\`:
|
|
437
|
+
|
|
438
|
+
\`\`\`yaml
|
|
439
|
+
auth:
|
|
440
|
+
roles:
|
|
441
|
+
- name: ADMIN
|
|
442
|
+
permissions: ['*'] # Full access
|
|
443
|
+
- name: ANALYST
|
|
444
|
+
permissions: ['data:read', 'data:write'] # Read/write data
|
|
445
|
+
- name: VIEWER
|
|
446
|
+
permissions: ['data:read'] # Read-only
|
|
447
|
+
\`\`\`
|
|
448
|
+
|
|
449
|
+
**Gate content in your YAML:**
|
|
450
|
+
|
|
451
|
+
\`\`\`yaml
|
|
452
|
+
sections:
|
|
453
|
+
- type: button
|
|
454
|
+
label: Delete Equipment
|
|
455
|
+
action: /api/equipment/delete
|
|
456
|
+
auth:
|
|
457
|
+
required_roles: [ADMIN]
|
|
458
|
+
fallback: hide # Options: hide, disable, show_message
|
|
459
|
+
\`\`\`
|
|
460
|
+
|
|
461
|
+
Only admins see the button. Analysts and viewers? Button doesn't exist in the DOM.
|
|
462
|
+
|
|
463
|
+
**Route protection:**
|
|
464
|
+
|
|
465
|
+
\`\`\`yaml
|
|
466
|
+
auth:
|
|
467
|
+
protected_routes:
|
|
468
|
+
- path: /admin/*
|
|
469
|
+
roles: [ADMIN]
|
|
470
|
+
- path: /equipment/*
|
|
471
|
+
roles: [ANALYST, ADMIN]
|
|
472
|
+
public_routes:
|
|
473
|
+
- /
|
|
474
|
+
- /about
|
|
475
|
+
\`\`\`
|
|
476
|
+
|
|
477
|
+
No middleware to write. No useAuth hooks to remember. RBAC is declarative.
|
|
478
|
+
|
|
479
|
+
${aiAgentsSection}## \u{1F4DA} Learn More
|
|
480
|
+
|
|
481
|
+
- **Stackwright Docs:** [https://stackwright.dev](https://stackwright.dev)
|
|
482
|
+
- **OSS Repo:** [https://github.com/Per-Aspera-LLC/stackwright](https://github.com/Per-Aspera-LLC/stackwright)
|
|
483
|
+
- **Pro Repo:** [https://github.com/Per-Aspera-LLC/stackwright-pro](https://github.com/Per-Aspera-LLC/stackwright-pro)
|
|
484
|
+
|
|
485
|
+
**Questions?** File an issue or ping us in the discussions. We're here to help you ship faster.
|
|
486
|
+
`;
|
|
487
|
+
}
|
|
488
|
+
async function launch(targetDir, options) {
|
|
489
|
+
const dirName = import_path.default.basename(targetDir);
|
|
490
|
+
console.log(import_chalk.default.cyan.bold("\n\u{1F6A2} Launching Stackwright Pro...\n"));
|
|
491
|
+
const scaffoldOpts = {
|
|
492
|
+
name: options.name || dirName,
|
|
493
|
+
title: options.title,
|
|
494
|
+
theme: options.theme,
|
|
495
|
+
force: options.force,
|
|
496
|
+
noInteractive: options.yes
|
|
497
|
+
};
|
|
498
|
+
const result = await (0, import_cli.scaffold)(targetDir, scaffoldOpts);
|
|
499
|
+
console.log(import_chalk.default.green("\u2705 Base project scaffolded"));
|
|
500
|
+
await copyProTemplate("_app.tsx", import_path.default.join(targetDir, "pages", "_app.tsx"));
|
|
501
|
+
await copyProTemplate("next.config.js", import_path.default.join(targetDir, "next.config.js"));
|
|
502
|
+
await addAuthToStackwrightYml(targetDir);
|
|
503
|
+
await import_fs_extra.default.ensureDir(import_path.default.join(targetDir, "lib"));
|
|
504
|
+
await copyProTemplate("mock-auth.ts", import_path.default.join(targetDir, "lib", "mock-auth.ts"));
|
|
505
|
+
await copyProTemplate("yaml.d.ts", import_path.default.join(targetDir, "yaml.d.ts"));
|
|
506
|
+
await import_fs_extra.default.ensureDir(import_path.default.join(targetDir, "scripts"));
|
|
507
|
+
await copyProTemplate("prebuild.js", import_path.default.join(targetDir, "scripts", "prebuild.js"));
|
|
508
|
+
console.log(import_chalk.default.green("\u{1F510} Auth integration added (RBAC with 3 roles)"));
|
|
509
|
+
let specInfo = null;
|
|
510
|
+
const MOCK_URL = "http://localhost:4010";
|
|
511
|
+
if (options.spec) {
|
|
512
|
+
specInfo = await handleSpec(targetDir, options.spec, options.specName);
|
|
513
|
+
await addIntegrationToStackwrightYml(
|
|
514
|
+
targetDir,
|
|
515
|
+
specInfo.derivedName,
|
|
516
|
+
specInfo.specFilename,
|
|
517
|
+
options.mock ? MOCK_URL : void 0
|
|
518
|
+
);
|
|
519
|
+
console.log(import_chalk.default.green("\u{1F4E1} OpenAPI integration wired up"));
|
|
520
|
+
if (options.mock) {
|
|
521
|
+
console.log(import_chalk.default.green("\u{1F3AD} Prism mock server configured"));
|
|
522
|
+
}
|
|
523
|
+
} else if (options.mock) {
|
|
524
|
+
console.log(import_chalk.default.yellow("\u26A0\uFE0F No spec provided with --mock. Using sample Petstore spec for demo. Replace with your API spec."));
|
|
525
|
+
const specsDir = import_path.default.join(targetDir, "specs");
|
|
526
|
+
await import_fs_extra.default.ensureDir(specsDir);
|
|
527
|
+
await copyProTemplate("petstore.yaml", import_path.default.join(specsDir, "petstore.yaml"));
|
|
528
|
+
specInfo = { specFilename: "petstore.yaml", derivedName: "petstore" };
|
|
529
|
+
await addIntegrationToStackwrightYml(
|
|
530
|
+
targetDir,
|
|
531
|
+
specInfo.derivedName,
|
|
532
|
+
specInfo.specFilename,
|
|
533
|
+
MOCK_URL
|
|
534
|
+
);
|
|
535
|
+
console.log(import_chalk.default.green("\u{1F4E1} Sample Petstore spec wired up"));
|
|
536
|
+
console.log(import_chalk.default.green("\u{1F3AD} Prism mock server configured"));
|
|
537
|
+
}
|
|
538
|
+
await addProDependencies(targetDir, options.mock ? specInfo?.specFilename : void 0);
|
|
539
|
+
if (!options.skipOtters) {
|
|
540
|
+
await writeCodePuppyConfig(targetDir);
|
|
541
|
+
console.log(import_chalk.default.green("\u{1F9A6}\u{1F9A6} Otter packages configured (OSS + Pro)"));
|
|
542
|
+
}
|
|
543
|
+
const readmeContent = generateReadme({
|
|
544
|
+
projectName: options.name || dirName,
|
|
545
|
+
hasSpec: !!specInfo,
|
|
546
|
+
specName: specInfo?.derivedName,
|
|
547
|
+
specFilename: specInfo?.specFilename,
|
|
548
|
+
hasOtters: !options.skipOtters,
|
|
549
|
+
hasMock: !!options.mock
|
|
550
|
+
});
|
|
551
|
+
await import_fs_extra.default.writeFile(import_path.default.join(targetDir, "README.md"), readmeContent);
|
|
552
|
+
console.log(import_chalk.default.green("\u{1F4C4} README.md created"));
|
|
553
|
+
const relDir = import_path.default.relative(process.cwd(), targetDir) || ".";
|
|
554
|
+
console.log(import_chalk.default.cyan.bold("\n\u{1F389} All set! Here's what to do next:\n"));
|
|
555
|
+
console.log(import_chalk.default.white(` 1. cd ${relDir}`));
|
|
556
|
+
console.log(import_chalk.default.white(" 2. pnpm install"));
|
|
557
|
+
console.log(import_chalk.default.white(" 3. pnpm dev # No auth"));
|
|
558
|
+
console.log(import_chalk.default.white(" pnpm dev:admin # As admin"));
|
|
559
|
+
console.log(import_chalk.default.white(" pnpm dev:analyst # As analyst"));
|
|
560
|
+
console.log(import_chalk.default.white(" pnpm dev:viewer # As viewer"));
|
|
561
|
+
if (specInfo) {
|
|
562
|
+
console.log(import_chalk.default.cyan(`
|
|
563
|
+
\u{1F4E1} Your API spec was copied to specs/${specInfo.specFilename}`));
|
|
564
|
+
console.log(import_chalk.default.dim(" The prebuild will generate types & client on first `pnpm dev`."));
|
|
565
|
+
}
|
|
566
|
+
if (options.mock) {
|
|
567
|
+
console.log(import_chalk.default.cyan("\n\u{1F3AD} Run with mock server:"));
|
|
568
|
+
console.log(import_chalk.default.white(" pnpm dev:mock # Starts Prism + Next.js"));
|
|
569
|
+
}
|
|
570
|
+
if (!options.skipOtters) {
|
|
571
|
+
console.log(import_chalk.default.cyan.bold("\n\u{1F9A6}\u{1F9A6} Want the otter raft to build your site for you?\n"));
|
|
572
|
+
console.log(import_chalk.default.white(" # OSS: Branded static site"));
|
|
573
|
+
console.log(import_chalk.default.dim(" code-puppy -i -a stackwright-foreman-otter"));
|
|
574
|
+
console.log(import_chalk.default.white("\n # Pro: Full-stack with live API data"));
|
|
575
|
+
console.log(import_chalk.default.dim(" code-puppy -i -a stackwright-pro-foreman-otter\n"));
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
async function main() {
|
|
579
|
+
const program = new import_commander.Command();
|
|
580
|
+
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(
|
|
581
|
+
"--spec <path>",
|
|
582
|
+
"Path to an OpenAPI spec (YAML or JSON) \u2014 copies into project and wires up integration"
|
|
583
|
+
).option(
|
|
584
|
+
"--spec-name <name>",
|
|
585
|
+
"Name for the API integration (default: derived from spec filename)"
|
|
586
|
+
).action(async (directory, options) => {
|
|
587
|
+
const targetDir = import_path.default.resolve(directory);
|
|
588
|
+
await launch(targetDir, options);
|
|
589
|
+
});
|
|
590
|
+
await program.parseAsync(process.argv);
|
|
591
|
+
}
|
|
592
|
+
main().catch((err) => {
|
|
593
|
+
console.error(import_chalk.default.red("\n\u274C Launch failed:"), err);
|
|
594
|
+
process.exit(1);
|
|
595
|
+
});
|
|
596
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@stackwright-pro/launch-stackwright-pro\",\n \"version\": \"0.2.0\",\n \"description\": \"Launch a new Stackwright Pro project with OpenAPI integration, auth, and the otter raft\",\n \"license\": \"MIT\",\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 ],\n \"bin\": {\n \"launch-stackwright-pro\": \"dist/index.js\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\"\n },\n \"dependencies\": {\n \"@stackwright/cli\": \"latest\",\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 }\n}\n","import { Command } from 'commander';\nimport path from 'path';\nimport fs from 'fs-extra';\nimport chalk from 'chalk';\nimport yaml from 'js-yaml';\n\nimport { scaffold, ScaffoldOptions } from '@stackwright/cli';\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 yes?: boolean;\n spec?: string;\n specName?: string;\n mock?: boolean; // Auto-configure Prism mock server\n}\n\n// ---------------------------------------------------------------------------\n// Post-processing helpers\n// ---------------------------------------------------------------------------\n\n// Fixed npm versions for @stackwright/* packages (avoid workspace:* refs from scaffold)\nconst STACKWRIGHT_NPM_VERSIONS: Record<string, string> = {\n '@stackwright/core': '^0.7.0',\n '@stackwright/icons': '^0.3.0',\n '@stackwright/nextjs': '^0.3.1',\n '@stackwright/ui-shadcn': '^0.1.0',\n '@stackwright/build-scripts': '^0.4.0',\n '@stackwright/mcp': '^0.2.0',\n '@stackwright-pro/mcp': 'latest',\n};\n\nconst PRO_DEPENDENCIES: Record<string, string> = {\n '@stackwright/otters': 'latest', // OSS otters (installed as package)\n '@stackwright-pro/otters': 'latest', // Pro otters (installed as package)\n '@stackwright-pro/openapi': 'latest',\n '@stackwright-pro/auth': 'latest',\n '@stackwright-pro/auth-nextjs': 'latest',\n zod: '^3.23.0',\n};\n\nconst PRO_DEV_DEPENDENCIES: Record<string, string> = {\n '@stoplight/prism-cli': '^5.14.2', // Mock server for API development\n};\n\nasync function fixWorkspaceRefs(targetDir: string): Promise<void> {\n const pkgPath = path.join(targetDir, 'package.json');\n const pkg = await fs.readJSON(pkgPath);\n\n // Fix workspace:* references in dependencies\n for (const [pkgName, version] of Object.entries(STACKWRIGHT_NPM_VERSIONS)) {\n if (pkg.dependencies?.[pkgName] === 'workspace:*') {\n pkg.dependencies[pkgName] = version;\n console.log(chalk.dim(` Fixed ${pkgName}: workspace:* ā ${version}`));\n }\n if (pkg.devDependencies?.[pkgName] === 'workspace:*') {\n pkg.devDependencies[pkgName] = version;\n console.log(chalk.dim(` Fixed ${pkgName} (dev): workspace:* ā ${version}`));\n }\n }\n\n await fs.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\\n');\n}\n\nasync function addProDependencies(targetDir: string, specFilename?: string): Promise<void> {\n const pkgPath = path.join(targetDir, 'package.json');\n\n // First, fix any workspace:* references from scaffold\n await fixWorkspaceRefs(targetDir);\n\n // Re-read after fixing workspace refs\n const pkg = await fs.readJSON(pkgPath);\n\n // Add MCP packages for code-puppy integration\n pkg.dependencies['@stackwright/mcp'] = STACKWRIGHT_NPM_VERSIONS['@stackwright/mcp'];\n pkg.dependencies['@stackwright-pro/mcp'] = 'latest';\n\n pkg.dependencies = { ...pkg.dependencies, ...PRO_DEPENDENCIES };\n pkg.devDependencies = { ...pkg.devDependencies, ...PRO_DEV_DEPENDENCIES };\n\n // Build scripts object with role-based dev scripts (always included)\n const scripts = { ...pkg.scripts };\n scripts['dev:admin'] = 'MOCK_USER=admin next dev';\n scripts['dev:analyst'] = 'MOCK_USER=analyst next dev';\n scripts['dev:viewer'] = 'MOCK_USER=viewer next dev';\n scripts.prebuild = 'node scripts/prebuild.js';\n scripts.predev = 'node scripts/prebuild.js';\n\n // Add mock script ONLY if we have a spec (Prism needs actual file path, not glob)\n if (specFilename) {\n scripts['dev:mock'] = `prism mock ./specs/${specFilename} --port 4010 --dynamic & next dev`;\n }\n\n pkg.scripts = scripts;\n\n await fs.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\\n');\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\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) 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 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) 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 // Add mock URL if mock server is configured\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\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// Otters are now installed as packages - no file copying needed!\n\nfunction writeCodePuppyConfig(targetDir: string): Promise<void> {\n const config = {\n mcpServers: {\n stackwright: {\n command: 'node',\n args: [path.join(targetDir, 'node_modules', '@stackwright', 'mcp', 'dist', 'server.js')],\n env: { NODE_ENV: 'development' },\n },\n 'stackwright-pro': {\n command: 'node',\n args: [path.join(targetDir, 'node_modules', '@stackwright-pro', 'mcp', 'dist', 'server.js')],\n env: { NODE_ENV: 'development' },\n },\n },\n // Both OSS and Pro otters are installed as packages - no file copying!\n agents_path: [\n 'node_modules/@stackwright/otters', // OSS otters (installed as package)\n 'node_modules/@stackwright-pro/otters' // Pro otters (installed as package)\n ],\n };\n\n return fs.writeFile(\n path.join(targetDir, '.code-puppy.json'),\n JSON.stringify(config, null, 2) + '\\n'\n );\n}\n\n// ---------------------------------------------------------------------------\n// README generator\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 **EIGHT specialized AI agents** in \\`.stackwright/\\`:\n\n### OSS Pipeline (Visual Design)\n- \\`stackwright-foreman-otter\\` - Orchestrates Brand ā Theme ā Pages\n- \\`stackwright-brand-otter\\` - Brand discovery through conversation\n- \\`stackwright-theme-otter\\` - Visual design (colors, fonts, spacing)\n- \\`stackwright-page-otter\\` - Content page building\n\n### Pro Pipeline (API Integration)\n- \\`stackwright-pro-foreman-otter\\` - Master coordinator (installed via @stackwright-pro/otters package)\n- \\`stackwright-pro-api-otter\\` - Discovers entities from OpenAPI specs\n- \\`stackwright-pro-data-otter\\` - Configures endpoint filters & ISR\n- \\`stackwright-pro-dashboard-otter\\` - Builds live data dashboards\n\n**Invoke the Foreman to build for you:**\n\n\\`\\`\\`bash\n# OSS: Build a branded static site\ncode-puppy -i -a stackwright-foreman-otter\n\n# Pro: Build a full-stack site with live API data\ncode-puppy -i -a stackwright-pro-foreman-otter\n\\`\\`\\`\n\n**Example prompts:**\n\nOSS Foreman: \"Build me a law firm website with navy and gold colors\"\n\nPro Foreman: \"Build me a logistics dashboard from our OpenAPI spec. Connect to /equipment and /supplies endpoints.\"\n\nThe foreman will orchestrate specialist otters, validate outputs, and render previews.\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# Install dependencies\npnpm install\n\n# Start development server (no auth mock)\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 // ------------------------------------------------------------------\n\n const scaffoldOpts: ScaffoldOptions = {\n name: options.name || dirName,\n title: options.title,\n theme: options.theme,\n force: options.force,\n noInteractive: options.yes,\n };\n\n const result = await scaffold(targetDir, scaffoldOpts);\n console.log(chalk.green('ā
Base project scaffolded'));\n\n // ------------------------------------------------------------------\n // 2. Post-process for Pro\n // ------------------------------------------------------------------\n\n // c. Replace _app.tsx with pro version (AuthProvider, shadcn, etc.)\n await copyProTemplate('_app.tsx', path.join(targetDir, 'pages', '_app.tsx'));\n\n // c. Replace next.config.js with pro version (transpile pro pkgs)\n await copyProTemplate('next.config.js', path.join(targetDir, 'next.config.js'));\n\n // d. Add auth section to stackwright.yml\n await addAuthToStackwrightYml(targetDir);\n\n // e. 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 // f. Add yaml.d.ts for TypeScript support\n await copyProTemplate('yaml.d.ts', path.join(targetDir, 'yaml.d.ts'));\n\n // g. 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 // h. Handle --spec if provided\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 // Handle --mock if provided\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(chalk.yellow('ā ļø No spec provided with --mock. Using sample Petstore spec for demo. Replace with your API spec.'));\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 // b. Inject pro deps + scripts into package.json\n // Pass specFilename only if --mock is set (Prism needs actual file, not glob)\n await addProDependencies(targetDir, options.mock ? specInfo?.specFilename : undefined);\n // ------------------------------------------------------------------\n\n // 3. Configure code-puppy with otter packages (unless --skip-otters)\n // ------------------------------------------------------------------\n\n if (!options.skipOtters) {\n // Both OSS and Pro otters are installed as npm packages - no file copying!\n await writeCodePuppyConfig(targetDir);\n console.log(chalk.green('š¦¦š¦¦ Otter packages configured (OSS + Pro)'));\n }\n\n // ------------------------------------------------------------------\n // 4. Generate README\n // ------------------------------------------------------------------\n\n const readmeContent = generateReadme({\n projectName: options.name || dirName,\n hasSpec: !!specInfo,\n specName: specInfo?.derivedName,\n 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 // 5. 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. pnpm install'));\n console.log(chalk.white(' 3. pnpm dev # No auth'));\n console.log(chalk.white(' pnpm dev:admin # As admin'));\n console.log(chalk.white(' pnpm dev:analyst # As analyst'));\n console.log(chalk.white(' pnpm dev:viewer # As viewer'));\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š¦¦š¦¦ Want the otter raft to build your site for you?\\n'));\n console.log(chalk.white(' # OSS: Branded static site'));\n console.log(chalk.dim(' code-puppy -i -a stackwright-foreman-otter'));\n console.log(chalk.white('\\n # Pro: Full-stack with live API data'));\n console.log(chalk.dim(' code-puppy -i -a stackwright-pro-foreman-otter\\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 .action(async (directory: string, options: LaunchProOptions) => {\n const targetDir = path.resolve(directory);\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"],"mappings":"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","names":["exports","module","path","fs","version","chalk","yaml"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stackwright-pro/launch-stackwright-pro",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Launch a new Stackwright Pro project with OpenAPI integration, auth, and the otter raft",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/Per-Aspera-LLC/stackwright-pro"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"stackwright",
|
|
12
|
+
"stackwright-pro",
|
|
13
|
+
"scaffolding",
|
|
14
|
+
"openapi",
|
|
15
|
+
"government",
|
|
16
|
+
"hackathon"
|
|
17
|
+
],
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"bin": {
|
|
22
|
+
"launch-stackwright-pro": "dist/index.js"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@stackwright/cli": "latest",
|
|
26
|
+
"chalk": "^5.6.2",
|
|
27
|
+
"commander": "^14.0.3",
|
|
28
|
+
"fs-extra": "^11.3",
|
|
29
|
+
"js-yaml": "^4.1.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/fs-extra": "^11.0",
|
|
33
|
+
"@types/js-yaml": "^4.0.9",
|
|
34
|
+
"@types/node": "^24.0.0",
|
|
35
|
+
"typescript": "^5.0",
|
|
36
|
+
"tsup": "^8.5"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsup",
|
|
40
|
+
"dev": "tsup --watch"
|
|
41
|
+
}
|
|
42
|
+
}
|