@emeryld/manager 0.4.2 → 0.4.4
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/create-package/index.js +49 -4
- package/dist/create-package/shared.js +63 -3
- package/dist/create-package/variants/client.js +8 -4
- package/dist/create-package/variants/contract.js +7 -5
- package/dist/create-package/variants/docker.js +10 -9
- package/dist/create-package/variants/empty.js +5 -4
- package/dist/create-package/variants/server.js +5 -4
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdir, readdir, readFile, stat } from 'node:fs/promises';
|
|
1
|
+
import { mkdir, readdir, readFile, rm, stat } from 'node:fs/promises';
|
|
2
2
|
import { spawn } from 'node:child_process';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { stdin as input } from 'node:process';
|
|
@@ -105,6 +105,10 @@ function parseCreateCliArgs(argv) {
|
|
|
105
105
|
options.skipBuild = true;
|
|
106
106
|
continue;
|
|
107
107
|
}
|
|
108
|
+
if (arg === '--reset') {
|
|
109
|
+
options.reset = true;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
108
112
|
if (arg === '--help' || arg === '-h') {
|
|
109
113
|
options.help = true;
|
|
110
114
|
continue;
|
|
@@ -123,6 +127,7 @@ function printCreateHelp() {
|
|
|
123
127
|
console.log(' pnpm manager-cli create --describe rrr-server');
|
|
124
128
|
console.log(' pnpm manager-cli create --variant rrr-client --dir packages/rrr-client --name @scope/client');
|
|
125
129
|
console.log(' pnpm manager-cli create --variant rrr-server --contract @scope/contract --skip-install');
|
|
130
|
+
console.log(' pnpm manager-cli create --variant rrr-server --reset # blow away an existing target before scaffolding');
|
|
126
131
|
console.log('');
|
|
127
132
|
console.log('Flags:');
|
|
128
133
|
console.log(' --list, -l Show available templates');
|
|
@@ -131,16 +136,28 @@ function printCreateHelp() {
|
|
|
131
136
|
console.log(' --dir, --path, -p Target directory (skips path prompt)');
|
|
132
137
|
console.log(' --name, -n Package name (skips name prompt)');
|
|
133
138
|
console.log(' --contract Contract import to inject (server/client variants)');
|
|
139
|
+
console.log(' --reset Remove the target directory if it already exists');
|
|
134
140
|
console.log(' --skip-install Do not run pnpm install after scaffolding');
|
|
135
141
|
console.log(' --skip-build Skip build after scaffolding');
|
|
136
142
|
console.log(' --help, -h Show this help');
|
|
137
143
|
}
|
|
138
|
-
async function ensureTargetDir(targetDir) {
|
|
144
|
+
async function ensureTargetDir(targetDir, options) {
|
|
145
|
+
const resolvedTarget = path.resolve(targetDir);
|
|
146
|
+
const shouldReset = options?.reset ?? false;
|
|
147
|
+
if (shouldReset && resolvedTarget === workspaceRoot) {
|
|
148
|
+
throw new Error('Refusing to reset the workspace root directory.');
|
|
149
|
+
}
|
|
139
150
|
try {
|
|
140
151
|
const stats = await stat(targetDir);
|
|
141
152
|
if (!stats.isDirectory()) {
|
|
142
153
|
throw new Error(`Target "${targetDir}" exists and is not a directory.`);
|
|
143
154
|
}
|
|
155
|
+
if (shouldReset) {
|
|
156
|
+
logGlobal(`Resetting existing target ${path.relative(workspaceRoot, resolvedTarget) || '.'}…`, colors.yellow);
|
|
157
|
+
await rm(resolvedTarget, { recursive: true, force: true });
|
|
158
|
+
await mkdir(resolvedTarget, { recursive: true });
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
144
161
|
const entries = await readdir(targetDir);
|
|
145
162
|
if (entries.length > 0) {
|
|
146
163
|
logGlobal(`Target ${path.relative(workspaceRoot, targetDir)} is not empty; existing files will be preserved.`, colors.yellow);
|
|
@@ -150,7 +167,7 @@ async function ensureTargetDir(targetDir) {
|
|
|
150
167
|
if (error &&
|
|
151
168
|
typeof error === 'object' &&
|
|
152
169
|
error.code === 'ENOENT') {
|
|
153
|
-
await mkdir(
|
|
170
|
+
await mkdir(resolvedTarget, { recursive: true });
|
|
154
171
|
return;
|
|
155
172
|
}
|
|
156
173
|
throw error;
|
|
@@ -289,6 +306,10 @@ async function promptForTargetDir(fallback) {
|
|
|
289
306
|
const normalized = answer || fallback;
|
|
290
307
|
return path.resolve(workspaceRoot, normalized);
|
|
291
308
|
}
|
|
309
|
+
/**
|
|
310
|
+
* ✅ Build solution #1: after install, build the workspace graph (or at least deps)
|
|
311
|
+
* ✅ Keeps a safe fallback to the old "build just the new package" behavior.
|
|
312
|
+
*/
|
|
292
313
|
async function postCreateTasks(targetDir, options) {
|
|
293
314
|
if (options?.skipInstall) {
|
|
294
315
|
logGlobal('Skipping pnpm install (flag).', colors.dim);
|
|
@@ -306,6 +327,27 @@ async function postCreateTasks(targetDir, options) {
|
|
|
306
327
|
logGlobal('Skipping build (flag).', colors.dim);
|
|
307
328
|
return;
|
|
308
329
|
}
|
|
330
|
+
// Prefer building the dependency graph rooted at the new package (fast),
|
|
331
|
+
// fall back to building the whole workspace, then fall back to old behavior.
|
|
332
|
+
try {
|
|
333
|
+
if (options?.pkgName) {
|
|
334
|
+
logGlobal(`Building workspace deps for ${options.pkgName}…`, colors.cyan);
|
|
335
|
+
await runCommand('pnpm', ['-r', '--filter', `${options.pkgName}...`, 'build'], workspaceRoot);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
catch (error) {
|
|
340
|
+
logGlobal(`Filtered workspace build failed; will try full workspace build: ${error instanceof Error ? error.message : String(error)}`, colors.yellow);
|
|
341
|
+
}
|
|
342
|
+
try {
|
|
343
|
+
logGlobal('Building full workspace…', colors.cyan);
|
|
344
|
+
await runCommand('pnpm', ['-r', 'build'], workspaceRoot);
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
catch (error) {
|
|
348
|
+
logGlobal(`Full workspace build failed; falling back to building only the new package: ${error instanceof Error ? error.message : String(error)}`, colors.yellow);
|
|
349
|
+
}
|
|
350
|
+
// Old behavior fallback: build only the new package if it has a build script
|
|
309
351
|
try {
|
|
310
352
|
const pkgJsonPath = path.join(targetDir, 'package.json');
|
|
311
353
|
const pkgRaw = await readFile(pkgJsonPath, 'utf8');
|
|
@@ -329,12 +371,13 @@ async function gatherTarget(initial = {}) {
|
|
|
329
371
|
? await askLine(`Package name? (${fallbackName}): `)
|
|
330
372
|
: initial.pkgName;
|
|
331
373
|
const pkgName = (nameAnswer || fallbackName).trim() || fallbackName;
|
|
332
|
-
await ensureTargetDir(targetDir);
|
|
374
|
+
await ensureTargetDir(targetDir, { reset: initial.reset });
|
|
333
375
|
return {
|
|
334
376
|
variant,
|
|
335
377
|
targetDir,
|
|
336
378
|
pkgName,
|
|
337
379
|
contractName: initial.contractName,
|
|
380
|
+
reset: initial.reset,
|
|
338
381
|
};
|
|
339
382
|
}
|
|
340
383
|
export async function createRrrPackage(options = {}) {
|
|
@@ -348,6 +391,7 @@ export async function createRrrPackage(options = {}) {
|
|
|
348
391
|
await postCreateTasks(target.targetDir, {
|
|
349
392
|
skipInstall: options.skipInstall,
|
|
350
393
|
skipBuild: options.skipBuild ?? options.skipInstall,
|
|
394
|
+
pkgName: target.pkgName,
|
|
351
395
|
});
|
|
352
396
|
logGlobal('Scaffold complete. Install/build steps were attempted; ready to run!', colors.green);
|
|
353
397
|
}
|
|
@@ -381,6 +425,7 @@ export async function runCreatePackageCli(argv) {
|
|
|
381
425
|
targetDir,
|
|
382
426
|
pkgName: parsed.pkgName,
|
|
383
427
|
contractName: parsed.contractName,
|
|
428
|
+
reset: parsed.reset,
|
|
384
429
|
skipInstall: parsed.skipInstall,
|
|
385
430
|
skipBuild: parsed.skipBuild ?? parsed.skipInstall,
|
|
386
431
|
});
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
1
2
|
import { access, mkdir, writeFile } from 'node:fs/promises';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
export const workspaceRoot = process.cwd();
|
|
5
|
+
function pathExists(target) {
|
|
6
|
+
return access(target)
|
|
7
|
+
.then(() => true)
|
|
8
|
+
.catch(() => false);
|
|
9
|
+
}
|
|
10
|
+
function toPosixPath(value) {
|
|
11
|
+
return value.split(path.sep).join('/');
|
|
12
|
+
}
|
|
4
13
|
export async function writeFileIfMissing(baseDir, relative, contents) {
|
|
5
14
|
const fullPath = path.join(baseDir, relative);
|
|
6
15
|
await mkdir(path.dirname(fullPath), { recursive: true });
|
|
@@ -23,7 +32,8 @@ export async function writeFileIfMissing(baseDir, relative, contents) {
|
|
|
23
32
|
return 'created';
|
|
24
33
|
}
|
|
25
34
|
export function baseTsConfig(options) {
|
|
26
|
-
|
|
35
|
+
const config = {
|
|
36
|
+
...(options?.extends ? { extends: options.extends } : {}),
|
|
27
37
|
compilerOptions: {
|
|
28
38
|
target: 'ES2020',
|
|
29
39
|
module: 'NodeNext',
|
|
@@ -41,11 +51,15 @@ export function baseTsConfig(options) {
|
|
|
41
51
|
},
|
|
42
52
|
include: options?.include ?? ['src/**/*'],
|
|
43
53
|
exclude: options?.exclude ?? ['dist', 'node_modules'],
|
|
44
|
-
}
|
|
54
|
+
};
|
|
55
|
+
return `${JSON.stringify(config, null, 2)}\n`;
|
|
45
56
|
}
|
|
46
57
|
export function baseEslintConfig(tsconfigPath = './tsconfig.json') {
|
|
47
58
|
return `import tseslint from 'typescript-eslint'
|
|
48
59
|
import prettierPlugin from 'eslint-plugin-prettier'
|
|
60
|
+
import { fileURLToPath } from 'node:url'
|
|
61
|
+
|
|
62
|
+
const __dirname = fileURLToPath(new URL('.', import.meta.url))
|
|
49
63
|
|
|
50
64
|
export default tseslint.config(
|
|
51
65
|
{ ignores: ['dist', 'node_modules'] },
|
|
@@ -55,7 +69,7 @@ export default tseslint.config(
|
|
|
55
69
|
languageOptions: {
|
|
56
70
|
parserOptions: {
|
|
57
71
|
project: ${JSON.stringify(tsconfigPath)},
|
|
58
|
-
tsconfigRootDir:
|
|
72
|
+
tsconfigRootDir: __dirname,
|
|
59
73
|
},
|
|
60
74
|
},
|
|
61
75
|
plugins: {
|
|
@@ -125,6 +139,8 @@ const DEFAULT_GITIGNORE_ENTRIES = [
|
|
|
125
139
|
'.env',
|
|
126
140
|
'coverage',
|
|
127
141
|
'*.log',
|
|
142
|
+
'.vscode',
|
|
143
|
+
'.husky',
|
|
128
144
|
];
|
|
129
145
|
export function gitignoreFrom(entries = DEFAULT_GITIGNORE_ENTRIES) {
|
|
130
146
|
return entries.join('\n');
|
|
@@ -199,6 +215,10 @@ function stripUndefined(obj) {
|
|
|
199
215
|
}
|
|
200
216
|
export function basePackageJson(options) {
|
|
201
217
|
const applyDefaults = options.useDefaults ?? true;
|
|
218
|
+
const inheritPackageManager = options.inheritPackageManager ?? true;
|
|
219
|
+
const packageManager = inheritPackageManager && !options.extraFields?.packageManager
|
|
220
|
+
? readRootPackageManager()
|
|
221
|
+
: undefined;
|
|
202
222
|
const pkg = stripUndefined({
|
|
203
223
|
name: options.name,
|
|
204
224
|
version: options.version ?? '0.1.0',
|
|
@@ -221,7 +241,47 @@ export function basePackageJson(options) {
|
|
|
221
241
|
dependencies: options.dependencies,
|
|
222
242
|
devDependencies: options.devDependencies,
|
|
223
243
|
'lint-staged': LINT_STAGED_CONFIG,
|
|
244
|
+
packageManager,
|
|
224
245
|
...options.extraFields,
|
|
225
246
|
});
|
|
226
247
|
return `${JSON.stringify(pkg, null, 2)}\n`;
|
|
227
248
|
}
|
|
249
|
+
function readRootPackageManager() {
|
|
250
|
+
try {
|
|
251
|
+
const raw = readFileSync(path.join(workspaceRoot, 'package.json'), 'utf8');
|
|
252
|
+
const pkg = JSON.parse(raw);
|
|
253
|
+
return pkg.packageManager;
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
if (error &&
|
|
257
|
+
typeof error === 'object' &&
|
|
258
|
+
error.code !== 'ENOENT') {
|
|
259
|
+
console.warn(`Could not read root package.json for packageManager: ${error instanceof Error ? error.message : String(error)}`);
|
|
260
|
+
}
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
async function resolveRootTsconfig() {
|
|
265
|
+
const candidates = ['tsconfig.base.json', 'tsconfig.json'];
|
|
266
|
+
for (const candidate of candidates) {
|
|
267
|
+
const fullPath = path.join(workspaceRoot, candidate);
|
|
268
|
+
if (await pathExists(fullPath)) {
|
|
269
|
+
return fullPath;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return undefined;
|
|
273
|
+
}
|
|
274
|
+
export async function packageTsConfig(targetDir, options) {
|
|
275
|
+
const extendsFromRoot = options?.extendsFromRoot ?? true;
|
|
276
|
+
let extendsPath;
|
|
277
|
+
if (extendsFromRoot) {
|
|
278
|
+
const rootConfig = await resolveRootTsconfig();
|
|
279
|
+
if (rootConfig) {
|
|
280
|
+
const relative = path.relative(targetDir, rootConfig);
|
|
281
|
+
if (relative !== '') {
|
|
282
|
+
extendsPath = toPosixPath(relative || './tsconfig.json');
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return baseTsConfig({ ...options, extends: extendsPath });
|
|
287
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BASE_LINT_DEV_DEPENDENCIES, basePackageFiles, basePackageJson, buildReadme, baseScripts,
|
|
1
|
+
import { BASE_LINT_DEV_DEPENDENCIES, basePackageFiles, basePackageJson, buildReadme, baseScripts, packageTsConfig, writeFileIfMissing, } from '../shared.js';
|
|
2
2
|
const CLIENT_SCRIPTS = [
|
|
3
3
|
'dev',
|
|
4
4
|
'build',
|
|
@@ -45,10 +45,14 @@ export function clientPackageJson(name, contractName = CONTRACT_IMPORT_PLACEHOLD
|
|
|
45
45
|
},
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
|
-
function clientFiles(pkgName, contractImport) {
|
|
48
|
+
async function clientFiles(pkgName, contractImport, targetDir) {
|
|
49
|
+
const tsconfig = await packageTsConfig(targetDir, {
|
|
50
|
+
lib: ['ES2020', 'DOM'],
|
|
51
|
+
types: ['node'],
|
|
52
|
+
});
|
|
49
53
|
return {
|
|
50
54
|
'package.json': clientPackageJson(pkgName, contractImport),
|
|
51
|
-
'tsconfig.json':
|
|
55
|
+
'tsconfig.json': tsconfig,
|
|
52
56
|
...basePackageFiles(),
|
|
53
57
|
'src/index.ts': clientIndexTs(contractImport),
|
|
54
58
|
'README.md': buildReadme({
|
|
@@ -92,7 +96,7 @@ export const clientVariant = {
|
|
|
92
96
|
],
|
|
93
97
|
async scaffold(ctx) {
|
|
94
98
|
const contractImport = ctx.contractName ?? CONTRACT_IMPORT_PLACEHOLDER;
|
|
95
|
-
const files = clientFiles(ctx.pkgName, contractImport);
|
|
99
|
+
const files = await clientFiles(ctx.pkgName, contractImport, ctx.targetDir);
|
|
96
100
|
for (const [relative, contents] of Object.entries(files)) {
|
|
97
101
|
// eslint-disable-next-line no-await-in-loop
|
|
98
102
|
await writeFileIfMissing(ctx.targetDir, relative, contents);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BASE_LINT_DEV_DEPENDENCIES, basePackageFiles, basePackageJson, buildReadme, baseScripts,
|
|
1
|
+
import { BASE_LINT_DEV_DEPENDENCIES, basePackageFiles, basePackageJson, buildReadme, baseScripts, packageTsConfig, writeFileIfMissing, } from '../shared.js';
|
|
2
2
|
const CONTRACT_SCRIPTS = [
|
|
3
3
|
'dev',
|
|
4
4
|
'build',
|
|
@@ -90,7 +90,8 @@ function contractPackageJson(name) {
|
|
|
90
90
|
import: './dist/index.js',
|
|
91
91
|
},
|
|
92
92
|
},
|
|
93
|
-
|
|
93
|
+
// ✅ Dev now *builds/updates dist + .d.ts continuously*
|
|
94
|
+
scripts: baseScripts('tsc -p tsconfig.json --watch --preserveWatchOutput'),
|
|
94
95
|
dependencies: {
|
|
95
96
|
'@emeryld/rrroutes-contract': '^2.5.2',
|
|
96
97
|
zod: '^4.2.1',
|
|
@@ -100,10 +101,11 @@ function contractPackageJson(name) {
|
|
|
100
101
|
},
|
|
101
102
|
});
|
|
102
103
|
}
|
|
103
|
-
function contractFiles(pkgName) {
|
|
104
|
+
async function contractFiles(pkgName, targetDir) {
|
|
105
|
+
const tsconfig = await packageTsConfig(targetDir);
|
|
104
106
|
return {
|
|
105
107
|
'package.json': contractPackageJson(pkgName),
|
|
106
|
-
'tsconfig.json':
|
|
108
|
+
'tsconfig.json': tsconfig,
|
|
107
109
|
...basePackageFiles(),
|
|
108
110
|
'src/index.ts': CONTRACT_TS,
|
|
109
111
|
'README.md': buildReadme({
|
|
@@ -141,7 +143,7 @@ export const contractVariant = {
|
|
|
141
143
|
'Edit src/index.ts to define routes and socket events; exports registry/socket config.',
|
|
142
144
|
],
|
|
143
145
|
async scaffold(ctx) {
|
|
144
|
-
const files = contractFiles(ctx.pkgName);
|
|
146
|
+
const files = await contractFiles(ctx.pkgName, ctx.targetDir);
|
|
145
147
|
for (const [relative, contents] of Object.entries(files)) {
|
|
146
148
|
// eslint-disable-next-line no-await-in-loop
|
|
147
149
|
await writeFileIfMissing(ctx.targetDir, relative, contents);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BASE_LINT_DEV_DEPENDENCIES, basePackageFiles, basePackageJson, buildReadme, baseScripts,
|
|
1
|
+
import { BASE_LINT_DEV_DEPENDENCIES, basePackageFiles, basePackageJson, buildReadme, baseScripts, packageTsConfig, writeFileIfMissing, } from '../shared.js';
|
|
2
2
|
const DOCKER_SCRIPTS = [
|
|
3
3
|
'dev',
|
|
4
4
|
'build',
|
|
@@ -41,7 +41,7 @@ function dockerPackageJson(name) {
|
|
|
41
41
|
'@types/cors': '^2.8.5',
|
|
42
42
|
'@types/express': '^5.0.6',
|
|
43
43
|
'@types/node': '^24.10.2',
|
|
44
|
-
'docker-cli-js': '^
|
|
44
|
+
'docker-cli-js': '^2.10.0',
|
|
45
45
|
},
|
|
46
46
|
});
|
|
47
47
|
}
|
|
@@ -95,10 +95,11 @@ EXPOSE 3000
|
|
|
95
95
|
CMD ["node", "dist/index.js"]
|
|
96
96
|
`;
|
|
97
97
|
}
|
|
98
|
-
function dockerFiles(pkgName) {
|
|
98
|
+
async function dockerFiles(pkgName, targetDir) {
|
|
99
|
+
const tsconfig = await packageTsConfig(targetDir, { types: ['node'] });
|
|
99
100
|
return {
|
|
100
101
|
'package.json': dockerPackageJson(pkgName),
|
|
101
|
-
'tsconfig.json':
|
|
102
|
+
'tsconfig.json': tsconfig,
|
|
102
103
|
'src/index.ts': dockerIndexTs(),
|
|
103
104
|
'scripts/docker.ts': dockerCliScript(pkgName),
|
|
104
105
|
'.dockerignore': DOCKER_DOCKERIGNORE,
|
|
@@ -190,8 +191,8 @@ async function main() {
|
|
|
190
191
|
async function safe(run: () => Promise<unknown>) {
|
|
191
192
|
try {
|
|
192
193
|
await run()
|
|
193
|
-
} catch (error) {
|
|
194
|
-
console.warn(String(error))
|
|
194
|
+
} catch (error: unknown) {
|
|
195
|
+
console.warn(error instanceof Error ? error.message : String(error))
|
|
195
196
|
}
|
|
196
197
|
}
|
|
197
198
|
|
|
@@ -211,8 +212,8 @@ function printHelp() {
|
|
|
211
212
|
)
|
|
212
213
|
}
|
|
213
214
|
|
|
214
|
-
main().catch((
|
|
215
|
-
console.error(
|
|
215
|
+
main().catch((error: unknown) => {
|
|
216
|
+
console.error(error instanceof Error ? error.message : String(error))
|
|
216
217
|
process.exit(1)
|
|
217
218
|
})
|
|
218
219
|
`;
|
|
@@ -234,7 +235,7 @@ export const dockerVariant = {
|
|
|
234
235
|
'scripts/docker.ts wraps common docker commands with consistent naming.',
|
|
235
236
|
],
|
|
236
237
|
async scaffold(ctx) {
|
|
237
|
-
const files = dockerFiles(ctx.pkgName);
|
|
238
|
+
const files = await dockerFiles(ctx.pkgName, ctx.targetDir);
|
|
238
239
|
for (const [relative, contents] of Object.entries(files)) {
|
|
239
240
|
// eslint-disable-next-line no-await-in-loop
|
|
240
241
|
await writeFileIfMissing(ctx.targetDir, relative, contents);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BASE_LINT_DEV_DEPENDENCIES, basePackageFiles, basePackageJson, buildReadme, baseScripts,
|
|
1
|
+
import { BASE_LINT_DEV_DEPENDENCIES, basePackageFiles, basePackageJson, buildReadme, baseScripts, packageTsConfig, writeFileIfMissing, } from '../shared.js';
|
|
2
2
|
const EMPTY_SCRIPTS = [
|
|
3
3
|
'dev',
|
|
4
4
|
'build',
|
|
@@ -19,10 +19,11 @@ function emptyPackageJson(name) {
|
|
|
19
19
|
},
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
|
-
function emptyFiles(pkgName) {
|
|
22
|
+
async function emptyFiles(pkgName, targetDir) {
|
|
23
|
+
const tsconfig = await packageTsConfig(targetDir, { types: ['node'] });
|
|
23
24
|
return {
|
|
24
25
|
'package.json': emptyPackageJson(pkgName),
|
|
25
|
-
'tsconfig.json':
|
|
26
|
+
'tsconfig.json': tsconfig,
|
|
26
27
|
...basePackageFiles(),
|
|
27
28
|
'src/index.ts': "export const hello = 'world'\n",
|
|
28
29
|
'README.md': buildReadme({
|
|
@@ -55,7 +56,7 @@ export const emptyVariant = {
|
|
|
55
56
|
scripts: EMPTY_SCRIPTS,
|
|
56
57
|
notes: ['Start coding in src/index.ts; everything else is wired up.'],
|
|
57
58
|
async scaffold(ctx) {
|
|
58
|
-
const files = emptyFiles(ctx.pkgName);
|
|
59
|
+
const files = await emptyFiles(ctx.pkgName, ctx.targetDir);
|
|
59
60
|
for (const [relative, contents] of Object.entries(files)) {
|
|
60
61
|
// eslint-disable-next-line no-await-in-loop
|
|
61
62
|
await writeFileIfMissing(ctx.targetDir, relative, contents);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BASE_LINT_DEV_DEPENDENCIES, basePackageFiles, basePackageJson, buildReadme, baseScripts,
|
|
1
|
+
import { BASE_LINT_DEV_DEPENDENCIES, basePackageFiles, basePackageJson, buildReadme, baseScripts, packageTsConfig, writeFileIfMissing, } from '../shared.js';
|
|
2
2
|
const SERVER_SCRIPTS = [
|
|
3
3
|
'dev',
|
|
4
4
|
'build',
|
|
@@ -81,10 +81,11 @@ export function serverPackageJson(name, contractName = CONTRACT_IMPORT_PLACEHOLD
|
|
|
81
81
|
},
|
|
82
82
|
});
|
|
83
83
|
}
|
|
84
|
-
function serverFiles(pkgName, contractImport) {
|
|
84
|
+
async function serverFiles(pkgName, contractImport, targetDir) {
|
|
85
|
+
const tsconfig = await packageTsConfig(targetDir, { types: ['node'] });
|
|
85
86
|
return {
|
|
86
87
|
'package.json': serverPackageJson(pkgName, contractImport),
|
|
87
|
-
'tsconfig.json':
|
|
88
|
+
'tsconfig.json': tsconfig,
|
|
88
89
|
...basePackageFiles(),
|
|
89
90
|
'src/index.ts': serverIndexTs(contractImport),
|
|
90
91
|
'.env.example': 'PORT=4000\n',
|
|
@@ -130,7 +131,7 @@ export const serverVariant = {
|
|
|
130
131
|
],
|
|
131
132
|
async scaffold(ctx) {
|
|
132
133
|
const contractImport = ctx.contractName ?? CONTRACT_IMPORT_PLACEHOLDER;
|
|
133
|
-
const files = serverFiles(ctx.pkgName, contractImport);
|
|
134
|
+
const files = await serverFiles(ctx.pkgName, contractImport, ctx.targetDir);
|
|
134
135
|
for (const [relative, contents] of Object.entries(files)) {
|
|
135
136
|
// eslint-disable-next-line no-await-in-loop
|
|
136
137
|
await writeFileIfMissing(ctx.targetDir, relative, contents);
|