spfn 0.2.0-beta.15 → 0.2.0-beta.17
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 +128 -93
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -755,7 +755,7 @@ var init_deployment_config = __esm({
|
|
|
755
755
|
|
|
756
756
|
// src/utils/version.ts
|
|
757
757
|
function getCliVersion() {
|
|
758
|
-
return "0.2.0-beta.
|
|
758
|
+
return "0.2.0-beta.17";
|
|
759
759
|
}
|
|
760
760
|
function getTagFromVersion(version) {
|
|
761
761
|
const match = version.match(/-([a-z]+)\./i);
|
|
@@ -2228,6 +2228,8 @@ async function dbPush() {
|
|
|
2228
2228
|
|
|
2229
2229
|
// src/commands/db/migrate.ts
|
|
2230
2230
|
import chalk16 from "chalk";
|
|
2231
|
+
import { join as join16 } from "path";
|
|
2232
|
+
import { existsSync as existsSync18 } from "fs";
|
|
2231
2233
|
|
|
2232
2234
|
// src/commands/db/backup.ts
|
|
2233
2235
|
import { promises as fs3 } from "fs";
|
|
@@ -2580,7 +2582,8 @@ async function dbBackup(options) {
|
|
|
2580
2582
|
}
|
|
2581
2583
|
|
|
2582
2584
|
// src/commands/db/migrate.ts
|
|
2583
|
-
import "@spfn/core/config";
|
|
2585
|
+
import { env as env4 } from "@spfn/core/config";
|
|
2586
|
+
import { loadEnv as loadEnv4 } from "@spfn/core/server";
|
|
2584
2587
|
async function dbMigrate(options = {}) {
|
|
2585
2588
|
try {
|
|
2586
2589
|
validateDatabasePrerequisites();
|
|
@@ -2596,35 +2599,67 @@ async function dbMigrate(options = {}) {
|
|
|
2596
2599
|
});
|
|
2597
2600
|
console.log("");
|
|
2598
2601
|
}
|
|
2599
|
-
const {
|
|
2602
|
+
const { drizzle } = await import("drizzle-orm/postgres-js");
|
|
2603
|
+
const { migrate } = await import("drizzle-orm/postgres-js/migrator");
|
|
2604
|
+
const postgres = await import("postgres");
|
|
2605
|
+
loadEnv4();
|
|
2606
|
+
if (!env4.DATABASE_URL) {
|
|
2607
|
+
console.error(chalk16.red("\u274C DATABASE_URL not found in environment"));
|
|
2608
|
+
process.exit(1);
|
|
2609
|
+
}
|
|
2610
|
+
const { discoverFunctionMigrations: discoverFunctionMigrations2 } = await Promise.resolve().then(() => (init_function_migrations(), function_migrations_exports));
|
|
2600
2611
|
const functions = discoverFunctionMigrations2(process.cwd());
|
|
2601
2612
|
if (functions.length > 0) {
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
console.log(chalk16.dim(` - ${func.packageName}`));
|
|
2605
|
-
});
|
|
2613
|
+
const fnConn = postgres.default(env4.DATABASE_URL, { max: 1 });
|
|
2614
|
+
const fnDb = drizzle(fnConn);
|
|
2606
2615
|
try {
|
|
2607
|
-
|
|
2616
|
+
console.log(chalk16.blue("\u{1F4E6} Applying function package migrations:"));
|
|
2617
|
+
functions.forEach((func) => {
|
|
2618
|
+
console.log(chalk16.dim(` - ${func.packageName}`));
|
|
2619
|
+
});
|
|
2620
|
+
for (const func of functions) {
|
|
2621
|
+
console.log(chalk16.blue(`
|
|
2622
|
+
\u{1F4E6} Running ${func.packageName} migrations...`));
|
|
2623
|
+
await migrate(fnDb, { migrationsFolder: func.migrationsDir });
|
|
2624
|
+
console.log(chalk16.green(` \u2713 ${func.packageName} migrations applied`));
|
|
2625
|
+
}
|
|
2608
2626
|
console.log(chalk16.green("\u2705 Function migrations applied\n"));
|
|
2609
|
-
}
|
|
2610
|
-
|
|
2611
|
-
console.error(chalk16.red(error instanceof Error ? error.message : "Unknown error"));
|
|
2612
|
-
process.exit(1);
|
|
2627
|
+
} finally {
|
|
2628
|
+
await fnConn.end();
|
|
2613
2629
|
}
|
|
2614
2630
|
}
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2631
|
+
const projectMigrationsDir = join16(process.cwd(), "src/server/drizzle");
|
|
2632
|
+
if (existsSync18(projectMigrationsDir)) {
|
|
2633
|
+
const projConn = postgres.default(env4.DATABASE_URL, { max: 1 });
|
|
2634
|
+
const projDb = drizzle(projConn);
|
|
2635
|
+
try {
|
|
2636
|
+
const beforeCount = await projConn`
|
|
2637
|
+
SELECT count(*)::int as count FROM drizzle.__drizzle_migrations
|
|
2638
|
+
`;
|
|
2639
|
+
console.log(chalk16.blue(`\u{1F4E6} Running project migrations... (${beforeCount[0].count} already recorded)`));
|
|
2640
|
+
await migrate(projDb, { migrationsFolder: projectMigrationsDir });
|
|
2641
|
+
const afterCount = await projConn`
|
|
2642
|
+
SELECT count(*)::int as count FROM drizzle.__drizzle_migrations
|
|
2643
|
+
`;
|
|
2644
|
+
const applied = afterCount[0].count - beforeCount[0].count;
|
|
2645
|
+
if (applied > 0) {
|
|
2646
|
+
console.log(chalk16.green(`\u2705 Project migrations applied successfully (${applied} new)`));
|
|
2647
|
+
} else {
|
|
2648
|
+
console.log(chalk16.yellow(`\u26A0\uFE0F No new project migrations to apply (${afterCount[0].count} already recorded)`));
|
|
2649
|
+
}
|
|
2650
|
+
} finally {
|
|
2651
|
+
await projConn.end();
|
|
2652
|
+
}
|
|
2653
|
+
} else {
|
|
2654
|
+
console.log(chalk16.dim("No project migrations found (src/server/drizzle)"));
|
|
2655
|
+
}
|
|
2621
2656
|
}
|
|
2622
2657
|
|
|
2623
2658
|
// src/commands/db/studio.ts
|
|
2624
2659
|
import chalk17 from "chalk";
|
|
2625
|
-
import { existsSync as
|
|
2660
|
+
import { existsSync as existsSync19, writeFileSync as writeFileSync10, unlinkSync as unlinkSync3 } from "fs";
|
|
2626
2661
|
import { spawn as spawn3 } from "child_process";
|
|
2627
|
-
import { env as
|
|
2662
|
+
import { env as env5 } from "@spfn/core/config";
|
|
2628
2663
|
import "@spfn/core/config";
|
|
2629
2664
|
async function dbStudio(requestedPort) {
|
|
2630
2665
|
console.log(chalk17.blue("\u{1F3A8} Opening Drizzle Studio...\n"));
|
|
@@ -2641,12 +2676,12 @@ async function dbStudio(requestedPort) {
|
|
|
2641
2676
|
console.error(chalk17.red(error instanceof Error ? error.message : "Failed to find available port"));
|
|
2642
2677
|
process.exit(1);
|
|
2643
2678
|
}
|
|
2644
|
-
const hasUserConfig =
|
|
2679
|
+
const hasUserConfig = existsSync19("./drizzle.config.ts");
|
|
2645
2680
|
const tempConfigPath = `./drizzle.config.${process.pid}.${Date.now()}.temp.ts`;
|
|
2646
2681
|
try {
|
|
2647
2682
|
const configPath = hasUserConfig ? "./drizzle.config.ts" : tempConfigPath;
|
|
2648
2683
|
if (!hasUserConfig) {
|
|
2649
|
-
if (!
|
|
2684
|
+
if (!env5.DATABASE_URL) {
|
|
2650
2685
|
console.error(chalk17.red("\u274C DATABASE_URL not found in environment"));
|
|
2651
2686
|
console.log(chalk17.yellow("\n\u{1F4A1} Tip: Add DATABASE_URL to your .env file"));
|
|
2652
2687
|
process.exit(1);
|
|
@@ -2667,7 +2702,7 @@ async function dbStudio(requestedPort) {
|
|
|
2667
2702
|
env: { ...process.env, NODE_TLS_REJECT_UNAUTHORIZED: "0" }
|
|
2668
2703
|
});
|
|
2669
2704
|
const cleanup = () => {
|
|
2670
|
-
if (!hasUserConfig &&
|
|
2705
|
+
if (!hasUserConfig && existsSync19(tempConfigPath)) {
|
|
2671
2706
|
unlinkSync3(tempConfigPath);
|
|
2672
2707
|
}
|
|
2673
2708
|
};
|
|
@@ -2697,7 +2732,7 @@ async function dbStudio(requestedPort) {
|
|
|
2697
2732
|
process.exit(0);
|
|
2698
2733
|
});
|
|
2699
2734
|
} catch (error) {
|
|
2700
|
-
if (!hasUserConfig &&
|
|
2735
|
+
if (!hasUserConfig && existsSync19(tempConfigPath)) {
|
|
2701
2736
|
unlinkSync3(tempConfigPath);
|
|
2702
2737
|
}
|
|
2703
2738
|
console.error(chalk17.red("\u274C Failed to start Drizzle Studio"));
|
|
@@ -2750,12 +2785,12 @@ import { spawn as spawn4 } from "child_process";
|
|
|
2750
2785
|
import chalk20 from "chalk";
|
|
2751
2786
|
import ora9 from "ora";
|
|
2752
2787
|
import prompts4 from "prompts";
|
|
2753
|
-
import { env as
|
|
2754
|
-
import { loadEnv as
|
|
2788
|
+
import { env as env6 } from "@spfn/core/config";
|
|
2789
|
+
import { loadEnv as loadEnv5 } from "@spfn/core/server";
|
|
2755
2790
|
async function dbRestore(backupFile, options = {}) {
|
|
2756
2791
|
console.log(chalk20.blue("\u267B\uFE0F Restoring database from backup...\n"));
|
|
2757
|
-
|
|
2758
|
-
const dbUrl =
|
|
2792
|
+
loadEnv5();
|
|
2793
|
+
const dbUrl = env6.DATABASE_URL;
|
|
2759
2794
|
if (!dbUrl) {
|
|
2760
2795
|
console.error(chalk20.red("\u274C DATABASE_URL not found in environment"));
|
|
2761
2796
|
console.log(chalk20.yellow("\n\u{1F4A1} Tip: Add DATABASE_URL to your .env file"));
|
|
@@ -3081,8 +3116,8 @@ dbCommand.command("backup:clean").description("Clean old database backups").opti
|
|
|
3081
3116
|
|
|
3082
3117
|
// src/commands/add.ts
|
|
3083
3118
|
import { Command as Command10 } from "commander";
|
|
3084
|
-
import { existsSync as
|
|
3085
|
-
import { join as
|
|
3119
|
+
import { existsSync as existsSync20, readFileSync as readFileSync6 } from "fs";
|
|
3120
|
+
import { join as join17 } from "path";
|
|
3086
3121
|
import { exec as exec2 } from "child_process";
|
|
3087
3122
|
import { promisify as promisify2 } from "util";
|
|
3088
3123
|
import chalk23 from "chalk";
|
|
@@ -3100,9 +3135,9 @@ async function addPackage(packageName) {
|
|
|
3100
3135
|
\u{1F4E6} Setting up ${packageName}...
|
|
3101
3136
|
`));
|
|
3102
3137
|
try {
|
|
3103
|
-
const pkgPath =
|
|
3104
|
-
const pkgJsonPath =
|
|
3105
|
-
if (!
|
|
3138
|
+
const pkgPath = join17(process.cwd(), "node_modules", ...packageName.split("/"));
|
|
3139
|
+
const pkgJsonPath = join17(pkgPath, "package.json");
|
|
3140
|
+
if (!existsSync20(pkgJsonPath)) {
|
|
3106
3141
|
const installSpinner = ora11("Installing package...").start();
|
|
3107
3142
|
try {
|
|
3108
3143
|
await execAsync2(`pnpm add ${packageName}`);
|
|
@@ -3114,7 +3149,7 @@ async function addPackage(packageName) {
|
|
|
3114
3149
|
} else {
|
|
3115
3150
|
console.log(chalk23.gray("\u2713 Package already installed (using local version)\n"));
|
|
3116
3151
|
}
|
|
3117
|
-
if (!
|
|
3152
|
+
if (!existsSync20(pkgJsonPath)) {
|
|
3118
3153
|
throw new Error(`Package ${packageName} not found after installation`);
|
|
3119
3154
|
}
|
|
3120
3155
|
const pkgJson = JSON.parse(readFileSync6(pkgJsonPath, "utf-8"));
|
|
@@ -3122,8 +3157,8 @@ async function addPackage(packageName) {
|
|
|
3122
3157
|
console.log(chalk23.blue(`
|
|
3123
3158
|
\u{1F5C4}\uFE0F Setting up database for ${packageName}...
|
|
3124
3159
|
`));
|
|
3125
|
-
const { env:
|
|
3126
|
-
if (!
|
|
3160
|
+
const { env: env7 } = await import("@spfn/core/config");
|
|
3161
|
+
if (!env7.DATABASE_URL) {
|
|
3127
3162
|
console.log(chalk23.yellow("\u26A0\uFE0F DATABASE_URL not found"));
|
|
3128
3163
|
console.log(chalk23.gray("Skipping database setup. Run migrations manually when ready:\n"));
|
|
3129
3164
|
console.log(chalk23.gray(` pnpm spfn db push
|
|
@@ -3170,8 +3205,8 @@ var addCommand = new Command10("add").description("Install and set up SPFN ecosy
|
|
|
3170
3205
|
init_logger();
|
|
3171
3206
|
import { Command as Command11 } from "commander";
|
|
3172
3207
|
import ora12 from "ora";
|
|
3173
|
-
import { join as
|
|
3174
|
-
import { existsSync as
|
|
3208
|
+
import { join as join26 } from "path";
|
|
3209
|
+
import { existsSync as existsSync23 } from "fs";
|
|
3175
3210
|
import chalk25 from "chalk";
|
|
3176
3211
|
|
|
3177
3212
|
// src/commands/generate/prompts.ts
|
|
@@ -3264,11 +3299,11 @@ async function confirmConfiguration(config) {
|
|
|
3264
3299
|
}
|
|
3265
3300
|
|
|
3266
3301
|
// src/commands/generate/generators/structure.ts
|
|
3267
|
-
import { join as
|
|
3302
|
+
import { join as join25 } from "path";
|
|
3268
3303
|
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync17 } from "fs";
|
|
3269
3304
|
|
|
3270
3305
|
// src/commands/generate/generators/config.ts
|
|
3271
|
-
import { join as
|
|
3306
|
+
import { join as join19 } from "path";
|
|
3272
3307
|
import { writeFileSync as writeFileSync11, mkdirSync as mkdirSync3 } from "fs";
|
|
3273
3308
|
|
|
3274
3309
|
// src/commands/generate/string-utils.ts
|
|
@@ -3298,29 +3333,29 @@ function toSafeSchemaName(str) {
|
|
|
3298
3333
|
}
|
|
3299
3334
|
|
|
3300
3335
|
// src/commands/generate/template-loader.ts
|
|
3301
|
-
import { readFileSync as readFileSync7, existsSync as
|
|
3302
|
-
import { join as
|
|
3336
|
+
import { readFileSync as readFileSync7, existsSync as existsSync21 } from "fs";
|
|
3337
|
+
import { join as join18, dirname as dirname2 } from "path";
|
|
3303
3338
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3304
3339
|
function findTemplatesPath2() {
|
|
3305
3340
|
const __filename = fileURLToPath2(import.meta.url);
|
|
3306
3341
|
const __dirname2 = dirname2(__filename);
|
|
3307
|
-
const distPath =
|
|
3308
|
-
if (
|
|
3342
|
+
const distPath = join18(__dirname2, "commands", "generate", "templates");
|
|
3343
|
+
if (existsSync21(distPath)) {
|
|
3309
3344
|
return distPath;
|
|
3310
3345
|
}
|
|
3311
|
-
const sameDirPath =
|
|
3312
|
-
if (
|
|
3346
|
+
const sameDirPath = join18(__dirname2, "templates");
|
|
3347
|
+
if (existsSync21(sameDirPath)) {
|
|
3313
3348
|
return sameDirPath;
|
|
3314
3349
|
}
|
|
3315
|
-
const srcPath =
|
|
3316
|
-
if (
|
|
3350
|
+
const srcPath = join18(__dirname2, "..", "..", "src", "commands", "generate", "templates");
|
|
3351
|
+
if (existsSync21(srcPath)) {
|
|
3317
3352
|
return srcPath;
|
|
3318
3353
|
}
|
|
3319
3354
|
throw new Error(`Templates directory not found. Tried: ${distPath}, ${sameDirPath}, ${srcPath}`);
|
|
3320
3355
|
}
|
|
3321
3356
|
function loadTemplate(templateName, variables) {
|
|
3322
3357
|
const templatesDir = findTemplatesPath2();
|
|
3323
|
-
const templatePath =
|
|
3358
|
+
const templatePath = join18(templatesDir, `${templateName}.template`);
|
|
3324
3359
|
let content = readFileSync7(templatePath, "utf-8");
|
|
3325
3360
|
for (const [key, value] of Object.entries(variables)) {
|
|
3326
3361
|
const regex = new RegExp(`\\{\\{${key}\\}\\}`, "g");
|
|
@@ -3424,7 +3459,7 @@ function generatePackageJson(fnDir, scope, fnName, description) {
|
|
|
3424
3459
|
}
|
|
3425
3460
|
};
|
|
3426
3461
|
writeFileSync11(
|
|
3427
|
-
|
|
3462
|
+
join19(fnDir, "package.json"),
|
|
3428
3463
|
JSON.stringify(content, null, 4) + "\n"
|
|
3429
3464
|
);
|
|
3430
3465
|
}
|
|
@@ -3458,7 +3493,7 @@ function generateTsConfig(fnDir) {
|
|
|
3458
3493
|
exclude: ["node_modules", "dist", "**/*.test.ts", "**/__tests__/**"]
|
|
3459
3494
|
};
|
|
3460
3495
|
writeFileSync11(
|
|
3461
|
-
|
|
3496
|
+
join19(fnDir, "tsconfig.json"),
|
|
3462
3497
|
JSON.stringify(content, null, 4) + "\n"
|
|
3463
3498
|
);
|
|
3464
3499
|
}
|
|
@@ -3534,7 +3569,7 @@ export default defineConfig({
|
|
|
3534
3569
|
],
|
|
3535
3570
|
});
|
|
3536
3571
|
`;
|
|
3537
|
-
writeFileSync11(
|
|
3572
|
+
writeFileSync11(join19(fnDir, "tsup.config.ts"), content);
|
|
3538
3573
|
}
|
|
3539
3574
|
function generateDrizzleConfig(fnDir, scope, fnName) {
|
|
3540
3575
|
const schemaName = `spfn_${toSnakeCase(fnName)}`;
|
|
@@ -3554,7 +3589,7 @@ export default defineConfig({
|
|
|
3554
3589
|
schemaFilter: ['${schemaName}'], // Only generate for ${fnName} schema
|
|
3555
3590
|
});
|
|
3556
3591
|
`;
|
|
3557
|
-
writeFileSync11(
|
|
3592
|
+
writeFileSync11(join19(fnDir, "drizzle.config.ts"), content);
|
|
3558
3593
|
}
|
|
3559
3594
|
function generateExampleGenerator(fnDir, scope, fnName) {
|
|
3560
3595
|
const pascalName = toPascalCase(fnName);
|
|
@@ -3623,10 +3658,10 @@ export const moduleName = '${fnName}';
|
|
|
3623
3658
|
};
|
|
3624
3659
|
}
|
|
3625
3660
|
`;
|
|
3626
|
-
const generatorsDir =
|
|
3661
|
+
const generatorsDir = join19(fnDir, "src/server/generators");
|
|
3627
3662
|
mkdirSync3(generatorsDir, { recursive: true });
|
|
3628
3663
|
writeFileSync11(
|
|
3629
|
-
|
|
3664
|
+
join19(generatorsDir, "example-generator.ts"),
|
|
3630
3665
|
content
|
|
3631
3666
|
);
|
|
3632
3667
|
const indexContent = `/**
|
|
@@ -3641,7 +3676,7 @@ export const moduleName = '${fnName}';
|
|
|
3641
3676
|
export { create${pascalName}ExampleGenerator } from './example-generator.js';
|
|
3642
3677
|
`;
|
|
3643
3678
|
writeFileSync11(
|
|
3644
|
-
|
|
3679
|
+
join19(generatorsDir, "index.ts"),
|
|
3645
3680
|
indexContent
|
|
3646
3681
|
);
|
|
3647
3682
|
}
|
|
@@ -4130,15 +4165,15 @@ Contributions are welcome! Please follow the development workflow above.
|
|
|
4130
4165
|
|
|
4131
4166
|
MIT
|
|
4132
4167
|
`;
|
|
4133
|
-
writeFileSync11(
|
|
4168
|
+
writeFileSync11(join19(fnDir, "README.md"), content);
|
|
4134
4169
|
}
|
|
4135
4170
|
|
|
4136
4171
|
// src/commands/generate/generators/entity.ts
|
|
4137
|
-
import { join as
|
|
4138
|
-
import { writeFileSync as writeFileSync12, existsSync as
|
|
4172
|
+
import { join as join20 } from "path";
|
|
4173
|
+
import { writeFileSync as writeFileSync12, existsSync as existsSync22 } from "fs";
|
|
4139
4174
|
function generateSchema(fnDir, scope, fnName) {
|
|
4140
|
-
const schemaFilePath =
|
|
4141
|
-
if (
|
|
4175
|
+
const schemaFilePath = join20(fnDir, "src/server/entities/schema.ts");
|
|
4176
|
+
if (existsSync22(schemaFilePath)) {
|
|
4142
4177
|
return;
|
|
4143
4178
|
}
|
|
4144
4179
|
const packageName = `${scope}/${fnName}`;
|
|
@@ -4169,7 +4204,7 @@ function generateEntity(fnDir, scope, fnName, entityName) {
|
|
|
4169
4204
|
SCHEMA_FILE_NAME: schemaFileName
|
|
4170
4205
|
});
|
|
4171
4206
|
writeFileSync12(
|
|
4172
|
-
|
|
4207
|
+
join20(fnDir, `src/server/entities/${toKebabCase(entityName)}.ts`),
|
|
4173
4208
|
content
|
|
4174
4209
|
);
|
|
4175
4210
|
}
|
|
@@ -4177,11 +4212,11 @@ function generateEntitiesIndex(fnDir, entities) {
|
|
|
4177
4212
|
const schemaExport = `export * from './schema';`;
|
|
4178
4213
|
const entityExports = entities.map((entity) => `export * from './${toKebabCase(entity)}';`).join("\n");
|
|
4179
4214
|
const content = [schemaExport, entityExports].filter(Boolean).join("\n");
|
|
4180
|
-
writeFileSync12(
|
|
4215
|
+
writeFileSync12(join20(fnDir, "src/server/entities/index.ts"), content + "\n");
|
|
4181
4216
|
}
|
|
4182
4217
|
|
|
4183
4218
|
// src/commands/generate/generators/repository.ts
|
|
4184
|
-
import { join as
|
|
4219
|
+
import { join as join21 } from "path";
|
|
4185
4220
|
import { writeFileSync as writeFileSync13 } from "fs";
|
|
4186
4221
|
function generateRepository(fnDir, entityName) {
|
|
4187
4222
|
const pascalName = toPascalCase(entityName);
|
|
@@ -4192,17 +4227,17 @@ function generateRepository(fnDir, entityName) {
|
|
|
4192
4227
|
REPO_NAME: repoName
|
|
4193
4228
|
});
|
|
4194
4229
|
writeFileSync13(
|
|
4195
|
-
|
|
4230
|
+
join21(fnDir, `src/server/repositories/${toKebabCase(entityName)}.repository.ts`),
|
|
4196
4231
|
content
|
|
4197
4232
|
);
|
|
4198
4233
|
}
|
|
4199
4234
|
function generateRepositoriesIndex(fnDir, entities) {
|
|
4200
4235
|
const exports = entities.map((entity) => `export * from './${toKebabCase(entity)}.repository';`).join("\n");
|
|
4201
|
-
writeFileSync13(
|
|
4236
|
+
writeFileSync13(join21(fnDir, "src/server/repositories/index.ts"), exports + "\n");
|
|
4202
4237
|
}
|
|
4203
4238
|
|
|
4204
4239
|
// src/commands/generate/generators/route.ts
|
|
4205
|
-
import { join as
|
|
4240
|
+
import { join as join22 } from "path";
|
|
4206
4241
|
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync14 } from "fs";
|
|
4207
4242
|
function generateRoute(fnDir, entityName) {
|
|
4208
4243
|
const pascalName = toPascalCase(entityName);
|
|
@@ -4214,13 +4249,13 @@ function generateRoute(fnDir, entityName) {
|
|
|
4214
4249
|
REPO_NAME: repoName,
|
|
4215
4250
|
KEBAB_NAME: kebabName
|
|
4216
4251
|
});
|
|
4217
|
-
const routeDir =
|
|
4252
|
+
const routeDir = join22(fnDir, `src/server/routes/${kebabName}`);
|
|
4218
4253
|
mkdirSync4(routeDir, { recursive: true });
|
|
4219
|
-
writeFileSync14(
|
|
4254
|
+
writeFileSync14(join22(routeDir, "index.ts"), content);
|
|
4220
4255
|
}
|
|
4221
4256
|
|
|
4222
4257
|
// src/commands/generate/generators/contract.ts
|
|
4223
|
-
import { join as
|
|
4258
|
+
import { join as join23 } from "path";
|
|
4224
4259
|
import { writeFileSync as writeFileSync15 } from "fs";
|
|
4225
4260
|
function generateContract(fnDir, entityName) {
|
|
4226
4261
|
const pascalName = toPascalCase(entityName);
|
|
@@ -4229,13 +4264,13 @@ function generateContract(fnDir, entityName) {
|
|
|
4229
4264
|
ENTITY_NAME: entityName
|
|
4230
4265
|
});
|
|
4231
4266
|
writeFileSync15(
|
|
4232
|
-
|
|
4267
|
+
join23(fnDir, `src/lib/contracts/${toKebabCase(entityName)}.ts`),
|
|
4233
4268
|
content
|
|
4234
4269
|
);
|
|
4235
4270
|
}
|
|
4236
4271
|
|
|
4237
4272
|
// src/commands/generate/generators/index-files.ts
|
|
4238
|
-
import { join as
|
|
4273
|
+
import { join as join24 } from "path";
|
|
4239
4274
|
import { writeFileSync as writeFileSync16 } from "fs";
|
|
4240
4275
|
function generateMainIndex(fnDir, fnName) {
|
|
4241
4276
|
const content = `/**
|
|
@@ -4262,7 +4297,7 @@ export * from '@/lib/types/index';
|
|
|
4262
4297
|
|
|
4263
4298
|
export * from '@/server/entities/index';
|
|
4264
4299
|
`;
|
|
4265
|
-
writeFileSync16(
|
|
4300
|
+
writeFileSync16(join24(fnDir, "src/index.ts"), content);
|
|
4266
4301
|
}
|
|
4267
4302
|
function generateServerIndex(fnDir) {
|
|
4268
4303
|
const content = `/**
|
|
@@ -4297,7 +4332,7 @@ export * from '@/server/repositories/index';
|
|
|
4297
4332
|
|
|
4298
4333
|
// TODO: Export helpers here
|
|
4299
4334
|
`;
|
|
4300
|
-
writeFileSync16(
|
|
4335
|
+
writeFileSync16(join24(fnDir, "src/server.ts"), content);
|
|
4301
4336
|
}
|
|
4302
4337
|
function generateClientIndex(fnDir) {
|
|
4303
4338
|
const content = `/**
|
|
@@ -4330,7 +4365,7 @@ export * from './client/store';
|
|
|
4330
4365
|
|
|
4331
4366
|
export * from './client/components';
|
|
4332
4367
|
`;
|
|
4333
|
-
writeFileSync16(
|
|
4368
|
+
writeFileSync16(join24(fnDir, "src/client.ts"), content);
|
|
4334
4369
|
}
|
|
4335
4370
|
function generateTypesFile(fnDir, fnName) {
|
|
4336
4371
|
const content = `/**
|
|
@@ -4342,7 +4377,7 @@ function generateTypesFile(fnDir, fnName) {
|
|
|
4342
4377
|
|
|
4343
4378
|
export * from '@/lib/types/index';
|
|
4344
4379
|
`;
|
|
4345
|
-
writeFileSync16(
|
|
4380
|
+
writeFileSync16(join24(fnDir, "src/types.ts"), content);
|
|
4346
4381
|
}
|
|
4347
4382
|
|
|
4348
4383
|
// src/commands/generate/generators/structure.ts
|
|
@@ -4364,7 +4399,7 @@ async function generateFunctionStructure(options) {
|
|
|
4364
4399
|
"src/client/store",
|
|
4365
4400
|
"src/client/components"
|
|
4366
4401
|
];
|
|
4367
|
-
dirs.forEach((dir) => mkdirSync5(
|
|
4402
|
+
dirs.forEach((dir) => mkdirSync5(join25(fnDir, dir), { recursive: true }));
|
|
4368
4403
|
generatePackageJson(fnDir, scope, fnName, description);
|
|
4369
4404
|
generateTsConfig(fnDir);
|
|
4370
4405
|
generateTsupConfig(fnDir);
|
|
@@ -4384,15 +4419,15 @@ async function generateFunctionStructure(options) {
|
|
|
4384
4419
|
generateEntitiesIndex(fnDir, entities);
|
|
4385
4420
|
generateRepositoriesIndex(fnDir, entities);
|
|
4386
4421
|
} else {
|
|
4387
|
-
writeFileSync17(
|
|
4388
|
-
writeFileSync17(
|
|
4389
|
-
}
|
|
4390
|
-
writeFileSync17(
|
|
4391
|
-
writeFileSync17(
|
|
4392
|
-
writeFileSync17(
|
|
4393
|
-
writeFileSync17(
|
|
4394
|
-
writeFileSync17(
|
|
4395
|
-
writeFileSync17(
|
|
4422
|
+
writeFileSync17(join25(fnDir, "src/server/entities/index.ts"), "// Export your entities here\nexport {}\n");
|
|
4423
|
+
writeFileSync17(join25(fnDir, "src/server/repositories/index.ts"), "// Export your repositories here\nexport {}\n");
|
|
4424
|
+
}
|
|
4425
|
+
writeFileSync17(join25(fnDir, "src/client/hooks/index.ts"), "/**\n * Client Hooks\n */\n\n// TODO: Add hooks (e.g., useAuth, useData, etc.)\nexport {}\n");
|
|
4426
|
+
writeFileSync17(join25(fnDir, "src/client/store/index.ts"), "/**\n * Client Store\n */\n\n// TODO: Add Zustand store if needed\nexport {}\n");
|
|
4427
|
+
writeFileSync17(join25(fnDir, "src/client/components/index.ts"), "/**\n * Client Components\n */\n\n// TODO: Add React components\nexport {}\n");
|
|
4428
|
+
writeFileSync17(join25(fnDir, "src/client/index.ts"), "/**\n * Client Module Entry\n */\n\nexport * from './hooks';\nexport * from './store';\nexport * from './components';\n");
|
|
4429
|
+
writeFileSync17(join25(fnDir, "src/lib/types/index.ts"), "/**\n * Shared Type Definitions\n */\n\n// Add your shared types here\nexport {}\n");
|
|
4430
|
+
writeFileSync17(join25(fnDir, "src/lib/contracts/index.ts"), "/**\n * API Contracts\n */\n\n// Export your contracts here\nexport {}\n");
|
|
4396
4431
|
generateMainIndex(fnDir, fnName);
|
|
4397
4432
|
generateServerIndex(fnDir);
|
|
4398
4433
|
generateClientIndex(fnDir);
|
|
@@ -4416,8 +4451,8 @@ async function generateFunction(name, options) {
|
|
|
4416
4451
|
logger.error("Function name is required");
|
|
4417
4452
|
process.exit(1);
|
|
4418
4453
|
}
|
|
4419
|
-
const fnDir =
|
|
4420
|
-
if (
|
|
4454
|
+
const fnDir = join26(cwd, fnName);
|
|
4455
|
+
if (existsSync23(fnDir)) {
|
|
4421
4456
|
logger.error(`Directory ${fnName} already exists at ${fnDir}`);
|
|
4422
4457
|
process.exit(1);
|
|
4423
4458
|
}
|
|
@@ -4482,7 +4517,7 @@ generateCommand.command("fn").description("Generate a new SPFN function module")
|
|
|
4482
4517
|
// src/commands/env.ts
|
|
4483
4518
|
import { Command as Command12 } from "commander";
|
|
4484
4519
|
import chalk26 from "chalk";
|
|
4485
|
-
import { existsSync as
|
|
4520
|
+
import { existsSync as existsSync24, readFileSync as readFileSync8, writeFileSync as writeFileSync18 } from "fs";
|
|
4486
4521
|
import { resolve } from "path";
|
|
4487
4522
|
import { parse } from "dotenv";
|
|
4488
4523
|
var VALID_ENVS = ["local", "development", "staging", "production", "test"];
|
|
@@ -4766,7 +4801,7 @@ async function initEnvFiles(options) {
|
|
|
4766
4801
|
}
|
|
4767
4802
|
function writeEnvTemplate(cwd, file, vars, force) {
|
|
4768
4803
|
const filePath = resolve(cwd, file);
|
|
4769
|
-
if (
|
|
4804
|
+
if (existsSync24(filePath) && !force) {
|
|
4770
4805
|
console.log(chalk26.yellow(` \u23ED\uFE0F ${file} already exists (use --force to overwrite)`));
|
|
4771
4806
|
return;
|
|
4772
4807
|
}
|
|
@@ -4815,7 +4850,7 @@ async function checkEnvFiles(options) {
|
|
|
4815
4850
|
const warnings = [];
|
|
4816
4851
|
for (const file of filesToCheck) {
|
|
4817
4852
|
const filePath = resolve(cwd, file);
|
|
4818
|
-
if (!
|
|
4853
|
+
if (!existsSync24(filePath)) {
|
|
4819
4854
|
continue;
|
|
4820
4855
|
}
|
|
4821
4856
|
const content = readFileSync8(filePath, "utf-8");
|
|
@@ -4892,8 +4927,8 @@ async function validateEnvVars(options) {
|
|
|
4892
4927
|
const packages = options.packages || ["@spfn/core"];
|
|
4893
4928
|
const targetEnv = options.env ? validateEnvOption(options.env) : void 0;
|
|
4894
4929
|
if (targetEnv) {
|
|
4895
|
-
const { loadEnv:
|
|
4896
|
-
const result =
|
|
4930
|
+
const { loadEnv: loadEnv6 } = await import("@spfn/core/env/loader");
|
|
4931
|
+
const result = loadEnv6({ nodeEnv: targetEnv });
|
|
4897
4932
|
console.log(chalk26.blue.bold(`
|
|
4898
4933
|
\u{1F50D} Validating environment variables for ${chalk26.cyan(targetEnv)}
|
|
4899
4934
|
`));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spfn",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.17",
|
|
4
4
|
"description": "Superfunction CLI - Add SPFN to your Next.js project",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"postgres": "^3.4.0",
|
|
68
68
|
"prompts": "^2.4.2",
|
|
69
69
|
"tsup": "^8.5.0",
|
|
70
|
-
"@spfn/core": "0.2.0-beta.
|
|
70
|
+
"@spfn/core": "0.2.0-beta.19"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@types/fs-extra": "^11.0.4",
|