@donotdev/cli 0.0.17 → 0.0.18
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/dependencies-matrix.json +166 -58
- package/dist/bin/commands/create-app.js +89 -140
- package/dist/bin/commands/create-project.js +90 -144
- package/dist/bin/dndev.js +9 -6
- package/dist/bin/donotdev.js +9 -6
- package/dist/index.js +97 -148
- package/package.json +1 -1
- package/templates/root-consumer/.claude/commands/brainstorm.md.example +15 -1
- package/templates/root-consumer/.claude/commands/build.md.example +24 -2
- package/templates/root-consumer/.claude/commands/design.md.example +17 -0
- package/templates/root-consumer/.claude/commands/polish.md.example +17 -0
- package/templates/root-consumer/AI.md.example +50 -18
- package/templates/root-consumer/guides/dndev/SETUP_PAGES.md.example +64 -0
- package/templates/root-consumer/guides/wai-way/blueprints/0_brainstorm.md.example +1 -1
- package/templates/functions-firebase/functions-firebase/README.md.example +0 -123
- package/templates/functions-firebase/functions-firebase/build.mjs.example +0 -5
- package/templates/functions-firebase/functions-firebase/src/auth/getCustomClaims.ts.example +0 -19
- package/templates/functions-firebase/functions-firebase/src/auth/getUserAuthStatus.ts.example +0 -21
- package/templates/functions-firebase/functions-firebase/src/auth/index.ts.example +0 -11
- package/templates/functions-firebase/functions-firebase/src/auth/removeCustomClaims.ts.example +0 -21
- package/templates/functions-firebase/functions-firebase/src/auth/setCustomClaims.ts.example +0 -21
- package/templates/functions-firebase/functions-firebase/src/billing/handleStripeWebhook.ts.example +0 -24
- package/templates/functions-firebase/functions-firebase/src/billing/index.ts.example +0 -10
- package/templates/functions-firebase/functions-firebase/src/billing/processPaymentSuccess.ts.example +0 -14
- package/templates/functions-firebase/functions-firebase/src/billing/refreshSubscriptionStatus.ts.example +0 -14
- package/templates/functions-firebase/functions-firebase/src/index.ts.example +0 -39
- package/templates/functions-firebase/functions-firebase/src/oauth/checkGitHubAccess.ts.example +0 -14
- package/templates/functions-firebase/functions-firebase/src/oauth/disconnect.ts.example +0 -14
- package/templates/functions-firebase/functions-firebase/src/oauth/exchangeToken.ts.example +0 -14
- package/templates/functions-firebase/functions-firebase/src/oauth/getConnections.ts.example +0 -14
- package/templates/functions-firebase/functions-firebase/src/oauth/grantGitHubAccess.ts.example +0 -14
- package/templates/functions-firebase/functions-firebase/src/oauth/index.ts.example +0 -17
- package/templates/functions-firebase/functions-firebase/src/oauth/refreshToken.ts.example +0 -14
- package/templates/functions-firebase/functions-firebase/src/oauth/revokeGitHubAccess.ts.example +0 -14
- package/templates/functions-firebase/functions-firebase/tsconfig.json.example +0 -21
- package/templates/functions-vercel/functions-vercel/README.md.example +0 -116
- package/templates/functions-vercel/functions-vercel/build.mjs.example +0 -52
- package/templates/functions-vercel/functions-vercel/src/api/auth/getCustomClaims.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/auth/getUserAuthStatus.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/auth/removeCustomClaims.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/auth/setCustomClaims.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/billing/handleStripeWebhook.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/billing/processPaymentSuccess.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/billing/refreshSubscriptionStatus.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/crud/createEntity.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/crud/deleteEntity.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/crud/getEntity.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/crud/listEntities.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/crud/updateEntity.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/oauth/checkGitHubAccess.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/oauth/disconnect.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/oauth/exchangeToken.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/oauth/getConnections.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/oauth/grantGitHubAccess.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/oauth/refreshToken.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/src/api/oauth/revokeGitHubAccess.ts.example +0 -20
- package/templates/functions-vercel/functions-vercel/tsconfig.json.example +0 -21
- package/templates/functions-vercel/functions-vercel/vercel.json.example +0 -14
- package/templates/github/github/workflows/firebase-deploy.yml.example +0 -79
- /package/templates/functions-firebase/{functions-firebase/.env.example.example → .env.example} +0 -0
- /package/templates/functions-vercel/{functions-vercel/.env.example.example → .env.example} +0 -0
package/dist/bin/dndev.js
CHANGED
|
@@ -49,7 +49,7 @@ Usage: dndev <command>[:<app>] [options]
|
|
|
49
49
|
|
|
50
50
|
Commands:
|
|
51
51
|
init, create-project Create a new DoNotDev project
|
|
52
|
-
create-app [name] Add app (--builder
|
|
52
|
+
create-app [name] Add app (--builder, --host, --functions, --backend)
|
|
53
53
|
dev [app] Start development server
|
|
54
54
|
build [app] Build for production
|
|
55
55
|
preview [app] Preview production build
|
|
@@ -74,9 +74,10 @@ Options:
|
|
|
74
74
|
Examples:
|
|
75
75
|
dndev init my-project Create a new project
|
|
76
76
|
dndev create-app Interactive app creation
|
|
77
|
-
dndev create-app my-app Create 'my-app' with defaults (vite,
|
|
78
|
-
dndev create-app my-app --builder next --
|
|
79
|
-
dndev create-app my-app --functions --
|
|
77
|
+
dndev create-app my-app Create 'my-app' with defaults (vite, frontend-only)
|
|
78
|
+
dndev create-app my-app --builder next --host vercel Next.js + Vercel hosting
|
|
79
|
+
dndev create-app my-app --functions firebase --backend firebase Full Firebase stack
|
|
80
|
+
dndev create-app my-app --backend supabase --project my-fb-id Supabase + custom project
|
|
80
81
|
dndev dev Start dev server
|
|
81
82
|
dndev dev:web Start dev server for 'web' app
|
|
82
83
|
dndev agent Configure MCP for all AI agents
|
|
@@ -101,14 +102,16 @@ program.command("init [name]").alias("create-project").description("Create a new
|
|
|
101
102
|
const { main } = await import("./commands/create-project.js");
|
|
102
103
|
await main({ projectName: name });
|
|
103
104
|
});
|
|
104
|
-
program.command("create-app [name]").description("Add a new app to existing project").option("--name <name>", "App name (non-interactive)").option("--builder <builder>", "Framework: vite or
|
|
105
|
+
program.command("create-app [name]").description("Add a new app to existing project").option("--name <name>", "App name (non-interactive)").option("--builder <builder>", "Framework: vite, next, or expo (default: vite)").option("--host <host>", "Hosting: none, vercel, or firebase (default: none)").option("--functions <runtime>", "Functions: none, vercel, firebase, or supabase (default: none)").option("--backend <backend>", "BaaS: none, firebase, or supabase (default: none)").option("--project <id>", "Firebase project ID (default: app name)").option("--region <region>", "Firebase region (default: europe-west1)").action(async (name, options) => {
|
|
105
106
|
const { main } = await import("./commands/create-app.js");
|
|
106
107
|
const appName = name || options.name;
|
|
107
108
|
if (appName) {
|
|
108
109
|
await main({
|
|
109
110
|
name: appName,
|
|
110
111
|
builder: options.builder,
|
|
112
|
+
host: options.host,
|
|
111
113
|
functions: options.functions,
|
|
114
|
+
backend: options.backend,
|
|
112
115
|
firebaseProjectId: options.project,
|
|
113
116
|
firebaseRegion: options.region
|
|
114
117
|
});
|
|
@@ -252,7 +255,7 @@ program.command("wai").alias("wai-way").description("Output WAI-WAY activation p
|
|
|
252
255
|
function preprocessArgs(args2) {
|
|
253
256
|
if (args2.length === 0) return args2;
|
|
254
257
|
const firstArg = args2[0];
|
|
255
|
-
const appCommands = ["dev", "build", "preview", "emu", "deploy", "staging"];
|
|
258
|
+
const appCommands = ["dev", "build", "preview", "emu", "deploy", "staging", "tc", "type-check", "cacheout", "co"];
|
|
256
259
|
if (firstArg && firstArg.includes(":")) {
|
|
257
260
|
const colonIndex = firstArg.indexOf(":");
|
|
258
261
|
const command = firstArg.substring(0, colonIndex);
|
package/dist/bin/donotdev.js
CHANGED
|
@@ -49,7 +49,7 @@ Usage: dndev <command>[:<app>] [options]
|
|
|
49
49
|
|
|
50
50
|
Commands:
|
|
51
51
|
init, create-project Create a new DoNotDev project
|
|
52
|
-
create-app [name] Add app (--builder
|
|
52
|
+
create-app [name] Add app (--builder, --host, --functions, --backend)
|
|
53
53
|
dev [app] Start development server
|
|
54
54
|
build [app] Build for production
|
|
55
55
|
preview [app] Preview production build
|
|
@@ -74,9 +74,10 @@ Options:
|
|
|
74
74
|
Examples:
|
|
75
75
|
dndev init my-project Create a new project
|
|
76
76
|
dndev create-app Interactive app creation
|
|
77
|
-
dndev create-app my-app Create 'my-app' with defaults (vite,
|
|
78
|
-
dndev create-app my-app --builder next --
|
|
79
|
-
dndev create-app my-app --functions --
|
|
77
|
+
dndev create-app my-app Create 'my-app' with defaults (vite, frontend-only)
|
|
78
|
+
dndev create-app my-app --builder next --host vercel Next.js + Vercel hosting
|
|
79
|
+
dndev create-app my-app --functions firebase --backend firebase Full Firebase stack
|
|
80
|
+
dndev create-app my-app --backend supabase --project my-fb-id Supabase + custom project
|
|
80
81
|
dndev dev Start dev server
|
|
81
82
|
dndev dev:web Start dev server for 'web' app
|
|
82
83
|
dndev agent Configure MCP for all AI agents
|
|
@@ -101,14 +102,16 @@ program.command("init [name]").alias("create-project").description("Create a new
|
|
|
101
102
|
const { main } = await import("./commands/create-project.js");
|
|
102
103
|
await main({ projectName: name });
|
|
103
104
|
});
|
|
104
|
-
program.command("create-app [name]").description("Add a new app to existing project").option("--name <name>", "App name (non-interactive)").option("--builder <builder>", "Framework: vite or
|
|
105
|
+
program.command("create-app [name]").description("Add a new app to existing project").option("--name <name>", "App name (non-interactive)").option("--builder <builder>", "Framework: vite, next, or expo (default: vite)").option("--host <host>", "Hosting: none, vercel, or firebase (default: none)").option("--functions <runtime>", "Functions: none, vercel, firebase, or supabase (default: none)").option("--backend <backend>", "BaaS: none, firebase, or supabase (default: none)").option("--project <id>", "Firebase project ID (default: app name)").option("--region <region>", "Firebase region (default: europe-west1)").action(async (name, options) => {
|
|
105
106
|
const { main } = await import("./commands/create-app.js");
|
|
106
107
|
const appName = name || options.name;
|
|
107
108
|
if (appName) {
|
|
108
109
|
await main({
|
|
109
110
|
name: appName,
|
|
110
111
|
builder: options.builder,
|
|
112
|
+
host: options.host,
|
|
111
113
|
functions: options.functions,
|
|
114
|
+
backend: options.backend,
|
|
112
115
|
firebaseProjectId: options.project,
|
|
113
116
|
firebaseRegion: options.region
|
|
114
117
|
});
|
|
@@ -252,7 +255,7 @@ program.command("wai").alias("wai-way").description("Output WAI-WAY activation p
|
|
|
252
255
|
function preprocessArgs(args2) {
|
|
253
256
|
if (args2.length === 0) return args2;
|
|
254
257
|
const firstArg = args2[0];
|
|
255
|
-
const appCommands = ["dev", "build", "preview", "emu", "deploy", "staging"];
|
|
258
|
+
const appCommands = ["dev", "build", "preview", "emu", "deploy", "staging", "tc", "type-check", "cacheout", "co"];
|
|
256
259
|
if (firstArg && firstArg.includes(":")) {
|
|
257
260
|
const colonIndex = firstArg.indexOf(":");
|
|
258
261
|
const command = firstArg.substring(0, colonIndex);
|
package/dist/index.js
CHANGED
|
@@ -18617,34 +18617,67 @@ var APP_QUESTIONNAIRE = [
|
|
|
18617
18617
|
]
|
|
18618
18618
|
},
|
|
18619
18619
|
{
|
|
18620
|
-
id: "
|
|
18621
|
-
question: "
|
|
18622
|
-
type: "
|
|
18623
|
-
|
|
18620
|
+
id: "host",
|
|
18621
|
+
question: "Where will you host?",
|
|
18622
|
+
type: "select",
|
|
18623
|
+
condition: (answers) => answers.framework !== "expo",
|
|
18624
|
+
defaultValue: (answers) => {
|
|
18625
|
+
return answers.framework === "nextjs" ? "vercel" : "none";
|
|
18626
|
+
},
|
|
18627
|
+
choices: [
|
|
18628
|
+
{ title: "None \u2014 no hosting config", value: "none" },
|
|
18629
|
+
{ title: "Vercel \u2014 edge CDN + serverless", value: "vercel" },
|
|
18630
|
+
{ title: "Firebase Hosting \u2014 Google CDN", value: "firebase" }
|
|
18631
|
+
]
|
|
18632
|
+
},
|
|
18633
|
+
{
|
|
18634
|
+
id: "functions",
|
|
18635
|
+
question: "Serverless functions?",
|
|
18636
|
+
type: "select",
|
|
18637
|
+
defaultValue: "none",
|
|
18638
|
+
// Choices filtered dynamically based on host
|
|
18639
|
+
choices: [
|
|
18640
|
+
{ title: "None", value: "none" },
|
|
18641
|
+
{ title: "Vercel Functions \u2014 edge + node.js", value: "vercel" },
|
|
18642
|
+
{ title: "Firebase Functions \u2014 Google Cloud", value: "firebase" },
|
|
18643
|
+
{ title: "Supabase Edge Functions \u2014 Deno", value: "supabase" }
|
|
18644
|
+
],
|
|
18645
|
+
choicesFilter: (answers) => {
|
|
18646
|
+
const host = answers.host ?? "none";
|
|
18647
|
+
const framework = answers.framework;
|
|
18648
|
+
if (framework === "expo") return ["none", "firebase", "supabase"];
|
|
18649
|
+
if (host === "firebase") return ["none", "firebase"];
|
|
18650
|
+
if (host === "vercel") return ["none", "vercel", "supabase"];
|
|
18651
|
+
return ["none", "vercel", "firebase", "supabase"];
|
|
18652
|
+
}
|
|
18624
18653
|
},
|
|
18625
18654
|
{
|
|
18626
|
-
id: "
|
|
18627
|
-
question: "
|
|
18655
|
+
id: "backend",
|
|
18656
|
+
question: "Backend / BaaS provider?",
|
|
18628
18657
|
type: "select",
|
|
18629
|
-
dependsOn: "needsBackend",
|
|
18630
|
-
condition: (answers) => answers.needsBackend === true,
|
|
18631
18658
|
defaultValue: (answers) => {
|
|
18632
|
-
|
|
18659
|
+
if (answers.functions === "firebase") return "firebase";
|
|
18660
|
+
if (answers.functions === "supabase") return "supabase";
|
|
18661
|
+
return "none";
|
|
18633
18662
|
},
|
|
18634
18663
|
choices: [
|
|
18664
|
+
{ title: "None \u2014 frontend only", value: "none" },
|
|
18635
18665
|
{
|
|
18636
|
-
title: "Firebase \u2014
|
|
18666
|
+
title: "Firebase \u2014 Auth + Firestore + Storage",
|
|
18637
18667
|
value: "firebase"
|
|
18638
18668
|
},
|
|
18639
|
-
{
|
|
18640
|
-
title: "Vercel \u2014 Serverless functions (edge + node.js)",
|
|
18641
|
-
value: "vercel"
|
|
18642
|
-
},
|
|
18643
18669
|
{
|
|
18644
18670
|
title: "Supabase \u2014 Postgres + Auth + Storage",
|
|
18645
18671
|
value: "supabase"
|
|
18646
18672
|
}
|
|
18647
|
-
]
|
|
18673
|
+
],
|
|
18674
|
+
choicesFilter: (answers) => {
|
|
18675
|
+
const functions = answers.functions ?? "none";
|
|
18676
|
+
if (functions === "firebase") return ["none", "firebase"];
|
|
18677
|
+
if (functions === "supabase") return ["none", "supabase"];
|
|
18678
|
+
if (functions === "vercel") return ["none"];
|
|
18679
|
+
return ["none", "firebase", "supabase"];
|
|
18680
|
+
}
|
|
18648
18681
|
}
|
|
18649
18682
|
];
|
|
18650
18683
|
var PROJECT_QUESTIONNAIRE = [
|
|
@@ -18662,12 +18695,13 @@ var PROJECT_QUESTIONNAIRE = [
|
|
|
18662
18695
|
}
|
|
18663
18696
|
];
|
|
18664
18697
|
function aggregateRequirements(answers) {
|
|
18698
|
+
const hasBackend = answers.backend && answers.backend !== "none" || answers.functions && answers.functions !== "none";
|
|
18665
18699
|
const requirements = {
|
|
18666
18700
|
entities: [],
|
|
18667
18701
|
// Entities created in apps/<app>/entities/ (v1), root entities/ for v2
|
|
18668
18702
|
billing: true,
|
|
18669
18703
|
// Always on (useStripeBillingSafe handles missing package)
|
|
18670
|
-
backend:
|
|
18704
|
+
backend: hasBackend,
|
|
18671
18705
|
features: [],
|
|
18672
18706
|
template: "vite",
|
|
18673
18707
|
// Only Vite for now
|
|
@@ -18691,6 +18725,10 @@ async function runQuestionnaire(questions, initialAnswers, showWIP, askFor) {
|
|
|
18691
18725
|
if (!showWIP) {
|
|
18692
18726
|
choices = choices.filter((choice) => !choice.wip);
|
|
18693
18727
|
}
|
|
18728
|
+
if (question.choicesFilter) {
|
|
18729
|
+
const allowed = question.choicesFilter(answers);
|
|
18730
|
+
choices = choices.filter((c) => allowed.includes(c.value));
|
|
18731
|
+
}
|
|
18694
18732
|
if (choices.length === 0) continue;
|
|
18695
18733
|
answer = await askFor.selection(question.question, choices);
|
|
18696
18734
|
break;
|
|
@@ -20114,120 +20152,22 @@ init_pathResolver();
|
|
|
20114
20152
|
|
|
20115
20153
|
// packages/tooling/src/scaffolding/scaffold-matrix.ts
|
|
20116
20154
|
init_utils();
|
|
20117
|
-
|
|
20118
|
-
|
|
20119
|
-
|
|
20120
|
-
|
|
20121
|
-
|
|
20122
|
-
overlay: null,
|
|
20123
|
-
deployConfig: null,
|
|
20124
|
-
functionsTemplate: null
|
|
20125
|
-
},
|
|
20126
|
-
{
|
|
20127
|
-
builder: "vite",
|
|
20128
|
-
backend: "firebase",
|
|
20129
|
-
baseTemplate: "app-vite",
|
|
20130
|
-
overlay: "overlay-firebase",
|
|
20131
|
-
deployConfig: "firebase",
|
|
20132
|
-
functionsTemplate: "functions-firebase"
|
|
20133
|
-
},
|
|
20134
|
-
{
|
|
20135
|
-
builder: "vite",
|
|
20136
|
-
backend: "supabase",
|
|
20137
|
-
baseTemplate: "app-vite",
|
|
20138
|
-
overlay: "overlay-supabase",
|
|
20139
|
-
deployConfig: "vercel-supabase",
|
|
20140
|
-
functionsTemplate: "functions-supabase"
|
|
20141
|
-
},
|
|
20142
|
-
{
|
|
20143
|
-
builder: "vite",
|
|
20144
|
-
backend: "vercel",
|
|
20145
|
-
baseTemplate: "app-vite",
|
|
20146
|
-
overlay: "overlay-vercel",
|
|
20147
|
-
deployConfig: "vercel-vercel",
|
|
20148
|
-
functionsTemplate: "functions-vercel"
|
|
20149
|
-
},
|
|
20150
|
-
{
|
|
20151
|
-
builder: "nextjs",
|
|
20152
|
-
backend: "none",
|
|
20153
|
-
baseTemplate: "app-next",
|
|
20154
|
-
overlay: null,
|
|
20155
|
-
deployConfig: null,
|
|
20156
|
-
functionsTemplate: null
|
|
20157
|
-
},
|
|
20158
|
-
{
|
|
20159
|
-
builder: "nextjs",
|
|
20160
|
-
backend: "firebase",
|
|
20161
|
-
baseTemplate: "app-next",
|
|
20162
|
-
overlay: "overlay-firebase",
|
|
20163
|
-
deployConfig: "firebase",
|
|
20164
|
-
functionsTemplate: "functions-firebase"
|
|
20165
|
-
},
|
|
20166
|
-
{
|
|
20167
|
-
builder: "nextjs",
|
|
20168
|
-
backend: "supabase",
|
|
20169
|
-
baseTemplate: "app-next",
|
|
20170
|
-
overlay: "overlay-supabase",
|
|
20171
|
-
deployConfig: "vercel-supabase",
|
|
20172
|
-
functionsTemplate: "functions-supabase"
|
|
20173
|
-
},
|
|
20174
|
-
{
|
|
20175
|
-
builder: "nextjs",
|
|
20176
|
-
backend: "vercel",
|
|
20177
|
-
baseTemplate: "app-next",
|
|
20178
|
-
overlay: "overlay-vercel",
|
|
20179
|
-
deployConfig: "vercel-vercel",
|
|
20180
|
-
functionsTemplate: "functions-vercel"
|
|
20181
|
-
},
|
|
20182
|
-
{
|
|
20183
|
-
builder: "expo",
|
|
20184
|
-
backend: "none",
|
|
20185
|
-
baseTemplate: "app-expo",
|
|
20186
|
-
overlay: null,
|
|
20187
|
-
deployConfig: null,
|
|
20188
|
-
functionsTemplate: null
|
|
20189
|
-
},
|
|
20190
|
-
{
|
|
20191
|
-
builder: "expo",
|
|
20192
|
-
backend: "firebase",
|
|
20193
|
-
baseTemplate: "app-expo",
|
|
20194
|
-
overlay: "overlay-firebase",
|
|
20195
|
-
deployConfig: null,
|
|
20196
|
-
functionsTemplate: "functions-firebase"
|
|
20197
|
-
},
|
|
20198
|
-
{
|
|
20199
|
-
builder: "expo",
|
|
20200
|
-
backend: "supabase",
|
|
20201
|
-
baseTemplate: "app-expo",
|
|
20202
|
-
overlay: "overlay-supabase",
|
|
20203
|
-
deployConfig: null,
|
|
20204
|
-
functionsTemplate: "functions-supabase"
|
|
20205
|
-
},
|
|
20206
|
-
{
|
|
20207
|
-
builder: "demo",
|
|
20208
|
-
backend: "none",
|
|
20209
|
-
baseTemplate: "app-demo",
|
|
20210
|
-
overlay: null,
|
|
20211
|
-
deployConfig: null,
|
|
20212
|
-
functionsTemplate: null
|
|
20213
|
-
}
|
|
20214
|
-
];
|
|
20215
|
-
function comboKey(builder, backend) {
|
|
20216
|
-
return `${builder}-${backend}`;
|
|
20217
|
-
}
|
|
20218
|
-
var ROWS_BY_KEY = /* @__PURE__ */ new Map();
|
|
20219
|
-
for (const row of MATRIX) {
|
|
20220
|
-
ROWS_BY_KEY.set(comboKey(row.builder, row.backend), row);
|
|
20155
|
+
function resolveDeployConfig(host, backend) {
|
|
20156
|
+
if (host === "none") return null;
|
|
20157
|
+
if (host === "firebase") return "firebase";
|
|
20158
|
+
if (backend === "supabase") return "vercel-supabase";
|
|
20159
|
+
return "vercel-vercel";
|
|
20221
20160
|
}
|
|
20222
|
-
function
|
|
20223
|
-
const
|
|
20224
|
-
|
|
20225
|
-
|
|
20226
|
-
|
|
20227
|
-
|
|
20228
|
-
|
|
20229
|
-
|
|
20230
|
-
|
|
20161
|
+
function getScaffoldParts(builder, host, functions, backend) {
|
|
20162
|
+
const baseTemplate = builder === "nextjs" ? "app-next" : builder === "demo" ? "app-demo" : `app-${builder}`;
|
|
20163
|
+
return {
|
|
20164
|
+
builder,
|
|
20165
|
+
backend,
|
|
20166
|
+
baseTemplate,
|
|
20167
|
+
overlay: backend !== "none" ? `overlay-${backend}` : null,
|
|
20168
|
+
deployConfig: resolveDeployConfig(host, backend),
|
|
20169
|
+
functionsTemplate: functions !== "none" ? `functions-${functions}` : null
|
|
20170
|
+
};
|
|
20231
20171
|
}
|
|
20232
20172
|
|
|
20233
20173
|
// packages/tooling/src/scaffolding/create-app.ts
|
|
@@ -20267,11 +20207,15 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
20267
20207
|
input: askForInput
|
|
20268
20208
|
});
|
|
20269
20209
|
const requirements = aggregateRequirements(answers);
|
|
20270
|
-
const
|
|
20210
|
+
const framework = answers.framework || "vite";
|
|
20211
|
+
const host2 = answers.host || "none";
|
|
20212
|
+
const functions2 = answers.functions || "none";
|
|
20213
|
+
const backend2 = answers.backend || "none";
|
|
20271
20214
|
appConfig = {
|
|
20272
|
-
template:
|
|
20273
|
-
|
|
20274
|
-
|
|
20215
|
+
template: framework,
|
|
20216
|
+
host: host2,
|
|
20217
|
+
functions: functions2,
|
|
20218
|
+
backend: backend2,
|
|
20275
20219
|
needsCRUD: true,
|
|
20276
20220
|
// Always on
|
|
20277
20221
|
selectedEntities: [],
|
|
@@ -20317,12 +20261,14 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
20317
20261
|
s.start(`Creating app: ${appName}`);
|
|
20318
20262
|
await ensureDir(appDir);
|
|
20319
20263
|
const builder = appTemplate;
|
|
20320
|
-
const
|
|
20321
|
-
const
|
|
20264
|
+
const host = appConfig.host ?? "none";
|
|
20265
|
+
const functions = appConfig.functions ?? "none";
|
|
20266
|
+
const backend = appConfig.backend ?? "none";
|
|
20267
|
+
const row = getScaffoldParts(builder, host, functions, backend);
|
|
20322
20268
|
const templateDir = row.baseTemplate;
|
|
20323
20269
|
const firebaseProjectId = (appConfig?.firebaseProjectId ?? "").trim() || appName.toLowerCase().replace(/\s+/g, "-");
|
|
20324
20270
|
const firebaseRegion = appConfig?.firebaseRegion ?? "europe-west1";
|
|
20325
|
-
const backendPlatform =
|
|
20271
|
+
const backendPlatform = backend !== "none" ? backend : "firebase";
|
|
20326
20272
|
const deployConfig = row.deployConfig;
|
|
20327
20273
|
const replacements = {
|
|
20328
20274
|
projectName: appName,
|
|
@@ -20660,11 +20606,13 @@ Happy coding!`,
|
|
|
20660
20606
|
}
|
|
20661
20607
|
async function main8(options) {
|
|
20662
20608
|
try {
|
|
20663
|
-
const hasExplicitFlags = options?.builder !== void 0 || options?.functions !== void 0;
|
|
20609
|
+
const hasExplicitFlags = options?.builder !== void 0 || options?.host !== void 0 || options?.functions !== void 0 || options?.backend !== void 0;
|
|
20664
20610
|
if (hasExplicitFlags && options?.name) {
|
|
20665
20611
|
const appName = options.name;
|
|
20666
20612
|
const builder = options.builder || "vite";
|
|
20667
|
-
const
|
|
20613
|
+
const hostOpt = options.host ?? "none";
|
|
20614
|
+
const functionsOpt = options.functions ?? "none";
|
|
20615
|
+
const backendOpt = options.backend ?? "none";
|
|
20668
20616
|
if (!isValidFileName(appName)) {
|
|
20669
20617
|
throw new Error(
|
|
20670
20618
|
`Invalid app name "${appName}". Use only letters, numbers, dashes (-), and underscores (_).`
|
|
@@ -20677,8 +20625,9 @@ async function main8(options) {
|
|
|
20677
20625
|
}
|
|
20678
20626
|
const appConfig = {
|
|
20679
20627
|
template: builder === "next" ? "nextjs" : builder === "expo" ? "expo" : "vite",
|
|
20680
|
-
|
|
20681
|
-
|
|
20628
|
+
host: hostOpt,
|
|
20629
|
+
functions: functionsOpt,
|
|
20630
|
+
backend: backendOpt,
|
|
20682
20631
|
needsCRUD: true,
|
|
20683
20632
|
selectedEntities: [],
|
|
20684
20633
|
userAuth: "social",
|
|
@@ -20710,12 +20659,11 @@ async function collectAppConfig(appName) {
|
|
|
20710
20659
|
input: askForInput
|
|
20711
20660
|
});
|
|
20712
20661
|
const framework = answers.framework || "vite";
|
|
20713
|
-
const needsBackend = answers.needsBackend || false;
|
|
20714
|
-
const defaultPlatform = framework === "nextjs" ? "vercel" : "firebase";
|
|
20715
20662
|
return {
|
|
20716
20663
|
template: framework,
|
|
20717
|
-
|
|
20718
|
-
|
|
20664
|
+
host: answers.host || "none",
|
|
20665
|
+
functions: answers.functions || "none",
|
|
20666
|
+
backend: answers.backend || "none",
|
|
20719
20667
|
needsCRUD: false,
|
|
20720
20668
|
selectedEntities: [],
|
|
20721
20669
|
userAuth: "none",
|
|
@@ -20862,7 +20810,7 @@ async function main9(options) {
|
|
|
20862
20810
|
Me(`Configuring "${trimmedName}"...`, "\u2699\uFE0F");
|
|
20863
20811
|
const config = await collectAppConfig(trimmedName);
|
|
20864
20812
|
appConfigs[trimmedName] = config;
|
|
20865
|
-
if (config.
|
|
20813
|
+
if (config.backend !== "none" || config.functions !== "none") anyAppNeedsBackend = true;
|
|
20866
20814
|
}
|
|
20867
20815
|
let installDemoApp = await askForConfirmation(
|
|
20868
20816
|
"Would you like to install the demo app? (component showcase)",
|
|
@@ -20938,8 +20886,9 @@ async function main9(options) {
|
|
|
20938
20886
|
log.warn(`Missing config for app "${appName}", using defaults`);
|
|
20939
20887
|
appConfigs[appName] = {
|
|
20940
20888
|
template: "vite",
|
|
20941
|
-
|
|
20942
|
-
|
|
20889
|
+
host: "none",
|
|
20890
|
+
functions: "none",
|
|
20891
|
+
backend: "none",
|
|
20943
20892
|
needsCRUD: false,
|
|
20944
20893
|
selectedEntities: [],
|
|
20945
20894
|
userAuth: "none",
|
|
@@ -20987,7 +20936,7 @@ async function main9(options) {
|
|
|
20987
20936
|
overwrite: true
|
|
20988
20937
|
});
|
|
20989
20938
|
const relativeMonorepoPath = executionMode === "development" ? calculateRelativePath(projectDirNormalized, monorepoRoot) : "";
|
|
20990
|
-
const primaryPlatform = Object.values(appConfigs).find((c) => c.
|
|
20939
|
+
const primaryPlatform = Object.values(appConfigs).find((c) => c.backend !== "none")?.backend ?? "firebase";
|
|
20991
20940
|
const rootPackageJson = generatePackageJson(
|
|
20992
20941
|
"consumer-root",
|
|
20993
20942
|
executionMode,
|
package/package.json
CHANGED
|
@@ -41,6 +41,14 @@ description: Extract requirements and generate complete HLD through conversation
|
|
|
41
41
|
|
|
42
42
|
## Process
|
|
43
43
|
|
|
44
|
+
### Step 0: Start Phase (MANDATORY — DO THIS FIRST)
|
|
45
|
+
|
|
46
|
+
**BEFORE asking any questions or doing any work**, call:
|
|
47
|
+
```
|
|
48
|
+
start_phase(0)
|
|
49
|
+
```
|
|
50
|
+
This activates Phase 0: BRAINSTORM and loads the blueprint, persona, context, and lessons learned from previous sessions. **Do NOT proceed without this call.**
|
|
51
|
+
|
|
44
52
|
### Step 1: Activate EXTRACTOR Agent
|
|
45
53
|
|
|
46
54
|
**Deploy:** `/agents extractor` (BMAD EXTRACTOR persona)
|
|
@@ -87,7 +95,7 @@ EXTRACTOR generates `HLD.md` with:
|
|
|
87
95
|
|
|
88
96
|
---
|
|
89
97
|
|
|
90
|
-
## Validation Gate
|
|
98
|
+
## Validation Gate & Phase Completion (MANDATORY)
|
|
91
99
|
|
|
92
100
|
**Before proceeding to `/design`:**
|
|
93
101
|
- [ ] HLD is complete (no empty sections or TBDs)
|
|
@@ -97,6 +105,12 @@ EXTRACTOR generates `HLD.md` with:
|
|
|
97
105
|
- [ ] Native vs custom analysis complete
|
|
98
106
|
- [ ] User has validated HLD
|
|
99
107
|
|
|
108
|
+
**When HLD is complete**, write the filled-out spec to `docs/HLD.md` (the template at `guides/wai-way/spec_template.md` stays untouched as reference). Then call:
|
|
109
|
+
```
|
|
110
|
+
complete_phase({ files: ["docs/HLD.md"], summary: "HLD complete — N entities, N pages, N features" })
|
|
111
|
+
```
|
|
112
|
+
Then wait for the user to call `approve_phase()` before moving to `/design`.
|
|
113
|
+
|
|
100
114
|
**Quality Over Speed:** Take as long as needed. A complete HLD that takes 4 hours is better than an incomplete one that takes 20 minutes.
|
|
101
115
|
|
|
102
116
|
---
|
|
@@ -36,6 +36,14 @@ description: Two-agent workflow: Prompt Engineer → Coder (AFTER /design)
|
|
|
36
36
|
|
|
37
37
|
## Process
|
|
38
38
|
|
|
39
|
+
### Step 0: Start Phase (MANDATORY — DO THIS FIRST)
|
|
40
|
+
|
|
41
|
+
**BEFORE writing any code**, call:
|
|
42
|
+
```
|
|
43
|
+
start_phase(3)
|
|
44
|
+
```
|
|
45
|
+
This activates Phase 3: COMPOSE and loads the blueprint, persona, context, and lessons. **Do NOT write code without this call.**
|
|
46
|
+
|
|
39
47
|
### Step 1: Activate FORGER Agent
|
|
40
48
|
|
|
41
49
|
**Deploy:** `/agents builder` (BMAD FORGER persona)
|
|
@@ -54,10 +62,19 @@ description: Two-agent workflow: Prompt Engineer → Coder (AFTER /design)
|
|
|
54
62
|
- Phase 6: Integration (wire everything together)
|
|
55
63
|
4. Use framework defaults ONLY (no styling, no customization)
|
|
56
64
|
5. Hardcode all strings (no i18n yet)
|
|
57
|
-
6.
|
|
65
|
+
6. Run `dndev tc` after every file change — type errors must be fixed immediately
|
|
66
|
+
7. Validate each phase before proceeding
|
|
58
67
|
|
|
59
68
|
**Output:** Working app (functional MVP, no styling)
|
|
60
69
|
|
|
70
|
+
### Phase Completion (MANDATORY)
|
|
71
|
+
|
|
72
|
+
When all pages are built and `dndev tc` passes, call:
|
|
73
|
+
```
|
|
74
|
+
complete_phase({ files: ["src/pages/...all page files..."], summary: "N pages composed, all type-checking" })
|
|
75
|
+
```
|
|
76
|
+
Wait for user to call `approve_phase()` before moving to `/polish`.
|
|
77
|
+
|
|
61
78
|
---
|
|
62
79
|
|
|
63
80
|
## Alternative: Two-Agent Workflow
|
|
@@ -79,10 +96,15 @@ For complex builds, you can use:
|
|
|
79
96
|
- **Builder (FORGER):** Implements exactly what's in LLD, uses framework defaults only
|
|
80
97
|
- **Framework defaults ONLY:** No styling, no customization (deferred to /polish)
|
|
81
98
|
- **Hardcode strings:** No i18n yet (deferred to /polish)
|
|
82
|
-
- **MCP required:** Use lookup_symbol for ALL components
|
|
83
99
|
- **Phase by phase:** Complete each phase before proceeding
|
|
84
100
|
- **User:** Reviews output, proceeds to /polish when functional
|
|
85
101
|
|
|
102
|
+
## STOP — lookup_symbol Before Every Component (Repeated Here On Purpose)
|
|
103
|
+
|
|
104
|
+
**STOP before writing ANY `@donotdev` import.** Call `lookup_symbol({ symbol: "Name" })` first. Do NOT guess props, hooks, or APIs. Do NOT proceed without verification. `complete_phase` will reject un-looked-up symbols.
|
|
105
|
+
|
|
106
|
+
**Import convention:** Always `@donotdev/<package>` — never sub-paths. No `@donotdev/ui/routing`, no `@donotdev/components/card`. The only exceptions are `@donotdev/core/server`, `@donotdev/core/vite`, `@donotdev/core/next`, `@donotdev/core/functions`.
|
|
107
|
+
|
|
86
108
|
## Mode Detection
|
|
87
109
|
|
|
88
110
|
**CRITICAL:** Check working mode first.
|
|
@@ -36,6 +36,21 @@ description: Design workflow: Architect → Design Document (BEFORE /build)
|
|
|
36
36
|
|
|
37
37
|
## Process
|
|
38
38
|
|
|
39
|
+
### Step 0: Start Phase (MANDATORY — DO THIS FIRST)
|
|
40
|
+
|
|
41
|
+
**BEFORE doing any design work**, call the appropriate phase:
|
|
42
|
+
```
|
|
43
|
+
start_phase(1) # for SCAFFOLD (routes, page stubs)
|
|
44
|
+
start_phase(2) # for ENTITIES (data models, fields, access)
|
|
45
|
+
```
|
|
46
|
+
This loads the blueprint, persona, context, and lessons. **Do NOT proceed without this call.**
|
|
47
|
+
|
|
48
|
+
When design work is complete, call:
|
|
49
|
+
```
|
|
50
|
+
complete_phase({ files: ["...affected files..."], summary: "Description of what was designed" })
|
|
51
|
+
```
|
|
52
|
+
Wait for user to call `approve_phase()` before moving on.
|
|
53
|
+
|
|
39
54
|
### Step 1: Architect Phase
|
|
40
55
|
|
|
41
56
|
**Deploy:** `/agents architect` (WAI-WAY architect role)
|
|
@@ -102,6 +117,8 @@ UNRESOLVED:
|
|
|
102
117
|
- **ALWAYS reference framework architecture** - stay aligned
|
|
103
118
|
- **ALWAYS identify impacts** - what breaks if we change this?
|
|
104
119
|
- **ALWAYS prepare for /build** - design should be actionable
|
|
120
|
+
- **ALWAYS use `lookup_symbol`** when referencing @donotdev components in your design — verify the API exists before putting it in the plan
|
|
121
|
+
- **Import convention:** Always `@donotdev/<package>` top-level, never sub-paths. The only exceptions are `@donotdev/core/server`, `@donotdev/core/vite`, `@donotdev/core/next`, `@donotdev/core/functions`
|
|
105
122
|
|
|
106
123
|
## Integration with WAI-WAY & BMAD
|
|
107
124
|
|
|
@@ -42,6 +42,14 @@ description: Generate tests, firestore rules, CI/CD, config, fix bugs, i18n (Pha
|
|
|
42
42
|
|
|
43
43
|
## Process
|
|
44
44
|
|
|
45
|
+
### Step 0: Start Phase (MANDATORY — DO THIS FIRST)
|
|
46
|
+
|
|
47
|
+
**BEFORE any polish work**, call:
|
|
48
|
+
```
|
|
49
|
+
start_phase(4)
|
|
50
|
+
```
|
|
51
|
+
This activates Phase 4: CONFIGURE and loads the blueprint, persona, context, and lessons. **Do NOT proceed without this call.**
|
|
52
|
+
|
|
45
53
|
### Step 1: Activate Polisher Agent
|
|
46
54
|
|
|
47
55
|
**Deploy:** `/agents polisher` (Phase 4 Polisher persona)
|
|
@@ -112,6 +120,7 @@ Extract strings to `src/locales/`, replace with `useTranslation()`.
|
|
|
112
120
|
## Ship Readiness
|
|
113
121
|
|
|
114
122
|
App is ready to ship when:
|
|
123
|
+
- ✅ `dndev tc` passes
|
|
115
124
|
- ✅ `bun test` passes
|
|
116
125
|
- ✅ `firestore.rules` generated
|
|
117
126
|
- ✅ `.github/workflows/ci.yml` created
|
|
@@ -121,6 +130,14 @@ App is ready to ship when:
|
|
|
121
130
|
- ✅ Configuration complete
|
|
122
131
|
- ✅ (Optional) i18n added
|
|
123
132
|
|
|
133
|
+
## Phase Completion (MANDATORY)
|
|
134
|
+
|
|
135
|
+
When all ship readiness checks pass, call:
|
|
136
|
+
```
|
|
137
|
+
complete_phase({ files: ["...all test/config files..."], summary: "Tests passing, config complete, ready to ship" })
|
|
138
|
+
```
|
|
139
|
+
Wait for user to call `approve_phase()`.
|
|
140
|
+
|
|
124
141
|
---
|
|
125
142
|
|
|
126
143
|
## Next Step
|