@appsbyme/create-basekit 1.0.4 → 1.0.5
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 +2 -2
- package/dist/commands/app/index.cjs +361 -357
- package/dist/commands/mobile/index.cjs +68 -43
- package/dist/commands/web/index.cjs +108 -83
- package/dist/index.cjs +427 -423
- package/package.json +11 -3
- package/template-mobile/README.md +2 -2
- package/template-mobile/_yarnrc.yml +1 -0
- package/template-mobile/src/__mocks__/expo-env.ts +2 -1
- package/template-mobile/src/features/auth/api/auth.api.ts +1 -1
- package/template-mobile/src/features/auth/components/AuthBackButton.tsx +2 -1
- package/template-mobile/src/features/auth/guestAuth.ts +1 -1
- package/template-mobile/src/lib/certPinning.ts +2 -2
- package/template-mobile/src/lib/sentry.ts +1 -1
- package/template-mobile/src/services/http.ts +1 -1
- package/template-mobile/src/services/refreshSession.ts +1 -1
- package/template-mobile/src/services/websocket.ts +1 -1
- package/template-web/AGENTS.md +4 -4
- package/template-web/Dockerfile +2 -2
- package/template-web/_yarnrc.yml +4 -0
- package/template-web/docker-compose.yml +1 -1
- package/template-web/package.json +3 -0
- package/template-web/scripts/setup-add-docker.js +14 -3
|
@@ -5232,19 +5232,7 @@ function createSpinner(text) {
|
|
|
5232
5232
|
init_cjs_shims();
|
|
5233
5233
|
var import_fs2 = __toESM(require("fs"), 1);
|
|
5234
5234
|
var import_path = __toESM(require("path"), 1);
|
|
5235
|
-
var DJANGO_BASE_PYPI_REQUIREMENT = "appsbyme-basekit[cli]
|
|
5236
|
-
function getWebKitRootFromPackage() {
|
|
5237
|
-
let dir = import_path.default.resolve(__dirname);
|
|
5238
|
-
for (let i = 0; i < 6; i += 1) {
|
|
5239
|
-
if (import_fs2.default.existsSync(import_path.default.join(dir, "packages", "utils", "package.json"))) {
|
|
5240
|
-
return dir;
|
|
5241
|
-
}
|
|
5242
|
-
const parent = import_path.default.dirname(dir);
|
|
5243
|
-
if (parent === dir) break;
|
|
5244
|
-
dir = parent;
|
|
5245
|
-
}
|
|
5246
|
-
return import_path.default.resolve(__dirname, "../../..");
|
|
5247
|
-
}
|
|
5235
|
+
var DJANGO_BASE_PYPI_REQUIREMENT = "appsbyme-basekit[cli]>=1.0.0";
|
|
5248
5236
|
function djangoBasePipInstallArg(spec) {
|
|
5249
5237
|
if (spec.kind === "pypi") {
|
|
5250
5238
|
return spec.pipSpec;
|
|
@@ -5260,7 +5248,7 @@ function filePipSpec(absoluteDir) {
|
|
|
5260
5248
|
const withSlash = normalized.startsWith("/") ? normalized : `/${normalized}`;
|
|
5261
5249
|
return `file://${withSlash}`;
|
|
5262
5250
|
}
|
|
5263
|
-
function resolveDjangoBaseInstallSpec(opts) {
|
|
5251
|
+
function resolveDjangoBaseInstallSpec(opts = {}) {
|
|
5264
5252
|
const env = opts.env ?? process.env;
|
|
5265
5253
|
const envPath = env.BASEKIT_DJANGO_BASE?.trim();
|
|
5266
5254
|
if (envPath) {
|
|
@@ -5273,24 +5261,6 @@ function resolveDjangoBaseInstallSpec(opts) {
|
|
|
5273
5261
|
};
|
|
5274
5262
|
}
|
|
5275
5263
|
}
|
|
5276
|
-
const besideProject = import_path.default.resolve(opts.projectRoot, "..", "basekit");
|
|
5277
|
-
if (isUsableCheckout(besideProject)) {
|
|
5278
|
-
return {
|
|
5279
|
-
kind: "file",
|
|
5280
|
-
pipSpec: filePipSpec(besideProject),
|
|
5281
|
-
label: `sibling beside project (${besideProject})`
|
|
5282
|
-
};
|
|
5283
|
-
}
|
|
5284
|
-
if (opts.webKitRoot) {
|
|
5285
|
-
const besideWebKit = import_path.default.resolve(opts.webKitRoot, "..", "basekit");
|
|
5286
|
-
if (isUsableCheckout(besideWebKit)) {
|
|
5287
|
-
return {
|
|
5288
|
-
kind: "file",
|
|
5289
|
-
pipSpec: filePipSpec(besideWebKit),
|
|
5290
|
-
label: `sibling beside basekit-web (${besideWebKit})`
|
|
5291
|
-
};
|
|
5292
|
-
}
|
|
5293
|
-
}
|
|
5294
5264
|
return {
|
|
5295
5265
|
kind: "pypi",
|
|
5296
5266
|
pipSpec: DJANGO_BASE_PYPI_REQUIREMENT,
|
|
@@ -5315,10 +5285,7 @@ async function scaffoldBackend(opts) {
|
|
|
5315
5285
|
}
|
|
5316
5286
|
venvSpinner.succeed("Virtual environment created at backend/.venv");
|
|
5317
5287
|
const pip = venvBin(venvDir, "pip");
|
|
5318
|
-
const djangoBase = resolveDjangoBaseInstallSpec(
|
|
5319
|
-
projectRoot,
|
|
5320
|
-
webKitRoot: getWebKitRootFromPackage()
|
|
5321
|
-
});
|
|
5288
|
+
const djangoBase = resolveDjangoBaseInstallSpec();
|
|
5322
5289
|
const pipArg = djangoBasePipInstallArg(djangoBase);
|
|
5323
5290
|
const installSpinner = createSpinner(`Installing appsbyme-basekit[cli] from ${djangoBase.label}\u2026`);
|
|
5324
5291
|
const installResult = await execAsync(
|
|
@@ -5427,19 +5394,46 @@ function safeUnlink(absPath) {
|
|
|
5427
5394
|
// src/commands/app/frontend.ts
|
|
5428
5395
|
init_cjs_shims();
|
|
5429
5396
|
var import_path8 = __toESM(require("path"), 1);
|
|
5430
|
-
var
|
|
5397
|
+
var import_fs9 = __toESM(require("fs"), 1);
|
|
5431
5398
|
|
|
5432
5399
|
// src/commands/web/index.ts
|
|
5433
5400
|
init_cjs_shims();
|
|
5434
|
-
var
|
|
5435
|
-
var
|
|
5401
|
+
var import_path6 = __toESM(require("path"), 1);
|
|
5402
|
+
var import_fs7 = __toESM(require("fs"), 1);
|
|
5436
5403
|
var import_prompts = __toESM(require_prompts3(), 1);
|
|
5437
5404
|
|
|
5438
5405
|
// src/commands/web/scaffold.ts
|
|
5439
5406
|
init_cjs_shims();
|
|
5440
|
-
var
|
|
5441
|
-
var
|
|
5407
|
+
var import_fs6 = __toESM(require("fs"), 1);
|
|
5408
|
+
var import_path5 = __toESM(require("path"), 1);
|
|
5409
|
+
var import_node_url2 = require("url");
|
|
5410
|
+
|
|
5411
|
+
// src/commands/app/package-paths.ts
|
|
5412
|
+
init_cjs_shims();
|
|
5413
|
+
var import_fs4 = __toESM(require("fs"), 1);
|
|
5414
|
+
var import_path3 = __toESM(require("path"), 1);
|
|
5442
5415
|
var import_node_url = require("url");
|
|
5416
|
+
function getCreateBasekitPackageRoot(fromDir = import_path3.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl))) {
|
|
5417
|
+
let dir = import_path3.default.resolve(fromDir);
|
|
5418
|
+
for (let i = 0; i < 8; i += 1) {
|
|
5419
|
+
const pkgPath = import_path3.default.join(dir, "package.json");
|
|
5420
|
+
if (import_fs4.default.existsSync(pkgPath)) {
|
|
5421
|
+
try {
|
|
5422
|
+
const name = JSON.parse(import_fs4.default.readFileSync(pkgPath, "utf8")).name;
|
|
5423
|
+
if (name === "@appsbyme/create-basekit") {
|
|
5424
|
+
return dir;
|
|
5425
|
+
}
|
|
5426
|
+
} catch {
|
|
5427
|
+
}
|
|
5428
|
+
}
|
|
5429
|
+
const parent = import_path3.default.dirname(dir);
|
|
5430
|
+
if (parent === dir) break;
|
|
5431
|
+
dir = parent;
|
|
5432
|
+
}
|
|
5433
|
+
throw new Error(
|
|
5434
|
+
`Could not find @appsbyme/create-basekit package root (started at ${fromDir})`
|
|
5435
|
+
);
|
|
5436
|
+
}
|
|
5443
5437
|
|
|
5444
5438
|
// src/commands/web/spinner.ts
|
|
5445
5439
|
init_cjs_shims();
|
|
@@ -5473,8 +5467,8 @@ function createSpinner2(text) {
|
|
|
5473
5467
|
// src/commands/web/utils.ts
|
|
5474
5468
|
init_cjs_shims();
|
|
5475
5469
|
var import_child_process2 = require("child_process");
|
|
5476
|
-
var
|
|
5477
|
-
var
|
|
5470
|
+
var import_fs5 = __toESM(require("fs"), 1);
|
|
5471
|
+
var import_path4 = __toESM(require("path"), 1);
|
|
5478
5472
|
function logStep2(msg) {
|
|
5479
5473
|
console.log(`
|
|
5480
5474
|
\u25B6 ${msg}`);
|
|
@@ -5492,27 +5486,27 @@ function logError2(msg) {
|
|
|
5492
5486
|
console.error(` \u2717 ${msg}`);
|
|
5493
5487
|
}
|
|
5494
5488
|
function exists2(absPath) {
|
|
5495
|
-
return
|
|
5489
|
+
return import_fs5.default.existsSync(absPath);
|
|
5496
5490
|
}
|
|
5497
5491
|
function copyDir(src, dest) {
|
|
5498
|
-
|
|
5492
|
+
import_fs5.default.cpSync(src, dest, { recursive: true });
|
|
5499
5493
|
}
|
|
5500
5494
|
function readText2(absPath) {
|
|
5501
|
-
return
|
|
5495
|
+
return import_fs5.default.readFileSync(absPath, "utf-8");
|
|
5502
5496
|
}
|
|
5503
5497
|
function writeText2(absPath, content) {
|
|
5504
|
-
|
|
5498
|
+
import_fs5.default.writeFileSync(absPath, content);
|
|
5505
5499
|
}
|
|
5506
5500
|
function readJson(absPath) {
|
|
5507
|
-
return JSON.parse(
|
|
5501
|
+
return JSON.parse(import_fs5.default.readFileSync(absPath, "utf-8"));
|
|
5508
5502
|
}
|
|
5509
5503
|
function writeJson(absPath, data) {
|
|
5510
|
-
|
|
5504
|
+
import_fs5.default.writeFileSync(absPath, JSON.stringify(data, null, 2) + "\n");
|
|
5511
5505
|
}
|
|
5512
5506
|
function safeUnlink2(absPath) {
|
|
5513
5507
|
if (!exists2(absPath)) return false;
|
|
5514
5508
|
try {
|
|
5515
|
-
|
|
5509
|
+
import_fs5.default.unlinkSync(absPath);
|
|
5516
5510
|
return true;
|
|
5517
5511
|
} catch {
|
|
5518
5512
|
return false;
|
|
@@ -5521,7 +5515,7 @@ function safeUnlink2(absPath) {
|
|
|
5521
5515
|
function safeRmDir(absDir) {
|
|
5522
5516
|
if (!exists2(absDir)) return false;
|
|
5523
5517
|
try {
|
|
5524
|
-
|
|
5518
|
+
import_fs5.default.rmSync(absDir, { recursive: true, force: true });
|
|
5525
5519
|
return true;
|
|
5526
5520
|
} catch {
|
|
5527
5521
|
return false;
|
|
@@ -5589,7 +5583,7 @@ function removeMarkedSection(content, marker) {
|
|
|
5589
5583
|
return content.replace(regex, "\n");
|
|
5590
5584
|
}
|
|
5591
5585
|
function getDestDir(appName) {
|
|
5592
|
-
return
|
|
5586
|
+
return import_path4.default.resolve(process.cwd(), appName);
|
|
5593
5587
|
}
|
|
5594
5588
|
function patchReplace(content, pattern, replacement, description) {
|
|
5595
5589
|
const result = content.replace(pattern, replacement);
|
|
@@ -5601,23 +5595,15 @@ function patchReplace(content, pattern, replacement, description) {
|
|
|
5601
5595
|
|
|
5602
5596
|
// src/commands/web/scaffold.ts
|
|
5603
5597
|
function templateDir() {
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
import_path4.default.join(here, "../template-web")
|
|
5608
|
-
];
|
|
5609
|
-
for (const candidate of candidates) {
|
|
5610
|
-
const resolved = import_path4.default.resolve(candidate);
|
|
5611
|
-
if (import_fs5.default.existsSync(resolved)) return resolved;
|
|
5612
|
-
}
|
|
5613
|
-
throw new Error(
|
|
5614
|
-
`Starter template is missing (searched: ${candidates.map((c) => import_path4.default.resolve(c)).join(", ")})`
|
|
5598
|
+
return import_path5.default.join(
|
|
5599
|
+
getCreateBasekitPackageRoot(import_path5.default.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl))),
|
|
5600
|
+
"template-web"
|
|
5615
5601
|
);
|
|
5616
5602
|
}
|
|
5617
5603
|
async function scaffold(opts) {
|
|
5618
5604
|
const { appName, description, destDir, enableTailwind, enablePwa, enableDocker, enableHusky } = opts;
|
|
5619
5605
|
if (exists2(destDir)) {
|
|
5620
|
-
throw new Error(`Directory "${
|
|
5606
|
+
throw new Error(`Directory "${import_path5.default.basename(destDir)}" already exists.`);
|
|
5621
5607
|
}
|
|
5622
5608
|
try {
|
|
5623
5609
|
await scaffoldInner(opts);
|
|
@@ -5634,10 +5620,11 @@ async function scaffoldInner(opts) {
|
|
|
5634
5620
|
const { appName, description, destDir, enableTailwind, enablePwa, enableDocker, enableHusky, portOffset } = opts;
|
|
5635
5621
|
await cloneTemplate(destDir);
|
|
5636
5622
|
materializeGitignore(destDir);
|
|
5637
|
-
|
|
5638
|
-
|
|
5623
|
+
materializeYarnrc(destDir);
|
|
5624
|
+
safeUnlink2(import_path5.default.join(destDir, "yarn.lock"));
|
|
5625
|
+
safeRmDir(import_path5.default.join(destDir, ".git"));
|
|
5639
5626
|
logOk2("Removed .git history \u2014 clean slate");
|
|
5640
|
-
safeUnlink2(
|
|
5627
|
+
safeUnlink2(import_path5.default.join(destDir, "commitlint.config.js"));
|
|
5641
5628
|
cleanupGitignore(destDir);
|
|
5642
5629
|
logStep2("Customising template");
|
|
5643
5630
|
replaceTokens(destDir, appName, description);
|
|
@@ -5676,7 +5663,7 @@ async function scaffoldInner(opts) {
|
|
|
5676
5663
|
}
|
|
5677
5664
|
async function cloneTemplate(destDir) {
|
|
5678
5665
|
const source = templateDir();
|
|
5679
|
-
if (!
|
|
5666
|
+
if (!import_fs6.default.existsSync(source)) {
|
|
5680
5667
|
throw new Error(`Starter template is missing at ${source}`);
|
|
5681
5668
|
}
|
|
5682
5669
|
const spinner = createSpinner2("Copying starter template\u2026");
|
|
@@ -5689,16 +5676,21 @@ async function cloneTemplate(destDir) {
|
|
|
5689
5676
|
spinner.succeed("Template copied");
|
|
5690
5677
|
}
|
|
5691
5678
|
function materializeGitignore(destDir) {
|
|
5692
|
-
const packagedPath =
|
|
5679
|
+
const packagedPath = import_path5.default.join(destDir, "_gitignore");
|
|
5680
|
+
if (!exists2(packagedPath)) return;
|
|
5681
|
+
import_fs6.default.renameSync(packagedPath, import_path5.default.join(destDir, ".gitignore"));
|
|
5682
|
+
}
|
|
5683
|
+
function materializeYarnrc(destDir) {
|
|
5684
|
+
const packagedPath = import_path5.default.join(destDir, "_yarnrc.yml");
|
|
5693
5685
|
if (!exists2(packagedPath)) return;
|
|
5694
|
-
|
|
5686
|
+
import_fs6.default.renameSync(packagedPath, import_path5.default.join(destDir, ".yarnrc.yml"));
|
|
5695
5687
|
}
|
|
5696
5688
|
var TEMPLATE_TITLE = "React Starter Kit";
|
|
5697
5689
|
var TEMPLATE_DESCRIPTION = "A modern React starter kit with TypeScript, Vite, SCSS, and comprehensive tooling for building scalable applications";
|
|
5698
5690
|
function replaceTokens(destDir, appName, description) {
|
|
5699
5691
|
const pkgName = toPackageName(appName);
|
|
5700
5692
|
const appTitle = toTitle(appName);
|
|
5701
|
-
const pkgPath =
|
|
5693
|
+
const pkgPath = import_path5.default.join(destDir, "package.json");
|
|
5702
5694
|
if (exists2(pkgPath)) {
|
|
5703
5695
|
const pkg = readJson(pkgPath);
|
|
5704
5696
|
pkg["name"] = pkgName;
|
|
@@ -5713,7 +5705,7 @@ function replaceTokens(destDir, appName, description) {
|
|
|
5713
5705
|
writeJson(pkgPath, pkg);
|
|
5714
5706
|
logOk2("package.json \u2014 name, description, version, stripped monorepo fields");
|
|
5715
5707
|
}
|
|
5716
|
-
const indexPath =
|
|
5708
|
+
const indexPath = import_path5.default.join(destDir, "index.html");
|
|
5717
5709
|
if (exists2(indexPath)) {
|
|
5718
5710
|
let html = readText2(indexPath);
|
|
5719
5711
|
html = html.replace(
|
|
@@ -5731,7 +5723,7 @@ function replaceTokens(destDir, appName, description) {
|
|
|
5731
5723
|
writeText2(indexPath, html);
|
|
5732
5724
|
logOk2("index.html \u2014 title, meta description, application-name");
|
|
5733
5725
|
}
|
|
5734
|
-
const configPath =
|
|
5726
|
+
const configPath = import_path5.default.join(destDir, "src", "configs", "appConfig.ts");
|
|
5735
5727
|
if (exists2(configPath)) {
|
|
5736
5728
|
let cfg = readText2(configPath);
|
|
5737
5729
|
cfg = cfg.replace(
|
|
@@ -5741,7 +5733,7 @@ function replaceTokens(destDir, appName, description) {
|
|
|
5741
5733
|
writeText2(configPath, cfg);
|
|
5742
5734
|
logOk2("src/configs/appConfig.ts \u2014 default title");
|
|
5743
5735
|
}
|
|
5744
|
-
const readmePath =
|
|
5736
|
+
const readmePath = import_path5.default.join(destDir, "README.md");
|
|
5745
5737
|
if (exists2(readmePath)) {
|
|
5746
5738
|
let readme = readText2(readmePath);
|
|
5747
5739
|
readme = readme.replace(
|
|
@@ -5755,7 +5747,7 @@ function replaceTokens(destDir, appName, description) {
|
|
|
5755
5747
|
writeText2(readmePath, readme);
|
|
5756
5748
|
logOk2("README.md \u2014 heading");
|
|
5757
5749
|
}
|
|
5758
|
-
const manifestPath =
|
|
5750
|
+
const manifestPath = import_path5.default.join(destDir, "public", "manifest.webmanifest");
|
|
5759
5751
|
if (exists2(manifestPath)) {
|
|
5760
5752
|
let manifest = readText2(manifestPath);
|
|
5761
5753
|
manifest = manifest.replace(
|
|
@@ -5767,7 +5759,7 @@ function replaceTokens(destDir, appName, description) {
|
|
|
5767
5759
|
}
|
|
5768
5760
|
}
|
|
5769
5761
|
function patchDockerComposeForProject(destDir, appName, portOffset) {
|
|
5770
|
-
const composePath =
|
|
5762
|
+
const composePath = import_path5.default.join(destDir, "docker-compose.yml");
|
|
5771
5763
|
if (!exists2(composePath)) return;
|
|
5772
5764
|
logStep2("Patching docker-compose.yml \u2014 container names + ports");
|
|
5773
5765
|
let content = readText2(composePath);
|
|
@@ -5800,7 +5792,7 @@ function patchDockerComposeForProject(destDir, appName, portOffset) {
|
|
|
5800
5792
|
}
|
|
5801
5793
|
}
|
|
5802
5794
|
function patchMakefileForProject(destDir, appName) {
|
|
5803
|
-
const makefilePath =
|
|
5795
|
+
const makefilePath = import_path5.default.join(destDir, "Makefile");
|
|
5804
5796
|
if (!exists2(makefilePath)) return;
|
|
5805
5797
|
let content = readText2(makefilePath);
|
|
5806
5798
|
content = content.replace(
|
|
@@ -5813,7 +5805,7 @@ function patchMakefileForProject(destDir, appName) {
|
|
|
5813
5805
|
logOk2("Makefile \u2014 ensured dynamic container names");
|
|
5814
5806
|
}
|
|
5815
5807
|
function patchViteConfigPort(destDir, portOffset) {
|
|
5816
|
-
const configPath =
|
|
5808
|
+
const configPath = import_path5.default.join(destDir, "vite.config.ts");
|
|
5817
5809
|
if (!exists2(configPath)) return;
|
|
5818
5810
|
const devPort = 3e3 + portOffset;
|
|
5819
5811
|
let content = readText2(configPath);
|
|
@@ -5824,7 +5816,7 @@ function patchViteConfigPort(destDir, portOffset) {
|
|
|
5824
5816
|
function patchEnvExamplePorts(destDir, portOffset) {
|
|
5825
5817
|
const bePort = 8e3 + portOffset;
|
|
5826
5818
|
for (const envFile of [".env.example", ".env.local"]) {
|
|
5827
|
-
const envPath =
|
|
5819
|
+
const envPath = import_path5.default.join(destDir, envFile);
|
|
5828
5820
|
if (!exists2(envPath)) continue;
|
|
5829
5821
|
let content = readText2(envPath);
|
|
5830
5822
|
content = patchReplace(
|
|
@@ -5841,17 +5833,17 @@ function removeDocker(destDir) {
|
|
|
5841
5833
|
const files = ["Dockerfile", "docker-compose.yml", ".dockerignore", "nginx.conf"];
|
|
5842
5834
|
let deleted = 0;
|
|
5843
5835
|
for (const f of files) {
|
|
5844
|
-
if (safeUnlink2(
|
|
5836
|
+
if (safeUnlink2(import_path5.default.join(destDir, f))) deleted++;
|
|
5845
5837
|
}
|
|
5846
|
-
if (safeRmDir(
|
|
5838
|
+
if (safeRmDir(import_path5.default.join(destDir, "nginx"))) {
|
|
5847
5839
|
deleted++;
|
|
5848
5840
|
logInfo2("nginx/ \u2014 removed");
|
|
5849
5841
|
}
|
|
5850
|
-
if (safeUnlink2(
|
|
5842
|
+
if (safeUnlink2(import_path5.default.join(destDir, "Makefile"))) {
|
|
5851
5843
|
deleted++;
|
|
5852
5844
|
logInfo2("Makefile \u2014 removed");
|
|
5853
5845
|
}
|
|
5854
|
-
const readmePath =
|
|
5846
|
+
const readmePath = import_path5.default.join(destDir, "README.md");
|
|
5855
5847
|
if (exists2(readmePath)) {
|
|
5856
5848
|
let readme = readText2(readmePath);
|
|
5857
5849
|
readme = removeMarkedSection(readme, "DOCKER");
|
|
@@ -5861,7 +5853,7 @@ function removeDocker(destDir) {
|
|
|
5861
5853
|
writeText2(readmePath, readme);
|
|
5862
5854
|
logInfo2("README.md \u2014 removed Docker sections");
|
|
5863
5855
|
}
|
|
5864
|
-
const envExPath =
|
|
5856
|
+
const envExPath = import_path5.default.join(destDir, ".env.example");
|
|
5865
5857
|
if (exists2(envExPath)) {
|
|
5866
5858
|
let env = readText2(envExPath);
|
|
5867
5859
|
env = env.replace(/# -{5,}\s*\n# 🐳 Docker[^#]*/g, "");
|
|
@@ -5884,16 +5876,16 @@ var PWA_FILES = [
|
|
|
5884
5876
|
function removePwa(destDir) {
|
|
5885
5877
|
let deleted = 0;
|
|
5886
5878
|
for (const f of PWA_FILES) {
|
|
5887
|
-
if (safeUnlink2(
|
|
5879
|
+
if (safeUnlink2(import_path5.default.join(destDir, f))) deleted++;
|
|
5888
5880
|
}
|
|
5889
|
-
if (safeRmDir(
|
|
5890
|
-
safeRmDir(
|
|
5891
|
-
safeRmDir(
|
|
5881
|
+
if (safeRmDir(import_path5.default.join(destDir, "public", "icons"))) deleted++;
|
|
5882
|
+
safeRmDir(import_path5.default.join(destDir, "src", "sw"));
|
|
5883
|
+
safeRmDir(import_path5.default.join(destDir, "src", "pwa"));
|
|
5892
5884
|
removePwaFromPackageJson(destDir);
|
|
5893
5885
|
removePwaFromPluginsIndex(destDir);
|
|
5894
5886
|
removePwaFromViteConfig(destDir);
|
|
5895
5887
|
removePwaFromIndexHtml(destDir);
|
|
5896
|
-
const readmePath =
|
|
5888
|
+
const readmePath = import_path5.default.join(destDir, "README.md");
|
|
5897
5889
|
if (exists2(readmePath)) {
|
|
5898
5890
|
let readme = readText2(readmePath);
|
|
5899
5891
|
readme = removeMarkedSection(readme, "PWA");
|
|
@@ -5908,7 +5900,7 @@ function removePwa(destDir) {
|
|
|
5908
5900
|
logOk2(`Deleted ${deleted} PWA file(s)`);
|
|
5909
5901
|
}
|
|
5910
5902
|
function removePwaFromPackageJson(destDir) {
|
|
5911
|
-
const pkgPath =
|
|
5903
|
+
const pkgPath = import_path5.default.join(destDir, "package.json");
|
|
5912
5904
|
if (!exists2(pkgPath)) return;
|
|
5913
5905
|
const pkg = readJson(pkgPath);
|
|
5914
5906
|
let changed = false;
|
|
@@ -5929,7 +5921,7 @@ function removePwaFromPackageJson(destDir) {
|
|
|
5929
5921
|
removePkgScript(destDir, "setup:pwa");
|
|
5930
5922
|
}
|
|
5931
5923
|
function removePwaFromPluginsIndex(destDir) {
|
|
5932
|
-
const indexPath =
|
|
5924
|
+
const indexPath = import_path5.default.join(destDir, "plugins", "index.ts");
|
|
5933
5925
|
if (!exists2(indexPath)) return;
|
|
5934
5926
|
let content = readText2(indexPath);
|
|
5935
5927
|
content = content.replace(/^.*pwaPlugin.*\n/gm, "");
|
|
@@ -5941,7 +5933,7 @@ function removePwaFromPluginsIndex(destDir) {
|
|
|
5941
5933
|
logInfo2("plugins/index.ts \u2014 removed PWA plugin exports");
|
|
5942
5934
|
}
|
|
5943
5935
|
function removePwaFromViteConfig(destDir) {
|
|
5944
|
-
const configPath =
|
|
5936
|
+
const configPath = import_path5.default.join(destDir, "vite.config.ts");
|
|
5945
5937
|
if (!exists2(configPath)) return;
|
|
5946
5938
|
let content = readText2(configPath);
|
|
5947
5939
|
content = content.replace(
|
|
@@ -5962,7 +5954,7 @@ function removePwaFromViteConfig(destDir) {
|
|
|
5962
5954
|
logInfo2("vite.config.ts \u2014 removed PWA plugin usage");
|
|
5963
5955
|
}
|
|
5964
5956
|
function removePwaFromIndexHtml(destDir) {
|
|
5965
|
-
const indexPath =
|
|
5957
|
+
const indexPath = import_path5.default.join(destDir, "index.html");
|
|
5966
5958
|
if (!exists2(indexPath)) return;
|
|
5967
5959
|
let html = readText2(indexPath);
|
|
5968
5960
|
html = html.replace(/\s*<link rel="manifest"[^>]*>\s*/g, "\n ");
|
|
@@ -5980,7 +5972,7 @@ function removePwaFromIndexHtml(destDir) {
|
|
|
5980
5972
|
logInfo2("index.html \u2014 removed PWA meta tags and manifest link");
|
|
5981
5973
|
}
|
|
5982
5974
|
function removePwaFromMainTsx(destDir) {
|
|
5983
|
-
const mainPath =
|
|
5975
|
+
const mainPath = import_path5.default.join(destDir, "src", "main.tsx");
|
|
5984
5976
|
if (!exists2(mainPath)) return;
|
|
5985
5977
|
let content = readText2(mainPath);
|
|
5986
5978
|
content = content.replace(/^import\s*\{[^}]*initPWA[^}]*\}\s*from\s*['"][^'"]*pwa['"];\s*\n/gm, "");
|
|
@@ -5990,7 +5982,7 @@ function removePwaFromMainTsx(destDir) {
|
|
|
5990
5982
|
logInfo2("src/main.tsx \u2014 removed initPWA import and call");
|
|
5991
5983
|
}
|
|
5992
5984
|
function removePwaFromAppTsx(destDir) {
|
|
5993
|
-
const appPath =
|
|
5985
|
+
const appPath = import_path5.default.join(destDir, "src", "App.tsx");
|
|
5994
5986
|
if (!exists2(appPath)) return;
|
|
5995
5987
|
let content = readText2(appPath);
|
|
5996
5988
|
content = content.replace(/,\s*PwaUpdateBanner\b/g, "");
|
|
@@ -6001,11 +5993,11 @@ function removePwaFromAppTsx(destDir) {
|
|
|
6001
5993
|
logInfo2("src/App.tsx \u2014 removed PwaUpdateBanner");
|
|
6002
5994
|
}
|
|
6003
5995
|
function removeHusky(destDir) {
|
|
6004
|
-
const huskyDir =
|
|
5996
|
+
const huskyDir = import_path5.default.join(destDir, ".husky");
|
|
6005
5997
|
if (safeRmDir(huskyDir)) {
|
|
6006
5998
|
logInfo2(".husky/ \u2014 removed");
|
|
6007
5999
|
}
|
|
6008
|
-
const pkgPath =
|
|
6000
|
+
const pkgPath = import_path5.default.join(destDir, "package.json");
|
|
6009
6001
|
if (exists2(pkgPath)) {
|
|
6010
6002
|
const pkg = readJson(pkgPath);
|
|
6011
6003
|
let changed = false;
|
|
@@ -6045,7 +6037,7 @@ function addTailwind(destDir) {
|
|
|
6045
6037
|
importTailwindInMain(destDir);
|
|
6046
6038
|
}
|
|
6047
6039
|
function addTailwindDeps(destDir) {
|
|
6048
|
-
const pkgPath =
|
|
6040
|
+
const pkgPath = import_path5.default.join(destDir, "package.json");
|
|
6049
6041
|
if (!exists2(pkgPath)) return;
|
|
6050
6042
|
const pkg = readJson(pkgPath);
|
|
6051
6043
|
const devDeps = pkg["devDependencies"] ?? {};
|
|
@@ -6056,7 +6048,7 @@ function addTailwindDeps(destDir) {
|
|
|
6056
6048
|
logOk2("package.json \u2014 added tailwindcss + @tailwindcss/vite");
|
|
6057
6049
|
}
|
|
6058
6050
|
function addTailwindVitePlugin(destDir) {
|
|
6059
|
-
const configPath =
|
|
6051
|
+
const configPath = import_path5.default.join(destDir, "vite.config.ts");
|
|
6060
6052
|
if (!exists2(configPath)) return;
|
|
6061
6053
|
let content = readText2(configPath);
|
|
6062
6054
|
if (!content.includes("@tailwindcss/vite")) {
|
|
@@ -6127,12 +6119,12 @@ function createTailwindCss(destDir) {
|
|
|
6127
6119
|
--radius-lg: var(--radius-4);
|
|
6128
6120
|
}
|
|
6129
6121
|
`;
|
|
6130
|
-
const stylesDir =
|
|
6131
|
-
writeText2(
|
|
6122
|
+
const stylesDir = import_path5.default.join(destDir, "src", "styles");
|
|
6123
|
+
writeText2(import_path5.default.join(stylesDir, "tailwind.css"), tailwindCss);
|
|
6132
6124
|
logOk2("src/styles/tailwind.css \u2014 created with theme bridge");
|
|
6133
6125
|
}
|
|
6134
6126
|
function importTailwindInMain(destDir) {
|
|
6135
|
-
const mainPath =
|
|
6127
|
+
const mainPath = import_path5.default.join(destDir, "src", "main.tsx");
|
|
6136
6128
|
if (!exists2(mainPath)) return;
|
|
6137
6129
|
let content = readText2(mainPath);
|
|
6138
6130
|
const tailwindImport = "import '@styles/tailwind.css';";
|
|
@@ -6166,7 +6158,7 @@ function cleanupSetupScripts(destDir, opts) {
|
|
|
6166
6158
|
if (scriptsToRemove.length === 0) return;
|
|
6167
6159
|
logStep2("Removing unused setup scripts");
|
|
6168
6160
|
for (const script of scriptsToRemove) {
|
|
6169
|
-
const scriptPath =
|
|
6161
|
+
const scriptPath = import_path5.default.join(destDir, "scripts", script);
|
|
6170
6162
|
if (safeUnlink2(scriptPath)) {
|
|
6171
6163
|
logOk2(`scripts/${script} \u2014 removed`);
|
|
6172
6164
|
}
|
|
@@ -6243,11 +6235,11 @@ function injectBrandColors(destDir, opts) {
|
|
|
6243
6235
|
"}",
|
|
6244
6236
|
""
|
|
6245
6237
|
].join("\n");
|
|
6246
|
-
const themesDir =
|
|
6247
|
-
const brandPath =
|
|
6238
|
+
const themesDir = import_path5.default.join(destDir, "src", "styles", "themes");
|
|
6239
|
+
const brandPath = import_path5.default.join(themesDir, "_brand.scss");
|
|
6248
6240
|
writeText2(brandPath, brandScss);
|
|
6249
6241
|
logOk2("src/styles/themes/_brand.scss \u2014 created");
|
|
6250
|
-
const indexPath =
|
|
6242
|
+
const indexPath = import_path5.default.join(themesDir, "_index.scss");
|
|
6251
6243
|
if (exists2(indexPath)) {
|
|
6252
6244
|
let idx = readText2(indexPath);
|
|
6253
6245
|
if (!idx.includes("@forward './brand'")) {
|
|
@@ -6258,8 +6250,8 @@ function injectBrandColors(destDir, opts) {
|
|
|
6258
6250
|
}
|
|
6259
6251
|
}
|
|
6260
6252
|
function generateEnvLocal(destDir, appName) {
|
|
6261
|
-
const examplePath =
|
|
6262
|
-
const localPath =
|
|
6253
|
+
const examplePath = import_path5.default.join(destDir, ".env.example");
|
|
6254
|
+
const localPath = import_path5.default.join(destDir, ".env.local");
|
|
6263
6255
|
if (!exists2(examplePath)) {
|
|
6264
6256
|
logInfo2(".env.example not found \u2014 skipping .env.local generation");
|
|
6265
6257
|
return;
|
|
@@ -6274,7 +6266,7 @@ function generateEnvLocal(destDir, appName) {
|
|
|
6274
6266
|
logOk2(".env.local generated from .env.example");
|
|
6275
6267
|
}
|
|
6276
6268
|
function cleanupGitignore(destDir) {
|
|
6277
|
-
const gitignorePath =
|
|
6269
|
+
const gitignorePath = import_path5.default.join(destDir, ".gitignore");
|
|
6278
6270
|
if (!exists2(gitignorePath)) return;
|
|
6279
6271
|
let content = readText2(gitignorePath);
|
|
6280
6272
|
const monorepoPatterns = [
|
|
@@ -6306,7 +6298,7 @@ function cleanupTemplateDocs(destDir) {
|
|
|
6306
6298
|
logStep2("Removing template documentation files");
|
|
6307
6299
|
let removed = 0;
|
|
6308
6300
|
for (const f of docFiles) {
|
|
6309
|
-
if (safeUnlink2(
|
|
6301
|
+
if (safeUnlink2(import_path5.default.join(destDir, f))) {
|
|
6310
6302
|
logOk2(`${f} \u2014 removed`);
|
|
6311
6303
|
removed++;
|
|
6312
6304
|
}
|
|
@@ -6342,7 +6334,7 @@ function initGitRepo(destDir, appName) {
|
|
|
6342
6334
|
}
|
|
6343
6335
|
}
|
|
6344
6336
|
function removePkgScript(destDir, scriptName) {
|
|
6345
|
-
const pkgPath =
|
|
6337
|
+
const pkgPath = import_path5.default.join(destDir, "package.json");
|
|
6346
6338
|
if (!exists2(pkgPath)) return;
|
|
6347
6339
|
const pkg = readJson(pkgPath);
|
|
6348
6340
|
const scripts = pkg["scripts"];
|
|
@@ -6415,7 +6407,7 @@ async function runWebCommand(argv) {
|
|
|
6415
6407
|
return;
|
|
6416
6408
|
}
|
|
6417
6409
|
if (args.includes("--version") || args.includes("-v")) {
|
|
6418
|
-
console.log("1.0.
|
|
6410
|
+
console.log("1.0.5");
|
|
6419
6411
|
return;
|
|
6420
6412
|
}
|
|
6421
6413
|
printBanner();
|
|
@@ -6430,7 +6422,7 @@ async function runWebCommand(argv) {
|
|
|
6430
6422
|
const destDir2 = getDestDir(appName2);
|
|
6431
6423
|
const pm2 = detectDefaultPm();
|
|
6432
6424
|
console.log("");
|
|
6433
|
-
logStep2(`Creating "${appName2}" (non-interactive) in ${
|
|
6425
|
+
logStep2(`Creating "${appName2}" (non-interactive) in ${import_path6.default.relative(process.cwd(), import_path6.default.dirname(destDir2))}`);
|
|
6434
6426
|
try {
|
|
6435
6427
|
await scaffold({
|
|
6436
6428
|
appName: appName2,
|
|
@@ -6579,7 +6571,7 @@ async function runWebCommand(argv) {
|
|
|
6579
6571
|
const appName = toPackageName(argName ?? answers.appName ?? "my-web-app");
|
|
6580
6572
|
const destDir = getDestDir(appName);
|
|
6581
6573
|
console.log("");
|
|
6582
|
-
logStep2(`Creating "${appName}" in ${
|
|
6574
|
+
logStep2(`Creating "${appName}" in ${import_path6.default.relative(process.cwd(), import_path6.default.dirname(destDir))}`);
|
|
6583
6575
|
try {
|
|
6584
6576
|
await scaffold({
|
|
6585
6577
|
appName,
|
|
@@ -6619,19 +6611,19 @@ async function runWebCommand(argv) {
|
|
|
6619
6611
|
function printBanner() {
|
|
6620
6612
|
console.log("");
|
|
6621
6613
|
console.log(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
|
|
6622
|
-
console.log(` \u2551 create-basekit web v${"1.0.
|
|
6614
|
+
console.log(` \u2551 create-basekit web v${"1.0.5"} \u2551`);
|
|
6623
6615
|
console.log(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D");
|
|
6624
6616
|
console.log("");
|
|
6625
6617
|
}
|
|
6626
6618
|
function abortIfInsideWorkspace(argv) {
|
|
6627
6619
|
const exampleName = argv.find((a) => !a.startsWith("-") && !isValueOfFlag(argv, a))?.trim() ?? "my-app";
|
|
6628
6620
|
let dir = process.cwd();
|
|
6629
|
-
const root =
|
|
6621
|
+
const root = import_path6.default.parse(dir).root;
|
|
6630
6622
|
while (dir !== root) {
|
|
6631
|
-
const pkgPath =
|
|
6632
|
-
if (
|
|
6623
|
+
const pkgPath = import_path6.default.join(dir, "package.json");
|
|
6624
|
+
if (import_fs7.default.existsSync(pkgPath)) {
|
|
6633
6625
|
try {
|
|
6634
|
-
const pkg = JSON.parse(
|
|
6626
|
+
const pkg = JSON.parse(import_fs7.default.readFileSync(pkgPath, "utf8"));
|
|
6635
6627
|
if (pkg.workspaces) {
|
|
6636
6628
|
console.error("");
|
|
6637
6629
|
console.error(" \u2717 Cannot create app inside a Yarn workspace.");
|
|
@@ -6653,7 +6645,7 @@ function abortIfInsideWorkspace(argv) {
|
|
|
6653
6645
|
} catch {
|
|
6654
6646
|
}
|
|
6655
6647
|
}
|
|
6656
|
-
const parent =
|
|
6648
|
+
const parent = import_path6.default.dirname(dir);
|
|
6657
6649
|
if (parent === dir) break;
|
|
6658
6650
|
dir = parent;
|
|
6659
6651
|
}
|
|
@@ -6725,82 +6717,12 @@ function isValueOfFlag(args, value) {
|
|
|
6725
6717
|
return prev !== void 0 && prev.startsWith("--");
|
|
6726
6718
|
}
|
|
6727
6719
|
|
|
6728
|
-
// src/commands/app/local-basekit-pins.ts
|
|
6729
|
-
init_cjs_shims();
|
|
6730
|
-
var import_path6 = __toESM(require("path"), 1);
|
|
6731
|
-
var BASEKIT_PACKAGE_DIRS = {
|
|
6732
|
-
"@appsbyme/basekit-hooks": "hooks",
|
|
6733
|
-
"@appsbyme/basekit-styles": "styles",
|
|
6734
|
-
"@appsbyme/basekit-ui": "ui",
|
|
6735
|
-
"@appsbyme/basekit-utils": "utils",
|
|
6736
|
-
"@appsbyme/basekit-eslint-config": "eslint-config",
|
|
6737
|
-
"@appsbyme/basekit-stylelint-config": "stylelint-config",
|
|
6738
|
-
"@appsbyme/basekit-tsconfig": "tsconfig"
|
|
6739
|
-
};
|
|
6740
|
-
function webKitPackagesAvailable(webKitRoot) {
|
|
6741
|
-
return exists(import_path6.default.join(webKitRoot, "packages", "utils", "package.json"));
|
|
6742
|
-
}
|
|
6743
|
-
function toFileSpecifier(fromDir, absolutePackageDir) {
|
|
6744
|
-
let relative = import_path6.default.relative(fromDir, absolutePackageDir);
|
|
6745
|
-
if (!relative.startsWith(".")) {
|
|
6746
|
-
relative = `./${relative}`;
|
|
6747
|
-
}
|
|
6748
|
-
return `file:${relative.replace(/\\/g, "/")}`;
|
|
6749
|
-
}
|
|
6750
|
-
function rewriteSection(section, frontendDir, webKitRoot) {
|
|
6751
|
-
if (!section) return 0;
|
|
6752
|
-
let count = 0;
|
|
6753
|
-
for (const [name, dirName] of Object.entries(BASEKIT_PACKAGE_DIRS)) {
|
|
6754
|
-
if (!(name in section)) continue;
|
|
6755
|
-
const absolute = import_path6.default.join(webKitRoot, "packages", dirName);
|
|
6756
|
-
if (!exists(import_path6.default.join(absolute, "package.json"))) {
|
|
6757
|
-
logWarn(`Local package missing for ${name} \u2014 left as ${section[name]}`);
|
|
6758
|
-
continue;
|
|
6759
|
-
}
|
|
6760
|
-
section[name] = toFileSpecifier(frontendDir, absolute);
|
|
6761
|
-
count += 1;
|
|
6762
|
-
}
|
|
6763
|
-
return count;
|
|
6764
|
-
}
|
|
6765
|
-
function applyLocalBasekitPins(projectRoot, webKitRoot = getWebKitRootFromPackage()) {
|
|
6766
|
-
if (!webKitPackagesAvailable(webKitRoot)) {
|
|
6767
|
-
logInfo("Local basekit-web packages not found \u2014 leaving @appsbyme registry pins");
|
|
6768
|
-
return false;
|
|
6769
|
-
}
|
|
6770
|
-
const packageJsonPath = import_path6.default.join(projectRoot, "frontend", "package.json");
|
|
6771
|
-
if (!exists(packageJsonPath)) {
|
|
6772
|
-
logWarn("frontend/package.json not found \u2014 skipping local @appsbyme pins");
|
|
6773
|
-
return false;
|
|
6774
|
-
}
|
|
6775
|
-
const pkg = JSON.parse(readText(packageJsonPath));
|
|
6776
|
-
const frontendDir = import_path6.default.join(projectRoot, "frontend");
|
|
6777
|
-
let rewritten = rewriteSection(pkg.dependencies, frontendDir, webKitRoot) + rewriteSection(pkg.devDependencies, frontendDir, webKitRoot) + rewriteSection(pkg.resolutions, frontendDir, webKitRoot);
|
|
6778
|
-
if (!pkg.resolutions) pkg.resolutions = {};
|
|
6779
|
-
for (const [name, dirName] of Object.entries(BASEKIT_PACKAGE_DIRS)) {
|
|
6780
|
-
const absolute = import_path6.default.join(webKitRoot, "packages", dirName);
|
|
6781
|
-
if (!exists(import_path6.default.join(absolute, "package.json"))) continue;
|
|
6782
|
-
const next = toFileSpecifier(frontendDir, absolute);
|
|
6783
|
-
if (pkg.resolutions[name] !== next) {
|
|
6784
|
-
pkg.resolutions[name] = next;
|
|
6785
|
-
rewritten += 1;
|
|
6786
|
-
}
|
|
6787
|
-
}
|
|
6788
|
-
if (rewritten === 0) {
|
|
6789
|
-
logInfo("No @appsbyme pins to rewrite in frontend/package.json");
|
|
6790
|
-
return false;
|
|
6791
|
-
}
|
|
6792
|
-
writeText(packageJsonPath, `${JSON.stringify(pkg, null, 2)}
|
|
6793
|
-
`);
|
|
6794
|
-
logOk(`Rewrote ${rewritten} @appsbyme pin(s) to local file: paths`);
|
|
6795
|
-
return true;
|
|
6796
|
-
}
|
|
6797
|
-
|
|
6798
6720
|
// src/commands/app/yarn-install.ts
|
|
6799
6721
|
init_cjs_shims();
|
|
6800
|
-
var
|
|
6722
|
+
var import_fs8 = __toESM(require("fs"), 1);
|
|
6801
6723
|
var import_path7 = __toESM(require("path"), 1);
|
|
6802
6724
|
async function yarnInstall(dir, label) {
|
|
6803
|
-
if (!
|
|
6725
|
+
if (!import_fs8.default.existsSync(import_path7.default.join(dir, "package.json"))) {
|
|
6804
6726
|
logWarn(`${label}/package.json not found \u2014 skipping yarn install`);
|
|
6805
6727
|
return false;
|
|
6806
6728
|
}
|
|
@@ -6854,7 +6776,6 @@ function buildWebScaffoldArgv(projectName, portOffset, nonInteractive) {
|
|
|
6854
6776
|
"--port-offset",
|
|
6855
6777
|
String(portOffset),
|
|
6856
6778
|
"--no-git",
|
|
6857
|
-
// Install after optional local @appsbyme file: pin rewrite (kit authors)
|
|
6858
6779
|
"--no-install"
|
|
6859
6780
|
];
|
|
6860
6781
|
if (nonInteractive) {
|
|
@@ -6862,6 +6783,14 @@ function buildWebScaffoldArgv(projectName, portOffset, nonInteractive) {
|
|
|
6862
6783
|
}
|
|
6863
6784
|
return args;
|
|
6864
6785
|
}
|
|
6786
|
+
function stripNestedFrontendGithub(frontendDir) {
|
|
6787
|
+
const nestedGithub = import_path8.default.join(frontendDir, ".github");
|
|
6788
|
+
if (!import_fs9.default.existsSync(nestedGithub)) {
|
|
6789
|
+
return false;
|
|
6790
|
+
}
|
|
6791
|
+
import_fs9.default.rmSync(nestedGithub, { recursive: true, force: true });
|
|
6792
|
+
return true;
|
|
6793
|
+
}
|
|
6865
6794
|
async function scaffoldFrontend(opts) {
|
|
6866
6795
|
const { projectName, portOffset, projectRoot, nonInteractive } = opts;
|
|
6867
6796
|
logStep("Running create-basekit web (answer the remaining prompts)");
|
|
@@ -6873,11 +6802,13 @@ async function scaffoldFrontend(opts) {
|
|
|
6873
6802
|
}
|
|
6874
6803
|
const scaffoldedDir = import_path8.default.join(projectRoot, projectName);
|
|
6875
6804
|
const frontendDir = import_path8.default.join(projectRoot, "frontend");
|
|
6876
|
-
if (
|
|
6877
|
-
|
|
6805
|
+
if (import_fs9.default.existsSync(scaffoldedDir)) {
|
|
6806
|
+
import_fs9.default.renameSync(scaffoldedDir, frontendDir);
|
|
6878
6807
|
logOk(`Renamed ${projectName}/ \u2192 frontend/`);
|
|
6879
6808
|
}
|
|
6880
|
-
|
|
6809
|
+
if (stripNestedFrontendGithub(frontendDir)) {
|
|
6810
|
+
logOk("Removed frontend/.github (root CI owns workflows)");
|
|
6811
|
+
}
|
|
6881
6812
|
await yarnInstall(frontendDir, "frontend");
|
|
6882
6813
|
logOk("Frontend scaffolded");
|
|
6883
6814
|
}
|
|
@@ -6885,7 +6816,7 @@ async function scaffoldFrontend(opts) {
|
|
|
6885
6816
|
// src/commands/app/mobile.ts
|
|
6886
6817
|
init_cjs_shims();
|
|
6887
6818
|
var import_path11 = __toESM(require("path"), 1);
|
|
6888
|
-
var
|
|
6819
|
+
var import_fs12 = __toESM(require("fs"), 1);
|
|
6889
6820
|
|
|
6890
6821
|
// src/commands/mobile/index.ts
|
|
6891
6822
|
init_cjs_shims();
|
|
@@ -6893,14 +6824,14 @@ var import_prompts2 = __toESM(require_prompts3(), 1);
|
|
|
6893
6824
|
|
|
6894
6825
|
// src/commands/mobile/scaffold.ts
|
|
6895
6826
|
init_cjs_shims();
|
|
6896
|
-
var
|
|
6827
|
+
var import_fs11 = __toESM(require("fs"), 1);
|
|
6897
6828
|
var import_path10 = __toESM(require("path"), 1);
|
|
6898
|
-
var
|
|
6829
|
+
var import_node_url3 = require("url");
|
|
6899
6830
|
|
|
6900
6831
|
// src/commands/mobile/utils.ts
|
|
6901
6832
|
init_cjs_shims();
|
|
6902
6833
|
var import_child_process3 = require("child_process");
|
|
6903
|
-
var
|
|
6834
|
+
var import_fs10 = __toESM(require("fs"), 1);
|
|
6904
6835
|
var import_path9 = __toESM(require("path"), 1);
|
|
6905
6836
|
function logStep3(msg) {
|
|
6906
6837
|
console.log(`
|
|
@@ -6916,21 +6847,21 @@ function logError3(msg) {
|
|
|
6916
6847
|
console.error(` \u2717 ${msg}`);
|
|
6917
6848
|
}
|
|
6918
6849
|
function exists3(absPath) {
|
|
6919
|
-
return
|
|
6850
|
+
return import_fs10.default.existsSync(absPath);
|
|
6920
6851
|
}
|
|
6921
6852
|
function copyDir2(src, dest) {
|
|
6922
|
-
|
|
6853
|
+
import_fs10.default.cpSync(src, dest, { recursive: true });
|
|
6923
6854
|
}
|
|
6924
6855
|
function readText3(absPath) {
|
|
6925
|
-
return
|
|
6856
|
+
return import_fs10.default.readFileSync(absPath, "utf-8");
|
|
6926
6857
|
}
|
|
6927
6858
|
function writeText3(absPath, content) {
|
|
6928
|
-
|
|
6859
|
+
import_fs10.default.writeFileSync(absPath, content);
|
|
6929
6860
|
}
|
|
6930
6861
|
function safeRmDir2(absDir) {
|
|
6931
6862
|
if (!exists3(absDir)) return false;
|
|
6932
6863
|
try {
|
|
6933
|
-
|
|
6864
|
+
import_fs10.default.rmSync(absDir, { recursive: true, force: true });
|
|
6934
6865
|
return true;
|
|
6935
6866
|
} catch {
|
|
6936
6867
|
return false;
|
|
@@ -7025,17 +6956,9 @@ function createSpinner3(text) {
|
|
|
7025
6956
|
|
|
7026
6957
|
// src/commands/mobile/scaffold.ts
|
|
7027
6958
|
function templateDir2() {
|
|
7028
|
-
|
|
7029
|
-
|
|
7030
|
-
|
|
7031
|
-
import_path10.default.join(here, "../template-mobile")
|
|
7032
|
-
];
|
|
7033
|
-
for (const candidate of candidates) {
|
|
7034
|
-
const resolved = import_path10.default.resolve(candidate);
|
|
7035
|
-
if (import_fs10.default.existsSync(resolved)) return resolved;
|
|
7036
|
-
}
|
|
7037
|
-
throw new Error(
|
|
7038
|
-
`Starter template is missing (searched: ${candidates.map((c) => import_path10.default.resolve(c)).join(", ")})`
|
|
6959
|
+
return import_path10.default.join(
|
|
6960
|
+
getCreateBasekitPackageRoot(import_path10.default.dirname((0, import_node_url3.fileURLToPath)(importMetaUrl))),
|
|
6961
|
+
"template-mobile"
|
|
7039
6962
|
);
|
|
7040
6963
|
}
|
|
7041
6964
|
async function scaffold2(opts) {
|
|
@@ -7059,6 +6982,7 @@ async function scaffoldInner2(opts) {
|
|
|
7059
6982
|
const apiUrl = `http://localhost:${8e3 + portOffset}/api/v1`;
|
|
7060
6983
|
await cloneTemplate2(destDir);
|
|
7061
6984
|
materializeGitignore2(destDir);
|
|
6985
|
+
materializeYarnrc2(destDir);
|
|
7062
6986
|
if (opts.monorepo) {
|
|
7063
6987
|
stripBundledShared(destDir);
|
|
7064
6988
|
adjustSharedPaths(destDir);
|
|
@@ -7080,7 +7004,7 @@ async function scaffoldInner2(opts) {
|
|
|
7080
7004
|
}
|
|
7081
7005
|
async function cloneTemplate2(destDir) {
|
|
7082
7006
|
const source = templateDir2();
|
|
7083
|
-
if (!
|
|
7007
|
+
if (!import_fs11.default.existsSync(source)) {
|
|
7084
7008
|
throw new Error(`Starter template is missing at ${source}`);
|
|
7085
7009
|
}
|
|
7086
7010
|
logStep3("Copying the Expo starter");
|
|
@@ -7097,7 +7021,12 @@ async function cloneTemplate2(destDir) {
|
|
|
7097
7021
|
function materializeGitignore2(destDir) {
|
|
7098
7022
|
const packagedPath = import_path10.default.join(destDir, "_gitignore");
|
|
7099
7023
|
if (!exists3(packagedPath)) return;
|
|
7100
|
-
|
|
7024
|
+
import_fs11.default.renameSync(packagedPath, import_path10.default.join(destDir, ".gitignore"));
|
|
7025
|
+
}
|
|
7026
|
+
function materializeYarnrc2(destDir) {
|
|
7027
|
+
const packagedPath = import_path10.default.join(destDir, "_yarnrc.yml");
|
|
7028
|
+
if (!exists3(packagedPath)) return;
|
|
7029
|
+
import_fs11.default.renameSync(packagedPath, import_path10.default.join(destDir, ".yarnrc.yml"));
|
|
7101
7030
|
}
|
|
7102
7031
|
function stripBundledShared(destDir) {
|
|
7103
7032
|
const sharedDir = import_path10.default.join(destDir, "packages");
|
|
@@ -7203,15 +7132,15 @@ function cleanupArtifacts(destDir) {
|
|
|
7203
7132
|
safeRmDir2(import_path10.default.join(destDir, ".git"));
|
|
7204
7133
|
const lockPath = import_path10.default.join(destDir, "yarn.lock");
|
|
7205
7134
|
if (exists3(lockPath)) {
|
|
7206
|
-
|
|
7135
|
+
import_fs11.default.unlinkSync(lockPath);
|
|
7207
7136
|
}
|
|
7208
7137
|
const readmePath = import_path10.default.join(destDir, "README.md");
|
|
7209
7138
|
if (exists3(readmePath)) {
|
|
7210
|
-
|
|
7139
|
+
import_fs11.default.unlinkSync(readmePath);
|
|
7211
7140
|
}
|
|
7212
7141
|
const licensePath = import_path10.default.join(destDir, "LICENSE");
|
|
7213
7142
|
if (exists3(licensePath)) {
|
|
7214
|
-
|
|
7143
|
+
import_fs11.default.unlinkSync(licensePath);
|
|
7215
7144
|
}
|
|
7216
7145
|
}
|
|
7217
7146
|
function initGitRepo2(destDir) {
|
|
@@ -7281,7 +7210,7 @@ async function runMobileCommand(argv) {
|
|
|
7281
7210
|
return;
|
|
7282
7211
|
}
|
|
7283
7212
|
if (args.includes("--version") || args.includes("-v")) {
|
|
7284
|
-
console.log("1.0.
|
|
7213
|
+
console.log("1.0.5");
|
|
7285
7214
|
return;
|
|
7286
7215
|
}
|
|
7287
7216
|
printBanner2();
|
|
@@ -7384,7 +7313,7 @@ async function runMobileCommand(argv) {
|
|
|
7384
7313
|
function printBanner2() {
|
|
7385
7314
|
console.log("");
|
|
7386
7315
|
console.log(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
|
|
7387
|
-
console.log(` \u2551 create-basekit mobile v${"1.0.
|
|
7316
|
+
console.log(` \u2551 create-basekit mobile v${"1.0.5"} \u2551`);
|
|
7388
7317
|
console.log(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D");
|
|
7389
7318
|
console.log("");
|
|
7390
7319
|
console.log(" Expo (React Native) app scaffolder");
|
|
@@ -7489,7 +7418,7 @@ async function scaffoldMobile(opts) {
|
|
|
7489
7418
|
const scaffoldedDir = import_path11.default.join(projectRoot, projectName);
|
|
7490
7419
|
const mobileDir = import_path11.default.join(projectRoot, "mobile");
|
|
7491
7420
|
if (exists(scaffoldedDir)) {
|
|
7492
|
-
|
|
7421
|
+
import_fs12.default.renameSync(scaffoldedDir, mobileDir);
|
|
7493
7422
|
logOk(`Renamed ${projectName}/ \u2192 mobile/`);
|
|
7494
7423
|
}
|
|
7495
7424
|
return true;
|
|
@@ -7501,21 +7430,12 @@ var import_path13 = __toESM(require("path"), 1);
|
|
|
7501
7430
|
|
|
7502
7431
|
// src/commands/app/project-identity.ts
|
|
7503
7432
|
init_cjs_shims();
|
|
7504
|
-
var
|
|
7433
|
+
var import_fs13 = __toESM(require("fs"), 1);
|
|
7505
7434
|
var import_path12 = __toESM(require("path"), 1);
|
|
7506
|
-
var
|
|
7507
|
-
function resolveNewProjectFixturePath(fromDir = import_path12.default.dirname((0,
|
|
7508
|
-
const
|
|
7509
|
-
|
|
7510
|
-
import_path12.default.join(fromDir, "../fixtures/new_project.py")
|
|
7511
|
-
];
|
|
7512
|
-
for (const candidate of candidates) {
|
|
7513
|
-
const resolved = import_path12.default.resolve(candidate);
|
|
7514
|
-
if (import_fs12.default.existsSync(resolved)) return resolved;
|
|
7515
|
-
}
|
|
7516
|
-
throw new Error(
|
|
7517
|
-
`fixtures/new_project.py missing (searched: ${candidates.map((c) => import_path12.default.resolve(c)).join(", ")})`
|
|
7518
|
-
);
|
|
7435
|
+
var import_node_url4 = require("url");
|
|
7436
|
+
function resolveNewProjectFixturePath(fromDir = import_path12.default.dirname((0, import_node_url4.fileURLToPath)(importMetaUrl))) {
|
|
7437
|
+
const fixture = import_path12.default.join(getCreateBasekitPackageRoot(fromDir), "fixtures", "new_project.py");
|
|
7438
|
+
return fixture;
|
|
7519
7439
|
}
|
|
7520
7440
|
function deriveProjectIdentity(projectName) {
|
|
7521
7441
|
const slug = toPythonSlug(projectName);
|
|
@@ -7537,8 +7457,8 @@ function writeProjectIdentity(projectRoot, projectName) {
|
|
|
7537
7457
|
mkdirp(scriptsDir);
|
|
7538
7458
|
const fixturePath = resolveNewProjectFixturePath();
|
|
7539
7459
|
const scriptPath = import_path12.default.join(scriptsDir, "new_project.py");
|
|
7540
|
-
|
|
7541
|
-
|
|
7460
|
+
import_fs13.default.copyFileSync(fixturePath, scriptPath);
|
|
7461
|
+
import_fs13.default.chmodSync(scriptPath, 493);
|
|
7542
7462
|
}
|
|
7543
7463
|
|
|
7544
7464
|
// src/commands/app/root-files.ts
|
|
@@ -7570,14 +7490,10 @@ function createRootFiles({
|
|
|
7570
7490
|
logOk(".github/");
|
|
7571
7491
|
mkdirp(import_path13.default.join(projectRoot, ".claude"));
|
|
7572
7492
|
logOk(".claude/");
|
|
7573
|
-
|
|
7574
|
-
|
|
7575
|
-
|
|
7576
|
-
|
|
7577
|
-
logOk(".github/workflows/ci.yml");
|
|
7578
|
-
writeText(import_path13.default.join(projectRoot, ".github", "dependabot.yml"), githubDependabot(frontend));
|
|
7579
|
-
logOk(".github/dependabot.yml");
|
|
7580
|
-
}
|
|
7493
|
+
const workflowsDir = import_path13.default.join(projectRoot, ".github", "workflows");
|
|
7494
|
+
mkdirp(workflowsDir);
|
|
7495
|
+
writeText(import_path13.default.join(workflowsDir, "ci.yml"), githubCi(projectName, frontend, mobile));
|
|
7496
|
+
logOk(".github/workflows/ci.yml");
|
|
7581
7497
|
}
|
|
7582
7498
|
function rootReadme(projectName, portOffset, mobile, frontend = true) {
|
|
7583
7499
|
const bePort = 8e3 + portOffset;
|
|
@@ -7903,7 +7819,7 @@ function rootMakefile(mobile, frontend = true) {
|
|
|
7903
7819
|
` : "";
|
|
7904
7820
|
const feStop = frontend ? ' @pkill -f "[v]ite" >/dev/null 2>&1 || true\n' : "";
|
|
7905
7821
|
const feTarget = frontend ? `
|
|
7906
|
-
start-fe: ## Start frontend only (host yarn
|
|
7822
|
+
start-fe: ## Start frontend only (host yarn)
|
|
7907
7823
|
@cd frontend && yarn dev
|
|
7908
7824
|
` : "";
|
|
7909
7825
|
const setupFe = frontend ? " @cd frontend && yarn install\n" : "";
|
|
@@ -7971,32 +7887,95 @@ ${setupTarget}${feTarget}${mobileTargets}stop: ## Stop all running services
|
|
|
7971
7887
|
${feStop}${mobile ? ' @pkill -f "[e]xpo start" >/dev/null 2>&1 || true\n' : ""} @echo "Done."
|
|
7972
7888
|
`;
|
|
7973
7889
|
}
|
|
7974
|
-
function githubCi(projectName, frontend = true) {
|
|
7890
|
+
function githubCi(projectName, frontend = true, mobile = false) {
|
|
7891
|
+
const dockerNeeds = frontend ? "[backend, frontend]" : "[backend]";
|
|
7892
|
+
const frontendDockerStep = frontend ? `
|
|
7893
|
+
- name: Build frontend image
|
|
7894
|
+
run: docker build -f frontend/Dockerfile -t ${projectName}-fe:\${{ github.sha }} .
|
|
7895
|
+
` : "";
|
|
7896
|
+
const frontendSharedInstall = mobile ? `
|
|
7897
|
+
- name: Install shared dependencies
|
|
7898
|
+
working-directory: packages/shared
|
|
7899
|
+
run: yarn install --immutable
|
|
7900
|
+
` : "";
|
|
7901
|
+
const frontendCachePath = mobile ? `|
|
|
7902
|
+
frontend/yarn.lock
|
|
7903
|
+
packages/shared/yarn.lock` : "frontend/yarn.lock";
|
|
7975
7904
|
const frontendJob = frontend ? `
|
|
7976
7905
|
frontend:
|
|
7977
|
-
name: Frontend
|
|
7906
|
+
name: "Frontend \u2014 type-check + lint + test"
|
|
7978
7907
|
runs-on: ubuntu-latest
|
|
7979
7908
|
defaults:
|
|
7980
7909
|
run:
|
|
7981
7910
|
working-directory: frontend
|
|
7982
7911
|
steps:
|
|
7983
7912
|
- uses: actions/checkout@v4
|
|
7913
|
+
- name: Enable Corepack (Yarn 4)
|
|
7914
|
+
run: corepack enable
|
|
7984
7915
|
- uses: actions/setup-node@v4
|
|
7985
7916
|
with:
|
|
7986
|
-
node-version:
|
|
7987
|
-
|
|
7917
|
+
node-version: 22
|
|
7918
|
+
cache: yarn
|
|
7919
|
+
cache-dependency-path: ${frontendCachePath}
|
|
7920
|
+
${frontendSharedInstall} - run: yarn install --immutable
|
|
7921
|
+
- run: yarn type-check
|
|
7922
|
+
- run: yarn lint
|
|
7923
|
+
- run: yarn stylelint
|
|
7924
|
+
- run: yarn test:run
|
|
7925
|
+
- run: yarn build
|
|
7926
|
+
` : "";
|
|
7927
|
+
const mobileJobs = mobile ? `
|
|
7928
|
+
mobile:
|
|
7929
|
+
name: "Mobile \u2014 type-check + lint + test"
|
|
7930
|
+
runs-on: ubuntu-latest
|
|
7931
|
+
defaults:
|
|
7932
|
+
run:
|
|
7933
|
+
working-directory: mobile
|
|
7934
|
+
steps:
|
|
7935
|
+
- uses: actions/checkout@v4
|
|
7936
|
+
- name: Enable Corepack (Yarn 4)
|
|
7937
|
+
run: corepack enable
|
|
7938
|
+
- uses: actions/setup-node@v4
|
|
7939
|
+
with:
|
|
7940
|
+
node-version: 22
|
|
7941
|
+
cache: yarn
|
|
7942
|
+
cache-dependency-path: |
|
|
7943
|
+
mobile/yarn.lock
|
|
7944
|
+
packages/shared/yarn.lock
|
|
7988
7945
|
- run: yarn install --immutable
|
|
7946
|
+
- name: Install shared dependencies
|
|
7947
|
+
working-directory: packages/shared
|
|
7948
|
+
run: yarn install --immutable
|
|
7949
|
+
- run: yarn type-check
|
|
7989
7950
|
- run: yarn lint
|
|
7990
|
-
- run:
|
|
7991
|
-
|
|
7951
|
+
- run: yarn test --watchman=false
|
|
7952
|
+
|
|
7953
|
+
shared:
|
|
7954
|
+
name: "Shared \u2014 type-check + test"
|
|
7955
|
+
runs-on: ubuntu-latest
|
|
7956
|
+
defaults:
|
|
7957
|
+
run:
|
|
7958
|
+
working-directory: packages/shared
|
|
7959
|
+
steps:
|
|
7960
|
+
- uses: actions/checkout@v4
|
|
7961
|
+
- name: Enable Corepack (Yarn 4)
|
|
7962
|
+
run: corepack enable
|
|
7963
|
+
- uses: actions/setup-node@v4
|
|
7964
|
+
with:
|
|
7965
|
+
node-version: 22
|
|
7966
|
+
cache: yarn
|
|
7967
|
+
cache-dependency-path: packages/shared/yarn.lock
|
|
7968
|
+
- run: yarn install --immutable
|
|
7969
|
+
- run: yarn type-check
|
|
7970
|
+
- run: yarn test
|
|
7992
7971
|
` : "";
|
|
7993
7972
|
return `name: CI
|
|
7994
7973
|
|
|
7995
7974
|
on:
|
|
7996
7975
|
push:
|
|
7997
|
-
branches: [
|
|
7976
|
+
branches: [master]
|
|
7998
7977
|
pull_request:
|
|
7999
|
-
branches: [
|
|
7978
|
+
branches: [master]
|
|
8000
7979
|
|
|
8001
7980
|
concurrency:
|
|
8002
7981
|
group: \${{ github.workflow }}-\${{ github.ref }}
|
|
@@ -8004,94 +7983,41 @@ concurrency:
|
|
|
8004
7983
|
|
|
8005
7984
|
jobs:
|
|
8006
7985
|
backend:
|
|
8007
|
-
name: Backend
|
|
7986
|
+
name: "Backend \u2014 lint + test"
|
|
8008
7987
|
runs-on: ubuntu-latest
|
|
8009
7988
|
defaults:
|
|
8010
7989
|
run:
|
|
8011
7990
|
working-directory: backend
|
|
8012
|
-
services:
|
|
8013
|
-
postgres:
|
|
8014
|
-
image: postgres:16
|
|
8015
|
-
env:
|
|
8016
|
-
POSTGRES_USER: ci
|
|
8017
|
-
POSTGRES_PASSWORD: ci
|
|
8018
|
-
POSTGRES_DB: ${projectName.replace(/-/g, "_")}_test
|
|
8019
|
-
ports: ["5432:5432"]
|
|
8020
|
-
options: >-
|
|
8021
|
-
--health-cmd pg_isready
|
|
8022
|
-
--health-interval 10s
|
|
8023
|
-
--health-timeout 5s
|
|
8024
|
-
--health-retries 5
|
|
8025
|
-
redis:
|
|
8026
|
-
image: redis:7
|
|
8027
|
-
ports: ["6379:6379"]
|
|
8028
7991
|
steps:
|
|
8029
7992
|
- uses: actions/checkout@v4
|
|
8030
7993
|
- uses: actions/setup-python@v5
|
|
8031
7994
|
with:
|
|
8032
7995
|
python-version: "3.12"
|
|
8033
|
-
|
|
7996
|
+
cache: pip
|
|
7997
|
+
cache-dependency-path: backend/requirements*.txt
|
|
7998
|
+
- name: Install dependencies
|
|
7999
|
+
run: |
|
|
8000
|
+
python -m pip install --upgrade pip
|
|
8001
|
+
pip install -r requirements.txt -r requirements-dev.txt
|
|
8034
8002
|
- run: ruff check .
|
|
8035
8003
|
- run: ruff format --check .
|
|
8036
|
-
-
|
|
8037
|
-
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
- uses: actions/checkout@v4
|
|
8046
|
-
- uses: actions/setup-node@v4
|
|
8047
|
-
with:
|
|
8048
|
-
node-version: 20
|
|
8049
|
-
- run: yarn install
|
|
8050
|
-
- run: npx tsc --noEmit
|
|
8051
|
-
- run: yarn test --ci
|
|
8052
|
-
|
|
8053
|
-
shared:
|
|
8054
|
-
name: Shared packages
|
|
8004
|
+
- name: Run tests
|
|
8005
|
+
env:
|
|
8006
|
+
DJANGO_SETTINGS_MODULE: config.settings.test
|
|
8007
|
+
SECRET_KEY: ci-test-secret-key-not-for-production
|
|
8008
|
+
CELERY_TASK_ALWAYS_EAGER: "True"
|
|
8009
|
+
run: python -m pytest --tb=short -q
|
|
8010
|
+
${frontendJob}${mobileJobs}
|
|
8011
|
+
docker:
|
|
8012
|
+
name: "Docker \u2014 smoke build"
|
|
8055
8013
|
runs-on: ubuntu-latest
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
working-directory: packages/shared
|
|
8014
|
+
needs: ${dockerNeeds}
|
|
8015
|
+
if: github.ref == 'refs/heads/master'
|
|
8059
8016
|
steps:
|
|
8060
8017
|
- uses: actions/checkout@v4
|
|
8061
|
-
-
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
- run: npx tsc --noEmit
|
|
8065
|
-
`;
|
|
8066
|
-
}
|
|
8067
|
-
function githubDependabot(frontend = true) {
|
|
8068
|
-
const frontendUpdate = frontend ? `
|
|
8069
|
-
- package-ecosystem: npm
|
|
8070
|
-
directory: /frontend
|
|
8071
|
-
schedule:
|
|
8072
|
-
interval: weekly
|
|
8073
|
-
open-pull-requests-limit: 10
|
|
8074
|
-
` : "";
|
|
8075
|
-
return `version: 2
|
|
8076
|
-
updates:
|
|
8077
|
-
- package-ecosystem: pip
|
|
8078
|
-
directory: /backend
|
|
8079
|
-
schedule:
|
|
8080
|
-
interval: weekly
|
|
8081
|
-
open-pull-requests-limit: 10
|
|
8082
|
-
${frontendUpdate}
|
|
8083
|
-
- package-ecosystem: npm
|
|
8084
|
-
directory: /mobile
|
|
8085
|
-
schedule:
|
|
8086
|
-
interval: weekly
|
|
8087
|
-
open-pull-requests-limit: 10
|
|
8088
|
-
|
|
8089
|
-
- package-ecosystem: github-actions
|
|
8090
|
-
directory: /
|
|
8091
|
-
schedule:
|
|
8092
|
-
interval: weekly
|
|
8093
|
-
open-pull-requests-limit: 5
|
|
8094
|
-
`;
|
|
8018
|
+
- name: Build backend image
|
|
8019
|
+
run: docker build -t ${projectName}-be:\${{ github.sha }} ./backend
|
|
8020
|
+
${frontendDockerStep}`;
|
|
8095
8021
|
}
|
|
8096
8022
|
|
|
8097
8023
|
// src/commands/app/shared-package.ts
|
|
@@ -8110,6 +8036,8 @@ function scaffoldSharedPackage(projectRoot, projectName) {
|
|
|
8110
8036
|
mkdirp(import_path14.default.join(sharedRoot, "src", "i18n"));
|
|
8111
8037
|
writeText(import_path14.default.join(sharedRoot, "package.json"), sharedPackageJson(projectName));
|
|
8112
8038
|
logOk("package.json");
|
|
8039
|
+
writeText(import_path14.default.join(sharedRoot, ".yarnrc.yml"), "nodeLinker: node-modules\n");
|
|
8040
|
+
logOk(".yarnrc.yml");
|
|
8113
8041
|
writeText(import_path14.default.join(sharedRoot, "tsconfig.json"), sharedTsconfig());
|
|
8114
8042
|
logOk("tsconfig.json");
|
|
8115
8043
|
writeText(import_path14.default.join(sharedRoot, "vitest.config.ts"), sharedVitestConfig());
|
|
@@ -8442,10 +8370,14 @@ init_cjs_shims();
|
|
|
8442
8370
|
var import_path15 = __toESM(require("path"), 1);
|
|
8443
8371
|
function patchSharedReferences(projectRoot) {
|
|
8444
8372
|
logStep("Patching shared package references");
|
|
8445
|
-
|
|
8373
|
+
patchFrontendDocker(projectRoot);
|
|
8446
8374
|
verifyFrontendSharedAlias(projectRoot);
|
|
8447
8375
|
verifyMobileSharedPaths(projectRoot);
|
|
8448
8376
|
}
|
|
8377
|
+
function patchFrontendDocker(projectRoot) {
|
|
8378
|
+
patchFrontendDockerfile(projectRoot);
|
|
8379
|
+
patchFrontendCompose(projectRoot);
|
|
8380
|
+
}
|
|
8449
8381
|
function patchFrontendDockerfile(projectRoot) {
|
|
8450
8382
|
const dockerfilePath = import_path15.default.join(projectRoot, "frontend", "Dockerfile");
|
|
8451
8383
|
if (!exists(dockerfilePath)) {
|
|
@@ -8453,30 +8385,102 @@ function patchFrontendDockerfile(projectRoot) {
|
|
|
8453
8385
|
return;
|
|
8454
8386
|
}
|
|
8455
8387
|
let content = readText(dockerfilePath);
|
|
8456
|
-
if (content.includes("COPY packages/shared/")) {
|
|
8457
|
-
logOk("Dockerfile \u2014
|
|
8388
|
+
if (content.includes("WORKDIR /workspace/packages/shared") && content.includes("COPY packages/shared/") && content.includes("COPY frontend/")) {
|
|
8389
|
+
logOk("Dockerfile \u2014 monorepo shared COPY + install already present");
|
|
8458
8390
|
return;
|
|
8459
8391
|
}
|
|
8460
|
-
|
|
8461
|
-
/^(COPY package\.json \.yarnrc\.yml \.\/\n)/m,
|
|
8462
|
-
/^(COPY package\.json yarn\.lock \.yarnrc\.yml \.\/\n)/m
|
|
8463
|
-
];
|
|
8464
|
-
const matched = manifestCopyPatterns.find((pattern) => pattern.test(content));
|
|
8465
|
-
if (matched) {
|
|
8466
|
-
content = content.replace(matched, "$1COPY packages/shared/ packages/shared/\n");
|
|
8467
|
-
content = content.replace(
|
|
8468
|
-
/# Root manifests and lockfile are copied first so `yarn install` is only\n# re-run when dependencies change, not on every source file change\.\n/,
|
|
8469
|
-
"# Root manifests, lockfile, and shared packages are copied first so\n# `yarn install` is only re-run when dependencies change.\n"
|
|
8470
|
-
);
|
|
8392
|
+
if (content.includes("COPY packages/shared/") && content.includes("WORKDIR /workspace/frontend") && !content.includes("WORKDIR /workspace/packages/shared")) {
|
|
8471
8393
|
content = content.replace(
|
|
8472
|
-
|
|
8473
|
-
|
|
8394
|
+
"WORKDIR /workspace/frontend\nRUN --mount=type=cache,target=/root/.yarn/berry/cache \\\n yarn install --immutable",
|
|
8395
|
+
[
|
|
8396
|
+
"# Shared must have its own node_modules (zod, etc.) \u2014 tsc resolves from source.",
|
|
8397
|
+
"WORKDIR /workspace/packages/shared",
|
|
8398
|
+
"RUN --mount=type=cache,target=/root/.yarn/berry/cache \\",
|
|
8399
|
+
" yarn install --immutable",
|
|
8400
|
+
"",
|
|
8401
|
+
"WORKDIR /workspace/frontend",
|
|
8402
|
+
"RUN --mount=type=cache,target=/root/.yarn/berry/cache \\",
|
|
8403
|
+
" yarn install --immutable"
|
|
8404
|
+
].join("\n")
|
|
8474
8405
|
);
|
|
8475
8406
|
writeText(dockerfilePath, content);
|
|
8476
|
-
logOk("Dockerfile \u2014 added
|
|
8407
|
+
logOk("Dockerfile \u2014 added packages/shared yarn install for Docker builds");
|
|
8408
|
+
return;
|
|
8409
|
+
}
|
|
8410
|
+
const builderCopy = [
|
|
8411
|
+
"WORKDIR /workspace",
|
|
8412
|
+
"",
|
|
8413
|
+
"RUN corepack enable",
|
|
8414
|
+
"",
|
|
8415
|
+
"COPY packages/shared/ packages/shared/",
|
|
8416
|
+
"COPY frontend/package.json frontend/yarn.lock frontend/.yarnrc.yml frontend/",
|
|
8417
|
+
"",
|
|
8418
|
+
"# Shared must have its own node_modules (zod, etc.) \u2014 tsc resolves from source.",
|
|
8419
|
+
"WORKDIR /workspace/packages/shared",
|
|
8420
|
+
"RUN --mount=type=cache,target=/root/.yarn/berry/cache \\",
|
|
8421
|
+
" yarn install --immutable",
|
|
8422
|
+
"",
|
|
8423
|
+
"WORKDIR /workspace/frontend",
|
|
8424
|
+
"RUN --mount=type=cache,target=/root/.yarn/berry/cache \\",
|
|
8425
|
+
" yarn install --immutable",
|
|
8426
|
+
"",
|
|
8427
|
+
"COPY frontend/ .",
|
|
8428
|
+
"RUN yarn build"
|
|
8429
|
+
].join("\n");
|
|
8430
|
+
const replaced = content.replace(
|
|
8431
|
+
/WORKDIR \/app[\s\S]*?RUN yarn build/,
|
|
8432
|
+
builderCopy
|
|
8433
|
+
);
|
|
8434
|
+
if (replaced === content) {
|
|
8435
|
+
const replaced2 = content.replace(
|
|
8436
|
+
/# Set working directory\nWORKDIR \/app[\s\S]*?RUN yarn build/,
|
|
8437
|
+
`# Monorepo root is the build context (see docker-compose app-prod).
|
|
8438
|
+
${builderCopy}`
|
|
8439
|
+
);
|
|
8440
|
+
if (replaced2 === content) {
|
|
8441
|
+
logWarn("Dockerfile \u2014 could not rewrite builder stage; patch skipped");
|
|
8442
|
+
return;
|
|
8443
|
+
}
|
|
8444
|
+
content = replaced2;
|
|
8477
8445
|
} else {
|
|
8478
|
-
|
|
8446
|
+
content = replaced;
|
|
8447
|
+
}
|
|
8448
|
+
content = content.replace(
|
|
8449
|
+
/^COPY nginx\.conf /m,
|
|
8450
|
+
"COPY frontend/nginx.conf "
|
|
8451
|
+
);
|
|
8452
|
+
content = content.replace(
|
|
8453
|
+
/^COPY nginx\//m,
|
|
8454
|
+
"COPY frontend/nginx/"
|
|
8455
|
+
);
|
|
8456
|
+
content = content.replace(
|
|
8457
|
+
/COPY --from=builder \/app\/dist /,
|
|
8458
|
+
"COPY --from=builder /workspace/frontend/dist "
|
|
8459
|
+
);
|
|
8460
|
+
writeText(dockerfilePath, content);
|
|
8461
|
+
logOk("Dockerfile \u2014 switched to monorepo root context with packages/shared");
|
|
8462
|
+
}
|
|
8463
|
+
function patchFrontendCompose(projectRoot) {
|
|
8464
|
+
const composePath = import_path15.default.join(projectRoot, "frontend", "docker-compose.yml");
|
|
8465
|
+
if (!exists(composePath)) {
|
|
8466
|
+
logWarn("Frontend docker-compose.yml not found \u2014 skipping compose patch");
|
|
8467
|
+
return;
|
|
8479
8468
|
}
|
|
8469
|
+
let content = readText(composePath);
|
|
8470
|
+
if (content.includes("context: ..") && content.includes("dockerfile: frontend/Dockerfile")) {
|
|
8471
|
+
logOk("docker-compose.yml \u2014 monorepo build context already set");
|
|
8472
|
+
return;
|
|
8473
|
+
}
|
|
8474
|
+
const next = content.replace(
|
|
8475
|
+
/app-prod:\n(\s+)build:\n\s+context: \.\n\s+dockerfile: Dockerfile/,
|
|
8476
|
+
"app-prod:\n$1build:\n$1 context: ..\n$1 dockerfile: frontend/Dockerfile"
|
|
8477
|
+
);
|
|
8478
|
+
if (next === content) {
|
|
8479
|
+
logWarn("docker-compose.yml \u2014 could not locate app-prod build block; patch skipped");
|
|
8480
|
+
return;
|
|
8481
|
+
}
|
|
8482
|
+
writeText(composePath, next);
|
|
8483
|
+
logOk("docker-compose.yml \u2014 app-prod build context set to repo root");
|
|
8480
8484
|
}
|
|
8481
8485
|
function verifyFrontendSharedAlias(projectRoot) {
|
|
8482
8486
|
const tsconfigPath = import_path15.default.join(projectRoot, "frontend", "tsconfig.json");
|
|
@@ -8530,7 +8534,7 @@ function verifyMobileSharedPaths(projectRoot) {
|
|
|
8530
8534
|
}
|
|
8531
8535
|
|
|
8532
8536
|
// src/commands/app/index.ts
|
|
8533
|
-
var
|
|
8537
|
+
var import_fs14 = __toESM(require("fs"), 1);
|
|
8534
8538
|
|
|
8535
8539
|
// src/commands/app/ai-helpers.ts
|
|
8536
8540
|
init_cjs_shims();
|
|
@@ -8552,7 +8556,7 @@ function getAiHelpersRetryHint(target) {
|
|
|
8552
8556
|
const packageJson = require2.resolve(AI_HELPERS_PACKAGE_JSON);
|
|
8553
8557
|
binPath = import_path16.default.join(import_path16.default.dirname(packageJson), "bin", "cli.mjs");
|
|
8554
8558
|
} catch {
|
|
8555
|
-
return
|
|
8559
|
+
return `Install with \`npm i -D ${AI_HELPERS_PKG}\` (or \`npx ${AI_HELPERS_PKG}\`), then re-run create-basekit app with --ai-helpers.`;
|
|
8556
8560
|
}
|
|
8557
8561
|
}
|
|
8558
8562
|
return `node ${JSON.stringify(binPath)} ${JSON.stringify(target)} --with-claude`;
|
|
@@ -8581,7 +8585,7 @@ async function runAppCommand(argv) {
|
|
|
8581
8585
|
return;
|
|
8582
8586
|
}
|
|
8583
8587
|
if (args.includes("--version") || args.includes("-V")) {
|
|
8584
|
-
console.log("1.0.
|
|
8588
|
+
console.log("1.0.5");
|
|
8585
8589
|
return;
|
|
8586
8590
|
}
|
|
8587
8591
|
printBanner3();
|
|
@@ -8688,7 +8692,7 @@ async function runAppCommand(argv) {
|
|
|
8688
8692
|
logError(err instanceof Error ? err.message : String(err));
|
|
8689
8693
|
if (exists(projectRoot)) {
|
|
8690
8694
|
try {
|
|
8691
|
-
|
|
8695
|
+
import_fs14.default.rmSync(projectRoot, { recursive: true, force: true });
|
|
8692
8696
|
logInfo(`Cleaned up ${projectName}/`);
|
|
8693
8697
|
} catch {
|
|
8694
8698
|
logError(`Could not clean up ${projectName}/ \u2014 remove it manually before retrying.`);
|
|
@@ -8715,12 +8719,12 @@ function initRootGit(projectRoot, includeMobile = false) {
|
|
|
8715
8719
|
logInfo("git not found \u2014 skipping repository initialisation");
|
|
8716
8720
|
return;
|
|
8717
8721
|
}
|
|
8718
|
-
const
|
|
8722
|
+
const fs15 = require("fs");
|
|
8719
8723
|
const subDirs = includeMobile ? ["backend", "frontend", "mobile"] : ["backend", "frontend"];
|
|
8720
8724
|
for (const sub of subDirs) {
|
|
8721
8725
|
const gitDir = import_path17.default.join(projectRoot, sub, ".git");
|
|
8722
8726
|
if (exists(gitDir)) {
|
|
8723
|
-
|
|
8727
|
+
fs15.rmSync(gitDir, { recursive: true, force: true });
|
|
8724
8728
|
}
|
|
8725
8729
|
}
|
|
8726
8730
|
const init = exec("git init", projectRoot);
|
|
@@ -8743,7 +8747,7 @@ function initRootGit(projectRoot, includeMobile = false) {
|
|
|
8743
8747
|
function printBanner3() {
|
|
8744
8748
|
console.log("");
|
|
8745
8749
|
console.log(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
|
|
8746
|
-
console.log(` \u2551 create-basekit app v${"1.0.
|
|
8750
|
+
console.log(` \u2551 create-basekit app v${"1.0.5"} \u2551`);
|
|
8747
8751
|
console.log(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D");
|
|
8748
8752
|
console.log("");
|
|
8749
8753
|
console.log(" Full-stack project scaffolder");
|
|
@@ -8751,7 +8755,7 @@ function printBanner3() {
|
|
|
8751
8755
|
}
|
|
8752
8756
|
function printHelp3() {
|
|
8753
8757
|
console.log(`
|
|
8754
|
-
create-basekit app v${"1.0.
|
|
8758
|
+
create-basekit app v${"1.0.5"}
|
|
8755
8759
|
|
|
8756
8760
|
Usage: npx @appsbyme/create-basekit app [project-name] [options]
|
|
8757
8761
|
|