create-taserjs 0.0.2 → 0.0.3
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 -0
- package/dist/cjs/addons/arktype/index.cjs.map +1 -1
- package/dist/cjs/addons/drizzle/index.cjs.map +1 -1
- package/dist/cjs/addons/kysely/index.cjs.map +1 -1
- package/dist/cjs/addons/pino/index.cjs.map +1 -1
- package/dist/cjs/addons/prisma/index.cjs +84 -24
- package/dist/cjs/addons/prisma/index.cjs.map +1 -1
- package/dist/cjs/addons/registry.cjs +1 -1
- package/dist/cjs/addons/registry.cjs.map +1 -1
- package/dist/cjs/addons/types.d.cts +1 -1
- package/dist/cjs/addons/valibot/index.cjs.map +1 -1
- package/dist/cjs/addons/validators.cjs.map +1 -1
- package/dist/cjs/addons/winston/index.cjs.map +1 -1
- package/dist/cjs/addons/zod/index.cjs.map +1 -1
- package/dist/cjs/cli.cjs +5 -0
- package/dist/cjs/cli.cjs.map +1 -1
- package/dist/cjs/commands/create.cjs +44 -11
- package/dist/cjs/commands/create.cjs.map +1 -1
- package/dist/cjs/commands/create.d.cts +1 -0
- package/dist/cjs/core/json-output.cjs.map +1 -1
- package/dist/cjs/core/package-manager.cjs.map +1 -1
- package/dist/cjs/core/package-manager.d.cts +1 -1
- package/dist/cjs/core/parse-options.cjs +7 -7
- package/dist/cjs/core/parse-options.cjs.map +1 -1
- package/dist/cjs/core/parse-options.d.cts +3 -3
- package/dist/cjs/core/project-config.cjs +1 -1
- package/dist/cjs/core/project-config.cjs.map +1 -1
- package/dist/cjs/core/resolve-packages.cjs +41 -7
- package/dist/cjs/core/resolve-packages.cjs.map +1 -1
- package/dist/cjs/core/resolve-packages.d.cts +2 -2
- package/dist/cjs/core/scaffold-engine.cjs +33 -6
- package/dist/cjs/core/scaffold-engine.cjs.map +1 -1
- package/dist/cjs/core/types.cjs +11 -3
- package/dist/cjs/core/types.cjs.map +1 -1
- package/dist/cjs/core/types.d.cts +8 -8
- package/dist/cjs/core/validate-project-name.cjs.map +1 -1
- package/dist/cjs/frameworks/index.cjs +138 -17
- package/dist/cjs/frameworks/index.cjs.map +1 -1
- package/dist/cjs/frameworks/index.d.cts +3 -3
- package/dist/cjs/scaffold.d.cts +1 -1
- package/dist/cjs/templates/base.cjs +6 -6
- package/dist/cjs/templates/base.cjs.map +1 -1
- package/dist/cjs/types.d.cts +1 -1
- package/dist/esm/addons/arktype/index.js.map +1 -1
- package/dist/esm/addons/drizzle/index.js.map +1 -1
- package/dist/esm/addons/kysely/index.js.map +1 -1
- package/dist/esm/addons/pino/index.js.map +1 -1
- package/dist/esm/addons/prisma/index.js +84 -24
- package/dist/esm/addons/prisma/index.js.map +1 -1
- package/dist/esm/addons/registry.js +2 -2
- package/dist/esm/addons/registry.js.map +1 -1
- package/dist/esm/addons/types.d.ts +1 -1
- package/dist/esm/addons/valibot/index.js.map +1 -1
- package/dist/esm/addons/validators.js.map +1 -1
- package/dist/esm/addons/winston/index.js.map +1 -1
- package/dist/esm/addons/zod/index.js.map +1 -1
- package/dist/esm/cli.js +5 -0
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/commands/create.d.ts +1 -0
- package/dist/esm/commands/create.js +46 -13
- package/dist/esm/commands/create.js.map +1 -1
- package/dist/esm/core/json-output.js.map +1 -1
- package/dist/esm/core/package-manager.d.ts +1 -1
- package/dist/esm/core/package-manager.js.map +1 -1
- package/dist/esm/core/parse-options.d.ts +3 -3
- package/dist/esm/core/parse-options.js +8 -8
- package/dist/esm/core/parse-options.js.map +1 -1
- package/dist/esm/core/project-config.js +1 -1
- package/dist/esm/core/project-config.js.map +1 -1
- package/dist/esm/core/resolve-packages.d.ts +2 -2
- package/dist/esm/core/resolve-packages.js +41 -7
- package/dist/esm/core/resolve-packages.js.map +1 -1
- package/dist/esm/core/scaffold-engine.js +34 -7
- package/dist/esm/core/scaffold-engine.js.map +1 -1
- package/dist/esm/core/types.d.ts +8 -8
- package/dist/esm/core/types.js +11 -3
- package/dist/esm/core/types.js.map +1 -1
- package/dist/esm/core/validate-project-name.js.map +1 -1
- package/dist/esm/frameworks/index.d.ts +3 -3
- package/dist/esm/frameworks/index.js +138 -17
- package/dist/esm/frameworks/index.js.map +1 -1
- package/dist/esm/scaffold.d.ts +1 -1
- package/dist/esm/templates/base.js +6 -6
- package/dist/esm/templates/base.js.map +1 -1
- package/dist/esm/types.d.ts +1 -1
- package/package.json +13 -13
- package/src/addons/arktype/index.ts +2 -2
- package/src/addons/drizzle/index.ts +53 -53
- package/src/addons/kysely/index.ts +42 -42
- package/src/addons/pino/index.ts +12 -12
- package/src/addons/prisma/index.ts +128 -55
- package/src/addons/registry.ts +37 -37
- package/src/addons/types.ts +14 -14
- package/src/addons/valibot/index.ts +2 -2
- package/src/addons/validators.ts +9 -9
- package/src/addons/winston/index.ts +12 -12
- package/src/addons/zod/index.ts +2 -2
- package/src/cli.ts +27 -26
- package/src/commands/create.ts +181 -152
- package/src/core/json-output.ts +4 -4
- package/src/core/package-manager.ts +38 -31
- package/src/core/parse-options.ts +50 -48
- package/src/core/project-config.ts +10 -14
- package/src/core/resolve-packages.ts +79 -41
- package/src/core/scaffold-engine.ts +106 -36
- package/src/core/types.ts +61 -36
- package/src/core/validate-project-name.ts +40 -40
- package/src/frameworks/index.ts +164 -29
- package/src/scaffold.ts +3 -3
- package/src/templates/base.ts +57 -51
- package/src/types.ts +5 -4
|
@@ -2,115 +2,117 @@ import {
|
|
|
2
2
|
DB_DRIVERS,
|
|
3
3
|
DB_ODMS,
|
|
4
4
|
DEFAULT_DB_DRIVER,
|
|
5
|
-
FRAMEWORKS,
|
|
6
5
|
LOGGERS,
|
|
6
|
+
PROJECT_TYPES,
|
|
7
7
|
VALIDATORS,
|
|
8
8
|
type DbDriver,
|
|
9
9
|
type DbOdm,
|
|
10
|
-
type Framework,
|
|
11
10
|
type LoggerId,
|
|
11
|
+
type ProjectType,
|
|
12
12
|
type ScaffoldContext,
|
|
13
13
|
type ValidatorId,
|
|
14
|
-
} from
|
|
14
|
+
} from "./types.js";
|
|
15
15
|
|
|
16
16
|
export type ParsedCreateArgs = {
|
|
17
|
-
projectName?: string
|
|
18
|
-
|
|
19
|
-
db?: DbOdm
|
|
20
|
-
driver?: DbDriver
|
|
21
|
-
logger?: LoggerId
|
|
22
|
-
validator?: ValidatorId
|
|
23
|
-
yes: boolean
|
|
24
|
-
noInstall: boolean
|
|
25
|
-
json: boolean
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function
|
|
29
|
-
return (
|
|
17
|
+
projectName?: string;
|
|
18
|
+
type?: ProjectType;
|
|
19
|
+
db?: DbOdm;
|
|
20
|
+
driver?: DbDriver;
|
|
21
|
+
logger?: LoggerId;
|
|
22
|
+
validator?: ValidatorId;
|
|
23
|
+
yes: boolean;
|
|
24
|
+
noInstall: boolean;
|
|
25
|
+
json: boolean;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
function isProjectType(value: string): value is ProjectType {
|
|
29
|
+
return (PROJECT_TYPES as readonly string[]).includes(value);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
function isDbOdm(value: string): value is DbOdm {
|
|
33
|
-
return (DB_ODMS as readonly string[]).includes(value)
|
|
33
|
+
return (DB_ODMS as readonly string[]).includes(value);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
function isDbDriver(value: string): value is DbDriver {
|
|
37
|
-
return (DB_DRIVERS as readonly string[]).includes(value)
|
|
37
|
+
return (DB_DRIVERS as readonly string[]).includes(value);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
function isLoggerId(value: string): value is LoggerId {
|
|
41
|
-
return (LOGGERS as readonly string[]).includes(value)
|
|
41
|
+
return (LOGGERS as readonly string[]).includes(value);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
function isValidatorId(value: string): value is ValidatorId {
|
|
45
|
-
return (VALIDATORS as readonly string[]).includes(value)
|
|
45
|
+
return (VALIDATORS as readonly string[]).includes(value);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
export function parseDbFlag(value: string): { db: DbOdm
|
|
49
|
-
const [odm, driver] = value.split(
|
|
48
|
+
export function parseDbFlag(value: string): { db: DbOdm; driver: DbDriver } {
|
|
49
|
+
const [odm, driver] = value.split(":");
|
|
50
50
|
if (!odm || !isDbOdm(odm)) {
|
|
51
|
-
throw new Error(
|
|
51
|
+
throw new Error(
|
|
52
|
+
`Invalid --db value "${value}". Use drizzle, prisma, or kysely (optionally with :postgres, :sqlite, or :mysql).`,
|
|
53
|
+
);
|
|
52
54
|
}
|
|
53
55
|
|
|
54
|
-
if (driver === undefined || driver ===
|
|
55
|
-
return { db: odm, driver: DEFAULT_DB_DRIVER }
|
|
56
|
+
if (driver === undefined || driver === "") {
|
|
57
|
+
return { db: odm, driver: DEFAULT_DB_DRIVER };
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
if (!isDbDriver(driver)) {
|
|
59
|
-
throw new Error(`Invalid database driver "${driver}". Use postgres, sqlite, or mysql.`)
|
|
61
|
+
throw new Error(`Invalid database driver "${driver}". Use postgres, sqlite, or mysql.`);
|
|
60
62
|
}
|
|
61
63
|
|
|
62
|
-
return { db: odm, driver }
|
|
64
|
+
return { db: odm, driver };
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
export function resolveScaffoldDefaults(args: ParsedCreateArgs): ScaffoldContext {
|
|
66
|
-
const
|
|
67
|
-
const db = args.db
|
|
68
|
-
const logger = args.logger
|
|
69
|
-
const validator = args.validator
|
|
68
|
+
const type = args.type ?? "node";
|
|
69
|
+
const db = args.db;
|
|
70
|
+
const logger = args.logger;
|
|
71
|
+
const validator = args.validator;
|
|
70
72
|
|
|
71
73
|
if (!args.projectName) {
|
|
72
|
-
throw new Error(
|
|
74
|
+
throw new Error("Project name is required");
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
const result: ScaffoldContext = {
|
|
76
78
|
projectName: args.projectName.trim(),
|
|
77
|
-
targetDir:
|
|
78
|
-
|
|
79
|
-
}
|
|
79
|
+
targetDir: "",
|
|
80
|
+
type,
|
|
81
|
+
};
|
|
80
82
|
|
|
81
83
|
if (db) {
|
|
82
|
-
result.db = db
|
|
83
|
-
result.driver = args.driver ?? DEFAULT_DB_DRIVER
|
|
84
|
+
result.db = db;
|
|
85
|
+
result.driver = args.driver ?? DEFAULT_DB_DRIVER;
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
if (logger) {
|
|
87
|
-
result.logger = logger
|
|
89
|
+
result.logger = logger;
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
if (validator) {
|
|
91
|
-
result.validator = validator
|
|
93
|
+
result.validator = validator;
|
|
92
94
|
}
|
|
93
95
|
|
|
94
|
-
return result
|
|
96
|
+
return result;
|
|
95
97
|
}
|
|
96
98
|
|
|
97
|
-
export function
|
|
98
|
-
if (!
|
|
99
|
-
throw new Error(`Invalid --
|
|
99
|
+
export function parseTypeFlag(value: string): ProjectType {
|
|
100
|
+
if (!isProjectType(value)) {
|
|
101
|
+
throw new Error(`Invalid --type "${value}". Use ${PROJECT_TYPES.join(", ")}.`);
|
|
100
102
|
}
|
|
101
|
-
return value
|
|
103
|
+
return value;
|
|
102
104
|
}
|
|
103
105
|
|
|
104
106
|
export function parseLoggerFlag(value: string): LoggerId {
|
|
105
107
|
if (!isLoggerId(value)) {
|
|
106
|
-
throw new Error(`Invalid --logger "${value}". Use pino or winston.`)
|
|
108
|
+
throw new Error(`Invalid --logger "${value}". Use pino or winston.`);
|
|
107
109
|
}
|
|
108
|
-
return value
|
|
110
|
+
return value;
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
export function parseValidatorFlag(value: string): ValidatorId {
|
|
112
114
|
if (!isValidatorId(value)) {
|
|
113
|
-
throw new Error(`Invalid --validator "${value}". Use zod, arktype, or valibot.`)
|
|
115
|
+
throw new Error(`Invalid --validator "${value}". Use zod, arktype, or valibot.`);
|
|
114
116
|
}
|
|
115
|
-
return value
|
|
117
|
+
return value;
|
|
116
118
|
}
|
|
@@ -1,31 +1,27 @@
|
|
|
1
|
-
import { writeFile } from
|
|
2
|
-
import path from
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
3
|
|
|
4
|
-
import type { ScaffoldContext } from
|
|
4
|
+
import type { ScaffoldContext } from "./types.js";
|
|
5
5
|
|
|
6
6
|
export async function writeProjectConfig(root: string, ctx: ScaffoldContext): Promise<void> {
|
|
7
7
|
const config: Record<string, string> = {
|
|
8
|
-
|
|
9
|
-
}
|
|
8
|
+
type: ctx.type,
|
|
9
|
+
};
|
|
10
10
|
|
|
11
11
|
if (ctx.db) {
|
|
12
|
-
config.db = ctx.db
|
|
12
|
+
config.db = ctx.db;
|
|
13
13
|
if (ctx.driver) {
|
|
14
|
-
config.driver = ctx.driver
|
|
14
|
+
config.driver = ctx.driver;
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
if (ctx.logger) {
|
|
19
|
-
config.logger = ctx.logger
|
|
19
|
+
config.logger = ctx.logger;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
if (ctx.validator) {
|
|
23
|
-
config.validator = ctx.validator
|
|
23
|
+
config.validator = ctx.validator;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
await writeFile(
|
|
27
|
-
path.join(root, '.taser.json'),
|
|
28
|
-
`${JSON.stringify(config, null, 2)}\n`,
|
|
29
|
-
'utf8',
|
|
30
|
-
)
|
|
26
|
+
await writeFile(path.join(root, ".taser.json"), `${JSON.stringify(config, null, 2)}\n`, "utf8");
|
|
31
27
|
}
|
|
@@ -1,51 +1,88 @@
|
|
|
1
|
-
import { resolveAddons } from
|
|
2
|
-
import type { PackageGroups,
|
|
1
|
+
import { resolveAddons } from "../addons/registry.js";
|
|
2
|
+
import type { PackageGroups, ProjectType, ScaffoldContext } from "../core/types.js";
|
|
3
3
|
|
|
4
|
-
function
|
|
5
|
-
const dependencies = [
|
|
4
|
+
function typePackages(type: ProjectType): PackageGroups {
|
|
5
|
+
const dependencies = ["@taserjs/router", "dotenv"];
|
|
6
6
|
const devDependencies = [
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
]
|
|
14
|
-
const scripts: Record<string, string> = {}
|
|
15
|
-
|
|
16
|
-
switch (
|
|
17
|
-
case
|
|
18
|
-
dependencies.push(
|
|
19
|
-
devDependencies.push(
|
|
20
|
-
break
|
|
21
|
-
case
|
|
22
|
-
dependencies.push(
|
|
23
|
-
break
|
|
24
|
-
case
|
|
25
|
-
dependencies.push(
|
|
26
|
-
break
|
|
27
|
-
case
|
|
7
|
+
"@taserjs/router-cli",
|
|
8
|
+
"npm-run-all2",
|
|
9
|
+
"tsdown",
|
|
10
|
+
"tsx",
|
|
11
|
+
"typescript",
|
|
12
|
+
"@types/node",
|
|
13
|
+
];
|
|
14
|
+
const scripts: Record<string, string> = {};
|
|
15
|
+
|
|
16
|
+
switch (type) {
|
|
17
|
+
case "express":
|
|
18
|
+
dependencies.push("@taserjs/adapter-express", "express");
|
|
19
|
+
devDependencies.push("@types/express");
|
|
20
|
+
break;
|
|
21
|
+
case "fastify":
|
|
22
|
+
dependencies.push("@taserjs/adapter-fastify", "fastify");
|
|
23
|
+
break;
|
|
24
|
+
case "hono":
|
|
25
|
+
dependencies.push("@hono/node-server", "hono");
|
|
26
|
+
break;
|
|
27
|
+
case "bun":
|
|
28
|
+
// Bun has native TypeScript and runtime execution
|
|
29
|
+
devDependencies.push("@types/bun");
|
|
30
|
+
scripts["dev:server"] = "bun --watch src/index.ts";
|
|
31
|
+
scripts.start = "bun src/index.ts";
|
|
32
|
+
scripts.serve = "bun dist/index.mjs";
|
|
33
|
+
break;
|
|
34
|
+
case "deno":
|
|
35
|
+
scripts["dev:server"] = "deno run --watch --allow-net --allow-env --allow-read src/index.ts";
|
|
36
|
+
scripts.start = "deno run --allow-net --allow-env --allow-read src/index.ts";
|
|
37
|
+
scripts.serve = "deno run --allow-net --allow-env --allow-read dist/index.mjs";
|
|
38
|
+
break;
|
|
39
|
+
case "aws-lambda":
|
|
40
|
+
dependencies.push("hono");
|
|
41
|
+
devDependencies.push("@types/aws-lambda");
|
|
42
|
+
break;
|
|
43
|
+
case "cloudflare-workers": {
|
|
44
|
+
// Cloudflare workers uses wrangler
|
|
45
|
+
const cfDevDeps = devDependencies.filter((d) => d !== "tsx");
|
|
46
|
+
cfDevDeps.push("wrangler", "@cloudflare/workers-types");
|
|
47
|
+
devDependencies.length = 0;
|
|
48
|
+
devDependencies.push(...cfDevDeps);
|
|
49
|
+
scripts["dev:server"] = "wrangler dev";
|
|
50
|
+
scripts.deploy = "wrangler deploy";
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
case "netlify":
|
|
54
|
+
dependencies.push("hono", "@netlify/functions");
|
|
55
|
+
break;
|
|
56
|
+
case "vercel":
|
|
57
|
+
dependencies.push("hono");
|
|
58
|
+
devDependencies.push("@vercel/node");
|
|
59
|
+
break;
|
|
60
|
+
case "azure-functions":
|
|
61
|
+
dependencies.push("hono", "@azure/functions", "@marplex/hono-azurefunc-adapter");
|
|
62
|
+
break;
|
|
63
|
+
case "google-cloud-run":
|
|
64
|
+
case "node":
|
|
28
65
|
default:
|
|
29
|
-
dependencies.push(
|
|
30
|
-
break
|
|
66
|
+
dependencies.push("@hono/node-server");
|
|
67
|
+
break;
|
|
31
68
|
}
|
|
32
69
|
|
|
33
|
-
return { dependencies, devDependencies, scripts }
|
|
70
|
+
return { dependencies, devDependencies, scripts };
|
|
34
71
|
}
|
|
35
72
|
|
|
36
73
|
export function resolvePackages(ctx: ScaffoldContext): PackageGroups {
|
|
37
|
-
const base =
|
|
38
|
-
const addons = resolveAddons(ctx)
|
|
74
|
+
const base = typePackages(ctx.type);
|
|
75
|
+
const addons = resolveAddons(ctx);
|
|
39
76
|
|
|
40
|
-
const dependencies = [...base.dependencies]
|
|
41
|
-
const devDependencies = [...base.devDependencies]
|
|
42
|
-
const scripts = { ...base.scripts }
|
|
77
|
+
const dependencies = [...base.dependencies];
|
|
78
|
+
const devDependencies = [...base.devDependencies];
|
|
79
|
+
const scripts = { ...base.scripts };
|
|
43
80
|
|
|
44
81
|
for (const addon of addons) {
|
|
45
|
-
dependencies.push(...addon.dependencies(ctx))
|
|
46
|
-
devDependencies.push(...addon.devDependencies(ctx))
|
|
82
|
+
dependencies.push(...addon.dependencies(ctx));
|
|
83
|
+
devDependencies.push(...addon.devDependencies(ctx));
|
|
47
84
|
if (addon.scripts) {
|
|
48
|
-
Object.assign(scripts, addon.scripts(ctx))
|
|
85
|
+
Object.assign(scripts, addon.scripts(ctx));
|
|
49
86
|
}
|
|
50
87
|
}
|
|
51
88
|
|
|
@@ -53,11 +90,12 @@ export function resolvePackages(ctx: ScaffoldContext): PackageGroups {
|
|
|
53
90
|
dependencies: [...new Set(dependencies)],
|
|
54
91
|
devDependencies: [...new Set(devDependencies)],
|
|
55
92
|
scripts,
|
|
56
|
-
}
|
|
93
|
+
};
|
|
57
94
|
}
|
|
58
95
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
96
|
+
export function getPackageGroups(
|
|
97
|
+
type: ProjectType,
|
|
98
|
+
): Omit<PackageGroups, "scripts"> & { scripts?: Record<string, string> } {
|
|
99
|
+
const groups = typePackages(type);
|
|
100
|
+
return groups;
|
|
63
101
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { mkdir, writeFile } from
|
|
2
|
-
import path from
|
|
1
|
+
import { copyFile, mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
3
|
|
|
4
|
-
import { collectBootBindings, resolveAddons } from
|
|
5
|
-
import { indexTemplate, taserTsTemplate } from
|
|
6
|
-
import { installPackages, resolveUserAgent } from
|
|
7
|
-
import { writeProjectConfig } from
|
|
8
|
-
import { resolvePackages } from
|
|
9
|
-
import type { ScaffoldOptions, ScaffoldResult } from
|
|
4
|
+
import { collectBootBindings, resolveAddons } from "../addons/registry.js";
|
|
5
|
+
import { indexTemplate, taserTsTemplate } from "../frameworks/index.js";
|
|
6
|
+
import { installPackages, resolveUserAgent } from "./package-manager.js";
|
|
7
|
+
import { writeProjectConfig } from "./project-config.js";
|
|
8
|
+
import { resolvePackages } from "./resolve-packages.js";
|
|
9
|
+
import type { ScaffoldOptions, ScaffoldResult } from "./types.js";
|
|
10
10
|
import {
|
|
11
11
|
contextTemplate,
|
|
12
12
|
gitignoreTemplate,
|
|
@@ -17,69 +17,139 @@ import {
|
|
|
17
17
|
starterManifestTemplate,
|
|
18
18
|
tsconfigTemplate,
|
|
19
19
|
tsdownConfigTemplate,
|
|
20
|
-
} from
|
|
20
|
+
} from "../templates/base.js";
|
|
21
21
|
|
|
22
22
|
async function write(filePath: string, contents: string): Promise<void> {
|
|
23
|
-
await mkdir(path.dirname(filePath), { recursive: true })
|
|
24
|
-
await writeFile(filePath, contents,
|
|
23
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
24
|
+
await writeFile(filePath, contents, "utf8");
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export async function scaffoldProject(options: ScaffoldOptions): Promise<ScaffoldResult> {
|
|
28
|
-
const root = options.targetDir
|
|
28
|
+
const root = options.targetDir;
|
|
29
29
|
const ctx = {
|
|
30
30
|
projectName: options.projectName,
|
|
31
31
|
targetDir: root,
|
|
32
|
-
|
|
32
|
+
type: options.type,
|
|
33
33
|
...(options.db ? { db: options.db, driver: options.driver } : {}),
|
|
34
34
|
...(options.logger ? { logger: options.logger } : {}),
|
|
35
35
|
...(options.validator ? { validator: options.validator } : {}),
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const addons = resolveAddons(ctx);
|
|
39
|
+
const packages = resolvePackages(ctx);
|
|
40
|
+
const bootBindings = collectBootBindings(ctx);
|
|
41
|
+
|
|
42
|
+
await write(
|
|
43
|
+
path.join(root, "package.json"),
|
|
44
|
+
packageJsonTemplate(options.projectName, packages.scripts),
|
|
45
|
+
);
|
|
46
|
+
await write(path.join(root, "tsconfig.json"), tsconfigTemplate());
|
|
47
|
+
await write(path.join(root, "tsdown.config.ts"), tsdownConfigTemplate());
|
|
48
|
+
await write(path.join(root, ".gitignore"), gitignoreTemplate());
|
|
49
|
+
await write(path.join(root, "src/context.ts"), contextTemplate(bootBindings));
|
|
50
|
+
await write(path.join(root, "src/taser.ts"), taserTsTemplate(options.type));
|
|
51
|
+
await write(path.join(root, "src/index.ts"), indexTemplate(options.type));
|
|
52
|
+
await write(path.join(root, "src/routes/$.ts"), rootLayoutTemplate());
|
|
53
|
+
await write(path.join(root, "src/routes/index.get.ts"), indexRouteTemplate());
|
|
54
|
+
await write(path.join(root, "src/routes/health.get.ts"), healthRouteTemplate(ctx));
|
|
55
|
+
await write(path.join(root, "src/routeManifest.gen.ts"), starterManifestTemplate());
|
|
56
|
+
|
|
57
|
+
if (options.type === "cloudflare-workers") {
|
|
58
|
+
await write(
|
|
59
|
+
path.join(root, "wrangler.jsonc"),
|
|
60
|
+
JSON.stringify(
|
|
61
|
+
{
|
|
62
|
+
$schema: "node_modules/wrangler/config-schema.json",
|
|
63
|
+
name: options.projectName,
|
|
64
|
+
main: "src/index.ts",
|
|
65
|
+
compatibility_date: "2024-11-01",
|
|
66
|
+
},
|
|
67
|
+
null,
|
|
68
|
+
2,
|
|
69
|
+
) + "\n",
|
|
70
|
+
);
|
|
36
71
|
}
|
|
37
72
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
73
|
+
if (options.type === "vercel") {
|
|
74
|
+
await write(
|
|
75
|
+
path.join(root, "vercel.json"),
|
|
76
|
+
JSON.stringify(
|
|
77
|
+
{
|
|
78
|
+
rewrites: [{ source: "/(.*)", destination: "/src/index.ts" }],
|
|
79
|
+
},
|
|
80
|
+
null,
|
|
81
|
+
2,
|
|
82
|
+
) + "\n",
|
|
83
|
+
);
|
|
84
|
+
}
|
|
41
85
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
86
|
+
if (options.type === "azure-functions") {
|
|
87
|
+
await write(
|
|
88
|
+
path.join(root, "host.json"),
|
|
89
|
+
JSON.stringify(
|
|
90
|
+
{
|
|
91
|
+
version: "2.0",
|
|
92
|
+
logging: {
|
|
93
|
+
applicationInsights: {
|
|
94
|
+
samplingSettings: {
|
|
95
|
+
isEnabled: true,
|
|
96
|
+
excludedTypes: "Request",
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
extensionBundle: {
|
|
101
|
+
id: "Microsoft.Azure.Functions.ExtensionBundle",
|
|
102
|
+
version: "[4.*, 5.0.0)",
|
|
103
|
+
},
|
|
104
|
+
extensions: {
|
|
105
|
+
http: {
|
|
106
|
+
routePrefix: "",
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
null,
|
|
111
|
+
2,
|
|
112
|
+
) + "\n",
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
await Promise.all(
|
|
117
|
+
addons.map(async (addon) => {
|
|
118
|
+
await addon.apply(ctx, (filePath, contents) => write(path.join(root, filePath), contents));
|
|
119
|
+
}),
|
|
120
|
+
);
|
|
53
121
|
|
|
54
|
-
|
|
55
|
-
await
|
|
122
|
+
try {
|
|
123
|
+
await copyFile(path.join(root, ".env.example"), path.join(root, ".env"));
|
|
124
|
+
} catch {
|
|
125
|
+
// .env.example was not created
|
|
56
126
|
}
|
|
57
127
|
|
|
58
|
-
await writeProjectConfig(root, ctx)
|
|
128
|
+
await writeProjectConfig(root, ctx);
|
|
59
129
|
|
|
60
130
|
if (options.skipInstall) {
|
|
61
131
|
return {
|
|
62
132
|
projectName: ctx.projectName,
|
|
63
133
|
targetDir: root,
|
|
64
|
-
|
|
134
|
+
type: ctx.type,
|
|
65
135
|
...(ctx.db ? { db: ctx.db, driver: ctx.driver } : {}),
|
|
66
136
|
...(ctx.logger ? { logger: ctx.logger } : {}),
|
|
67
137
|
...(ctx.validator ? { validator: ctx.validator } : {}),
|
|
68
|
-
}
|
|
138
|
+
};
|
|
69
139
|
}
|
|
70
140
|
|
|
71
|
-
const agent = options.agent ?? resolveUserAgent()
|
|
141
|
+
const agent = options.agent ?? resolveUserAgent();
|
|
72
142
|
await installPackages(agent, root, {
|
|
73
143
|
dependencies: packages.dependencies,
|
|
74
144
|
devDependencies: packages.devDependencies,
|
|
75
|
-
})
|
|
145
|
+
});
|
|
76
146
|
|
|
77
147
|
return {
|
|
78
148
|
projectName: ctx.projectName,
|
|
79
149
|
targetDir: root,
|
|
80
|
-
|
|
150
|
+
type: ctx.type,
|
|
81
151
|
...(ctx.db ? { db: ctx.db, driver: ctx.driver } : {}),
|
|
82
152
|
...(ctx.logger ? { logger: ctx.logger } : {}),
|
|
83
153
|
...(ctx.validator ? { validator: ctx.validator } : {}),
|
|
84
|
-
}
|
|
154
|
+
};
|
|
85
155
|
}
|
package/src/core/types.ts
CHANGED
|
@@ -1,57 +1,82 @@
|
|
|
1
|
-
import type { Agent } from
|
|
1
|
+
import type { Agent } from "package-manager-detector";
|
|
2
2
|
|
|
3
|
-
export type
|
|
3
|
+
export type ProjectType =
|
|
4
|
+
| "node"
|
|
5
|
+
| "express"
|
|
6
|
+
| "fastify"
|
|
7
|
+
| "hono"
|
|
8
|
+
| "bun"
|
|
9
|
+
| "deno"
|
|
10
|
+
| "aws-lambda"
|
|
11
|
+
| "cloudflare-workers"
|
|
12
|
+
| "netlify"
|
|
13
|
+
| "vercel"
|
|
14
|
+
| "azure-functions"
|
|
15
|
+
| "google-cloud-run";
|
|
4
16
|
|
|
5
|
-
export const
|
|
17
|
+
export const PROJECT_TYPES: readonly ProjectType[] = [
|
|
18
|
+
"node",
|
|
19
|
+
"express",
|
|
20
|
+
"fastify",
|
|
21
|
+
"hono",
|
|
22
|
+
"bun",
|
|
23
|
+
"deno",
|
|
24
|
+
"aws-lambda",
|
|
25
|
+
"cloudflare-workers",
|
|
26
|
+
"netlify",
|
|
27
|
+
"vercel",
|
|
28
|
+
"azure-functions",
|
|
29
|
+
"google-cloud-run",
|
|
30
|
+
];
|
|
6
31
|
|
|
7
|
-
export type DbOdm =
|
|
32
|
+
export type DbOdm = "drizzle" | "prisma" | "kysely";
|
|
8
33
|
|
|
9
|
-
export const DB_ODMS: readonly DbOdm[] = [
|
|
34
|
+
export const DB_ODMS: readonly DbOdm[] = ["drizzle", "prisma", "kysely"];
|
|
10
35
|
|
|
11
|
-
export type DbDriver =
|
|
36
|
+
export type DbDriver = "postgres" | "sqlite" | "mysql";
|
|
12
37
|
|
|
13
|
-
export const DB_DRIVERS: readonly DbDriver[] = [
|
|
38
|
+
export const DB_DRIVERS: readonly DbDriver[] = ["postgres", "sqlite", "mysql"];
|
|
14
39
|
|
|
15
|
-
export const DEFAULT_DB_DRIVER: DbDriver =
|
|
40
|
+
export const DEFAULT_DB_DRIVER: DbDriver = "sqlite";
|
|
16
41
|
|
|
17
|
-
export type LoggerId =
|
|
42
|
+
export type LoggerId = "pino" | "winston";
|
|
18
43
|
|
|
19
|
-
export const LOGGERS: readonly LoggerId[] = [
|
|
44
|
+
export const LOGGERS: readonly LoggerId[] = ["pino", "winston"];
|
|
20
45
|
|
|
21
|
-
export type ValidatorId =
|
|
46
|
+
export type ValidatorId = "zod" | "arktype" | "valibot";
|
|
22
47
|
|
|
23
|
-
export const VALIDATORS: readonly ValidatorId[] = [
|
|
48
|
+
export const VALIDATORS: readonly ValidatorId[] = ["zod", "arktype", "valibot"];
|
|
24
49
|
|
|
25
50
|
export type PackageGroups = {
|
|
26
|
-
dependencies: string[]
|
|
27
|
-
devDependencies: string[]
|
|
28
|
-
scripts: Record<string, string
|
|
29
|
-
}
|
|
51
|
+
dependencies: string[];
|
|
52
|
+
devDependencies: string[];
|
|
53
|
+
scripts: Record<string, string>;
|
|
54
|
+
};
|
|
30
55
|
|
|
31
56
|
export type ScaffoldContext = {
|
|
32
|
-
projectName: string
|
|
33
|
-
targetDir: string
|
|
34
|
-
|
|
35
|
-
db?: DbOdm
|
|
36
|
-
driver?: DbDriver
|
|
37
|
-
logger?: LoggerId
|
|
38
|
-
validator?: ValidatorId
|
|
39
|
-
}
|
|
57
|
+
projectName: string;
|
|
58
|
+
targetDir: string;
|
|
59
|
+
type: ProjectType;
|
|
60
|
+
db?: DbOdm;
|
|
61
|
+
driver?: DbDriver;
|
|
62
|
+
logger?: LoggerId;
|
|
63
|
+
validator?: ValidatorId;
|
|
64
|
+
};
|
|
40
65
|
|
|
41
66
|
export type ScaffoldOptions = ScaffoldContext & {
|
|
42
|
-
skipInstall?: boolean
|
|
43
|
-
agent?: Agent
|
|
44
|
-
}
|
|
67
|
+
skipInstall?: boolean;
|
|
68
|
+
agent?: Agent;
|
|
69
|
+
};
|
|
45
70
|
|
|
46
|
-
export type ScaffoldResult = ScaffoldContext
|
|
71
|
+
export type ScaffoldResult = ScaffoldContext;
|
|
47
72
|
|
|
48
73
|
export type CapabilitiesCatalog = {
|
|
49
|
-
|
|
74
|
+
types: ProjectType[];
|
|
50
75
|
db: {
|
|
51
|
-
odms: DbOdm[]
|
|
52
|
-
drivers: DbDriver[]
|
|
53
|
-
defaultDriver: DbDriver
|
|
54
|
-
}
|
|
55
|
-
loggers: LoggerId[]
|
|
56
|
-
validators: ValidatorId[]
|
|
57
|
-
}
|
|
76
|
+
odms: DbOdm[];
|
|
77
|
+
drivers: DbDriver[];
|
|
78
|
+
defaultDriver: DbDriver;
|
|
79
|
+
};
|
|
80
|
+
loggers: LoggerId[];
|
|
81
|
+
validators: ValidatorId[];
|
|
82
|
+
};
|