@donotdev/cli 0.0.7 → 0.0.9
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 +3 -18
- package/dependencies-matrix.json +54 -45
- package/dist/bin/commands/build.js +19 -5
- package/dist/bin/commands/bump.js +30 -5
- package/dist/bin/commands/cacheout.js +36 -19
- package/dist/bin/commands/create-app.js +73 -7
- package/dist/bin/commands/create-project.js +90 -8
- package/dist/bin/commands/deploy.js +130 -27
- package/dist/bin/commands/dev.js +23 -7
- package/dist/bin/commands/emu.js +28 -12
- package/dist/bin/commands/format.js +39 -22
- package/dist/bin/commands/lint.js +36 -19
- package/dist/bin/commands/preview.js +24 -8
- package/dist/bin/commands/sync-secrets.js +19 -5
- package/dist/bin/dndev.js +7 -20
- package/dist/bin/donotdev.js +7 -20
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +209 -100
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/templates/app-next/src/config/app.ts.example +1 -1
- package/templates/app-vite/index.html.example +24 -2
- package/templates/app-vite/src/config/app.ts.example +1 -1
- package/templates/app-vite/src/pages/FormPageExample.tsx.example +8 -5
- package/templates/app-vite/src/pages/ListPageExample.tsx.example +4 -7
- package/templates/root-consumer/.firebaserc.example +5 -0
- package/templates/root-consumer/entities/ExampleEntity.ts.example +2 -1
- package/templates/root-consumer/entities/demo.ts.example +15 -1
- package/templates/root-consumer/eslint.config.js.example +2 -80
- package/templates/root-consumer/firestore.indexes.json.example +4 -0
- package/templates/root-consumer/firestore.rules.example +11 -0
- package/templates/root-consumer/guides/dndev/COMPONENTS_CRUD.md.example +9 -6
- package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +376 -38
- package/templates/root-consumer/guides/dndev/SETUP_I18N.md.example +46 -0
- package/templates/root-consumer/guides/wai-way/entity_patterns.md.example +1 -1
- package/templates/root-consumer/storage.rules.example +8 -0
package/dist/bin/donotdev.js
CHANGED
|
@@ -46,13 +46,12 @@ Usage: dndev <command>[:<app>] [options]
|
|
|
46
46
|
|
|
47
47
|
Commands:
|
|
48
48
|
init, create-project Create a new DoNotDev project
|
|
49
|
-
create-app [name] Add app
|
|
49
|
+
create-app [name] Add app (--builder vite|next, --functions, --project <id>)
|
|
50
50
|
dev [app] Start development server
|
|
51
51
|
build [app] Build for production
|
|
52
52
|
preview [app] Preview production build
|
|
53
53
|
emu [app] Start dev with Firebase emulators
|
|
54
54
|
format Format code with Prettier
|
|
55
|
-
lint Lint code with ESLint
|
|
56
55
|
deploy [app] Deploy to Firebase
|
|
57
56
|
sync-secrets Sync env vars to Firebase/Vercel
|
|
58
57
|
cacheout [app] Clear build caches
|
|
@@ -67,7 +66,8 @@ Examples:
|
|
|
67
66
|
dndev init my-project Create a new project
|
|
68
67
|
dndev create-app Interactive app creation
|
|
69
68
|
dndev create-app my-app Create 'my-app' with defaults (vite, no functions)
|
|
70
|
-
dndev create-app my-app --builder next --functions
|
|
69
|
+
dndev create-app my-app --builder next --functions Next.js + functions
|
|
70
|
+
dndev create-app my-app --functions --project my-fb-id Set Firebase project (2-min setup)
|
|
71
71
|
dndev dev Start dev server
|
|
72
72
|
dndev dev:web Start dev server for 'web' app
|
|
73
73
|
dndev wai Output WAI-WAY activation prompt
|
|
@@ -91,14 +91,16 @@ program.command("init [name]").alias("create-project").description("Create a new
|
|
|
91
91
|
const { main } = await import("./commands/create-project.js");
|
|
92
92
|
await main({ projectName: name });
|
|
93
93
|
});
|
|
94
|
-
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 next (default: vite)").option("--functions", "Include Firebase functions").action(async (name, options) => {
|
|
94
|
+
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 next (default: vite)").option("--functions", "Include Firebase functions").option("--project <id>", "Firebase project ID (default: app name)").option("--region <region>", "Firebase region (default: europe-west1)").action(async (name, options) => {
|
|
95
95
|
const { main } = await import("./commands/create-app.js");
|
|
96
96
|
const appName = name || options.name;
|
|
97
97
|
if (appName) {
|
|
98
98
|
await main({
|
|
99
99
|
name: appName,
|
|
100
100
|
builder: options.builder,
|
|
101
|
-
functions: options.functions
|
|
101
|
+
functions: options.functions,
|
|
102
|
+
firebaseProjectId: options.project,
|
|
103
|
+
firebaseRegion: options.region
|
|
102
104
|
});
|
|
103
105
|
} else {
|
|
104
106
|
await main();
|
|
@@ -119,21 +121,6 @@ formatCmd.action(async (commanderOptions) => {
|
|
|
119
121
|
throw error;
|
|
120
122
|
}
|
|
121
123
|
});
|
|
122
|
-
var lintCmd = program.command("lint").description("Lint code with ESLint").option("-f, --fix", "automatically fix issues");
|
|
123
|
-
addCommonOptions(lintCmd);
|
|
124
|
-
lintCmd.action(async (commanderOptions) => {
|
|
125
|
-
const commonOptions = extractCommonOptions(commanderOptions);
|
|
126
|
-
const options = { ...commonOptions, ...commanderOptions };
|
|
127
|
-
try {
|
|
128
|
-
const { main } = await import("./commands/lint.js");
|
|
129
|
-
await main(options);
|
|
130
|
-
} catch (error) {
|
|
131
|
-
if (error.code === "invalid-argument" || error.name === "DoNotDevError") {
|
|
132
|
-
process.exit(error.context?.exitCode || 1);
|
|
133
|
-
}
|
|
134
|
-
throw error;
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
124
|
var cacheoutCmd = program.command("cacheout [app]").alias("co").description("Clear build caches").option("--app <app>", "App name to clear cache for");
|
|
138
125
|
addCommonOptions(cacheoutCmd);
|
|
139
126
|
cacheoutCmd.action(async (app, commanderOptions) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* Thin wrapper around @donotdev/tooling for public distribution.
|
|
5
5
|
* Tooling is the source of truth for all CLI code.
|
|
6
6
|
*/
|
|
7
|
-
export { createApp, createProject, format,
|
|
7
|
+
export { createApp, createProject, format, dev, build, preview, emu, cacheout, syncSecrets, deploy, } from '@donotdev/tooling';
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAGH,OAAO,EACL,SAAS,EACT,aAAa,EACb,MAAM,EACN,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAGH,OAAO,EACL,SAAS,EACT,aAAa,EACb,MAAM,EACN,GAAG,EACH,KAAK,EACL,OAAO,EACP,GAAG,EACH,QAAQ,EACR,WAAW,EACX,MAAM,GACP,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -897,6 +897,7 @@ __export(cli_output_exports, {
|
|
|
897
897
|
success: () => success,
|
|
898
898
|
warn: () => warn
|
|
899
899
|
});
|
|
900
|
+
import "node:os";
|
|
900
901
|
function supportsColor() {
|
|
901
902
|
if (process.env.NO_COLOR) return false;
|
|
902
903
|
if (process.platform === "win32") {
|
|
@@ -6730,7 +6731,16 @@ var init_constants = __esm({
|
|
|
6730
6731
|
},
|
|
6731
6732
|
i18n: {
|
|
6732
6733
|
eager: ["src/locales/*_*.json"],
|
|
6733
|
-
lazy: [
|
|
6734
|
+
lazy: [
|
|
6735
|
+
"src/**/locales/*_*.json",
|
|
6736
|
+
"!src/locales/*_*.json",
|
|
6737
|
+
// Auto-detect shared entity translations in monorepos (if exists, use it; if not, no problem)
|
|
6738
|
+
"../../entities/locales/*_*.json"
|
|
6739
|
+
],
|
|
6740
|
+
// Additional paths from workspace packages (e.g., shared entities)
|
|
6741
|
+
// Consumers can still configure via i18n.additionalPaths in dndev/vite config for custom paths
|
|
6742
|
+
// Example: ['../../packages/shared/locales/*_*.json']
|
|
6743
|
+
additional: [],
|
|
6734
6744
|
framework: {
|
|
6735
6745
|
eager: [`${I18N_PATHS.SOURCE_EAGER}/*_*.json`],
|
|
6736
6746
|
lazy: [`${I18N_PATHS.SOURCE_LAZY}/*_*.json`]
|
|
@@ -6823,6 +6833,7 @@ var init_constants = __esm({
|
|
|
6823
6833
|
|
|
6824
6834
|
// packages/core/config/utils/PathResolver.ts
|
|
6825
6835
|
import * as fs from "node:fs";
|
|
6836
|
+
import "node:fs";
|
|
6826
6837
|
import { createRequire } from "node:module";
|
|
6827
6838
|
import {
|
|
6828
6839
|
resolve,
|
|
@@ -8290,6 +8301,7 @@ var init_pathResolver = __esm({
|
|
|
8290
8301
|
|
|
8291
8302
|
// packages/tooling/src/bundler/utils.ts
|
|
8292
8303
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
8304
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "node:fs";
|
|
8293
8305
|
import { createRequire as createRequire3 } from "node:module";
|
|
8294
8306
|
import { dirname as dirname3, resolve as resolve3 } from "node:path";
|
|
8295
8307
|
import process from "node:process";
|
|
@@ -8791,8 +8803,10 @@ function executeFirebaseCommand(args, options) {
|
|
|
8791
8803
|
errorOutput
|
|
8792
8804
|
};
|
|
8793
8805
|
}
|
|
8794
|
-
function buildFirebaseDeployArgs(
|
|
8795
|
-
const
|
|
8806
|
+
function buildFirebaseDeployArgs(deployTargets, projectId, debug, force) {
|
|
8807
|
+
const targets = Array.isArray(deployTargets) ? deployTargets : [deployTargets];
|
|
8808
|
+
const targetString = targets.join(",");
|
|
8809
|
+
const args = ["deploy", "--only", targetString, "--non-interactive"];
|
|
8796
8810
|
if (projectId) {
|
|
8797
8811
|
args.push("--project", projectId);
|
|
8798
8812
|
}
|
|
@@ -10200,6 +10214,47 @@ To fix this, run:
|
|
|
10200
10214
|
}
|
|
10201
10215
|
}
|
|
10202
10216
|
|
|
10217
|
+
// packages/tooling/src/apps/deploy-rules.ts
|
|
10218
|
+
init_utils();
|
|
10219
|
+
async function deployRules(appDir, serviceAccountPath, projectId, config, options) {
|
|
10220
|
+
const targets = [];
|
|
10221
|
+
if (options.firestore) {
|
|
10222
|
+
targets.push("firestore:rules");
|
|
10223
|
+
}
|
|
10224
|
+
if (options.firestoreIndexes) {
|
|
10225
|
+
targets.push("firestore:indexes");
|
|
10226
|
+
}
|
|
10227
|
+
if (options.storage) {
|
|
10228
|
+
targets.push("storage");
|
|
10229
|
+
}
|
|
10230
|
+
if (targets.length === 0) {
|
|
10231
|
+
return;
|
|
10232
|
+
}
|
|
10233
|
+
const targetNames = targets.join(", ");
|
|
10234
|
+
const s = Y2();
|
|
10235
|
+
s.start(`Deploying ${targetNames}...`);
|
|
10236
|
+
const args = buildFirebaseDeployArgs(targets, projectId, config.debug);
|
|
10237
|
+
const result = executeFirebaseCommand(args, {
|
|
10238
|
+
cwd: appDir,
|
|
10239
|
+
serviceAccountPath,
|
|
10240
|
+
projectId,
|
|
10241
|
+
debug: config.debug
|
|
10242
|
+
});
|
|
10243
|
+
if (result.error) {
|
|
10244
|
+
s.stop("Rules deployment failed");
|
|
10245
|
+
throw result.error;
|
|
10246
|
+
}
|
|
10247
|
+
if (!result.success) {
|
|
10248
|
+
s.stop("Rules deployment failed");
|
|
10249
|
+
handleDeploymentFailure(
|
|
10250
|
+
result,
|
|
10251
|
+
`firebase ${args.join(" ")}`,
|
|
10252
|
+
serviceAccountPath
|
|
10253
|
+
);
|
|
10254
|
+
}
|
|
10255
|
+
s.stop(`${targetNames} deployed successfully`);
|
|
10256
|
+
}
|
|
10257
|
+
|
|
10203
10258
|
// packages/tooling/src/apps/deploy-utils.ts
|
|
10204
10259
|
init_utils();
|
|
10205
10260
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
@@ -10320,6 +10375,9 @@ function validateFirebaseJson2(appDir) {
|
|
|
10320
10375
|
valid: false,
|
|
10321
10376
|
hasHosting: false,
|
|
10322
10377
|
hasFunctions: false,
|
|
10378
|
+
hasFirestoreRules: false,
|
|
10379
|
+
hasFirestoreIndexes: false,
|
|
10380
|
+
hasStorageRules: false,
|
|
10323
10381
|
errors: [`firebase.json not found at: ${firebaseJsonPath}`]
|
|
10324
10382
|
};
|
|
10325
10383
|
}
|
|
@@ -10332,11 +10390,17 @@ function validateFirebaseJson2(appDir) {
|
|
|
10332
10390
|
}
|
|
10333
10391
|
const hasHosting = !!config.hosting;
|
|
10334
10392
|
const hasFunctions = !!config.functions && Array.isArray(config.functions);
|
|
10393
|
+
const hasFirestoreRules = !!config.firestore?.rules && pathExists(joinPath(appDir, config.firestore.rules));
|
|
10394
|
+
const hasFirestoreIndexes = !!config.firestore?.indexes && pathExists(joinPath(appDir, config.firestore.indexes));
|
|
10395
|
+
const hasStorageRules = !!config.storage?.rules && pathExists(joinPath(appDir, config.storage.rules));
|
|
10335
10396
|
return {
|
|
10336
10397
|
valid: true,
|
|
10337
10398
|
projectId: config.projectId,
|
|
10338
10399
|
hasHosting,
|
|
10339
10400
|
hasFunctions,
|
|
10401
|
+
hasFirestoreRules,
|
|
10402
|
+
hasFirestoreIndexes,
|
|
10403
|
+
hasStorageRules,
|
|
10340
10404
|
errors: []
|
|
10341
10405
|
};
|
|
10342
10406
|
} catch (error2) {
|
|
@@ -10344,6 +10408,9 @@ function validateFirebaseJson2(appDir) {
|
|
|
10344
10408
|
valid: false,
|
|
10345
10409
|
hasHosting: false,
|
|
10346
10410
|
hasFunctions: false,
|
|
10411
|
+
hasFirestoreRules: false,
|
|
10412
|
+
hasFirestoreIndexes: false,
|
|
10413
|
+
hasStorageRules: false,
|
|
10347
10414
|
errors: [
|
|
10348
10415
|
`Invalid JSON format: ${error2 instanceof DoNotDevError ? error2.message : error2 instanceof Error ? error2.message : String(error2)}`
|
|
10349
10416
|
]
|
|
@@ -10508,16 +10575,36 @@ async function main5(options = {}) {
|
|
|
10508
10575
|
hint: "Deploy cloud functions"
|
|
10509
10576
|
});
|
|
10510
10577
|
}
|
|
10578
|
+
const hasRules = firebaseConfig2.hasFirestoreRules || firebaseConfig2.hasFirestoreIndexes || firebaseConfig2.hasStorageRules;
|
|
10579
|
+
if (hasRules) {
|
|
10580
|
+
choices.push({
|
|
10581
|
+
title: "Rules only",
|
|
10582
|
+
value: "rules",
|
|
10583
|
+
hint: "Deploy Firestore/Storage rules"
|
|
10584
|
+
});
|
|
10585
|
+
}
|
|
10511
10586
|
if (firebaseConfig2.hasHosting && firebaseConfig2.hasFunctions) {
|
|
10512
10587
|
choices.push({
|
|
10513
|
-
title: "
|
|
10588
|
+
title: "Frontend + Functions",
|
|
10514
10589
|
value: "both",
|
|
10515
|
-
hint: "Deploy
|
|
10590
|
+
hint: "Deploy hosting and functions"
|
|
10591
|
+
});
|
|
10592
|
+
}
|
|
10593
|
+
const deployableKindsCount = [
|
|
10594
|
+
firebaseConfig2.hasHosting,
|
|
10595
|
+
firebaseConfig2.hasFunctions,
|
|
10596
|
+
hasRules
|
|
10597
|
+
].filter(Boolean).length;
|
|
10598
|
+
if (deployableKindsCount > 1) {
|
|
10599
|
+
choices.push({
|
|
10600
|
+
title: "All",
|
|
10601
|
+
value: "all",
|
|
10602
|
+
hint: "Deploy everything (hosting, functions, rules)"
|
|
10516
10603
|
});
|
|
10517
10604
|
}
|
|
10518
10605
|
if (choices.length === 0) {
|
|
10519
10606
|
log.error(
|
|
10520
|
-
"No deployment targets found. firebase.json must have hosting or
|
|
10607
|
+
"No deployment targets found. firebase.json must have hosting, functions, or rules configuration."
|
|
10521
10608
|
);
|
|
10522
10609
|
process.exit(1);
|
|
10523
10610
|
}
|
|
@@ -10562,13 +10649,28 @@ async function main5(options = {}) {
|
|
|
10562
10649
|
showFirebaseJsonError(firebaseConfig.errors, appDir, deploymentType);
|
|
10563
10650
|
process.exit(1);
|
|
10564
10651
|
}
|
|
10565
|
-
|
|
10566
|
-
|
|
10567
|
-
|
|
10568
|
-
|
|
10569
|
-
|
|
10570
|
-
|
|
10571
|
-
|
|
10652
|
+
const shouldDeployFrontend = (deploymentType === "frontend" || deploymentType === "both" || deploymentType === "all") && firebaseConfig.hasHosting;
|
|
10653
|
+
const shouldDeployFunctions = (deploymentType === "functions" || deploymentType === "both" || deploymentType === "all") && firebaseConfig.hasFunctions;
|
|
10654
|
+
const shouldDeployRules = (deploymentType === "rules" || deploymentType === "all") && (firebaseConfig.hasFirestoreRules || firebaseConfig.hasFirestoreIndexes || firebaseConfig.hasStorageRules);
|
|
10655
|
+
if (deploymentType === "frontend" && !firebaseConfig.hasHosting) {
|
|
10656
|
+
log.error(
|
|
10657
|
+
"firebase.json does not contain hosting configuration, but frontend deployment was requested."
|
|
10658
|
+
);
|
|
10659
|
+
process.exit(1);
|
|
10660
|
+
}
|
|
10661
|
+
if (deploymentType === "functions" && !firebaseConfig.hasFunctions) {
|
|
10662
|
+
log.error(
|
|
10663
|
+
"firebase.json does not contain functions configuration, but functions deployment was requested."
|
|
10664
|
+
);
|
|
10665
|
+
process.exit(1);
|
|
10666
|
+
}
|
|
10667
|
+
if (deploymentType === "rules" && !shouldDeployRules) {
|
|
10668
|
+
log.error(
|
|
10669
|
+
"firebase.json does not contain rules configuration, but rules deployment was requested."
|
|
10670
|
+
);
|
|
10671
|
+
process.exit(1);
|
|
10672
|
+
}
|
|
10673
|
+
if (shouldDeployFrontend) {
|
|
10572
10674
|
const buildStatus = validateBuild(appDir);
|
|
10573
10675
|
let shouldBuild = false;
|
|
10574
10676
|
if (!buildStatus.exists || buildStatus.isEmpty) {
|
|
@@ -10611,14 +10713,6 @@ async function main5(options = {}) {
|
|
|
10611
10713
|
}
|
|
10612
10714
|
}
|
|
10613
10715
|
}
|
|
10614
|
-
if (deploymentType === "functions" || deploymentType === "both") {
|
|
10615
|
-
if (!firebaseConfig.hasFunctions) {
|
|
10616
|
-
log.error(
|
|
10617
|
-
"firebase.json does not contain functions configuration, but functions deployment was requested."
|
|
10618
|
-
);
|
|
10619
|
-
process.exit(1);
|
|
10620
|
-
}
|
|
10621
|
-
}
|
|
10622
10716
|
clearFirebaseCache(appDir);
|
|
10623
10717
|
Me(
|
|
10624
10718
|
`App: ${appName}
|
|
@@ -10627,10 +10721,10 @@ Deployment: ${deploymentType}
|
|
|
10627
10721
|
Service Account: ${serviceAccountResult.info.clientEmail}`,
|
|
10628
10722
|
"Deployment Configuration"
|
|
10629
10723
|
);
|
|
10630
|
-
if (
|
|
10724
|
+
if (shouldDeployFrontend) {
|
|
10631
10725
|
await deployFrontend(appDir, serviceAccountPath, config.project, config);
|
|
10632
10726
|
}
|
|
10633
|
-
if (
|
|
10727
|
+
if (shouldDeployFunctions) {
|
|
10634
10728
|
await deployFunctions(
|
|
10635
10729
|
appDir,
|
|
10636
10730
|
serviceAccountPath,
|
|
@@ -10638,6 +10732,13 @@ Service Account: ${serviceAccountResult.info.clientEmail}`,
|
|
|
10638
10732
|
config
|
|
10639
10733
|
);
|
|
10640
10734
|
}
|
|
10735
|
+
if (shouldDeployRules) {
|
|
10736
|
+
await deployRules(appDir, serviceAccountPath, config.project, config, {
|
|
10737
|
+
firestore: firebaseConfig.hasFirestoreRules,
|
|
10738
|
+
firestoreIndexes: firebaseConfig.hasFirestoreIndexes,
|
|
10739
|
+
storage: firebaseConfig.hasStorageRules
|
|
10740
|
+
});
|
|
10741
|
+
}
|
|
10641
10742
|
Se("Deployment completed successfully!");
|
|
10642
10743
|
} catch (error2) {
|
|
10643
10744
|
if (error2 instanceof DoNotDevError) {
|
|
@@ -11168,7 +11269,7 @@ function generatePackageJson(templateName, mode, options = {}) {
|
|
|
11168
11269
|
"dependencies-matrix.json not found. This command requires the matrix file."
|
|
11169
11270
|
);
|
|
11170
11271
|
}
|
|
11171
|
-
const { matrix
|
|
11272
|
+
const { matrix } = matrixResult;
|
|
11172
11273
|
const template = matrix.templateMapping?.[templateName];
|
|
11173
11274
|
if (!template) {
|
|
11174
11275
|
throw new Error(`Template "${templateName}" not found in matrix`);
|
|
@@ -11232,6 +11333,7 @@ function generatePackageJson(templateName, mode, options = {}) {
|
|
|
11232
11333
|
}
|
|
11233
11334
|
}
|
|
11234
11335
|
if (templateName.includes("functions")) {
|
|
11336
|
+
result.main = "lib/index.js";
|
|
11235
11337
|
result.engines = { node: "20" };
|
|
11236
11338
|
if (options.appName) {
|
|
11237
11339
|
const platform = templateName.includes("vercel") ? "Vercel" : "Firebase";
|
|
@@ -11250,6 +11352,23 @@ function generatePackageJson(templateName, mode, options = {}) {
|
|
|
11250
11352
|
}
|
|
11251
11353
|
}
|
|
11252
11354
|
}
|
|
11355
|
+
if (mode === "published") {
|
|
11356
|
+
const overrides = {};
|
|
11357
|
+
for (const [groupName, group] of Object.entries(matrix.groups || {})) {
|
|
11358
|
+
if (groupName.startsWith("@donotdev/")) {
|
|
11359
|
+
const version = group.packages?.[groupName];
|
|
11360
|
+
if (version) {
|
|
11361
|
+
overrides[groupName] = version.replace(/^\^/, "");
|
|
11362
|
+
}
|
|
11363
|
+
}
|
|
11364
|
+
}
|
|
11365
|
+
if (matrix.overrides) {
|
|
11366
|
+
Object.assign(overrides, matrix.overrides);
|
|
11367
|
+
}
|
|
11368
|
+
if (Object.keys(overrides).length > 0) {
|
|
11369
|
+
result.overrides = overrides;
|
|
11370
|
+
}
|
|
11371
|
+
}
|
|
11253
11372
|
return result;
|
|
11254
11373
|
}
|
|
11255
11374
|
|
|
@@ -11342,6 +11461,8 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
11342
11461
|
s.start(`Creating app: ${appName}`);
|
|
11343
11462
|
await ensureDir(appDir);
|
|
11344
11463
|
const templateDir = appTemplate === "demo" ? "app-demo" : appTemplate === "nextjs" ? "app-next" : "app-vite";
|
|
11464
|
+
const firebaseProjectId = (appConfig?.firebaseProjectId ?? "").trim() || appName.toLowerCase().replace(/\s+/g, "-");
|
|
11465
|
+
const firebaseRegion = appConfig?.firebaseRegion ?? "europe-west1";
|
|
11345
11466
|
const replacements = {
|
|
11346
11467
|
projectName: appName,
|
|
11347
11468
|
appName,
|
|
@@ -11350,11 +11471,14 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
11350
11471
|
needsCRUD: Boolean(appConfig.needsCRUD),
|
|
11351
11472
|
setupGithubActions: false,
|
|
11352
11473
|
appNames: [appName],
|
|
11353
|
-
firebaseProjectId
|
|
11474
|
+
firebaseProjectId,
|
|
11475
|
+
firebaseRegion,
|
|
11354
11476
|
firebaseSecretName: appName.toUpperCase().replace(/-/g, "_"),
|
|
11355
11477
|
monorepoRelativePath: "../../packages/tooling",
|
|
11356
11478
|
appTemplate,
|
|
11357
|
-
isNextjs: appTemplate === "nextjs"
|
|
11479
|
+
isNextjs: appTemplate === "nextjs",
|
|
11480
|
+
YOUR_FIREBASE_PROJECT_ID: firebaseProjectId,
|
|
11481
|
+
YOUR_REGION: firebaseRegion
|
|
11358
11482
|
};
|
|
11359
11483
|
const templateSourceDir = joinPath(templatesRoot, templateDir);
|
|
11360
11484
|
const templateFiles = await glob("**/*", {
|
|
@@ -11447,6 +11571,32 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
11447
11571
|
await replacePlaceholders(firebaseJsonDest, replacements);
|
|
11448
11572
|
}
|
|
11449
11573
|
}
|
|
11574
|
+
const firebasercSource = joinPath(
|
|
11575
|
+
deploymentTemplateDir,
|
|
11576
|
+
".firebaserc.example"
|
|
11577
|
+
);
|
|
11578
|
+
if (pathExists(firebasercSource)) {
|
|
11579
|
+
const firebasercDest = joinPath(appDir, ".firebaserc");
|
|
11580
|
+
await copy(firebasercSource, firebasercDest);
|
|
11581
|
+
if (await isTextFile(firebasercDest)) {
|
|
11582
|
+
await replacePlaceholders(firebasercDest, replacements);
|
|
11583
|
+
}
|
|
11584
|
+
}
|
|
11585
|
+
if (appConfig.needsBackend && appConfig.backendPlatform === "firebase") {
|
|
11586
|
+
const rulesFiles = [
|
|
11587
|
+
"firestore.rules.example",
|
|
11588
|
+
"firestore.indexes.json.example",
|
|
11589
|
+
"storage.rules.example"
|
|
11590
|
+
];
|
|
11591
|
+
for (const example of rulesFiles) {
|
|
11592
|
+
const src = joinPath(deploymentTemplateDir, example);
|
|
11593
|
+
if (pathExists(src)) {
|
|
11594
|
+
const destName = example.replace(".example", "");
|
|
11595
|
+
const dest = joinPath(appDir, destName);
|
|
11596
|
+
await copy(src, dest);
|
|
11597
|
+
}
|
|
11598
|
+
}
|
|
11599
|
+
}
|
|
11450
11600
|
if (appTemplate === "nextjs" || appConfig.needsBackend && appConfig.backendPlatform === "vercel") {
|
|
11451
11601
|
const vercelJsonSource = joinPath(
|
|
11452
11602
|
deploymentTemplateDir,
|
|
@@ -11472,12 +11622,15 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
11472
11622
|
}
|
|
11473
11623
|
if (isInteractive) {
|
|
11474
11624
|
Se("\u{1F389} App created successfully!");
|
|
11625
|
+
const firebaseStep = appConfig.needsBackend && appConfig.backendPlatform === "firebase" ? `2. Set Firebase project: cd apps/${appName} && firebase use --add (or edit .firebase rc)
|
|
11626
|
+
3. bun install
|
|
11627
|
+
4. bun run dev` : `2. bun install
|
|
11628
|
+
3. bun run dev`;
|
|
11475
11629
|
Me(
|
|
11476
11630
|
`Next steps:
|
|
11477
11631
|
|
|
11478
11632
|
1. cd apps/${appName}
|
|
11479
|
-
|
|
11480
|
-
3. bun run dev
|
|
11633
|
+
${firebaseStep}
|
|
11481
11634
|
|
|
11482
11635
|
Happy coding!`,
|
|
11483
11636
|
"\u{1F4CB} Next Steps"
|
|
@@ -11509,7 +11662,9 @@ async function main7(options) {
|
|
|
11509
11662
|
selectedEntities: [],
|
|
11510
11663
|
userAuth: "social",
|
|
11511
11664
|
billing: true,
|
|
11512
|
-
features: []
|
|
11665
|
+
features: [],
|
|
11666
|
+
firebaseProjectId: options.firebaseProjectId,
|
|
11667
|
+
firebaseRegion: options.firebaseRegion
|
|
11513
11668
|
};
|
|
11514
11669
|
await createApp(appName, appConfig);
|
|
11515
11670
|
} else {
|
|
@@ -11849,6 +12004,8 @@ async function main8(options) {
|
|
|
11849
12004
|
overwrite: true
|
|
11850
12005
|
});
|
|
11851
12006
|
const rootTemplateDir = joinPath(templatesRoot, "root-consumer");
|
|
12007
|
+
const firebaseProjectId = projectName.toLowerCase().replace(/\s+/g, "-");
|
|
12008
|
+
const firebaseRegion = "europe-west1";
|
|
11852
12009
|
const rootReplacements = {
|
|
11853
12010
|
projectName,
|
|
11854
12011
|
appNames: isMergeMode ? allAppNames : appNames,
|
|
@@ -11857,12 +12014,22 @@ async function main8(options) {
|
|
|
11857
12014
|
monorepoRelativePath: relativeMonorepoPath,
|
|
11858
12015
|
appTemplate: "vite",
|
|
11859
12016
|
isNextjs: false,
|
|
11860
|
-
firebaseProjectId
|
|
12017
|
+
firebaseProjectId,
|
|
12018
|
+
firebaseRegion,
|
|
11861
12019
|
firebaseSecretName: projectName.toUpperCase().replace(/-/g, "_"),
|
|
12020
|
+
YOUR_FIREBASE_PROJECT_ID: firebaseProjectId,
|
|
12021
|
+
YOUR_REGION: firebaseRegion,
|
|
11862
12022
|
needsAuth,
|
|
11863
12023
|
needsOAuth,
|
|
11864
12024
|
needsBilling
|
|
11865
12025
|
};
|
|
12026
|
+
const firebaseRootFiles = /* @__PURE__ */ new Set([
|
|
12027
|
+
"firebase.json.example",
|
|
12028
|
+
".firebaserc.example",
|
|
12029
|
+
"firestore.rules.example",
|
|
12030
|
+
"firestore.indexes.json.example",
|
|
12031
|
+
"storage.rules.example"
|
|
12032
|
+
]);
|
|
11866
12033
|
const files = await glob("**/*", {
|
|
11867
12034
|
cwd: rootTemplateDir,
|
|
11868
12035
|
dot: true,
|
|
@@ -11870,6 +12037,7 @@ async function main8(options) {
|
|
|
11870
12037
|
});
|
|
11871
12038
|
for (const file of files) {
|
|
11872
12039
|
if (file === "package.json.example") continue;
|
|
12040
|
+
if (firebaseRootFiles.has(file)) continue;
|
|
11873
12041
|
const sourcePath = joinPath(rootTemplateDir, file);
|
|
11874
12042
|
let destFileName = file;
|
|
11875
12043
|
if (destFileName.endsWith(".example")) {
|
|
@@ -11944,6 +12112,8 @@ async function main8(options) {
|
|
|
11944
12112
|
}
|
|
11945
12113
|
}
|
|
11946
12114
|
if (installDemoApp) {
|
|
12115
|
+
const demoFirebaseProjectId = projectName.toLowerCase().replace(/\s+/g, "-");
|
|
12116
|
+
const demoFirebaseRegion = "europe-west1";
|
|
11947
12117
|
await copyTemplateFiles(demoTemplateDir, demoAppDir, {
|
|
11948
12118
|
projectName,
|
|
11949
12119
|
appName: "demo",
|
|
@@ -11951,8 +12121,11 @@ async function main8(options) {
|
|
|
11951
12121
|
needsCRUD: false,
|
|
11952
12122
|
setupGithubActions: false,
|
|
11953
12123
|
appNames,
|
|
11954
|
-
firebaseProjectId:
|
|
12124
|
+
firebaseProjectId: demoFirebaseProjectId,
|
|
12125
|
+
firebaseRegion: demoFirebaseRegion,
|
|
11955
12126
|
firebaseSecretName: projectName.toUpperCase().replace(/-/g, "_"),
|
|
12127
|
+
YOUR_FIREBASE_PROJECT_ID: demoFirebaseProjectId,
|
|
12128
|
+
YOUR_REGION: demoFirebaseRegion,
|
|
11956
12129
|
monorepoRelativePath: executionMode === "development" ? calculateRelativePath(projectDirNormalized, monorepoRoot) : "",
|
|
11957
12130
|
appTemplate: "demo"
|
|
11958
12131
|
});
|
|
@@ -12006,7 +12179,7 @@ init_cli_output();
|
|
|
12006
12179
|
init_errors();
|
|
12007
12180
|
init_pathResolver();
|
|
12008
12181
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
12009
|
-
import { EOL } from "node:os";
|
|
12182
|
+
import { EOL as EOL2 } from "node:os";
|
|
12010
12183
|
async function main9(options = {}) {
|
|
12011
12184
|
const dryRun = options.dryRun ?? false;
|
|
12012
12185
|
const verbose = options.verbose ?? false;
|
|
@@ -12124,7 +12297,7 @@ async function addPathComments(files, rootDir, dryRun, verbose) {
|
|
|
12124
12297
|
let modified = false;
|
|
12125
12298
|
if (contentLines.length === 0) {
|
|
12126
12299
|
if (!dryRun) {
|
|
12127
|
-
writeSync(file, `${expectedPathComment}${
|
|
12300
|
+
writeSync(file, `${expectedPathComment}${EOL2}`, {
|
|
12128
12301
|
overwrite: true
|
|
12129
12302
|
});
|
|
12130
12303
|
}
|
|
@@ -12249,7 +12422,7 @@ async function addPathComments(files, rootDir, dryRun, verbose) {
|
|
|
12249
12422
|
newLines.push("");
|
|
12250
12423
|
}
|
|
12251
12424
|
newLines.push(...contentLines);
|
|
12252
|
-
const newContent = newLines.join(
|
|
12425
|
+
const newContent = newLines.join(EOL2);
|
|
12253
12426
|
const contentChanged = fileContent !== newContent;
|
|
12254
12427
|
if (contentChanged) {
|
|
12255
12428
|
try {
|
|
@@ -12576,69 +12749,6 @@ ${stderr}` : "");
|
|
|
12576
12749
|
}
|
|
12577
12750
|
}
|
|
12578
12751
|
|
|
12579
|
-
// packages/tooling/src/quality/lint.ts
|
|
12580
|
-
init_utils();
|
|
12581
|
-
init_cli_output();
|
|
12582
|
-
init_errors();
|
|
12583
|
-
init_pathResolver();
|
|
12584
|
-
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
12585
|
-
async function main10(options = {}) {
|
|
12586
|
-
const fix = options.fix ?? false;
|
|
12587
|
-
const cwd = process.cwd();
|
|
12588
|
-
const eslintConfigs = [
|
|
12589
|
-
"eslint.config.js",
|
|
12590
|
-
"eslint.config.mjs",
|
|
12591
|
-
"eslint.config.cjs"
|
|
12592
|
-
];
|
|
12593
|
-
const hasEslintConfig = eslintConfigs.some(
|
|
12594
|
-
(config) => pathExists(joinPath(cwd, config))
|
|
12595
|
-
);
|
|
12596
|
-
if (!hasEslintConfig) {
|
|
12597
|
-
log.info("No eslint.config.js found in current directory. Skipping lint.");
|
|
12598
|
-
log.info("To enable linting, create an eslint.config.js file.");
|
|
12599
|
-
return 0;
|
|
12600
|
-
}
|
|
12601
|
-
const eslintArgs = fix ? ["--fix"] : [];
|
|
12602
|
-
if (options.debug) {
|
|
12603
|
-
eslintArgs.push("--debug");
|
|
12604
|
-
}
|
|
12605
|
-
if (options.quiet) {
|
|
12606
|
-
eslintArgs.push("--quiet");
|
|
12607
|
-
}
|
|
12608
|
-
if (options.debug || options.verbose) {
|
|
12609
|
-
log.debug(`Linting code${fix ? " and fixing issues" : ""}...`);
|
|
12610
|
-
log.debug(` Working directory: ${cwd}`);
|
|
12611
|
-
log.debug(` ESLint args: ${eslintArgs.join(" ")}`);
|
|
12612
|
-
} else {
|
|
12613
|
-
log.info(fix ? "Linting and fixing code..." : "Linting code...");
|
|
12614
|
-
}
|
|
12615
|
-
try {
|
|
12616
|
-
const result = spawnSync10("bunx", ["eslint", ".", ...eslintArgs], {
|
|
12617
|
-
cwd,
|
|
12618
|
-
stdio: "inherit",
|
|
12619
|
-
env: process.env,
|
|
12620
|
-
shell: true
|
|
12621
|
-
});
|
|
12622
|
-
const exitCode = result.status ?? 1;
|
|
12623
|
-
if (exitCode === 0) {
|
|
12624
|
-
if (!options.debug && !options.verbose) {
|
|
12625
|
-
log.success("Linting completed successfully");
|
|
12626
|
-
}
|
|
12627
|
-
} else {
|
|
12628
|
-
if (!options.debug && !options.verbose) {
|
|
12629
|
-
log.error("Linting found issues (see above for details)");
|
|
12630
|
-
}
|
|
12631
|
-
}
|
|
12632
|
-
return exitCode;
|
|
12633
|
-
} catch (err) {
|
|
12634
|
-
throw DoNotDevError.from(
|
|
12635
|
-
err,
|
|
12636
|
-
"Failed to run ESLint",
|
|
12637
|
-
"cli-execution-error"
|
|
12638
|
-
);
|
|
12639
|
-
}
|
|
12640
|
-
}
|
|
12641
|
-
|
|
12642
12752
|
// packages/tooling/src/maintenance/cacheout.ts
|
|
12643
12753
|
init_utils();
|
|
12644
12754
|
init_cli_output();
|
|
@@ -12765,7 +12875,7 @@ function removeItem(path, rootDir, dryRun, verbose) {
|
|
|
12765
12875
|
return false;
|
|
12766
12876
|
}
|
|
12767
12877
|
}
|
|
12768
|
-
async function
|
|
12878
|
+
async function main10(options) {
|
|
12769
12879
|
const opts = options;
|
|
12770
12880
|
const targetDir = opts.app ? joinPath(process.cwd(), "apps", opts.app) : process.cwd();
|
|
12771
12881
|
if (opts.app && !pathExists(targetDir)) {
|
|
@@ -12814,14 +12924,13 @@ async function main11(options) {
|
|
|
12814
12924
|
}
|
|
12815
12925
|
export {
|
|
12816
12926
|
main as build,
|
|
12817
|
-
|
|
12927
|
+
main10 as cacheout,
|
|
12818
12928
|
main7 as createApp,
|
|
12819
12929
|
main8 as createProject,
|
|
12820
12930
|
main5 as deploy,
|
|
12821
12931
|
main2 as dev,
|
|
12822
12932
|
main3 as emu,
|
|
12823
12933
|
main9 as format,
|
|
12824
|
-
main10 as lint,
|
|
12825
12934
|
main4 as preview,
|
|
12826
12935
|
main6 as syncSecrets
|
|
12827
12936
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAE5B;;;;;GAKG;AAEH,qFAAqF;AACrF,OAAO,EACL,SAAS,EACT,aAAa,EACb,MAAM,EACN,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAE5B;;;;;GAKG;AAEH,qFAAqF;AACrF,OAAO,EACL,SAAS,EACT,aAAa,EACb,MAAM,EACN,GAAG,EACH,KAAK,EACL,OAAO,EACP,GAAG,EACH,QAAQ,EACR,WAAW,EACX,MAAM,GACP,MAAM,mBAAmB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@donotdev/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "Command-line interface for DoNotDev Framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@clack/prompts": "^0.11.0",
|
|
37
|
-
"commander": "^14.0.
|
|
37
|
+
"commander": "^14.0.3",
|
|
38
38
|
"fast-glob": "^3.3.3"
|
|
39
39
|
},
|
|
40
40
|
"repository": {
|
|
@@ -59,5 +59,6 @@
|
|
|
59
59
|
"publishConfig": {
|
|
60
60
|
"registry": "https://registry.npmjs.org",
|
|
61
61
|
"access": "public"
|
|
62
|
-
}
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {}
|
|
63
64
|
}
|
|
@@ -29,7 +29,7 @@ export const appConfig: AppConfig = {
|
|
|
29
29
|
name: APP_NAME,
|
|
30
30
|
shortName: APP_SHORT_NAME,
|
|
31
31
|
description: APP_DESCRIPTION,
|
|
32
|
-
//
|
|
32
|
+
// Note: URL comes from NEXT_PUBLIC_APP_URL in .env, not here
|
|
33
33
|
|
|
34
34
|
// Footer legal links - remove any you don't need
|
|
35
35
|
footer: {
|