@donotdev/cli 0.0.6 → 0.0.8
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 +64 -121
- package/dist/bin/commands/build.js +173 -161
- package/dist/bin/commands/bump.js +181 -156
- package/dist/bin/commands/cacheout.js +188 -171
- package/dist/bin/commands/create-app.js +213 -156
- package/dist/bin/commands/create-project.js +183 -154
- package/dist/bin/commands/deploy.js +491 -477
- package/dist/bin/commands/dev.js +176 -160
- package/dist/bin/commands/emu.js +181 -165
- package/dist/bin/commands/format.js +191 -174
- package/dist/bin/commands/lint.js +191 -171
- package/dist/bin/commands/preview.js +177 -161
- package/dist/bin/commands/sync-secrets.js +172 -158
- package/dist/bin/commands/wai.d.ts +11 -0
- package/dist/bin/commands/wai.d.ts.map +1 -0
- package/dist/bin/commands/wai.js +12 -0
- package/dist/bin/commands/wai.js.map +1 -0
- package/dist/bin/dndev.js +24 -24
- package/dist/bin/donotdev.js +24 -24
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +661 -669
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/app-demo/src/config/app.ts.example +12 -0
- package/templates/app-next/src/config/app.ts.example +75 -48
- package/templates/app-vite/index.html.example +71 -37
- package/templates/app-vite/src/config/app.ts.example +75 -47
- package/templates/app-vite/src/pages/FormPageExample.tsx.example +152 -0
- package/templates/app-vite/src/pages/HomePage.tsx.example +81 -134
- package/templates/app-vite/src/pages/ListPageExample.tsx.example +88 -0
- package/templates/functions-firebase/build.mjs.example +8 -1
- package/templates/functions-firebase/functions-firebase/build.mjs.example +8 -1
- package/templates/functions-firebase/functions-firebase/src/index.ts.example +19 -25
- package/templates/functions-firebase/functions.config.js.example +35 -0
- package/templates/root-consumer/entities/ExampleEntity.ts.example +223 -0
- package/templates/root-consumer/entities/demo.ts.example +576 -0
- package/templates/root-consumer/entities/index.ts.example +15 -0
- package/templates/root-consumer/eslint.config.js.example +2 -80
- package/templates/root-consumer/guides/{AGENT_START_HERE.md.example → dndev/AGENT_START_HERE.md.example} +22 -0
- package/templates/root-consumer/guides/dndev/COMPONENTS_CRUD.md.example +231 -0
- package/templates/root-consumer/guides/{SETUP_AUTH.md.example → dndev/SETUP_AUTH.md.example} +30 -0
- package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +539 -0
- package/templates/root-consumer/guides/dndev/SETUP_FUNCTIONS.md.example +116 -0
- package/templates/root-consumer/guides/{SETUP_I18N.md.example → dndev/SETUP_I18N.md.example} +46 -0
- package/templates/root-consumer/guides/wai-way/WAI_WAY_CLI.md.example +404 -0
- package/templates/root-consumer/guides/wai-way/agents/architect.md.example +78 -0
- package/templates/root-consumer/guides/wai-way/agents/builder.md.example +87 -0
- package/templates/root-consumer/guides/wai-way/agents/extractor.md.example +325 -0
- package/templates/root-consumer/guides/wai-way/agents/polisher.md.example +100 -0
- package/templates/root-consumer/guides/wai-way/blueprints/0_brainstorm.md.example +281 -0
- package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +77 -0
- package/templates/root-consumer/guides/wai-way/blueprints/2_entities.md.example +104 -0
- package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +124 -0
- package/templates/root-consumer/guides/wai-way/blueprints/4_configure.md.example +165 -0
- package/templates/root-consumer/guides/wai-way/context_map.json.example +95 -0
- package/templates/root-consumer/guides/wai-way/entity_patterns.md.example +840 -0
- package/templates/root-consumer/guides/wai-way/page_patterns.md.example +686 -0
- package/templates/root-consumer/guides/wai-way/presets_guide.md.example +217 -0
- package/templates/root-consumer/guides/wai-way/spec_template.md.example +312 -0
- package/templates/functions-firebase/functions-firebase/src/crud/createEntity.ts.example +0 -19
- package/templates/functions-firebase/functions-firebase/src/crud/deleteEntity.ts.example +0 -14
- package/templates/functions-firebase/functions-firebase/src/crud/getEntity.ts.example +0 -14
- package/templates/functions-firebase/functions-firebase/src/crud/index.ts.example +0 -12
- package/templates/functions-firebase/functions-firebase/src/crud/listEntities.ts.example +0 -14
- package/templates/functions-firebase/functions-firebase/src/crud/updateEntity.ts.example +0 -14
- package/templates/root-consumer/guides/COMPONENTS_CRUD.md.example +0 -70
- package/templates/root-consumer/guides/SETUP_CRUD.md.example +0 -1244
- package/templates/root-consumer/guides/SETUP_FUNCTIONS.md.example +0 -114
- /package/templates/root-consumer/guides/{COMPONENTS_ADV.md.example → dndev/COMPONENTS_ADV.md.example} +0 -0
- /package/templates/root-consumer/guides/{COMPONENTS_ATOMIC.md.example → dndev/COMPONENTS_ATOMIC.md.example} +0 -0
- /package/templates/root-consumer/guides/{COMPONENTS_UI.md.example → dndev/COMPONENTS_UI.md.example} +0 -0
- /package/templates/root-consumer/guides/{ENV_SETUP.md.example → dndev/ENV_SETUP.md.example} +0 -0
- /package/templates/root-consumer/guides/{INDEX.md.example → dndev/INDEX.md.example} +0 -0
- /package/templates/root-consumer/guides/{SETUP_APP_CONFIG.md.example → dndev/SETUP_APP_CONFIG.md.example} +0 -0
- /package/templates/root-consumer/guides/{SETUP_BILLING.md.example → dndev/SETUP_BILLING.md.example} +0 -0
- /package/templates/root-consumer/guides/{SETUP_LAYOUTS.md.example → dndev/SETUP_LAYOUTS.md.example} +0 -0
- /package/templates/root-consumer/guides/{SETUP_OAUTH.md.example → dndev/SETUP_OAUTH.md.example} +0 -0
- /package/templates/root-consumer/guides/{SETUP_PAGES.md.example → dndev/SETUP_PAGES.md.example} +0 -0
- /package/templates/root-consumer/guides/{SETUP_PWA.md.example → dndev/SETUP_PWA.md.example} +0 -0
- /package/templates/root-consumer/guides/{SETUP_THEMES.md.example → dndev/SETUP_THEMES.md.example} +0 -0
- /package/templates/root-consumer/guides/{USE_ROUTING.md.example → dndev/USE_ROUTING.md.example} +0 -0
- /package/templates/root-consumer/guides/{advanced → dndev/advanced}/APP_CHECK.md.example +0 -0
- /package/templates/root-consumer/guides/{advanced → dndev/advanced}/COOKIE_REFERENCE.md.example +0 -0
- /package/templates/root-consumer/guides/{advanced → dndev/advanced}/EMULATORS.md.example +0 -0
- /package/templates/root-consumer/guides/{advanced → dndev/advanced}/VERSION_CONTROL.md.example +0 -0
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") {
|
|
@@ -1088,155 +1089,6 @@ var init_cli_output = __esm({
|
|
|
1088
1089
|
}
|
|
1089
1090
|
});
|
|
1090
1091
|
|
|
1091
|
-
// packages/core/config/constants.js
|
|
1092
|
-
function getPatternsFor(type, repoRoot = null) {
|
|
1093
|
-
const patterns = SCAN_PATTERNS[type];
|
|
1094
|
-
if (!patterns) {
|
|
1095
|
-
throw new Error(`Unknown pattern type: ${type}`);
|
|
1096
|
-
}
|
|
1097
|
-
if (repoRoot && patterns.framework) {
|
|
1098
|
-
return {
|
|
1099
|
-
...patterns,
|
|
1100
|
-
framework: patterns.framework.map((pattern) => `${repoRoot}/${pattern}`)
|
|
1101
|
-
};
|
|
1102
|
-
}
|
|
1103
|
-
return patterns;
|
|
1104
|
-
}
|
|
1105
|
-
function getGlobOptionsFor(type) {
|
|
1106
|
-
return GLOB_OPTIONS[type] || GLOB_OPTIONS.base;
|
|
1107
|
-
}
|
|
1108
|
-
var I18N_PATHS, SCAN_PATTERNS, GLOB_OPTIONS;
|
|
1109
|
-
var init_constants = __esm({
|
|
1110
|
-
"packages/core/config/constants.js"() {
|
|
1111
|
-
"use strict";
|
|
1112
|
-
init_utils();
|
|
1113
|
-
I18N_PATHS = {
|
|
1114
|
-
// Monorepo source structure (locales at root, not in src/)
|
|
1115
|
-
SOURCE_ROOT: "packages/core/i18n",
|
|
1116
|
-
SOURCE_LOCALES: "packages/core/i18n/locales",
|
|
1117
|
-
SOURCE_EAGER: "packages/core/i18n/locales/eager",
|
|
1118
|
-
SOURCE_LAZY: "packages/core/i18n/locales/lazy",
|
|
1119
|
-
// Published structure (same as source - no flattening needed)
|
|
1120
|
-
PUBLISHED_ROOT: "i18n",
|
|
1121
|
-
PUBLISHED_LOCALES: "i18n/locales",
|
|
1122
|
-
PUBLISHED_EAGER: "i18n/locales/eager",
|
|
1123
|
-
PUBLISHED_LAZY: "i18n/locales/lazy"
|
|
1124
|
-
};
|
|
1125
|
-
SCAN_PATTERNS = {
|
|
1126
|
-
routes: {
|
|
1127
|
-
consumer: ["src/**/*Page.tsx", "src/pages/**/*Page.tsx"],
|
|
1128
|
-
exclude: [
|
|
1129
|
-
"**/node_modules/**",
|
|
1130
|
-
"**/dist/**",
|
|
1131
|
-
"**/build/**",
|
|
1132
|
-
"**/*.test.tsx",
|
|
1133
|
-
"**/*.stories.tsx"
|
|
1134
|
-
],
|
|
1135
|
-
extensions: [".tsx"]
|
|
1136
|
-
},
|
|
1137
|
-
css: {
|
|
1138
|
-
consumer: ["src/**/*.css"],
|
|
1139
|
-
themes: ["src/**/*.css"],
|
|
1140
|
-
extensions: [".css", ".scss", ".sass"],
|
|
1141
|
-
framework: [
|
|
1142
|
-
"packages/ui/src/**/*.css",
|
|
1143
|
-
"packages/core/components/src/**/*.css",
|
|
1144
|
-
"packages/core/templates/src/**/*.css"
|
|
1145
|
-
]
|
|
1146
|
-
},
|
|
1147
|
-
i18n: {
|
|
1148
|
-
eager: ["src/locales/*_*.json"],
|
|
1149
|
-
lazy: ["src/**/locales/*_*.json", "!src/locales/*_*.json"],
|
|
1150
|
-
framework: {
|
|
1151
|
-
eager: [`${I18N_PATHS.SOURCE_EAGER}/*_*.json`],
|
|
1152
|
-
lazy: [`${I18N_PATHS.SOURCE_LAZY}/*_*.json`]
|
|
1153
|
-
},
|
|
1154
|
-
extensions: [".json"]
|
|
1155
|
-
},
|
|
1156
|
-
assets: {
|
|
1157
|
-
consumer: ["public/**/*"],
|
|
1158
|
-
fallback: ["manifest.json"],
|
|
1159
|
-
modern: [
|
|
1160
|
-
"logo.svg",
|
|
1161
|
-
"favicon.svg",
|
|
1162
|
-
"apple-touch-icon.png",
|
|
1163
|
-
"android-chrome-192x192.png",
|
|
1164
|
-
"android-chrome-512x512.png"
|
|
1165
|
-
],
|
|
1166
|
-
patterns: [
|
|
1167
|
-
"favicon.svg",
|
|
1168
|
-
"favicon.ico",
|
|
1169
|
-
"favicon-*.png",
|
|
1170
|
-
"logo.svg",
|
|
1171
|
-
"logo.png",
|
|
1172
|
-
"logo.webp",
|
|
1173
|
-
"logo.avif",
|
|
1174
|
-
"apple-touch-icon*.png",
|
|
1175
|
-
"android-chrome-*.png",
|
|
1176
|
-
"manifest.json"
|
|
1177
|
-
],
|
|
1178
|
-
fonts: ["fonts/**/*.woff2", "fonts/**/*.woff", "fonts/**/*.ttf"],
|
|
1179
|
-
framework: ["packages/ui/assets/**/*"]
|
|
1180
|
-
},
|
|
1181
|
-
pwa: {
|
|
1182
|
-
consumer: [
|
|
1183
|
-
"public/manifest.json",
|
|
1184
|
-
"public/service-worker.js",
|
|
1185
|
-
"public/sw.js",
|
|
1186
|
-
"public/icon-192x192.png",
|
|
1187
|
-
"public/icon-512x512.png",
|
|
1188
|
-
"public/favicon.ico",
|
|
1189
|
-
"public/favicon.svg",
|
|
1190
|
-
"public/apple-touch-icon.png",
|
|
1191
|
-
"public/logo.svg"
|
|
1192
|
-
],
|
|
1193
|
-
exclude: ["**/node_modules/**", "**/dist/**", "**/build/**"],
|
|
1194
|
-
extensions: [".json", ".js", ".png", ".svg", ".ico"],
|
|
1195
|
-
framework: ["packages/ui/assets/**/*"]
|
|
1196
|
-
},
|
|
1197
|
-
globalIgnore: [
|
|
1198
|
-
"**/node_modules/**",
|
|
1199
|
-
"**/dist/**",
|
|
1200
|
-
"**/build/**",
|
|
1201
|
-
"**/.git/**",
|
|
1202
|
-
"**/coverage/**",
|
|
1203
|
-
"**/test/**"
|
|
1204
|
-
]
|
|
1205
|
-
};
|
|
1206
|
-
GLOB_OPTIONS = {
|
|
1207
|
-
base: {
|
|
1208
|
-
absolute: true,
|
|
1209
|
-
onlyFiles: true,
|
|
1210
|
-
ignore: SCAN_PATTERNS.globalIgnore
|
|
1211
|
-
},
|
|
1212
|
-
css: {
|
|
1213
|
-
absolute: true,
|
|
1214
|
-
onlyFiles: true,
|
|
1215
|
-
ignore: [...SCAN_PATTERNS.globalIgnore, "**/*.test.css"]
|
|
1216
|
-
},
|
|
1217
|
-
routes: {
|
|
1218
|
-
absolute: true,
|
|
1219
|
-
onlyFiles: true,
|
|
1220
|
-
ignore: [
|
|
1221
|
-
...SCAN_PATTERNS.globalIgnore,
|
|
1222
|
-
"**/*.test.tsx",
|
|
1223
|
-
"**/*.stories.tsx"
|
|
1224
|
-
]
|
|
1225
|
-
},
|
|
1226
|
-
i18n: {
|
|
1227
|
-
absolute: true,
|
|
1228
|
-
onlyFiles: true,
|
|
1229
|
-
ignore: SCAN_PATTERNS.globalIgnore
|
|
1230
|
-
},
|
|
1231
|
-
assets: {
|
|
1232
|
-
absolute: true,
|
|
1233
|
-
onlyFiles: true,
|
|
1234
|
-
ignore: SCAN_PATTERNS.globalIgnore
|
|
1235
|
-
}
|
|
1236
|
-
};
|
|
1237
|
-
}
|
|
1238
|
-
});
|
|
1239
|
-
|
|
1240
1092
|
// node_modules/.bun/fast-glob@3.3.3/node_modules/fast-glob/out/utils/array.js
|
|
1241
1093
|
var require_array = __commonJS({
|
|
1242
1094
|
"node_modules/.bun/fast-glob@3.3.3/node_modules/fast-glob/out/utils/array.js"(exports) {
|
|
@@ -6821,70 +6673,229 @@ var require_out4 = __commonJS({
|
|
|
6821
6673
|
}
|
|
6822
6674
|
});
|
|
6823
6675
|
|
|
6824
|
-
// packages/core/config/
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
}
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
function safeExecuteAsync(fn, message) {
|
|
6838
|
-
return fn().catch((error2) => {
|
|
6839
|
-
throw new Error(
|
|
6840
|
-
`${message}: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
6841
|
-
);
|
|
6842
|
-
});
|
|
6676
|
+
// packages/core/config/constants.js
|
|
6677
|
+
function getPatternsFor(type, repoRoot = null) {
|
|
6678
|
+
const patterns = SCAN_PATTERNS[type];
|
|
6679
|
+
if (!patterns) {
|
|
6680
|
+
throw new Error(`Unknown pattern type: ${type}`);
|
|
6681
|
+
}
|
|
6682
|
+
if (repoRoot && patterns.framework) {
|
|
6683
|
+
return {
|
|
6684
|
+
...patterns,
|
|
6685
|
+
framework: patterns.framework.map((pattern) => `${repoRoot}/${pattern}`)
|
|
6686
|
+
};
|
|
6687
|
+
}
|
|
6688
|
+
return patterns;
|
|
6843
6689
|
}
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6690
|
+
function getGlobOptionsFor(type) {
|
|
6691
|
+
return GLOB_OPTIONS[type] || GLOB_OPTIONS.base;
|
|
6692
|
+
}
|
|
6693
|
+
var I18N_PATHS, SCAN_PATTERNS, GLOB_OPTIONS;
|
|
6694
|
+
var init_constants = __esm({
|
|
6695
|
+
"packages/core/config/constants.js"() {
|
|
6847
6696
|
"use strict";
|
|
6848
6697
|
init_utils();
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
|
|
6698
|
+
I18N_PATHS = {
|
|
6699
|
+
// Monorepo source structure (locales at root, not in src/)
|
|
6700
|
+
SOURCE_ROOT: "packages/core/i18n",
|
|
6701
|
+
SOURCE_LOCALES: "packages/core/i18n/locales",
|
|
6702
|
+
SOURCE_EAGER: "packages/core/i18n/locales/eager",
|
|
6703
|
+
SOURCE_LAZY: "packages/core/i18n/locales/lazy",
|
|
6704
|
+
// Published structure (same as source - no flattening needed)
|
|
6705
|
+
PUBLISHED_ROOT: "i18n",
|
|
6706
|
+
PUBLISHED_LOCALES: "i18n/locales",
|
|
6707
|
+
PUBLISHED_EAGER: "i18n/locales/eager",
|
|
6708
|
+
PUBLISHED_LAZY: "i18n/locales/lazy"
|
|
6856
6709
|
};
|
|
6857
|
-
|
|
6858
|
-
|
|
6710
|
+
SCAN_PATTERNS = {
|
|
6711
|
+
routes: {
|
|
6712
|
+
consumer: ["src/**/*Page.tsx", "src/pages/**/*Page.tsx"],
|
|
6713
|
+
exclude: [
|
|
6714
|
+
"**/node_modules/**",
|
|
6715
|
+
"**/dist/**",
|
|
6716
|
+
"**/build/**",
|
|
6717
|
+
"**/*.test.tsx",
|
|
6718
|
+
"**/*.stories.tsx"
|
|
6719
|
+
],
|
|
6720
|
+
extensions: [".tsx"]
|
|
6859
6721
|
},
|
|
6860
|
-
|
|
6722
|
+
css: {
|
|
6723
|
+
consumer: ["src/**/*.css"],
|
|
6724
|
+
themes: ["src/**/*.css"],
|
|
6725
|
+
extensions: [".css", ".scss", ".sass"],
|
|
6726
|
+
framework: [
|
|
6727
|
+
"packages/ui/src/**/*.css",
|
|
6728
|
+
"packages/core/components/src/**/*.css",
|
|
6729
|
+
"packages/core/templates/src/**/*.css"
|
|
6730
|
+
]
|
|
6861
6731
|
},
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6732
|
+
i18n: {
|
|
6733
|
+
eager: ["src/locales/*_*.json"],
|
|
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: [],
|
|
6744
|
+
framework: {
|
|
6745
|
+
eager: [`${I18N_PATHS.SOURCE_EAGER}/*_*.json`],
|
|
6746
|
+
lazy: [`${I18N_PATHS.SOURCE_LAZY}/*_*.json`]
|
|
6747
|
+
},
|
|
6748
|
+
extensions: [".json"]
|
|
6749
|
+
},
|
|
6750
|
+
assets: {
|
|
6751
|
+
consumer: ["public/**/*"],
|
|
6752
|
+
fallback: ["manifest.json"],
|
|
6753
|
+
modern: [
|
|
6754
|
+
"logo.svg",
|
|
6755
|
+
"favicon.svg",
|
|
6756
|
+
"apple-touch-icon.png",
|
|
6757
|
+
"android-chrome-192x192.png",
|
|
6758
|
+
"android-chrome-512x512.png"
|
|
6759
|
+
],
|
|
6760
|
+
patterns: [
|
|
6761
|
+
"favicon.svg",
|
|
6762
|
+
"favicon.ico",
|
|
6763
|
+
"favicon-*.png",
|
|
6764
|
+
"logo.svg",
|
|
6765
|
+
"logo.png",
|
|
6766
|
+
"logo.webp",
|
|
6767
|
+
"logo.avif",
|
|
6768
|
+
"apple-touch-icon*.png",
|
|
6769
|
+
"android-chrome-*.png",
|
|
6770
|
+
"manifest.json"
|
|
6771
|
+
],
|
|
6772
|
+
fonts: ["fonts/**/*.woff2", "fonts/**/*.woff", "fonts/**/*.ttf"],
|
|
6773
|
+
framework: ["packages/ui/assets/**/*"]
|
|
6774
|
+
},
|
|
6775
|
+
pwa: {
|
|
6776
|
+
consumer: [
|
|
6777
|
+
"public/manifest.json",
|
|
6778
|
+
"public/service-worker.js",
|
|
6779
|
+
"public/sw.js",
|
|
6780
|
+
"public/icon-192x192.png",
|
|
6781
|
+
"public/icon-512x512.png",
|
|
6782
|
+
"public/favicon.ico",
|
|
6783
|
+
"public/favicon.svg",
|
|
6784
|
+
"public/apple-touch-icon.png",
|
|
6785
|
+
"public/logo.svg"
|
|
6786
|
+
],
|
|
6787
|
+
exclude: ["**/node_modules/**", "**/dist/**", "**/build/**"],
|
|
6788
|
+
extensions: [".json", ".js", ".png", ".svg", ".ico"],
|
|
6789
|
+
framework: ["packages/ui/assets/**/*"]
|
|
6790
|
+
},
|
|
6791
|
+
globalIgnore: [
|
|
6792
|
+
"**/node_modules/**",
|
|
6793
|
+
"**/dist/**",
|
|
6794
|
+
"**/build/**",
|
|
6795
|
+
"**/.git/**",
|
|
6796
|
+
"**/coverage/**",
|
|
6797
|
+
"**/test/**"
|
|
6798
|
+
]
|
|
6799
|
+
};
|
|
6800
|
+
GLOB_OPTIONS = {
|
|
6801
|
+
base: {
|
|
6802
|
+
absolute: true,
|
|
6803
|
+
onlyFiles: true,
|
|
6804
|
+
ignore: SCAN_PATTERNS.globalIgnore
|
|
6805
|
+
},
|
|
6806
|
+
css: {
|
|
6807
|
+
absolute: true,
|
|
6808
|
+
onlyFiles: true,
|
|
6809
|
+
ignore: [...SCAN_PATTERNS.globalIgnore, "**/*.test.css"]
|
|
6810
|
+
},
|
|
6811
|
+
routes: {
|
|
6812
|
+
absolute: true,
|
|
6813
|
+
onlyFiles: true,
|
|
6814
|
+
ignore: [
|
|
6815
|
+
...SCAN_PATTERNS.globalIgnore,
|
|
6816
|
+
"**/*.test.tsx",
|
|
6817
|
+
"**/*.stories.tsx"
|
|
6818
|
+
]
|
|
6819
|
+
},
|
|
6820
|
+
i18n: {
|
|
6821
|
+
absolute: true,
|
|
6822
|
+
onlyFiles: true,
|
|
6823
|
+
ignore: SCAN_PATTERNS.globalIgnore
|
|
6824
|
+
},
|
|
6825
|
+
assets: {
|
|
6826
|
+
absolute: true,
|
|
6827
|
+
onlyFiles: true,
|
|
6828
|
+
ignore: SCAN_PATTERNS.globalIgnore
|
|
6829
|
+
}
|
|
6830
|
+
};
|
|
6831
|
+
}
|
|
6832
|
+
});
|
|
6833
|
+
|
|
6834
|
+
// packages/core/config/utils/PathResolver.ts
|
|
6835
|
+
import * as fs from "node:fs";
|
|
6836
|
+
import "node:fs";
|
|
6837
|
+
import { createRequire } from "node:module";
|
|
6838
|
+
import {
|
|
6839
|
+
resolve,
|
|
6840
|
+
join,
|
|
6841
|
+
dirname,
|
|
6842
|
+
relative,
|
|
6843
|
+
normalize,
|
|
6844
|
+
sep,
|
|
6845
|
+
extname
|
|
6846
|
+
} from "node:path";
|
|
6847
|
+
import { fileURLToPath } from "node:url";
|
|
6848
|
+
function safeExecuteAsync(fn, message) {
|
|
6849
|
+
return fn().catch((error2) => {
|
|
6850
|
+
throw new Error(
|
|
6851
|
+
`${message}: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
6852
|
+
);
|
|
6853
|
+
});
|
|
6854
|
+
}
|
|
6855
|
+
var import_fast_glob, constants, log2, PACKAGE_PATHS, PathResolver;
|
|
6856
|
+
var init_PathResolver = __esm({
|
|
6857
|
+
"packages/core/config/utils/PathResolver.ts"() {
|
|
6858
|
+
"use strict";
|
|
6859
|
+
init_utils();
|
|
6860
|
+
import_fast_glob = __toESM(require_out4(), 1);
|
|
6861
|
+
init_constants();
|
|
6862
|
+
constants = {
|
|
6863
|
+
getGlobOptionsFor: getGlobOptionsFor || void 0,
|
|
6864
|
+
SCAN_PATTERNS: SCAN_PATTERNS || void 0,
|
|
6865
|
+
getPatternsFor: getPatternsFor || void 0,
|
|
6866
|
+
I18N_PATHS: I18N_PATHS || void 0
|
|
6867
|
+
};
|
|
6868
|
+
log2 = {
|
|
6869
|
+
error: (message, error2) => {
|
|
6870
|
+
},
|
|
6871
|
+
warn: (message, error2) => {
|
|
6872
|
+
},
|
|
6873
|
+
info: (message) => {
|
|
6874
|
+
}
|
|
6875
|
+
};
|
|
6876
|
+
PACKAGE_PATHS = {
|
|
6877
|
+
CLI: "packages/cli",
|
|
6878
|
+
COMPONENTS: "packages/core/components",
|
|
6879
|
+
CONFIG: "packages/core/config",
|
|
6880
|
+
// I18n paths - single source of truth (use I18N_PATHS from constants.js)
|
|
6881
|
+
CORE: "packages/core",
|
|
6882
|
+
CRUD: "packages/core/crud",
|
|
6883
|
+
FEATURES: "packages/features",
|
|
6884
|
+
HOOKS: "packages/core/hooks",
|
|
6885
|
+
I18N: "packages/core/i18n",
|
|
6886
|
+
SCHEMAS: "packages/core/schemas",
|
|
6887
|
+
STORES: "packages/core/stores",
|
|
6888
|
+
TEMPLATES: "packages/templates",
|
|
6889
|
+
TOOLING: "packages/tooling",
|
|
6890
|
+
TYPES: "packages/core/types",
|
|
6891
|
+
UI: "packages/ui",
|
|
6892
|
+
UTILS: "packages/core/utils",
|
|
6893
|
+
AUTH: "packages/features/auth",
|
|
6894
|
+
BILLING: "packages/features/billing",
|
|
6895
|
+
OAUTH: "packages/features/oauth",
|
|
6896
|
+
FIREBASE: "packages/providers/firebase",
|
|
6897
|
+
FUNCTIONS: "packages/functions"
|
|
6898
|
+
};
|
|
6888
6899
|
PathResolver = class _PathResolver {
|
|
6889
6900
|
static _instance = null;
|
|
6890
6901
|
options;
|
|
@@ -8289,11 +8300,12 @@ var init_pathResolver = __esm({
|
|
|
8289
8300
|
});
|
|
8290
8301
|
|
|
8291
8302
|
// packages/tooling/src/bundler/utils.ts
|
|
8303
|
+
import { Buffer as Buffer2 } from "node:buffer";
|
|
8304
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "node:fs";
|
|
8292
8305
|
import { createRequire as createRequire3 } from "node:module";
|
|
8293
|
-
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
8294
8306
|
import { dirname as dirname3, resolve as resolve3 } from "node:path";
|
|
8295
|
-
import { Buffer as Buffer2 } from "node:buffer";
|
|
8296
8307
|
import process from "node:process";
|
|
8308
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
8297
8309
|
var require2, __filename, __dirname;
|
|
8298
8310
|
var init_utils = __esm({
|
|
8299
8311
|
"packages/tooling/src/bundler/utils.ts"() {
|
|
@@ -8327,7 +8339,6 @@ import { spawnSync, execSync } from "node:child_process";
|
|
|
8327
8339
|
// packages/tooling/src/utils/app-selector.ts
|
|
8328
8340
|
init_utils();
|
|
8329
8341
|
init_dist2();
|
|
8330
|
-
init_cli_output();
|
|
8331
8342
|
|
|
8332
8343
|
// packages/tooling/src/utils/app-detection.ts
|
|
8333
8344
|
init_utils();
|
|
@@ -8415,6 +8426,7 @@ function analyzeApp(appPath, appName) {
|
|
|
8415
8426
|
}
|
|
8416
8427
|
|
|
8417
8428
|
// packages/tooling/src/utils/app-selector.ts
|
|
8429
|
+
init_cli_output();
|
|
8418
8430
|
async function selectApp(projectRoot, appName) {
|
|
8419
8431
|
const apps = detectApps(projectRoot);
|
|
8420
8432
|
if (apps.length === 0) {
|
|
@@ -8449,10 +8461,6 @@ async function selectApp(projectRoot, appName) {
|
|
|
8449
8461
|
return apps.find((a) => a.name === selected) || null;
|
|
8450
8462
|
}
|
|
8451
8463
|
|
|
8452
|
-
// packages/tooling/src/apps/build.ts
|
|
8453
|
-
init_errors();
|
|
8454
|
-
init_cli_output();
|
|
8455
|
-
|
|
8456
8464
|
// packages/tooling/src/utils/cli-input.ts
|
|
8457
8465
|
init_utils();
|
|
8458
8466
|
init_dist2();
|
|
@@ -8516,6 +8524,8 @@ async function askForMultiSelection(message, choices, defaultIndices = []) {
|
|
|
8516
8524
|
}
|
|
8517
8525
|
|
|
8518
8526
|
// packages/tooling/src/apps/build.ts
|
|
8527
|
+
init_cli_output();
|
|
8528
|
+
init_errors();
|
|
8519
8529
|
init_pathResolver();
|
|
8520
8530
|
function validateFirebaseJson(appDir) {
|
|
8521
8531
|
const firebaseJsonPath = joinPath(appDir, "firebase.json");
|
|
@@ -8708,8 +8718,8 @@ async function main() {
|
|
|
8708
8718
|
// packages/tooling/src/apps/dev.ts
|
|
8709
8719
|
init_utils();
|
|
8710
8720
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
8711
|
-
init_errors();
|
|
8712
8721
|
init_cli_output();
|
|
8722
|
+
init_errors();
|
|
8713
8723
|
init_pathResolver();
|
|
8714
8724
|
|
|
8715
8725
|
// packages/tooling/src/utils/spawn-utils.ts
|
|
@@ -8896,8 +8906,8 @@ async function main2() {
|
|
|
8896
8906
|
// packages/tooling/src/apps/emu.ts
|
|
8897
8907
|
init_utils();
|
|
8898
8908
|
import { spawnSync as spawnSync4, execSync as execSync3 } from "node:child_process";
|
|
8899
|
-
init_errors();
|
|
8900
8909
|
init_cli_output();
|
|
8910
|
+
init_errors();
|
|
8901
8911
|
init_pathResolver();
|
|
8902
8912
|
init_pathResolver();
|
|
8903
8913
|
function discoverFirebaseProjectId(appPath) {
|
|
@@ -9201,8 +9211,8 @@ FIREBASE_AUTH_EMULATOR_HOST=${authEmulatorHost}
|
|
|
9201
9211
|
// packages/tooling/src/apps/preview.ts
|
|
9202
9212
|
init_utils();
|
|
9203
9213
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
9204
|
-
init_errors();
|
|
9205
9214
|
init_cli_output();
|
|
9215
|
+
init_errors();
|
|
9206
9216
|
init_pathResolver();
|
|
9207
9217
|
async function main4() {
|
|
9208
9218
|
const args = process.argv.slice(2);
|
|
@@ -9250,10 +9260,11 @@ async function main4() {
|
|
|
9250
9260
|
|
|
9251
9261
|
// packages/tooling/src/apps/deploy.ts
|
|
9252
9262
|
init_utils();
|
|
9253
|
-
init_cli_output();
|
|
9254
|
-
init_cli_output();
|
|
9255
9263
|
import { execSync as execSync5 } from "node:child_process";
|
|
9256
9264
|
|
|
9265
|
+
// packages/tooling/src/apps/deploy-frontend.ts
|
|
9266
|
+
init_utils();
|
|
9267
|
+
|
|
9257
9268
|
// packages/tooling/src/utils/cli-tools.ts
|
|
9258
9269
|
init_utils();
|
|
9259
9270
|
init_dist2();
|
|
@@ -9503,18 +9514,10 @@ function requireCLI(tool, additionalContext) {
|
|
|
9503
9514
|
return true;
|
|
9504
9515
|
}
|
|
9505
9516
|
|
|
9506
|
-
// packages/tooling/src/apps/deploy.ts
|
|
9507
|
-
init_errors();
|
|
9508
|
-
init_pathResolver();
|
|
9509
|
-
|
|
9510
|
-
// packages/tooling/src/apps/deploy-utils.ts
|
|
9511
|
-
init_utils();
|
|
9512
|
-
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
9513
|
-
|
|
9514
9517
|
// packages/tooling/src/utils/create-utils.ts
|
|
9515
9518
|
init_utils();
|
|
9516
|
-
init_pathResolver();
|
|
9517
9519
|
init_cli_output();
|
|
9520
|
+
init_pathResolver();
|
|
9518
9521
|
async function copyTemplateFiles(sourceDir, destDir, replacements) {
|
|
9519
9522
|
if (!pathExists(sourceDir)) {
|
|
9520
9523
|
log.warn(`Warning: Template directory does not exist: ${sourceDir}`);
|
|
@@ -9976,55 +9979,290 @@ async function runQuestionnaire(questions, initialAnswers, showWIP, askFor) {
|
|
|
9976
9979
|
return answers;
|
|
9977
9980
|
}
|
|
9978
9981
|
|
|
9979
|
-
// packages/tooling/src/apps/deploy-
|
|
9980
|
-
|
|
9981
|
-
|
|
9982
|
-
|
|
9983
|
-
const
|
|
9984
|
-
|
|
9985
|
-
|
|
9982
|
+
// packages/tooling/src/apps/deploy-frontend.ts
|
|
9983
|
+
async function deployFrontend(appDir, serviceAccountPath, projectId, config) {
|
|
9984
|
+
const s = Y2();
|
|
9985
|
+
s.start("Deploying frontend to Firebase Hosting...");
|
|
9986
|
+
const args = buildFirebaseDeployArgs("hosting", projectId, config.debug);
|
|
9987
|
+
const result = executeFirebaseCommand(args, {
|
|
9988
|
+
cwd: appDir,
|
|
9989
|
+
serviceAccountPath,
|
|
9990
|
+
projectId,
|
|
9991
|
+
debug: config.debug
|
|
9992
|
+
});
|
|
9993
|
+
if (result.error) {
|
|
9994
|
+
s.stop("Deployment failed");
|
|
9995
|
+
throw result.error;
|
|
9986
9996
|
}
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
return pathExists(firebaseJsonPath);
|
|
9994
|
-
}).sort();
|
|
9995
|
-
}
|
|
9996
|
-
function detectAppDir(appName) {
|
|
9997
|
-
const currentDir = process.cwd();
|
|
9998
|
-
const appDir = joinPath(currentDir, "apps", appName);
|
|
9999
|
-
if (!pathExists(appDir)) {
|
|
10000
|
-
throw new DoNotDevError(
|
|
10001
|
-
`App directory not found: ${appDir}`,
|
|
10002
|
-
"file-not-found",
|
|
10003
|
-
{ context: { appName, expectedPath: appDir } }
|
|
9997
|
+
if (!result.success) {
|
|
9998
|
+
s.stop("Deployment failed");
|
|
9999
|
+
handleDeploymentFailure(
|
|
10000
|
+
result,
|
|
10001
|
+
`firebase ${args.join(" ")}`,
|
|
10002
|
+
serviceAccountPath
|
|
10004
10003
|
);
|
|
10005
10004
|
}
|
|
10006
|
-
|
|
10005
|
+
s.stop("Frontend deployed successfully");
|
|
10007
10006
|
}
|
|
10008
|
-
|
|
10009
|
-
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
|
|
10013
|
-
|
|
10014
|
-
|
|
10015
|
-
|
|
10016
|
-
|
|
10017
|
-
|
|
10018
|
-
|
|
10019
|
-
|
|
10020
|
-
|
|
10021
|
-
|
|
10022
|
-
|
|
10023
|
-
|
|
10024
|
-
|
|
10025
|
-
|
|
10026
|
-
|
|
10027
|
-
|
|
10007
|
+
|
|
10008
|
+
// packages/tooling/src/apps/deploy-functions.ts
|
|
10009
|
+
init_utils();
|
|
10010
|
+
import { execSync as execSync4 } from "node:child_process";
|
|
10011
|
+
init_pathResolver();
|
|
10012
|
+
function backupFiles(functionsDir) {
|
|
10013
|
+
const backupDir = joinPath(functionsDir, ".deploy-backup");
|
|
10014
|
+
const packageJsonPath = joinPath(functionsDir, "package.json");
|
|
10015
|
+
const packageLockJsonPath = joinPath(functionsDir, "package-lock.json");
|
|
10016
|
+
try {
|
|
10017
|
+
ensureDirSync(backupDir);
|
|
10018
|
+
const backupPackageJson = joinPath(backupDir, "package.json");
|
|
10019
|
+
const backupPackageLockJson = joinPath(backupDir, "package-lock.json");
|
|
10020
|
+
if (pathExists(packageJsonPath)) {
|
|
10021
|
+
const content = readSync(packageJsonPath, { format: "text" });
|
|
10022
|
+
if (!content) {
|
|
10023
|
+
throw new Error(`Failed to read package.json: ${packageJsonPath}`);
|
|
10024
|
+
}
|
|
10025
|
+
writeSync(backupPackageJson, content, { overwrite: true });
|
|
10026
|
+
}
|
|
10027
|
+
if (pathExists(packageLockJsonPath)) {
|
|
10028
|
+
const content = readSync(packageLockJsonPath, { format: "text" });
|
|
10029
|
+
if (!content) {
|
|
10030
|
+
throw new Error(
|
|
10031
|
+
`Failed to read package-lock.json: ${packageLockJsonPath}`
|
|
10032
|
+
);
|
|
10033
|
+
}
|
|
10034
|
+
writeSync(backupPackageLockJson, content, { overwrite: true });
|
|
10035
|
+
}
|
|
10036
|
+
return {
|
|
10037
|
+
packageJson: backupPackageJson,
|
|
10038
|
+
packageLockJson: backupPackageLockJson
|
|
10039
|
+
};
|
|
10040
|
+
} catch (error2) {
|
|
10041
|
+
log.warn(
|
|
10042
|
+
`Failed to backup files: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
10043
|
+
);
|
|
10044
|
+
return null;
|
|
10045
|
+
}
|
|
10046
|
+
}
|
|
10047
|
+
function generateCleanPackageJson(functionsDir) {
|
|
10048
|
+
const packageJsonPath = joinPath(functionsDir, "package.json");
|
|
10049
|
+
if (!pathExists(packageJsonPath)) {
|
|
10050
|
+
throw new DoNotDevError(
|
|
10051
|
+
`package.json not found: ${packageJsonPath}`,
|
|
10052
|
+
"file-not-found"
|
|
10053
|
+
);
|
|
10054
|
+
}
|
|
10055
|
+
const packageJson = readSync(packageJsonPath, { format: "json" });
|
|
10056
|
+
if (!packageJson) {
|
|
10057
|
+
throw new Error(
|
|
10058
|
+
`package.json is empty or invalid JSON at ${packageJsonPath}`
|
|
10059
|
+
);
|
|
10060
|
+
}
|
|
10061
|
+
const cleanPackageJson = { ...packageJson };
|
|
10062
|
+
if (cleanPackageJson.dependencies) {
|
|
10063
|
+
cleanPackageJson.dependencies = Object.fromEntries(
|
|
10064
|
+
Object.entries(cleanPackageJson.dependencies).filter(
|
|
10065
|
+
([, version]) => !String(version).startsWith("file:") && !String(version).startsWith("workspace:")
|
|
10066
|
+
)
|
|
10067
|
+
);
|
|
10068
|
+
}
|
|
10069
|
+
if (cleanPackageJson.devDependencies) {
|
|
10070
|
+
cleanPackageJson.devDependencies = Object.fromEntries(
|
|
10071
|
+
Object.entries(cleanPackageJson.devDependencies).filter(
|
|
10072
|
+
([, version]) => !String(version).startsWith("file:") && !String(version).startsWith("workspace:")
|
|
10073
|
+
)
|
|
10074
|
+
);
|
|
10075
|
+
}
|
|
10076
|
+
if (cleanPackageJson.scripts?.preinstall) {
|
|
10077
|
+
delete cleanPackageJson.scripts.preinstall;
|
|
10078
|
+
}
|
|
10079
|
+
const content = JSON.stringify(cleanPackageJson, null, 2) + "\n";
|
|
10080
|
+
writeSync(packageJsonPath, content, { overwrite: true });
|
|
10081
|
+
}
|
|
10082
|
+
function prepareFunctionsForDeployment(functionsDir, verbose = false) {
|
|
10083
|
+
const s = Y2();
|
|
10084
|
+
s.start("Preparing functions for deployment...");
|
|
10085
|
+
try {
|
|
10086
|
+
backupFiles(functionsDir);
|
|
10087
|
+
generateCleanPackageJson(functionsDir);
|
|
10088
|
+
safeRemove(joinPath(functionsDir, "package-lock.json"), {
|
|
10089
|
+
logSuccess: true,
|
|
10090
|
+
successMessage: "Removed package-lock.json - Firebase Cloud Build will generate its own"
|
|
10091
|
+
});
|
|
10092
|
+
s.stop("Functions prepared for deployment");
|
|
10093
|
+
} catch (error2) {
|
|
10094
|
+
s.stop("Preparation failed");
|
|
10095
|
+
throw error2;
|
|
10096
|
+
}
|
|
10097
|
+
}
|
|
10098
|
+
function restoreFunctionsAfterDeployment(functionsDir) {
|
|
10099
|
+
const backupDir = joinPath(functionsDir, ".deploy-backup");
|
|
10100
|
+
const backupPackageJson = joinPath(backupDir, "package.json");
|
|
10101
|
+
const backupPackageLockJson = joinPath(backupDir, "package-lock.json");
|
|
10102
|
+
const packageJsonPath = joinPath(functionsDir, "package.json");
|
|
10103
|
+
const packageLockJsonPath = joinPath(functionsDir, "package-lock.json");
|
|
10104
|
+
try {
|
|
10105
|
+
if (pathExists(backupPackageJson)) {
|
|
10106
|
+
const content = readSync(backupPackageJson, { format: "text" });
|
|
10107
|
+
if (!content) {
|
|
10108
|
+
throw new Error(
|
|
10109
|
+
`Failed to read backup package.json: ${backupPackageJson}`
|
|
10110
|
+
);
|
|
10111
|
+
}
|
|
10112
|
+
writeSync(packageJsonPath, content, { overwrite: true });
|
|
10113
|
+
}
|
|
10114
|
+
if (pathExists(backupPackageLockJson)) {
|
|
10115
|
+
const content = readSync(backupPackageLockJson, { format: "text" });
|
|
10116
|
+
if (!content) {
|
|
10117
|
+
throw new Error(
|
|
10118
|
+
`Failed to read backup package-lock.json: ${backupPackageLockJson}`
|
|
10119
|
+
);
|
|
10120
|
+
}
|
|
10121
|
+
writeSync(packageLockJsonPath, content, { overwrite: true });
|
|
10122
|
+
}
|
|
10123
|
+
safeRemove(backupDir, { silent: true });
|
|
10124
|
+
} catch (error2) {
|
|
10125
|
+
log.warn(
|
|
10126
|
+
`Failed to restore files: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
10127
|
+
);
|
|
10128
|
+
log.warn(` Backup directory: ${backupDir}`);
|
|
10129
|
+
}
|
|
10130
|
+
}
|
|
10131
|
+
async function deployFunctions(appDir, serviceAccountPath, projectId, config) {
|
|
10132
|
+
const functionsDir = joinPath(appDir, "functions");
|
|
10133
|
+
if (!pathExists(functionsDir)) {
|
|
10134
|
+
throw new DoNotDevError(
|
|
10135
|
+
`Functions directory not found: ${functionsDir}`,
|
|
10136
|
+
"file-not-found"
|
|
10137
|
+
);
|
|
10138
|
+
}
|
|
10139
|
+
const s = Y2();
|
|
10140
|
+
s.start("Validating function dependencies...");
|
|
10141
|
+
const requiredPackages = ["firebase-functions", "firebase-admin"];
|
|
10142
|
+
const missingPackages = requiredPackages.filter((pkg) => {
|
|
10143
|
+
try {
|
|
10144
|
+
resolvePackage(pkg, functionsDir);
|
|
10145
|
+
return false;
|
|
10146
|
+
} catch {
|
|
10147
|
+
return true;
|
|
10148
|
+
}
|
|
10149
|
+
});
|
|
10150
|
+
if (missingPackages.length > 0) {
|
|
10151
|
+
s.stop("Missing dependencies");
|
|
10152
|
+
throw new DoNotDevError(
|
|
10153
|
+
`Missing required dependencies: ${missingPackages.join(", ")}
|
|
10154
|
+
|
|
10155
|
+
To fix this, run:
|
|
10156
|
+
cd ${functionsDir}
|
|
10157
|
+
npm install --production`,
|
|
10158
|
+
"file-not-found",
|
|
10159
|
+
{ context: { missingPackages, functionsDir } }
|
|
10160
|
+
);
|
|
10161
|
+
}
|
|
10162
|
+
s.stop("Dependencies validated");
|
|
10163
|
+
prepareFunctionsForDeployment(functionsDir, config.verbose);
|
|
10164
|
+
log.debug("Waiting for file system sync...");
|
|
10165
|
+
await new Promise((resolve4) => setTimeout(resolve4, 1e3));
|
|
10166
|
+
try {
|
|
10167
|
+
if (!config.skipBuild) {
|
|
10168
|
+
const s2 = Y2();
|
|
10169
|
+
s2.start("Building functions...");
|
|
10170
|
+
try {
|
|
10171
|
+
execSync4("bun run build", {
|
|
10172
|
+
cwd: functionsDir,
|
|
10173
|
+
stdio: config.verbose ? "inherit" : "pipe"
|
|
10174
|
+
});
|
|
10175
|
+
s2.stop("Functions built");
|
|
10176
|
+
} catch (error2) {
|
|
10177
|
+
s2.stop("Build failed");
|
|
10178
|
+
throw error2;
|
|
10179
|
+
}
|
|
10180
|
+
}
|
|
10181
|
+
s.start("Deploying functions to Firebase...");
|
|
10182
|
+
const firebaseProjectDir = pathExists(joinPath(appDir, "firebase.json")) ? appDir : functionsDir;
|
|
10183
|
+
log.debug(`Using service account: ${serviceAccountPath}`);
|
|
10184
|
+
log.debug(`Firebase project directory: ${firebaseProjectDir}`);
|
|
10185
|
+
const args = buildFirebaseDeployArgs(
|
|
10186
|
+
"functions",
|
|
10187
|
+
projectId,
|
|
10188
|
+
config.debug,
|
|
10189
|
+
config.force
|
|
10190
|
+
);
|
|
10191
|
+
const result = executeFirebaseCommand(args, {
|
|
10192
|
+
cwd: firebaseProjectDir,
|
|
10193
|
+
serviceAccountPath,
|
|
10194
|
+
projectId,
|
|
10195
|
+
debug: config.debug
|
|
10196
|
+
});
|
|
10197
|
+
if (result.error) {
|
|
10198
|
+
s.stop("Deployment failed");
|
|
10199
|
+
throw result.error;
|
|
10200
|
+
}
|
|
10201
|
+
if (!result.success) {
|
|
10202
|
+
s.stop("Deployment failed");
|
|
10203
|
+
handleDeploymentFailure(
|
|
10204
|
+
result,
|
|
10205
|
+
`firebase ${args.join(" ")}`,
|
|
10206
|
+
serviceAccountPath
|
|
10207
|
+
);
|
|
10208
|
+
}
|
|
10209
|
+
s.stop("Functions deployed successfully");
|
|
10210
|
+
} finally {
|
|
10211
|
+
restoreFunctionsAfterDeployment(functionsDir);
|
|
10212
|
+
}
|
|
10213
|
+
}
|
|
10214
|
+
|
|
10215
|
+
// packages/tooling/src/apps/deploy-utils.ts
|
|
10216
|
+
init_utils();
|
|
10217
|
+
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
10218
|
+
init_pathResolver();
|
|
10219
|
+
function detectAvailableApps() {
|
|
10220
|
+
const currentDir = process.cwd();
|
|
10221
|
+
const appsDir = joinPath(currentDir, "apps");
|
|
10222
|
+
if (!pathExists(appsDir)) {
|
|
10223
|
+
return [];
|
|
10224
|
+
}
|
|
10225
|
+
return readdirSync2(appsDir).filter((item) => {
|
|
10226
|
+
const itemPath = joinPath(appsDir, item);
|
|
10227
|
+
const stat = statSync2(itemPath);
|
|
10228
|
+
return stat?.isDirectory() === true;
|
|
10229
|
+
}).filter((app) => {
|
|
10230
|
+
const firebaseJsonPath = joinPath(appsDir, app, "firebase.json");
|
|
10231
|
+
return pathExists(firebaseJsonPath);
|
|
10232
|
+
}).sort();
|
|
10233
|
+
}
|
|
10234
|
+
function detectAppDir(appName) {
|
|
10235
|
+
const currentDir = process.cwd();
|
|
10236
|
+
const appDir = joinPath(currentDir, "apps", appName);
|
|
10237
|
+
if (!pathExists(appDir)) {
|
|
10238
|
+
throw new DoNotDevError(
|
|
10239
|
+
`App directory not found: ${appDir}`,
|
|
10240
|
+
"file-not-found",
|
|
10241
|
+
{ context: { appName, expectedPath: appDir } }
|
|
10242
|
+
);
|
|
10243
|
+
}
|
|
10244
|
+
return appDir;
|
|
10245
|
+
}
|
|
10246
|
+
function validateServiceAccount(appDir) {
|
|
10247
|
+
const rootKeyPath = joinPath(appDir, "service-account-key.json");
|
|
10248
|
+
const functionsDir = joinPath(appDir, "functions");
|
|
10249
|
+
const functionsKeyPath = joinPath(functionsDir, "service-account-key.json");
|
|
10250
|
+
const keyPath = pathExists(rootKeyPath) ? rootKeyPath : functionsKeyPath;
|
|
10251
|
+
const errors = [];
|
|
10252
|
+
if (!pathExists(keyPath)) {
|
|
10253
|
+
return {
|
|
10254
|
+
valid: false,
|
|
10255
|
+
info: {
|
|
10256
|
+
path: keyPath,
|
|
10257
|
+
projectId: "",
|
|
10258
|
+
clientEmail: "",
|
|
10259
|
+
valid: false,
|
|
10260
|
+
errors: [
|
|
10261
|
+
`Service account key file not found. Checked:`,
|
|
10262
|
+
` - ${rootKeyPath}`,
|
|
10263
|
+
` - ${functionsKeyPath}`
|
|
10264
|
+
]
|
|
10265
|
+
}
|
|
10028
10266
|
};
|
|
10029
10267
|
}
|
|
10030
10268
|
try {
|
|
@@ -10112,346 +10350,116 @@ function validateFirebaseJson2(appDir) {
|
|
|
10112
10350
|
hasHosting,
|
|
10113
10351
|
hasFunctions,
|
|
10114
10352
|
errors: []
|
|
10115
|
-
};
|
|
10116
|
-
} catch (error2) {
|
|
10117
|
-
return {
|
|
10118
|
-
valid: false,
|
|
10119
|
-
hasHosting: false,
|
|
10120
|
-
hasFunctions: false,
|
|
10121
|
-
errors: [
|
|
10122
|
-
`Invalid JSON format: ${error2 instanceof DoNotDevError ? error2.message : error2 instanceof Error ? error2.message : String(error2)}`
|
|
10123
|
-
]
|
|
10124
|
-
};
|
|
10125
|
-
}
|
|
10126
|
-
}
|
|
10127
|
-
function validateBuild(appDir) {
|
|
10128
|
-
const distPath = joinPath(appDir, "dist");
|
|
10129
|
-
if (!pathExists(distPath)) {
|
|
10130
|
-
return { exists: false, isEmpty: true, path: distPath };
|
|
10131
|
-
}
|
|
10132
|
-
try {
|
|
10133
|
-
const files = readdirSync2(distPath);
|
|
10134
|
-
return {
|
|
10135
|
-
exists: true,
|
|
10136
|
-
isEmpty: files.length === 0,
|
|
10137
|
-
path: distPath
|
|
10138
|
-
};
|
|
10139
|
-
} catch {
|
|
10140
|
-
return { exists: true, isEmpty: true, path: distPath };
|
|
10141
|
-
}
|
|
10142
|
-
}
|
|
10143
|
-
async function showServiceAccountError(info2, projectId) {
|
|
10144
|
-
const consoleUrl = projectId ? `https://console.firebase.google.com/project/${projectId}/settings/serviceaccounts/adminsdk` : "https://console.firebase.google.com/project/YOUR_PROJECT/settings/serviceaccounts/adminsdk";
|
|
10145
|
-
const errorList = info2.errors.map((e2) => `\u2022 ${e2}`).join("\n");
|
|
10146
|
-
Me(
|
|
10147
|
-
`${errorList}
|
|
10148
|
-
|
|
10149
|
-
Why it matters:
|
|
10150
|
-
Firebase CLI needs service account credentials to deploy.
|
|
10151
|
-
Without valid credentials, deployment will fail.
|
|
10152
|
-
|
|
10153
|
-
How to fix:
|
|
10154
|
-
1. Go to Firebase Console:
|
|
10155
|
-
${consoleUrl}
|
|
10156
|
-
2. Click "Generate New Private Key"
|
|
10157
|
-
3. Save the JSON file as: ${info2.path}
|
|
10158
|
-
4. Required IAM roles:
|
|
10159
|
-
\u2022 Firebase Hosting Admin (for frontend)
|
|
10160
|
-
\u2022 Cloud Functions Admin (for functions)
|
|
10161
|
-
\u2022 Or Firebase Admin (covers both)`,
|
|
10162
|
-
"Service Account Error"
|
|
10163
|
-
);
|
|
10164
|
-
if (projectId) {
|
|
10165
|
-
const shouldOpen = await askForConfirmation(
|
|
10166
|
-
"Open Firebase Console now?",
|
|
10167
|
-
true
|
|
10168
|
-
);
|
|
10169
|
-
if (shouldOpen) {
|
|
10170
|
-
try {
|
|
10171
|
-
const openCommand = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
|
|
10172
|
-
spawnSync7(openCommand, [consoleUrl], { shell: true });
|
|
10173
|
-
log.success("Opening Firebase Console...");
|
|
10174
|
-
} catch {
|
|
10175
|
-
log.warn("Could not open browser. Please open the URL manually.");
|
|
10176
|
-
}
|
|
10177
|
-
}
|
|
10178
|
-
}
|
|
10179
|
-
}
|
|
10180
|
-
function showFirebaseJsonError(errors, appDir, deploymentType) {
|
|
10181
|
-
const errorList = errors.map((e2) => `\u2022 ${e2}`).join("\n");
|
|
10182
|
-
const firebaseJsonPath = joinPath(appDir, "firebase.json");
|
|
10183
|
-
let configExample = "";
|
|
10184
|
-
if (deploymentType === "frontend" || deploymentType === "both") {
|
|
10185
|
-
configExample += `
|
|
10186
|
-
Hosting config:
|
|
10187
|
-
{ "hosting": { "public": "dist", ... } }`;
|
|
10188
|
-
}
|
|
10189
|
-
if (deploymentType === "functions" || deploymentType === "both") {
|
|
10190
|
-
configExample += `
|
|
10191
|
-
Functions config:
|
|
10192
|
-
{ "functions": [{ "source": "functions", ... }] }`;
|
|
10193
|
-
}
|
|
10194
|
-
Me(
|
|
10195
|
-
`${errorList}
|
|
10196
|
-
|
|
10197
|
-
Why it matters:
|
|
10198
|
-
firebase.json defines your deployment configuration.
|
|
10199
|
-
Without it, Firebase CLI doesn't know what to deploy.
|
|
10200
|
-
|
|
10201
|
-
How to fix:
|
|
10202
|
-
1. Ensure firebase.json exists at: ${firebaseJsonPath}
|
|
10203
|
-
2. Add required configuration:${configExample}`,
|
|
10204
|
-
"Firebase Configuration Error"
|
|
10205
|
-
);
|
|
10206
|
-
}
|
|
10207
|
-
function clearFirebaseCache(appDir) {
|
|
10208
|
-
const firebaseCacheDir = joinPath(appDir, ".firebase");
|
|
10209
|
-
if (pathExists(firebaseCacheDir)) {
|
|
10210
|
-
log.info("Clearing Firebase cache...");
|
|
10211
|
-
const removed = safeRemove(firebaseCacheDir, { silent: true });
|
|
10212
|
-
if (removed) {
|
|
10213
|
-
log.success("Firebase cache cleared");
|
|
10214
|
-
} else {
|
|
10215
|
-
log.warn("Could not clear Firebase cache (non-critical)");
|
|
10216
|
-
}
|
|
10217
|
-
}
|
|
10218
|
-
}
|
|
10219
|
-
|
|
10220
|
-
// packages/tooling/src/apps/deploy-frontend.ts
|
|
10221
|
-
init_utils();
|
|
10222
|
-
async function deployFrontend(appDir, serviceAccountPath, projectId, config) {
|
|
10223
|
-
const s = Y2();
|
|
10224
|
-
s.start("Deploying frontend to Firebase Hosting...");
|
|
10225
|
-
const args = buildFirebaseDeployArgs("hosting", projectId, config.debug);
|
|
10226
|
-
const result = executeFirebaseCommand(args, {
|
|
10227
|
-
cwd: appDir,
|
|
10228
|
-
serviceAccountPath,
|
|
10229
|
-
projectId,
|
|
10230
|
-
debug: config.debug
|
|
10231
|
-
});
|
|
10232
|
-
if (result.error) {
|
|
10233
|
-
s.stop("Deployment failed");
|
|
10234
|
-
throw result.error;
|
|
10235
|
-
}
|
|
10236
|
-
if (!result.success) {
|
|
10237
|
-
s.stop("Deployment failed");
|
|
10238
|
-
handleDeploymentFailure(
|
|
10239
|
-
result,
|
|
10240
|
-
`firebase ${args.join(" ")}`,
|
|
10241
|
-
serviceAccountPath
|
|
10242
|
-
);
|
|
10243
|
-
}
|
|
10244
|
-
s.stop("Frontend deployed successfully");
|
|
10245
|
-
}
|
|
10246
|
-
|
|
10247
|
-
// packages/tooling/src/apps/deploy-functions.ts
|
|
10248
|
-
init_utils();
|
|
10249
|
-
import { execSync as execSync4 } from "node:child_process";
|
|
10250
|
-
init_pathResolver();
|
|
10251
|
-
function backupFiles(functionsDir) {
|
|
10252
|
-
const backupDir = joinPath(functionsDir, ".deploy-backup");
|
|
10253
|
-
const packageJsonPath = joinPath(functionsDir, "package.json");
|
|
10254
|
-
const packageLockJsonPath = joinPath(functionsDir, "package-lock.json");
|
|
10255
|
-
try {
|
|
10256
|
-
ensureDirSync(backupDir);
|
|
10257
|
-
const backupPackageJson = joinPath(backupDir, "package.json");
|
|
10258
|
-
const backupPackageLockJson = joinPath(backupDir, "package-lock.json");
|
|
10259
|
-
if (pathExists(packageJsonPath)) {
|
|
10260
|
-
const content = readSync(packageJsonPath, { format: "text" });
|
|
10261
|
-
if (!content) {
|
|
10262
|
-
throw new Error(`Failed to read package.json: ${packageJsonPath}`);
|
|
10263
|
-
}
|
|
10264
|
-
writeSync(backupPackageJson, content, { overwrite: true });
|
|
10265
|
-
}
|
|
10266
|
-
if (pathExists(packageLockJsonPath)) {
|
|
10267
|
-
const content = readSync(packageLockJsonPath, { format: "text" });
|
|
10268
|
-
if (!content) {
|
|
10269
|
-
throw new Error(
|
|
10270
|
-
`Failed to read package-lock.json: ${packageLockJsonPath}`
|
|
10271
|
-
);
|
|
10272
|
-
}
|
|
10273
|
-
writeSync(backupPackageLockJson, content, { overwrite: true });
|
|
10274
|
-
}
|
|
10275
|
-
return {
|
|
10276
|
-
packageJson: backupPackageJson,
|
|
10277
|
-
packageLockJson: backupPackageLockJson
|
|
10278
|
-
};
|
|
10279
|
-
} catch (error2) {
|
|
10280
|
-
log.warn(
|
|
10281
|
-
`Failed to backup files: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
10282
|
-
);
|
|
10283
|
-
return null;
|
|
10284
|
-
}
|
|
10285
|
-
}
|
|
10286
|
-
function generateCleanPackageJson(functionsDir) {
|
|
10287
|
-
const packageJsonPath = joinPath(functionsDir, "package.json");
|
|
10288
|
-
if (!pathExists(packageJsonPath)) {
|
|
10289
|
-
throw new DoNotDevError(
|
|
10290
|
-
`package.json not found: ${packageJsonPath}`,
|
|
10291
|
-
"file-not-found"
|
|
10292
|
-
);
|
|
10293
|
-
}
|
|
10294
|
-
const packageJson = readSync(packageJsonPath, { format: "json" });
|
|
10295
|
-
if (!packageJson) {
|
|
10296
|
-
throw new Error(
|
|
10297
|
-
`package.json is empty or invalid JSON at ${packageJsonPath}`
|
|
10298
|
-
);
|
|
10299
|
-
}
|
|
10300
|
-
const cleanPackageJson = { ...packageJson };
|
|
10301
|
-
if (cleanPackageJson.dependencies) {
|
|
10302
|
-
cleanPackageJson.dependencies = Object.fromEntries(
|
|
10303
|
-
Object.entries(cleanPackageJson.dependencies).filter(
|
|
10304
|
-
([, version]) => !String(version).startsWith("file:") && !String(version).startsWith("workspace:")
|
|
10305
|
-
)
|
|
10306
|
-
);
|
|
10307
|
-
}
|
|
10308
|
-
if (cleanPackageJson.devDependencies) {
|
|
10309
|
-
cleanPackageJson.devDependencies = Object.fromEntries(
|
|
10310
|
-
Object.entries(cleanPackageJson.devDependencies).filter(
|
|
10311
|
-
([, version]) => !String(version).startsWith("file:") && !String(version).startsWith("workspace:")
|
|
10312
|
-
)
|
|
10313
|
-
);
|
|
10314
|
-
}
|
|
10315
|
-
if (cleanPackageJson.scripts?.preinstall) {
|
|
10316
|
-
delete cleanPackageJson.scripts.preinstall;
|
|
10317
|
-
}
|
|
10318
|
-
const content = JSON.stringify(cleanPackageJson, null, 2) + "\n";
|
|
10319
|
-
writeSync(packageJsonPath, content, { overwrite: true });
|
|
10320
|
-
}
|
|
10321
|
-
function prepareFunctionsForDeployment(functionsDir, verbose = false) {
|
|
10322
|
-
const s = Y2();
|
|
10323
|
-
s.start("Preparing functions for deployment...");
|
|
10324
|
-
try {
|
|
10325
|
-
backupFiles(functionsDir);
|
|
10326
|
-
generateCleanPackageJson(functionsDir);
|
|
10327
|
-
safeRemove(joinPath(functionsDir, "package-lock.json"), {
|
|
10328
|
-
logSuccess: true,
|
|
10329
|
-
successMessage: "Removed package-lock.json - Firebase Cloud Build will generate its own"
|
|
10330
|
-
});
|
|
10331
|
-
s.stop("Functions prepared for deployment");
|
|
10353
|
+
};
|
|
10332
10354
|
} catch (error2) {
|
|
10333
|
-
|
|
10334
|
-
|
|
10355
|
+
return {
|
|
10356
|
+
valid: false,
|
|
10357
|
+
hasHosting: false,
|
|
10358
|
+
hasFunctions: false,
|
|
10359
|
+
errors: [
|
|
10360
|
+
`Invalid JSON format: ${error2 instanceof DoNotDevError ? error2.message : error2 instanceof Error ? error2.message : String(error2)}`
|
|
10361
|
+
]
|
|
10362
|
+
};
|
|
10335
10363
|
}
|
|
10336
10364
|
}
|
|
10337
|
-
function
|
|
10338
|
-
const
|
|
10339
|
-
|
|
10340
|
-
|
|
10341
|
-
|
|
10342
|
-
const packageLockJsonPath = joinPath(functionsDir, "package-lock.json");
|
|
10365
|
+
function validateBuild(appDir) {
|
|
10366
|
+
const distPath = joinPath(appDir, "dist");
|
|
10367
|
+
if (!pathExists(distPath)) {
|
|
10368
|
+
return { exists: false, isEmpty: true, path: distPath };
|
|
10369
|
+
}
|
|
10343
10370
|
try {
|
|
10344
|
-
|
|
10345
|
-
|
|
10346
|
-
|
|
10347
|
-
|
|
10348
|
-
|
|
10349
|
-
|
|
10350
|
-
|
|
10351
|
-
|
|
10352
|
-
}
|
|
10353
|
-
if (pathExists(backupPackageLockJson)) {
|
|
10354
|
-
const content = readSync(backupPackageLockJson, { format: "text" });
|
|
10355
|
-
if (!content) {
|
|
10356
|
-
throw new Error(
|
|
10357
|
-
`Failed to read backup package-lock.json: ${backupPackageLockJson}`
|
|
10358
|
-
);
|
|
10359
|
-
}
|
|
10360
|
-
writeSync(packageLockJsonPath, content, { overwrite: true });
|
|
10361
|
-
}
|
|
10362
|
-
safeRemove(backupDir, { silent: true });
|
|
10363
|
-
} catch (error2) {
|
|
10364
|
-
log.warn(
|
|
10365
|
-
`Failed to restore files: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
10366
|
-
);
|
|
10367
|
-
log.warn(` Backup directory: ${backupDir}`);
|
|
10371
|
+
const files = readdirSync2(distPath);
|
|
10372
|
+
return {
|
|
10373
|
+
exists: true,
|
|
10374
|
+
isEmpty: files.length === 0,
|
|
10375
|
+
path: distPath
|
|
10376
|
+
};
|
|
10377
|
+
} catch {
|
|
10378
|
+
return { exists: true, isEmpty: true, path: distPath };
|
|
10368
10379
|
}
|
|
10369
10380
|
}
|
|
10370
|
-
async function
|
|
10371
|
-
const
|
|
10372
|
-
|
|
10373
|
-
|
|
10374
|
-
|
|
10375
|
-
"file-not-found"
|
|
10376
|
-
);
|
|
10377
|
-
}
|
|
10378
|
-
const s = Y2();
|
|
10379
|
-
s.start("Validating function dependencies...");
|
|
10380
|
-
const requiredPackages = ["firebase-functions", "firebase-admin"];
|
|
10381
|
-
const missingPackages = requiredPackages.filter((pkg) => {
|
|
10382
|
-
try {
|
|
10383
|
-
resolvePackage(pkg, functionsDir);
|
|
10384
|
-
return false;
|
|
10385
|
-
} catch {
|
|
10386
|
-
return true;
|
|
10387
|
-
}
|
|
10388
|
-
});
|
|
10389
|
-
if (missingPackages.length > 0) {
|
|
10390
|
-
s.stop("Missing dependencies");
|
|
10391
|
-
throw new DoNotDevError(
|
|
10392
|
-
`Missing required dependencies: ${missingPackages.join(", ")}
|
|
10381
|
+
async function showServiceAccountError(info2, projectId) {
|
|
10382
|
+
const consoleUrl = projectId ? `https://console.firebase.google.com/project/${projectId}/settings/serviceaccounts/adminsdk` : "https://console.firebase.google.com/project/YOUR_PROJECT/settings/serviceaccounts/adminsdk";
|
|
10383
|
+
const errorList = info2.errors.map((e2) => `\u2022 ${e2}`).join("\n");
|
|
10384
|
+
Me(
|
|
10385
|
+
`${errorList}
|
|
10393
10386
|
|
|
10394
|
-
|
|
10395
|
-
|
|
10396
|
-
|
|
10397
|
-
|
|
10398
|
-
|
|
10387
|
+
Why it matters:
|
|
10388
|
+
Firebase CLI needs service account credentials to deploy.
|
|
10389
|
+
Without valid credentials, deployment will fail.
|
|
10390
|
+
|
|
10391
|
+
How to fix:
|
|
10392
|
+
1. Go to Firebase Console:
|
|
10393
|
+
${consoleUrl}
|
|
10394
|
+
2. Click "Generate New Private Key"
|
|
10395
|
+
3. Save the JSON file as: ${info2.path}
|
|
10396
|
+
4. Required IAM roles:
|
|
10397
|
+
\u2022 Firebase Hosting Admin (for frontend)
|
|
10398
|
+
\u2022 Cloud Functions Admin (for functions)
|
|
10399
|
+
\u2022 Or Firebase Admin (covers both)`,
|
|
10400
|
+
"Service Account Error"
|
|
10401
|
+
);
|
|
10402
|
+
if (projectId) {
|
|
10403
|
+
const shouldOpen = await askForConfirmation(
|
|
10404
|
+
"Open Firebase Console now?",
|
|
10405
|
+
true
|
|
10399
10406
|
);
|
|
10400
|
-
|
|
10401
|
-
s.stop("Dependencies validated");
|
|
10402
|
-
prepareFunctionsForDeployment(functionsDir, config.verbose);
|
|
10403
|
-
log.debug("Waiting for file system sync...");
|
|
10404
|
-
await new Promise((resolve4) => setTimeout(resolve4, 1e3));
|
|
10405
|
-
try {
|
|
10406
|
-
if (!config.skipBuild) {
|
|
10407
|
-
const s2 = Y2();
|
|
10408
|
-
s2.start("Building functions...");
|
|
10407
|
+
if (shouldOpen) {
|
|
10409
10408
|
try {
|
|
10410
|
-
|
|
10411
|
-
|
|
10412
|
-
|
|
10413
|
-
|
|
10414
|
-
|
|
10415
|
-
} catch (error2) {
|
|
10416
|
-
s2.stop("Build failed");
|
|
10417
|
-
throw error2;
|
|
10409
|
+
const openCommand = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
|
|
10410
|
+
spawnSync7(openCommand, [consoleUrl], { shell: true });
|
|
10411
|
+
log.success("Opening Firebase Console...");
|
|
10412
|
+
} catch {
|
|
10413
|
+
log.warn("Could not open browser. Please open the URL manually.");
|
|
10418
10414
|
}
|
|
10419
10415
|
}
|
|
10420
|
-
|
|
10421
|
-
|
|
10422
|
-
|
|
10423
|
-
|
|
10424
|
-
|
|
10425
|
-
|
|
10426
|
-
|
|
10427
|
-
|
|
10428
|
-
|
|
10429
|
-
|
|
10430
|
-
|
|
10431
|
-
|
|
10432
|
-
|
|
10433
|
-
|
|
10434
|
-
|
|
10435
|
-
|
|
10436
|
-
|
|
10437
|
-
|
|
10438
|
-
|
|
10439
|
-
|
|
10440
|
-
|
|
10441
|
-
|
|
10442
|
-
|
|
10443
|
-
|
|
10444
|
-
|
|
10445
|
-
|
|
10446
|
-
|
|
10416
|
+
}
|
|
10417
|
+
}
|
|
10418
|
+
function showFirebaseJsonError(errors, appDir, deploymentType) {
|
|
10419
|
+
const errorList = errors.map((e2) => `\u2022 ${e2}`).join("\n");
|
|
10420
|
+
const firebaseJsonPath = joinPath(appDir, "firebase.json");
|
|
10421
|
+
let configExample = "";
|
|
10422
|
+
if (deploymentType === "frontend" || deploymentType === "both") {
|
|
10423
|
+
configExample += `
|
|
10424
|
+
Hosting config:
|
|
10425
|
+
{ "hosting": { "public": "dist", ... } }`;
|
|
10426
|
+
}
|
|
10427
|
+
if (deploymentType === "functions" || deploymentType === "both") {
|
|
10428
|
+
configExample += `
|
|
10429
|
+
Functions config:
|
|
10430
|
+
{ "functions": [{ "source": "functions", ... }] }`;
|
|
10431
|
+
}
|
|
10432
|
+
Me(
|
|
10433
|
+
`${errorList}
|
|
10434
|
+
|
|
10435
|
+
Why it matters:
|
|
10436
|
+
firebase.json defines your deployment configuration.
|
|
10437
|
+
Without it, Firebase CLI doesn't know what to deploy.
|
|
10438
|
+
|
|
10439
|
+
How to fix:
|
|
10440
|
+
1. Ensure firebase.json exists at: ${firebaseJsonPath}
|
|
10441
|
+
2. Add required configuration:${configExample}`,
|
|
10442
|
+
"Firebase Configuration Error"
|
|
10443
|
+
);
|
|
10444
|
+
}
|
|
10445
|
+
function clearFirebaseCache(appDir) {
|
|
10446
|
+
const firebaseCacheDir = joinPath(appDir, ".firebase");
|
|
10447
|
+
if (pathExists(firebaseCacheDir)) {
|
|
10448
|
+
log.info("Clearing Firebase cache...");
|
|
10449
|
+
const removed = safeRemove(firebaseCacheDir, { silent: true });
|
|
10450
|
+
if (removed) {
|
|
10451
|
+
log.success("Firebase cache cleared");
|
|
10452
|
+
} else {
|
|
10453
|
+
log.warn("Could not clear Firebase cache (non-critical)");
|
|
10447
10454
|
}
|
|
10448
|
-
s.stop("Functions deployed successfully");
|
|
10449
|
-
} finally {
|
|
10450
|
-
restoreFunctionsAfterDeployment(functionsDir);
|
|
10451
10455
|
}
|
|
10452
10456
|
}
|
|
10453
10457
|
|
|
10454
10458
|
// packages/tooling/src/apps/deploy.ts
|
|
10459
|
+
init_cli_output();
|
|
10460
|
+
init_cli_output();
|
|
10461
|
+
init_errors();
|
|
10462
|
+
init_pathResolver();
|
|
10455
10463
|
async function main5(options = {}) {
|
|
10456
10464
|
const config = {
|
|
10457
10465
|
app: options.app,
|
|
@@ -10660,9 +10668,9 @@ Service Account: ${serviceAccountResult.info.clientEmail}`,
|
|
|
10660
10668
|
|
|
10661
10669
|
// packages/tooling/src/apps/sync-secrets.ts
|
|
10662
10670
|
init_utils();
|
|
10663
|
-
init_errors();
|
|
10664
|
-
init_cli_output();
|
|
10665
10671
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
10672
|
+
init_cli_output();
|
|
10673
|
+
init_errors();
|
|
10666
10674
|
init_pathResolver();
|
|
10667
10675
|
function parseEnvFile(filePath) {
|
|
10668
10676
|
if (!pathExists(filePath)) {
|
|
@@ -11254,6 +11262,23 @@ function generatePackageJson(templateName, mode, options = {}) {
|
|
|
11254
11262
|
}
|
|
11255
11263
|
}
|
|
11256
11264
|
}
|
|
11265
|
+
if (mode === "published") {
|
|
11266
|
+
const overrides = {};
|
|
11267
|
+
for (const [groupName, group] of Object.entries(matrix.groups || {})) {
|
|
11268
|
+
if (groupName.startsWith("@donotdev/")) {
|
|
11269
|
+
const version = group.packages?.[groupName];
|
|
11270
|
+
if (version) {
|
|
11271
|
+
overrides[groupName] = version.replace(/^\^/, "");
|
|
11272
|
+
}
|
|
11273
|
+
}
|
|
11274
|
+
}
|
|
11275
|
+
if (matrix.overrides) {
|
|
11276
|
+
Object.assign(overrides, matrix.overrides);
|
|
11277
|
+
}
|
|
11278
|
+
if (Object.keys(overrides).length > 0) {
|
|
11279
|
+
result.overrides = overrides;
|
|
11280
|
+
}
|
|
11281
|
+
}
|
|
11257
11282
|
return result;
|
|
11258
11283
|
}
|
|
11259
11284
|
|
|
@@ -11488,9 +11513,37 @@ Happy coding!`,
|
|
|
11488
11513
|
);
|
|
11489
11514
|
}
|
|
11490
11515
|
}
|
|
11491
|
-
async function main7() {
|
|
11516
|
+
async function main7(options) {
|
|
11492
11517
|
try {
|
|
11493
|
-
|
|
11518
|
+
const hasCliOptions = options?.name || options?.builder !== void 0;
|
|
11519
|
+
if (hasCliOptions && options?.name) {
|
|
11520
|
+
const appName = options.name;
|
|
11521
|
+
const builder = options.builder || "vite";
|
|
11522
|
+
const includeFunctions = options.functions ?? false;
|
|
11523
|
+
if (!isValidFileName(appName)) {
|
|
11524
|
+
throw new Error(
|
|
11525
|
+
`Invalid app name "${appName}". Use only letters, numbers, dashes (-), and underscores (_).`
|
|
11526
|
+
);
|
|
11527
|
+
}
|
|
11528
|
+
if (isReservedAppName(appName)) {
|
|
11529
|
+
throw new Error(
|
|
11530
|
+
`App name "${appName}" is reserved for framework demos. Please choose a different name.`
|
|
11531
|
+
);
|
|
11532
|
+
}
|
|
11533
|
+
const appConfig = {
|
|
11534
|
+
template: builder === "next" ? "nextjs" : "vite",
|
|
11535
|
+
needsBackend: includeFunctions,
|
|
11536
|
+
backendPlatform: includeFunctions ? "firebase" : void 0,
|
|
11537
|
+
needsCRUD: true,
|
|
11538
|
+
selectedEntities: [],
|
|
11539
|
+
userAuth: "social",
|
|
11540
|
+
billing: true,
|
|
11541
|
+
features: []
|
|
11542
|
+
};
|
|
11543
|
+
await createApp(appName, appConfig);
|
|
11544
|
+
} else {
|
|
11545
|
+
await createApp();
|
|
11546
|
+
}
|
|
11494
11547
|
} catch (error2) {
|
|
11495
11548
|
log.error("\n\u274C Error creating app:", error2);
|
|
11496
11549
|
throw error2;
|
|
@@ -11978,11 +12031,11 @@ async function main8(options) {
|
|
|
11978
12031
|
|
|
11979
12032
|
// packages/tooling/src/quality/format.ts
|
|
11980
12033
|
init_utils();
|
|
11981
|
-
init_errors();
|
|
11982
12034
|
init_cli_output();
|
|
12035
|
+
init_errors();
|
|
11983
12036
|
init_pathResolver();
|
|
11984
12037
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
11985
|
-
import { EOL } from "node:os";
|
|
12038
|
+
import { EOL as EOL2 } from "node:os";
|
|
11986
12039
|
async function main9(options = {}) {
|
|
11987
12040
|
const dryRun = options.dryRun ?? false;
|
|
11988
12041
|
const verbose = options.verbose ?? false;
|
|
@@ -12100,7 +12153,7 @@ async function addPathComments(files, rootDir, dryRun, verbose) {
|
|
|
12100
12153
|
let modified = false;
|
|
12101
12154
|
if (contentLines.length === 0) {
|
|
12102
12155
|
if (!dryRun) {
|
|
12103
|
-
writeSync(file, `${expectedPathComment}${
|
|
12156
|
+
writeSync(file, `${expectedPathComment}${EOL2}`, {
|
|
12104
12157
|
overwrite: true
|
|
12105
12158
|
});
|
|
12106
12159
|
}
|
|
@@ -12225,7 +12278,7 @@ async function addPathComments(files, rootDir, dryRun, verbose) {
|
|
|
12225
12278
|
newLines.push("");
|
|
12226
12279
|
}
|
|
12227
12280
|
newLines.push(...contentLines);
|
|
12228
|
-
const newContent = newLines.join(
|
|
12281
|
+
const newContent = newLines.join(EOL2);
|
|
12229
12282
|
const contentChanged = fileContent !== newContent;
|
|
12230
12283
|
if (contentChanged) {
|
|
12231
12284
|
try {
|
|
@@ -12552,70 +12605,10 @@ ${stderr}` : "");
|
|
|
12552
12605
|
}
|
|
12553
12606
|
}
|
|
12554
12607
|
|
|
12555
|
-
// packages/tooling/src/quality/lint.ts
|
|
12556
|
-
init_utils();
|
|
12557
|
-
init_errors();
|
|
12558
|
-
init_cli_output();
|
|
12559
|
-
init_pathResolver();
|
|
12560
|
-
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
12561
|
-
async function main10(options = {}) {
|
|
12562
|
-
const fix = options.fix ?? false;
|
|
12563
|
-
const cwd = process.cwd();
|
|
12564
|
-
const eslintConfigs = [
|
|
12565
|
-
"eslint.config.js",
|
|
12566
|
-
"eslint.config.mjs",
|
|
12567
|
-
"eslint.config.cjs"
|
|
12568
|
-
];
|
|
12569
|
-
const hasEslintConfig = eslintConfigs.some(
|
|
12570
|
-
(config) => pathExists(joinPath(cwd, config))
|
|
12571
|
-
);
|
|
12572
|
-
if (!hasEslintConfig) {
|
|
12573
|
-
log.info("No eslint.config.js found in current directory. Skipping lint.");
|
|
12574
|
-
log.info("To enable linting, create an eslint.config.js file.");
|
|
12575
|
-
return 0;
|
|
12576
|
-
}
|
|
12577
|
-
const eslintArgs = fix ? ["--fix"] : [];
|
|
12578
|
-
if (options.debug) {
|
|
12579
|
-
eslintArgs.push("--debug");
|
|
12580
|
-
}
|
|
12581
|
-
if (options.debug || options.verbose) {
|
|
12582
|
-
log.debug(`Linting code${fix ? " and fixing issues" : ""}...`);
|
|
12583
|
-
log.debug(` Working directory: ${cwd}`);
|
|
12584
|
-
log.debug(` ESLint args: ${eslintArgs.join(" ")}`);
|
|
12585
|
-
} else {
|
|
12586
|
-
log.info(fix ? "Linting and fixing code..." : "Linting code...");
|
|
12587
|
-
}
|
|
12588
|
-
try {
|
|
12589
|
-
const result = spawnSync10("bunx", ["eslint", ".", ...eslintArgs], {
|
|
12590
|
-
cwd,
|
|
12591
|
-
stdio: "inherit",
|
|
12592
|
-
env: process.env,
|
|
12593
|
-
shell: true
|
|
12594
|
-
});
|
|
12595
|
-
const exitCode = result.status ?? 1;
|
|
12596
|
-
if (exitCode === 0) {
|
|
12597
|
-
if (!options.debug && !options.verbose) {
|
|
12598
|
-
log.success("Linting completed successfully");
|
|
12599
|
-
}
|
|
12600
|
-
} else {
|
|
12601
|
-
if (!options.debug && !options.verbose) {
|
|
12602
|
-
log.error("Linting found issues (see above for details)");
|
|
12603
|
-
}
|
|
12604
|
-
}
|
|
12605
|
-
return exitCode;
|
|
12606
|
-
} catch (err) {
|
|
12607
|
-
throw DoNotDevError.from(
|
|
12608
|
-
err,
|
|
12609
|
-
"Failed to run ESLint",
|
|
12610
|
-
"cli-execution-error"
|
|
12611
|
-
);
|
|
12612
|
-
}
|
|
12613
|
-
}
|
|
12614
|
-
|
|
12615
12608
|
// packages/tooling/src/maintenance/cacheout.ts
|
|
12616
12609
|
init_utils();
|
|
12617
|
-
init_errors();
|
|
12618
12610
|
init_cli_output();
|
|
12611
|
+
init_errors();
|
|
12619
12612
|
init_pathResolver();
|
|
12620
12613
|
async function findCacheItems(targetDir, verbose) {
|
|
12621
12614
|
const matches = /* @__PURE__ */ new Set();
|
|
@@ -12738,7 +12731,7 @@ function removeItem(path, rootDir, dryRun, verbose) {
|
|
|
12738
12731
|
return false;
|
|
12739
12732
|
}
|
|
12740
12733
|
}
|
|
12741
|
-
async function
|
|
12734
|
+
async function main10(options) {
|
|
12742
12735
|
const opts = options;
|
|
12743
12736
|
const targetDir = opts.app ? joinPath(process.cwd(), "apps", opts.app) : process.cwd();
|
|
12744
12737
|
if (opts.app && !pathExists(targetDir)) {
|
|
@@ -12787,14 +12780,13 @@ async function main11(options) {
|
|
|
12787
12780
|
}
|
|
12788
12781
|
export {
|
|
12789
12782
|
main as build,
|
|
12790
|
-
|
|
12783
|
+
main10 as cacheout,
|
|
12791
12784
|
main7 as createApp,
|
|
12792
12785
|
main8 as createProject,
|
|
12793
12786
|
main5 as deploy,
|
|
12794
12787
|
main2 as dev,
|
|
12795
12788
|
main3 as emu,
|
|
12796
12789
|
main9 as format,
|
|
12797
|
-
main10 as lint,
|
|
12798
12790
|
main4 as preview,
|
|
12799
12791
|
main6 as syncSecrets
|
|
12800
12792
|
};
|