@ghentcdh/create-crouton 0.0.1-alpha.26 → 0.0.1-alpha.28
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/dist/index.js +120 -35
- package/dist/index.js.map +1 -1
- package/dist/lib/index.js +20 -2
- package/dist/lib/index.js.map +1 -1
- package/dist/templates/nx/root/eslint.config.mjs.tmpl +45 -0
- package/dist/templates/nx/root/nx.json.tmpl +2 -1
- package/dist/templates/nx/root/package.json.tmpl +15 -2
- package/dist/templates/nx/root/pnpm-workspace.yaml.tmpl +18 -2
- package/dist/templates/nx/root/tsconfig.base.json.tmpl +4 -1
- package/dist/templates/nx/workspace/apps/backend/eslint.config.mjs.tmpl +3 -0
- package/dist/templates/nx/workspace/apps/backend/nodemon.json.tmpl +6 -0
- package/dist/templates/nx/workspace/apps/backend/package.json.tmpl +5 -5
- package/dist/templates/nx/workspace/apps/backend/project.json.tmpl +20 -2
- package/dist/templates/nx/workspace/apps/backend/src/app/app.module.ts.tmpl +1 -0
- package/dist/templates/nx/workspace/apps/backend/tsconfig.json.tmpl +2 -2
- package/dist/templates/nx/workspace/apps/backend/tsup.config.ts.tmpl +31 -0
- package/dist/templates/nx/workspace/apps/frontend/eslint.config.mjs.tmpl +3 -0
- package/dist/templates/nx/workspace/apps/frontend/package.json.tmpl +3 -0
- package/dist/templates/nx/workspace/apps/frontend/project.json.tmpl +1 -1
- package/dist/templates/nx/workspace/apps/frontend/src/App.vue.tmpl +1 -4
- package/dist/templates/nx/workspace/apps/frontend/src/main.ts.tmpl +22 -1
- package/dist/templates/nx/workspace/apps/frontend/src/style.css.tmpl +38 -0
- package/dist/templates/nx/workspace/apps/frontend/tsconfig.json.tmpl +1 -1
- package/dist/templates/nx/workspace/apps/frontend/vite.config.ts.tmpl +3 -1
- package/dist/templates/nx/workspace/generated/default/client/package.json.tmpl +10 -0
- package/dist/templates/nx/workspace/generated/default/types/package.json.tmpl +14 -0
- package/dist/templates/regular/.npmrc.tmpl +5 -0
- package/dist/templates/regular/package.json.tmpl +1 -0
- package/dist/templates/regular/src/app.module.ts.tmpl +1 -0
- package/dist/templates/regular/tsconfig.json.tmpl +2 -1
- package/package.json +6 -3
- package/dist/templates/nx/workspace/apps/backend/nest-cli.json.tmpl +0 -8
- package/dist/templates/nx/workspace/generated/types/package.json.tmpl +0 -6
package/dist/index.js
CHANGED
|
@@ -19069,7 +19069,7 @@ var SidebarGroupSchema = zod_default.object({
|
|
|
19069
19069
|
/** Human-readable heading shown in the sidebar. Defaults to a title-cased version of the slug. */
|
|
19070
19070
|
label: zod_default.string().optional(),
|
|
19071
19071
|
/** Controls the order of this group among top-level sidebar items. */
|
|
19072
|
-
position: zod_default.
|
|
19072
|
+
position: zod_default.number().optional()
|
|
19073
19073
|
});
|
|
19074
19074
|
var SidebarSchema = zod_default.object({
|
|
19075
19075
|
hide: zod_default.boolean().default(false),
|
|
@@ -19243,7 +19243,9 @@ var RulesetSchema = external_exports.object({
|
|
|
19243
19243
|
showRelationsInForm: external_exports.boolean().default(true),
|
|
19244
19244
|
enumValueLabel: external_exports.boolean().default(true),
|
|
19245
19245
|
sharedEnums: external_exports.boolean().default(true),
|
|
19246
|
-
defaultOperations: JsonOperationsSchema.default(
|
|
19246
|
+
defaultOperations: JsonOperationsSchema.default(
|
|
19247
|
+
JsonOperationsSchema.parse({})
|
|
19248
|
+
)
|
|
19247
19249
|
});
|
|
19248
19250
|
var CroutonConfigSchema = external_exports.object({
|
|
19249
19251
|
/**
|
|
@@ -19262,7 +19264,7 @@ var CroutonConfigSchema = external_exports.object({
|
|
|
19262
19264
|
*/
|
|
19263
19265
|
schemaExportName: external_exports.string().default("{Model}WithRelationsSchema"),
|
|
19264
19266
|
/** Path to the shared enum registry, relative to project root. Default `crouton.enums.json`. */
|
|
19265
|
-
enumsFile: external_exports.string().default("
|
|
19267
|
+
enumsFile: external_exports.string().default("crouton.enums.json"),
|
|
19266
19268
|
/** Optional overrides of the default visibility ruleset. */
|
|
19267
19269
|
rules: RulesetSchema.default(RulesetSchema.parse({})),
|
|
19268
19270
|
/**
|
|
@@ -19334,9 +19336,10 @@ var buildDatasourceFiles = (opts) => {
|
|
|
19334
19336
|
urlEnv: opts.urlEnv,
|
|
19335
19337
|
generatedTypesImport: opts.generatedTypesImport,
|
|
19336
19338
|
zodOutput,
|
|
19339
|
+
clientOutput,
|
|
19337
19340
|
prismaConfig
|
|
19338
19341
|
};
|
|
19339
|
-
const clientImport = relImport(dsDir, clientOutput);
|
|
19342
|
+
const clientImport = opts.generatedClientImport ?? relImport(dsDir, clientOutput);
|
|
19340
19343
|
const indexTs = `import { PrismaClient } from '${clientImport}';
|
|
19341
19344
|
import { PrismaPg } from '@prisma/adapter-pg';
|
|
19342
19345
|
|
|
@@ -19372,14 +19375,17 @@ datasource db {
|
|
|
19372
19375
|
// url is provided by ${prismaConfig} (Prisma 7 forbids \`url\` here)
|
|
19373
19376
|
}
|
|
19374
19377
|
`;
|
|
19378
|
+
const configDir = dirname4(prismaConfig);
|
|
19379
|
+
const relSchema = relImport(configDir, prismaSchema);
|
|
19380
|
+
const relMigrations = relImport(configDir, migrationsDir);
|
|
19375
19381
|
const prismaConfigTs = `// Generated by \`crouton create-datasource\`.
|
|
19376
19382
|
import 'dotenv/config';
|
|
19377
19383
|
import { defineConfig, env } from 'prisma/config';
|
|
19378
19384
|
|
|
19379
19385
|
export default defineConfig({
|
|
19380
|
-
schema: '${
|
|
19386
|
+
schema: '${relSchema}',
|
|
19381
19387
|
migrations: {
|
|
19382
|
-
path: '${
|
|
19388
|
+
path: '${relMigrations}',
|
|
19383
19389
|
},
|
|
19384
19390
|
datasource: {
|
|
19385
19391
|
url: env('${opts.urlEnv}'),
|
|
@@ -19433,7 +19439,24 @@ var writeFiles = async (files, opts = {}) => {
|
|
|
19433
19439
|
var loadTemplate = async (templateDir, relativePath) => readFile4(`${templateDir}/${relativePath}`, "utf-8");
|
|
19434
19440
|
|
|
19435
19441
|
// src/lib/pm.ts
|
|
19436
|
-
import { spawn } from "child_process";
|
|
19442
|
+
import { execSync, spawn } from "child_process";
|
|
19443
|
+
var MIN_PNPM_MAJOR = 11;
|
|
19444
|
+
var checkPnpmVersion = () => {
|
|
19445
|
+
let raw;
|
|
19446
|
+
try {
|
|
19447
|
+
raw = execSync("pnpm --version", { stdio: "pipe" }).toString().trim();
|
|
19448
|
+
} catch {
|
|
19449
|
+
throw new Error("pnpm is not installed. Install it with: npm i -g pnpm@latest");
|
|
19450
|
+
}
|
|
19451
|
+
const major = parseInt(raw.split(".")[0], 10);
|
|
19452
|
+
if (isNaN(major) || major < MIN_PNPM_MAJOR) {
|
|
19453
|
+
throw new Error(
|
|
19454
|
+
`pnpm ${raw} detected, but version ${MIN_PNPM_MAJOR}+ is required.
|
|
19455
|
+
Upgrade with: npm i -g pnpm@latest`
|
|
19456
|
+
);
|
|
19457
|
+
}
|
|
19458
|
+
return raw;
|
|
19459
|
+
};
|
|
19437
19460
|
var installDeps = (pm, cwd) => new Promise((resolve3, reject) => {
|
|
19438
19461
|
const child = spawn(pm, ["install"], { cwd, stdio: "inherit" });
|
|
19439
19462
|
child.on(
|
|
@@ -19469,7 +19492,7 @@ var render = (template, tokens) => {
|
|
|
19469
19492
|
};
|
|
19470
19493
|
|
|
19471
19494
|
// src/runner.ts
|
|
19472
|
-
import { execSync } from "child_process";
|
|
19495
|
+
import { execSync as execSync2 } from "child_process";
|
|
19473
19496
|
import { existsSync } from "fs";
|
|
19474
19497
|
import { readdir as readdir4 } from "fs/promises";
|
|
19475
19498
|
import { resolve as resolve2 } from "path";
|
|
@@ -19489,7 +19512,9 @@ var runCreate = async (name, opts) => {
|
|
|
19489
19512
|
if (existsSync(targetDir) && !opts.force) {
|
|
19490
19513
|
const entries = await readdir4(targetDir);
|
|
19491
19514
|
if (entries.length > 0) {
|
|
19492
|
-
M2.error(
|
|
19515
|
+
M2.error(
|
|
19516
|
+
`Directory "${name}" already exists and is not empty. Use --force to overwrite.`
|
|
19517
|
+
);
|
|
19493
19518
|
throw new CancelledError();
|
|
19494
19519
|
}
|
|
19495
19520
|
}
|
|
@@ -19497,6 +19522,10 @@ var runCreate = async (name, opts) => {
|
|
|
19497
19522
|
const frontend = await resolveFrontend(opts, layout);
|
|
19498
19523
|
const prefix = layout === "nx" ? await resolvePrefix(opts) : void 0;
|
|
19499
19524
|
const pm = await resolvePm(opts);
|
|
19525
|
+
if (pm === "pnpm") {
|
|
19526
|
+
const pnpmVersion = checkPnpmVersion();
|
|
19527
|
+
M2.info(`Using pnpm ${pnpmVersion}`);
|
|
19528
|
+
}
|
|
19500
19529
|
const dbUrl = await resolveDbUrl(opts);
|
|
19501
19530
|
const dbName = name.replace(/[^a-zA-Z0-9]/g, "_");
|
|
19502
19531
|
const tokens = {
|
|
@@ -19516,12 +19545,16 @@ var runCreate = async (name, opts) => {
|
|
|
19516
19545
|
tokens["prefix"] = prefix;
|
|
19517
19546
|
tokens["appsRoot"] = `${prefix}/apps`;
|
|
19518
19547
|
tokens["schemaPath"] = "../../../node_modules/nx/schemas/project-schema.json";
|
|
19519
|
-
tokens["
|
|
19548
|
+
tokens["tsconfigBase"] = "../../../tsconfig.base.json";
|
|
19549
|
+
tokens["generatedTypesPath"] = `${prefix}/generated/default/types/src`;
|
|
19550
|
+
tokens["generatedClientPath"] = `${prefix}/generated/default/client`;
|
|
19520
19551
|
} else {
|
|
19521
19552
|
tokens["noPrefix"] = "true";
|
|
19522
19553
|
tokens["appsRoot"] = "apps";
|
|
19523
19554
|
tokens["schemaPath"] = "../../node_modules/nx/schemas/project-schema.json";
|
|
19524
|
-
tokens["
|
|
19555
|
+
tokens["tsconfigBase"] = "../../tsconfig.base.json";
|
|
19556
|
+
tokens["generatedTypesPath"] = "generated/default/types/src";
|
|
19557
|
+
tokens["generatedClientPath"] = "generated/default/client";
|
|
19525
19558
|
}
|
|
19526
19559
|
}
|
|
19527
19560
|
if (frontend) {
|
|
@@ -19531,51 +19564,89 @@ var runCreate = async (name, opts) => {
|
|
|
19531
19564
|
const skipPaths = !frontend ? ["apps/frontend"] : [];
|
|
19532
19565
|
if (layout === "nx") {
|
|
19533
19566
|
const rootTemplateDir = resolve2(templateRoot, "nx", "root");
|
|
19534
|
-
const rootFiles = await loadAndRenderTemplates(
|
|
19567
|
+
const rootFiles = await loadAndRenderTemplates(
|
|
19568
|
+
rootTemplateDir,
|
|
19569
|
+
"",
|
|
19570
|
+
tokens,
|
|
19571
|
+
targetDir
|
|
19572
|
+
);
|
|
19535
19573
|
const files = [...rootFiles];
|
|
19536
19574
|
const workspaceTemplateDir = resolve2(templateRoot, "nx", "workspace");
|
|
19537
19575
|
const workspaceTarget = prefix ? resolve2(targetDir, prefix) : targetDir;
|
|
19538
|
-
const workspaceFiles = await loadAndRenderTemplates(
|
|
19576
|
+
const workspaceFiles = await loadAndRenderTemplates(
|
|
19577
|
+
workspaceTemplateDir,
|
|
19578
|
+
"",
|
|
19579
|
+
tokens,
|
|
19580
|
+
workspaceTarget,
|
|
19581
|
+
skipPaths
|
|
19582
|
+
);
|
|
19539
19583
|
files.push(...workspaceFiles);
|
|
19540
19584
|
if (opts.docker !== false) {
|
|
19541
19585
|
const dockerDir = resolve2(templateRoot, "docker");
|
|
19542
|
-
const dockerFiles = await loadAndRenderTemplates(
|
|
19586
|
+
const dockerFiles = await loadAndRenderTemplates(
|
|
19587
|
+
dockerDir,
|
|
19588
|
+
"",
|
|
19589
|
+
tokens,
|
|
19590
|
+
targetDir
|
|
19591
|
+
);
|
|
19543
19592
|
files.push(...dockerFiles);
|
|
19544
19593
|
}
|
|
19545
19594
|
const dataSourcesDir = "apps/backend/src/app/data-sources";
|
|
19546
|
-
const generatedImport = `@${name}/generated
|
|
19595
|
+
const generatedImport = `@${name}/generated-default-types`;
|
|
19596
|
+
const generatedClientImport = `@${name}/generated-default-client`;
|
|
19547
19597
|
const { files: dsFiles } = buildDatasourceFiles({
|
|
19548
19598
|
name: "default",
|
|
19549
19599
|
dataSourcesDir,
|
|
19550
19600
|
urlEnv: "DATABASE_URL",
|
|
19551
19601
|
generatedTypesImport: generatedImport,
|
|
19602
|
+
generatedClientImport,
|
|
19552
19603
|
type: "postgres",
|
|
19553
|
-
default: true
|
|
19604
|
+
default: true,
|
|
19605
|
+
zodOutput: "generated/default/types/src",
|
|
19606
|
+
clientOutput: "generated/default/client"
|
|
19554
19607
|
});
|
|
19555
19608
|
for (const f of dsFiles) {
|
|
19556
|
-
files.push({
|
|
19609
|
+
files.push({
|
|
19610
|
+
path: resolve2(workspaceTarget, f.path),
|
|
19611
|
+
contents: f.contents
|
|
19612
|
+
});
|
|
19557
19613
|
}
|
|
19558
19614
|
const written = await writeFiles(files, { force: opts.force });
|
|
19559
19615
|
M2.success(`Wrote ${written} file(s) to ${import_picocolors3.default.cyan(name)}/`);
|
|
19560
19616
|
await postScaffold(opts, targetDir, pm, dbUrl, prefix);
|
|
19561
19617
|
} else {
|
|
19562
19618
|
const templateDir = resolve2(templateRoot, "regular");
|
|
19563
|
-
const files = await loadAndRenderTemplates(
|
|
19619
|
+
const files = await loadAndRenderTemplates(
|
|
19620
|
+
templateDir,
|
|
19621
|
+
"",
|
|
19622
|
+
tokens,
|
|
19623
|
+
targetDir,
|
|
19624
|
+
skipPaths
|
|
19625
|
+
);
|
|
19564
19626
|
if (opts.docker !== false) {
|
|
19565
19627
|
const dockerTokens = { ...tokens, regular: "true" };
|
|
19566
19628
|
const dockerDir = resolve2(templateRoot, "docker");
|
|
19567
|
-
const dockerFiles = await loadAndRenderTemplates(
|
|
19629
|
+
const dockerFiles = await loadAndRenderTemplates(
|
|
19630
|
+
dockerDir,
|
|
19631
|
+
"",
|
|
19632
|
+
dockerTokens,
|
|
19633
|
+
targetDir
|
|
19634
|
+
);
|
|
19568
19635
|
files.push(...dockerFiles);
|
|
19569
19636
|
}
|
|
19570
19637
|
const dataSourcesDir = "src/data-sources";
|
|
19571
|
-
const generatedImport = "@app/generated/default";
|
|
19638
|
+
const generatedImport = "@app/generated/default/types";
|
|
19639
|
+
const generatedClientImport = "@app/generated/default/client";
|
|
19572
19640
|
const { files: dsFiles } = buildDatasourceFiles({
|
|
19573
19641
|
name: "default",
|
|
19574
19642
|
dataSourcesDir,
|
|
19575
19643
|
urlEnv: "DATABASE_URL",
|
|
19576
19644
|
generatedTypesImport: generatedImport,
|
|
19645
|
+
generatedClientImport,
|
|
19577
19646
|
type: "postgres",
|
|
19578
|
-
default: true
|
|
19647
|
+
default: true,
|
|
19648
|
+
zodOutput: "generated/default/types/src",
|
|
19649
|
+
clientOutput: "generated/default/client"
|
|
19579
19650
|
});
|
|
19580
19651
|
for (const f of dsFiles) {
|
|
19581
19652
|
files.push({ path: resolve2(targetDir, f.path), contents: f.contents });
|
|
@@ -19585,11 +19656,12 @@ var runCreate = async (name, opts) => {
|
|
|
19585
19656
|
await postScaffold(opts, targetDir, pm, dbUrl);
|
|
19586
19657
|
}
|
|
19587
19658
|
const pmRun = pm === "npm" ? "npm run" : pm;
|
|
19659
|
+
const prefixFlag = prefix ? ` --prefix ${prefix}` : "";
|
|
19588
19660
|
Me(
|
|
19589
19661
|
[
|
|
19590
19662
|
opts.docker !== false ? "docker compose up -d # start postgres" : null,
|
|
19591
19663
|
`${pmRun} prisma:migrate # create initial migration`,
|
|
19592
|
-
|
|
19664
|
+
`crouton update resources${prefixFlag} # generate resource CRUD`,
|
|
19593
19665
|
`${pmRun} dev # start dev server`
|
|
19594
19666
|
].filter(Boolean).join("\n"),
|
|
19595
19667
|
"Next steps"
|
|
@@ -19608,7 +19680,7 @@ var postScaffold = async (opts, targetDir, pm, dbUrl, prefix) => {
|
|
|
19608
19680
|
const s = Y2();
|
|
19609
19681
|
s.start("Initializing git repository");
|
|
19610
19682
|
try {
|
|
19611
|
-
|
|
19683
|
+
execSync2('git init && git add -A && git commit -m "Initial commit"', {
|
|
19612
19684
|
cwd: targetDir,
|
|
19613
19685
|
stdio: "pipe"
|
|
19614
19686
|
});
|
|
@@ -19629,22 +19701,26 @@ var postScaffold = async (opts, targetDir, pm, dbUrl, prefix) => {
|
|
|
19629
19701
|
if (dbUrl) {
|
|
19630
19702
|
try {
|
|
19631
19703
|
const s2 = Y2();
|
|
19632
|
-
s2.start("Running
|
|
19633
|
-
const
|
|
19634
|
-
|
|
19635
|
-
cwd:
|
|
19636
|
-
stdio: "pipe"
|
|
19704
|
+
s2.start("Running crouton update resources");
|
|
19705
|
+
const croutonCwd = prefix ? resolve2(targetDir, prefix) : targetDir;
|
|
19706
|
+
execSync2("npx crouton update resources --yes", {
|
|
19707
|
+
cwd: croutonCwd,
|
|
19708
|
+
stdio: "pipe",
|
|
19709
|
+
env: { ...process.env, DATABASE_URL: dbUrl }
|
|
19637
19710
|
});
|
|
19638
|
-
s2.stop("
|
|
19639
|
-
} catch {
|
|
19640
|
-
|
|
19711
|
+
s2.stop("Resources updated");
|
|
19712
|
+
} catch (err) {
|
|
19713
|
+
const stderr = err instanceof Error && "stderr" in err ? String(err.stderr).trim() : "";
|
|
19714
|
+
M2.warn(
|
|
19715
|
+
"crouton update resources failed \u2014 run it manually after setting up your database." + (stderr ? `
|
|
19716
|
+
${import_picocolors3.default.dim(stderr)}` : "")
|
|
19717
|
+
);
|
|
19641
19718
|
}
|
|
19642
|
-
} else {
|
|
19643
|
-
M2.info("Skipping prisma generate \u2014 no database URL provided.");
|
|
19644
19719
|
}
|
|
19645
19720
|
}
|
|
19646
19721
|
};
|
|
19647
19722
|
var resolveLayout = async (opts) => {
|
|
19723
|
+
if (opts.prefix) return "nx";
|
|
19648
19724
|
if (opts.yes) return opts.nx ? "nx" : "regular";
|
|
19649
19725
|
if (opts.nx) return "nx";
|
|
19650
19726
|
const layout = assertNotCancel(
|
|
@@ -19652,7 +19728,10 @@ var resolveLayout = async (opts) => {
|
|
|
19652
19728
|
message: "Project layout",
|
|
19653
19729
|
options: [
|
|
19654
19730
|
{ value: "regular", label: "Regular (single NestJS app)" },
|
|
19655
|
-
{
|
|
19731
|
+
{
|
|
19732
|
+
value: "nx",
|
|
19733
|
+
label: "Nx monorepo (backend + frontend + shared libs)"
|
|
19734
|
+
}
|
|
19656
19735
|
]
|
|
19657
19736
|
})
|
|
19658
19737
|
);
|
|
@@ -19717,7 +19796,13 @@ var loadAndRenderTemplates = async (templateDir, subPath, tokens, targetDir, ski
|
|
|
19717
19796
|
const relPath = subPath ? `${subPath}/${entry.name}` : entry.name;
|
|
19718
19797
|
if (skipPaths.some((sp) => relPath.startsWith(sp))) continue;
|
|
19719
19798
|
if (entry.isDirectory()) {
|
|
19720
|
-
const nested = await loadAndRenderTemplates(
|
|
19799
|
+
const nested = await loadAndRenderTemplates(
|
|
19800
|
+
templateDir,
|
|
19801
|
+
relPath,
|
|
19802
|
+
tokens,
|
|
19803
|
+
targetDir,
|
|
19804
|
+
skipPaths
|
|
19805
|
+
);
|
|
19721
19806
|
files.push(...nested);
|
|
19722
19807
|
} else if (entry.name.endsWith(".tmpl")) {
|
|
19723
19808
|
const raw = await loadTemplate(templateDir, relPath);
|