@ykdz/template 0.0.9 → 0.0.11

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.
Files changed (51) hide show
  1. package/dist/cli.js +2 -2
  2. package/node_modules/@ykdz/template-builtin-source/dist/src/index.d.ts +4 -4
  3. package/node_modules/@ykdz/template-builtin-source/dist/src/index.js +12 -5
  4. package/node_modules/@ykdz/template-builtin-source/dist/templates/hono-api/projection.d.ts +1 -1
  5. package/node_modules/@ykdz/template-builtin-source/dist/templates/hono-api/projection.js +1 -1
  6. package/node_modules/@ykdz/template-builtin-source/dist/templates/projection-plans.js +9 -6
  7. package/node_modules/@ykdz/template-builtin-source/dist/templates/rust-bin/projection.d.ts +1 -1
  8. package/node_modules/@ykdz/template-builtin-source/dist/templates/rust-bin/projection.js +1 -1
  9. package/node_modules/@ykdz/template-builtin-source/dist/templates/ts-lib/projection.d.ts +1 -1
  10. package/node_modules/@ykdz/template-builtin-source/dist/templates/ts-lib/projection.js +1 -1
  11. package/node_modules/@ykdz/template-builtin-source/dist/templates/vue-app/projection.d.ts +1 -1
  12. package/node_modules/@ykdz/template-builtin-source/dist/templates/vue-app/projection.js +9 -4
  13. package/node_modules/@ykdz/template-builtin-source/dist/templates/vue-hono-app/projection.d.ts +1 -1
  14. package/node_modules/@ykdz/template-builtin-source/dist/templates/vue-hono-app/projection.js +7 -7
  15. package/node_modules/@ykdz/template-builtin-source/package.json +4 -3
  16. package/node_modules/@ykdz/template-builtin-source/templates/preset-source.json +39 -11
  17. package/node_modules/@ykdz/template-builtin-source/templates/vue-app/scripts/run-playwright.ts +25 -0
  18. package/node_modules/@ykdz/template-builtin-source/templates/vue-app/src/App.vue +18 -4
  19. package/node_modules/@ykdz/template-builtin-source/templates/vue-hono-app/web/scripts/run-playwright.ts +25 -0
  20. package/node_modules/@ykdz/template-builtin-source/templates/vue-hono-app/web/src/App.vue +18 -4
  21. package/node_modules/@ykdz/template-core/dist/declarations.d.ts +2 -203
  22. package/node_modules/@ykdz/template-core/dist/declarations.js +1 -303
  23. package/node_modules/@ykdz/template-core/dist/devcontainer.d.ts +17 -0
  24. package/node_modules/@ykdz/template-core/dist/devcontainer.js +22 -21
  25. package/node_modules/@ykdz/template-core/dist/editor-customization.d.ts +10 -1
  26. package/node_modules/@ykdz/template-core/dist/editor-customization.js +36 -26
  27. package/node_modules/@ykdz/template-core/dist/generated-scenarios.d.ts +5 -0
  28. package/node_modules/@ykdz/template-core/dist/generated-scenarios.js +42 -24
  29. package/node_modules/@ykdz/template-core/dist/generation-context.d.ts +1 -1
  30. package/node_modules/@ykdz/template-core/dist/module-graph.d.ts +19 -1
  31. package/node_modules/@ykdz/template-core/dist/module-graph.js +42 -3
  32. package/node_modules/@ykdz/template-core/dist/next-step-instructions.d.ts +2 -0
  33. package/node_modules/@ykdz/template-core/dist/next-step-instructions.js +11 -22
  34. package/node_modules/@ykdz/template-core/dist/package-addition-support.d.ts +2 -1
  35. package/node_modules/@ykdz/template-core/dist/package-addition-support.js +2 -4
  36. package/node_modules/@ykdz/template-core/dist/package-addition.js +4 -3
  37. package/node_modules/@ykdz/template-core/dist/package-linking.d.ts +2 -6
  38. package/node_modules/@ykdz/template-core/dist/package-linking.js +1 -1
  39. package/node_modules/@ykdz/template-core/dist/pnpm-workspace.yaml +3 -5
  40. package/node_modules/@ykdz/template-core/dist/preset-projection.d.ts +1 -2
  41. package/node_modules/@ykdz/template-core/dist/preset-source.d.ts +4 -418
  42. package/node_modules/@ykdz/template-core/dist/preset-source.js +81 -726
  43. package/node_modules/@ykdz/template-core/dist/project-github.js +2 -6
  44. package/node_modules/@ykdz/template-core/dist/projection-capabilities.d.ts +5 -53
  45. package/node_modules/@ykdz/template-core/dist/projection-capabilities.js +108 -507
  46. package/node_modules/@ykdz/template-core/dist/toolchain-resolution.js +1 -1
  47. package/node_modules/@ykdz/template-core/package.json +4 -3
  48. package/node_modules/@ykdz/template-shared/dist/index.d.ts +794 -0
  49. package/node_modules/@ykdz/template-shared/dist/index.js +1637 -0
  50. package/node_modules/@ykdz/template-shared/package.json +32 -0
  51. package/package.json +9 -6
@@ -1,203 +1,2 @@
1
- import * as v from "valibot";
2
- import type { PackageAdditionSupport } from "./package-addition-support.js";
3
- import type { PackageLinkIntent, PackageRole, PackageSourcePreset } from "./package-linking.js";
4
- export type BuiltInPreset = {
5
- name: string;
6
- title: string;
7
- description: string;
8
- generation: "supported" | "future";
9
- supportedPackageManagers: readonly PackageManager[];
10
- supportedProjectKinds: readonly ProjectKind[];
11
- packageAdditionSupport: PackageAdditionSupport;
12
- features: readonly FeatureName[];
13
- };
14
- export type PackageManager = "pnpm";
15
- export type ProjectKind = "single-package" | "multi-package";
16
- export type FeatureName = "pnpm-catalog" | "oxc-format-lint" | "strict-typescript" | "root-check" | "fix-command" | "devcontainer" | "github-actions" | "dependabot" | "rustfmt-clippy" | "cargo-test" | "native-binary-release";
17
- export type PresetFile = {
18
- schemaVersion: 1;
19
- name: string;
20
- title: string;
21
- description: string;
22
- supportedPackageManagers: PackageManager[];
23
- supportedProjectKinds: ProjectKind[];
24
- features: FeatureName[];
25
- };
26
- export type ProjectPackage = {
27
- name: string;
28
- path: string;
29
- role?: PackageRole;
30
- sourcePreset?: PackageSourcePreset;
31
- };
32
- export type ProjectBlueprint = {
33
- schemaVersion: 1;
34
- preset: string;
35
- packageManager?: PackageManager;
36
- projectKind: ProjectKind;
37
- features: FeatureName[];
38
- packages?: ProjectPackage[];
39
- packageLinkIntents?: PackageLinkIntent[];
40
- };
41
- export declare const presetFileJsonSchema: {
42
- readonly $schema: "https://json-schema.org/draft/2020-12/schema";
43
- readonly $id: "https://ykdz.dev/schemas/project-kit/preset-file.schema.json";
44
- readonly title: "Project Kit Preset File";
45
- readonly type: "object";
46
- readonly additionalProperties: false;
47
- readonly required: readonly ["schemaVersion", "name", "title", "description", "supportedPackageManagers", "supportedProjectKinds", "features"];
48
- readonly properties: {
49
- readonly schemaVersion: {
50
- readonly const: 1;
51
- };
52
- readonly name: {
53
- readonly type: "string";
54
- readonly minLength: 1;
55
- };
56
- readonly title: {
57
- readonly type: "string";
58
- readonly minLength: 1;
59
- };
60
- readonly description: {
61
- readonly type: "string";
62
- readonly minLength: 1;
63
- };
64
- readonly supportedPackageManagers: {
65
- readonly type: "array";
66
- readonly items: {
67
- readonly enum: readonly ["pnpm"];
68
- };
69
- readonly uniqueItems: true;
70
- };
71
- readonly supportedProjectKinds: {
72
- readonly type: "array";
73
- readonly minItems: 1;
74
- readonly items: {
75
- readonly enum: readonly ["multi-package"];
76
- };
77
- readonly uniqueItems: true;
78
- };
79
- readonly features: {
80
- readonly type: "array";
81
- readonly items: {
82
- readonly enum: FeatureName[];
83
- };
84
- readonly uniqueItems: true;
85
- };
86
- };
87
- };
88
- export declare const blueprintJsonSchema: {
89
- readonly $schema: "https://json-schema.org/draft/2020-12/schema";
90
- readonly $id: "https://ykdz.dev/schemas/project-kit/blueprint.schema.json";
91
- readonly title: "Project Kit Blueprint";
92
- readonly type: "object";
93
- readonly additionalProperties: false;
94
- readonly required: readonly ["schemaVersion", "preset", "projectKind", "features"];
95
- readonly properties: {
96
- readonly schemaVersion: {
97
- readonly const: 1;
98
- };
99
- readonly preset: {
100
- readonly type: "string";
101
- readonly minLength: 1;
102
- };
103
- readonly packageManager: {
104
- readonly enum: readonly ["pnpm"];
105
- };
106
- readonly projectKind: {
107
- readonly enum: readonly ["multi-package"];
108
- };
109
- readonly features: {
110
- readonly type: "array";
111
- readonly items: {
112
- readonly enum: FeatureName[];
113
- };
114
- readonly uniqueItems: true;
115
- };
116
- readonly packages: {
117
- readonly type: "array";
118
- readonly items: {
119
- readonly type: "object";
120
- readonly additionalProperties: false;
121
- readonly required: readonly ["name", "path"];
122
- readonly properties: {
123
- readonly name: {
124
- readonly type: "string";
125
- readonly minLength: 1;
126
- };
127
- readonly path: {
128
- readonly type: "string";
129
- readonly minLength: 1;
130
- };
131
- readonly role: {
132
- readonly enum: readonly ["runtime-service", "shared-library"];
133
- };
134
- readonly sourcePreset: {
135
- readonly enum: readonly ["hono-api", "ts-lib", "vue-app"];
136
- };
137
- };
138
- };
139
- };
140
- readonly packageLinkIntents: {
141
- readonly type: "array";
142
- readonly items: {
143
- readonly type: "object";
144
- readonly additionalProperties: false;
145
- readonly required: readonly ["consumerPackagePath", "providerPackagePath"];
146
- readonly properties: {
147
- readonly consumerPackagePath: {
148
- readonly type: "string";
149
- readonly minLength: 1;
150
- };
151
- readonly providerPackagePath: {
152
- readonly type: "string";
153
- readonly minLength: 1;
154
- };
155
- };
156
- };
157
- };
158
- };
159
- };
160
- export declare const presetFileSchema: v.StrictObjectSchema<{
161
- readonly schemaVersion: v.LiteralSchema<1, undefined>;
162
- readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
163
- readonly title: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
164
- readonly description: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
165
- readonly supportedPackageManagers: v.ArraySchema<v.PicklistSchema<["pnpm"], undefined>, undefined>;
166
- readonly supportedProjectKinds: v.SchemaWithPipe<readonly [v.ArraySchema<v.PicklistSchema<["single-package", "multi-package"], undefined>, undefined>, v.MinLengthAction<("single-package" | "multi-package")[], 1, undefined>]>;
167
- readonly features: v.ArraySchema<v.PicklistSchema<FeatureName[], undefined>, undefined>;
168
- }, undefined>;
169
- export declare const projectBlueprintSchema: v.StrictObjectSchema<{
170
- readonly schemaVersion: v.LiteralSchema<1, undefined>;
171
- readonly preset: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
172
- readonly packageManager: v.OptionalSchema<v.PicklistSchema<["pnpm"], undefined>, undefined>;
173
- readonly projectKind: v.PicklistSchema<["single-package", "multi-package"], undefined>;
174
- readonly features: v.ArraySchema<v.PicklistSchema<FeatureName[], undefined>, undefined>;
175
- readonly packages: v.OptionalSchema<v.ArraySchema<v.StrictObjectSchema<{
176
- readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
177
- readonly path: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
178
- readonly role: v.OptionalSchema<v.PicklistSchema<["runtime-service", "shared-library"], undefined>, undefined>;
179
- readonly sourcePreset: v.OptionalSchema<v.PicklistSchema<["hono-api", "ts-lib", "vue-app"], undefined>, undefined>;
180
- }, undefined>, undefined>, undefined>;
181
- readonly packageLinkIntents: v.OptionalSchema<v.ArraySchema<v.StrictObjectSchema<{
182
- readonly consumerPackagePath: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
183
- readonly providerPackagePath: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
184
- }, undefined>, undefined>, undefined>;
185
- }, undefined>;
186
- export type ValidationIssue = {
187
- path: string;
188
- message: string;
189
- };
190
- export type ValidationResult<T> = {
191
- ok: true;
192
- value: T;
193
- } | {
194
- ok: false;
195
- issues: ValidationIssue[];
196
- };
197
- export type PresetCatalogValidationOptions = {
198
- readonly presets?: readonly BuiltInPreset[];
199
- readonly presetLabel?: string;
200
- };
201
- export declare function validatePresetFile(input: unknown, options?: PresetCatalogValidationOptions): ValidationResult<PresetFile>;
202
- export declare function findPreset(presets: readonly BuiltInPreset[], name: string): BuiltInPreset | undefined;
203
- export declare function validateProjectBlueprint(input: unknown, options?: PresetCatalogValidationOptions): ValidationResult<ProjectBlueprint>;
1
+ export { blueprintJsonSchema, findPreset, presetFileJsonSchema, presetFileSchema, projectBlueprintSchema, validatePresetFile, validateProjectBlueprint, } from "@ykdz/template-shared";
2
+ export type { BuiltInPreset, FeatureName, PackageManager, PresetCatalogValidationOptions, PresetFile, ProjectBlueprint, ProjectKind, ProjectPackage, ValidationIssue, ValidationResult, } from "@ykdz/template-shared";
@@ -1,303 +1 @@
1
- import * as v from "valibot";
2
- const featureNames = [
3
- "pnpm-catalog",
4
- "oxc-format-lint",
5
- "strict-typescript",
6
- "root-check",
7
- "fix-command",
8
- "devcontainer",
9
- "github-actions",
10
- "dependabot",
11
- "rustfmt-clippy",
12
- "cargo-test",
13
- "native-binary-release",
14
- ];
15
- export const presetFileJsonSchema = {
16
- $schema: "https://json-schema.org/draft/2020-12/schema",
17
- $id: "https://ykdz.dev/schemas/project-kit/preset-file.schema.json",
18
- title: "Project Kit Preset File",
19
- type: "object",
20
- additionalProperties: false,
21
- required: [
22
- "schemaVersion",
23
- "name",
24
- "title",
25
- "description",
26
- "supportedPackageManagers",
27
- "supportedProjectKinds",
28
- "features",
29
- ],
30
- properties: {
31
- schemaVersion: { const: 1 },
32
- name: { type: "string", minLength: 1 },
33
- title: { type: "string", minLength: 1 },
34
- description: { type: "string", minLength: 1 },
35
- supportedPackageManagers: {
36
- type: "array",
37
- items: { enum: ["pnpm"] },
38
- uniqueItems: true,
39
- },
40
- supportedProjectKinds: {
41
- type: "array",
42
- minItems: 1,
43
- items: { enum: ["multi-package"] },
44
- uniqueItems: true,
45
- },
46
- features: {
47
- type: "array",
48
- items: { enum: featureNames },
49
- uniqueItems: true,
50
- },
51
- },
52
- };
53
- export const blueprintJsonSchema = {
54
- $schema: "https://json-schema.org/draft/2020-12/schema",
55
- $id: "https://ykdz.dev/schemas/project-kit/blueprint.schema.json",
56
- title: "Project Kit Blueprint",
57
- type: "object",
58
- additionalProperties: false,
59
- required: ["schemaVersion", "preset", "projectKind", "features"],
60
- properties: {
61
- schemaVersion: { const: 1 },
62
- preset: { type: "string", minLength: 1 },
63
- packageManager: { enum: ["pnpm"] },
64
- projectKind: { enum: ["multi-package"] },
65
- features: {
66
- type: "array",
67
- items: { enum: featureNames },
68
- uniqueItems: true,
69
- },
70
- packages: {
71
- type: "array",
72
- items: {
73
- type: "object",
74
- additionalProperties: false,
75
- required: ["name", "path"],
76
- properties: {
77
- name: { type: "string", minLength: 1 },
78
- path: { type: "string", minLength: 1 },
79
- role: { enum: ["runtime-service", "shared-library"] },
80
- sourcePreset: { enum: ["hono-api", "ts-lib", "vue-app"] },
81
- },
82
- },
83
- },
84
- packageLinkIntents: {
85
- type: "array",
86
- items: {
87
- type: "object",
88
- additionalProperties: false,
89
- required: ["consumerPackagePath", "providerPackagePath"],
90
- properties: {
91
- consumerPackagePath: { type: "string", minLength: 1 },
92
- providerPackagePath: { type: "string", minLength: 1 },
93
- },
94
- },
95
- },
96
- },
97
- };
98
- const nonEmptyString = v.pipe(v.string(), v.minLength(1));
99
- const packageManagerSchema = v.picklist(["pnpm"]);
100
- const projectKindSchema = v.picklist([
101
- "single-package",
102
- "multi-package",
103
- ]);
104
- const featureNameSchema = v.picklist(featureNames);
105
- const packageRoleSchema = v.picklist([
106
- "runtime-service",
107
- "shared-library",
108
- ]);
109
- const packageSourcePresetSchema = v.picklist([
110
- "hono-api",
111
- "ts-lib",
112
- "vue-app",
113
- ]);
114
- export const presetFileSchema = v.strictObject({
115
- schemaVersion: v.literal(1),
116
- name: nonEmptyString,
117
- title: nonEmptyString,
118
- description: nonEmptyString,
119
- supportedPackageManagers: v.array(packageManagerSchema),
120
- supportedProjectKinds: v.pipe(v.array(projectKindSchema), v.minLength(1)),
121
- features: v.array(featureNameSchema),
122
- });
123
- export const projectBlueprintSchema = v.strictObject({
124
- schemaVersion: v.literal(1),
125
- preset: nonEmptyString,
126
- packageManager: v.optional(packageManagerSchema),
127
- projectKind: projectKindSchema,
128
- features: v.array(featureNameSchema),
129
- packages: v.optional(v.array(v.strictObject({
130
- name: nonEmptyString,
131
- path: nonEmptyString,
132
- role: v.optional(packageRoleSchema),
133
- sourcePreset: v.optional(packageSourcePresetSchema),
134
- }))),
135
- packageLinkIntents: v.optional(v.array(v.strictObject({
136
- consumerPackagePath: nonEmptyString,
137
- providerPackagePath: nonEmptyString,
138
- }))),
139
- });
140
- function formatIssuePath(issue) {
141
- if (!issue.path || issue.path.length === 0) {
142
- return "$";
143
- }
144
- return issue.path.reduce((path, item) => `${path}.${String(item.key)}`, "$");
145
- }
146
- function shapeIssues(issues) {
147
- return issues.map((issue) => ({
148
- path: formatIssuePath(issue),
149
- message: issue.message,
150
- }));
151
- }
152
- function duplicateIssues(values, path) {
153
- const seen = new Set();
154
- const duplicates = new Set();
155
- for (const value of values) {
156
- if (seen.has(value)) {
157
- duplicates.add(value);
158
- }
159
- seen.add(value);
160
- }
161
- return [...duplicates].map((value) => ({
162
- path,
163
- message: `Duplicate value: ${value}`,
164
- }));
165
- }
166
- function generationSupportIssue(preset, path) {
167
- if (preset.generation === "supported") {
168
- return undefined;
169
- }
170
- return {
171
- path,
172
- message: `Preset ${preset.name} is not supported for generation in this version`,
173
- };
174
- }
175
- function unsupportedSinglePackageProjectShapeIssue(path) {
176
- return {
177
- path,
178
- message: "single-package Project Shape is unsupported in V1; use the workspace monorepo Project Shape",
179
- };
180
- }
181
- export function validatePresetFile(input, options = {}) {
182
- const result = v.safeParse(presetFileSchema, input);
183
- if (!result.success) {
184
- return { ok: false, issues: shapeIssues(result.issues) };
185
- }
186
- const semanticIssues = [
187
- ...duplicateIssues(result.output.supportedPackageManagers, "$.supportedPackageManagers"),
188
- ...duplicateIssues(result.output.supportedProjectKinds, "$.supportedProjectKinds"),
189
- ...duplicateIssues(result.output.features, "$.features"),
190
- ];
191
- if (result.output.supportedProjectKinds.includes("single-package")) {
192
- semanticIssues.push(unsupportedSinglePackageProjectShapeIssue("$.supportedProjectKinds"));
193
- }
194
- const catalogPreset = findPreset(options.presets ?? [], result.output.name);
195
- const unsupportedGeneration = catalogPreset
196
- ? generationSupportIssue(catalogPreset, "$.name")
197
- : undefined;
198
- if (unsupportedGeneration) {
199
- semanticIssues.push(unsupportedGeneration);
200
- }
201
- if (semanticIssues.length > 0) {
202
- return { ok: false, issues: semanticIssues };
203
- }
204
- return { ok: true, value: result.output };
205
- }
206
- export function findPreset(presets, name) {
207
- return presets.find((preset) => preset.name === name);
208
- }
209
- function normalizeProjectBlueprint(blueprint) {
210
- return {
211
- schemaVersion: blueprint.schemaVersion,
212
- preset: blueprint.preset,
213
- ...(blueprint.packageManager === undefined
214
- ? {}
215
- : { packageManager: blueprint.packageManager }),
216
- projectKind: blueprint.projectKind,
217
- features: [...blueprint.features],
218
- ...(blueprint.packages === undefined
219
- ? {}
220
- : {
221
- packages: blueprint.packages.map((projectPackage) => ({
222
- name: projectPackage.name,
223
- path: projectPackage.path,
224
- ...(projectPackage.role === undefined
225
- ? {}
226
- : { role: projectPackage.role }),
227
- ...(projectPackage.sourcePreset === undefined
228
- ? {}
229
- : { sourcePreset: projectPackage.sourcePreset }),
230
- })),
231
- }),
232
- ...(blueprint.packageLinkIntents === undefined
233
- ? {}
234
- : {
235
- packageLinkIntents: blueprint.packageLinkIntents.map((intent) => ({
236
- consumerPackagePath: intent.consumerPackagePath,
237
- providerPackagePath: intent.providerPackagePath,
238
- })),
239
- }),
240
- };
241
- }
242
- export function validateProjectBlueprint(input, options = {}) {
243
- const result = v.safeParse(projectBlueprintSchema, input);
244
- if (!result.success) {
245
- return { ok: false, issues: shapeIssues(result.issues) };
246
- }
247
- const blueprint = normalizeProjectBlueprint(result.output);
248
- const preset = findPreset(options.presets ?? [], blueprint.preset);
249
- const semanticIssues = [
250
- ...duplicateIssues(blueprint.features, "$.features"),
251
- ];
252
- if (blueprint.projectKind === "single-package") {
253
- semanticIssues.push(unsupportedSinglePackageProjectShapeIssue("$.projectKind"));
254
- }
255
- if (options.presets && !preset) {
256
- semanticIssues.push({
257
- path: "$.preset",
258
- message: `Unknown ${options.presetLabel ?? "built-in"} preset: ${blueprint.preset}`,
259
- });
260
- }
261
- else if (preset) {
262
- const unsupportedGeneration = generationSupportIssue(preset, "$.preset");
263
- if (unsupportedGeneration) {
264
- semanticIssues.push(unsupportedGeneration);
265
- }
266
- if (blueprint.packageManager &&
267
- !preset.supportedPackageManagers.includes(blueprint.packageManager)) {
268
- semanticIssues.push({
269
- path: "$.packageManager",
270
- message: `${blueprint.packageManager} is not supported by preset ${preset.name}`,
271
- });
272
- }
273
- if (!blueprint.packageManager &&
274
- preset.supportedPackageManagers.length > 0) {
275
- semanticIssues.push({
276
- path: "$.packageManager",
277
- message: `packageManager is required by preset ${preset.name}`,
278
- });
279
- }
280
- if (!preset.supportedProjectKinds.includes(blueprint.projectKind)) {
281
- semanticIssues.push({
282
- path: "$.projectKind",
283
- message: `${blueprint.projectKind} is not supported by preset ${preset.name}`,
284
- });
285
- }
286
- const supportedFeatures = new Set(preset.features);
287
- for (const feature of blueprint.features) {
288
- if (!supportedFeatures.has(feature)) {
289
- semanticIssues.push({
290
- path: "$.features",
291
- message: `${feature} is not supported by preset ${preset.name}`,
292
- });
293
- }
294
- }
295
- }
296
- if (blueprint.packages) {
297
- semanticIssues.push(...duplicateIssues(blueprint.packages.map((projectPackage) => projectPackage.name), "$.packages.name"), ...duplicateIssues(blueprint.packages.map((projectPackage) => projectPackage.path), "$.packages.path"));
298
- }
299
- if (semanticIssues.length > 0) {
300
- return { ok: false, issues: semanticIssues };
301
- }
302
- return { ok: true, value: blueprint };
303
- }
1
+ export { blueprintJsonSchema, findPreset, presetFileJsonSchema, presetFileSchema, projectBlueprintSchema, validatePresetFile, validateProjectBlueprint, } from "@ykdz/template-shared";
@@ -13,6 +13,21 @@ export type DevelopmentContainerRustLayer = {
13
13
  readonly toolchain: string;
14
14
  };
15
15
  type DevelopmentContainerCapabilityLayer = DevelopmentContainerBrowserTestLayer | DevelopmentContainerRustLayer;
16
+ export type DevelopmentContainerDockerfileFragments = {
17
+ readonly sourceRoot: string;
18
+ readonly nodePnpm: {
19
+ readonly from: string;
20
+ readonly text: string;
21
+ };
22
+ readonly browserTest?: {
23
+ readonly from: string;
24
+ readonly text: string;
25
+ } | undefined;
26
+ readonly rust?: {
27
+ readonly from: string;
28
+ readonly text: string;
29
+ } | undefined;
30
+ };
16
31
  export type DevelopmentContainerPlan = {
17
32
  readonly devcontainer: Record<string, unknown>;
18
33
  readonly dockerfile: string;
@@ -43,6 +58,7 @@ export declare function dockerfileFirstNodePnpmDevcontainer(options: {
43
58
  export declare function checkedDockerfileFirstNodePnpmDevcontainer(options: {
44
59
  readonly name: string;
45
60
  readonly layer: DevelopmentContainerNodePnpmLayer;
61
+ readonly dockerfileFragments: DevelopmentContainerDockerfileFragments;
46
62
  readonly additionalLayers?: readonly DevelopmentContainerCapabilityLayer[] | undefined;
47
63
  readonly extensions: readonly string[];
48
64
  readonly settings?: Record<string, unknown> | undefined;
@@ -52,6 +68,7 @@ export declare function dockerfileFirstRustPnpmDevcontainer(options: {
52
68
  readonly name: string;
53
69
  readonly nodeLayer: DevelopmentContainerNodePnpmLayer;
54
70
  readonly rustLayer: DevelopmentContainerRustLayer;
71
+ readonly dockerfileFragments: DevelopmentContainerDockerfileFragments;
55
72
  readonly extensions: readonly string[];
56
73
  readonly settings?: Record<string, unknown> | undefined;
57
74
  }): DevelopmentContainerPlan;
@@ -1,8 +1,11 @@
1
- import { readFileSync } from "node:fs";
2
- import path from "node:path";
3
- import { fileURLToPath } from "node:url";
4
1
  import { loadTemplateDependencyCatalog } from "./dependency-catalog.js";
5
- import { packageTemplateRoot } from "./runtime-paths.js";
2
+ function requireDockerfileFragment(fragments, name) {
3
+ const fragment = fragments[name];
4
+ if (fragment === undefined) {
5
+ throw new Error(`Development Container Dockerfile fragment is missing: ${name}`);
6
+ }
7
+ return fragment;
8
+ }
6
9
  const runtimeDockerfileInstructions = new Set([
7
10
  "CMD",
8
11
  "ENTRYPOINT",
@@ -61,19 +64,13 @@ export function browserTestToolLayer() {
61
64
  export function rustToolLayer(options = {}) {
62
65
  return { kind: "rust", toolchain: options.toolchain ?? "stable" };
63
66
  }
64
- function sharedDevcontainerSourceRoot() {
65
- return packageTemplateRoot(path.dirname(fileURLToPath(import.meta.url)), "shared", "devcontainer");
66
- }
67
- function checkedDockerfileFragment(name) {
68
- return readFileSync(path.join(sharedDevcontainerSourceRoot(), name), "utf8");
69
- }
70
- function checkedNodePnpmDockerfile(options = {}) {
67
+ function checkedNodePnpmDockerfile(options) {
71
68
  return composeDevelopmentContainerDockerfile({
72
69
  layers: [
73
70
  {
74
71
  kind: "base",
75
72
  name: "node-pnpm",
76
- text: checkedDockerfileFragment("node-pnpm.Dockerfile"),
73
+ text: options.dockerfileFragments.nodePnpm.text,
77
74
  },
78
75
  ...(options.additionalLayers ?? []).map((layer) => {
79
76
  switch (layer.kind) {
@@ -81,36 +78,37 @@ function checkedNodePnpmDockerfile(options = {}) {
81
78
  return {
82
79
  kind: "capability",
83
80
  name: "browser-test",
84
- text: checkedDockerfileFragment("browser-test.Dockerfile"),
81
+ text: requireDockerfileFragment(options.dockerfileFragments, "browserTest").text,
85
82
  };
86
83
  case "rust":
87
84
  return {
88
85
  kind: "capability",
89
86
  name: "rust",
90
- text: checkedDockerfileFragment("rust.Dockerfile"),
87
+ text: requireDockerfileFragment(options.dockerfileFragments, "rust").text,
91
88
  };
92
89
  }
93
90
  }),
94
91
  ],
95
92
  });
96
93
  }
97
- function checkedNodePnpmDockerfileFragments(options = {}) {
94
+ function checkedNodePnpmDockerfileFragments(options) {
98
95
  return [
99
96
  {
100
- sourceRoot: "sharedDevcontainer",
101
- from: "node-pnpm.Dockerfile",
97
+ sourceRoot: options.dockerfileFragments.sourceRoot,
98
+ from: options.dockerfileFragments.nodePnpm.from,
102
99
  },
103
100
  ...(options.additionalLayers ?? []).map((layer) => {
104
101
  switch (layer.kind) {
105
102
  case "browser-test":
106
103
  return {
107
- sourceRoot: "sharedDevcontainer",
108
- from: "browser-test.Dockerfile",
104
+ sourceRoot: options.dockerfileFragments.sourceRoot,
105
+ from: requireDockerfileFragment(options.dockerfileFragments, "browserTest").from,
109
106
  };
110
107
  case "rust":
111
108
  return {
112
- sourceRoot: "sharedDevcontainer",
113
- from: "rust.Dockerfile",
109
+ sourceRoot: options.dockerfileFragments.sourceRoot,
110
+ from: requireDockerfileFragment(options.dockerfileFragments, "rust")
111
+ .from,
114
112
  };
115
113
  }
116
114
  }),
@@ -175,12 +173,14 @@ export function checkedDockerfileFirstNodePnpmDevcontainer(options) {
175
173
  ...(options.mounts ? { mounts: options.mounts } : {}),
176
174
  },
177
175
  dockerfile: checkedNodePnpmDockerfile({
176
+ dockerfileFragments: options.dockerfileFragments,
178
177
  additionalLayers: options.additionalLayers,
179
178
  }),
180
179
  dockerfileOperation: {
181
180
  kind: "writeTextFromFragments",
182
181
  to: ".devcontainer/Dockerfile",
183
182
  fragments: checkedNodePnpmDockerfileFragments({
183
+ dockerfileFragments: options.dockerfileFragments,
184
184
  additionalLayers: options.additionalLayers,
185
185
  }),
186
186
  },
@@ -190,6 +190,7 @@ export function dockerfileFirstRustPnpmDevcontainer(options) {
190
190
  return checkedDockerfileFirstNodePnpmDevcontainer({
191
191
  name: options.name,
192
192
  layer: options.nodeLayer,
193
+ dockerfileFragments: options.dockerfileFragments,
193
194
  additionalLayers: [options.rustLayer],
194
195
  extensions: options.extensions,
195
196
  settings: options.settings,
@@ -9,4 +9,13 @@ export type EditorCustomizationOptions = {
9
9
  readonly formatter?: string;
10
10
  };
11
11
  };
12
- export declare function editorCustomizationForCapabilities(capabilities: readonly EditorCustomizationCapability[], options?: EditorCustomizationOptions): EditorCustomization;
12
+ type CapabilityProjection = {
13
+ readonly extensions: readonly string[];
14
+ readonly settings: Record<string, unknown>;
15
+ };
16
+ export type EditorCustomizationDeclarations = {
17
+ readonly capabilities: Record<EditorCustomizationCapability, CapabilityProjection>;
18
+ };
19
+ export declare function loadEditorCustomizationDeclarations(resourcePath: string): EditorCustomizationDeclarations;
20
+ export declare function editorCustomizationForCapabilities(capabilities: readonly EditorCustomizationCapability[], declarations: EditorCustomizationDeclarations, options?: EditorCustomizationOptions): EditorCustomization;
21
+ export {};