create-qpq-app 0.1.5 → 0.1.6
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/lib/commonjs/steps/008_transpileToJavaScript.js +108 -5
- package/lib/commonjs/steps/008_transpileToJavaScript.js.map +1 -1
- package/lib/esm/steps/008_transpileToJavaScript.js +104 -5
- package/lib/esm/steps/008_transpileToJavaScript.js.map +1 -1
- package/package.json +6 -4
- package/template/apps/todo/packages/service-utils/src/defineTodoService.ts +15 -5
- package/template/tsconfig.base.json +4 -0
|
@@ -8,17 +8,120 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
exports.transpileToJavaScript = void 0;
|
|
16
|
+
const fs_1 = __importDefault(require("fs"));
|
|
17
|
+
const path_1 = __importDefault(require("path"));
|
|
18
|
+
const files_1 = require("../lib/files");
|
|
13
19
|
const types_1 = require("../types");
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
20
|
+
// Convert the scaffolded TypeScript app to JavaScript: per-file type
|
|
21
|
+
// stripping (JSX preserved, comments kept), then remove the TypeScript
|
|
22
|
+
// build plumbing the app no longer needs.
|
|
23
|
+
//
|
|
24
|
+
// The qpq toolchain runs the result as-is: the CLI's ts-node require hook
|
|
25
|
+
// compiles the app's ESM-syntax .js at load time (allowJs, added below), and
|
|
26
|
+
// rspack bundles .js/.jsx natively.
|
|
17
27
|
exports.transpileToJavaScript = {
|
|
18
28
|
name: 'Converting to JavaScript',
|
|
19
29
|
shouldRun: (answers) => answers.language === types_1.AppLanguage.javascript,
|
|
20
|
-
run: () => __awaiter(void 0,
|
|
21
|
-
|
|
30
|
+
run: (_a) => __awaiter(void 0, [_a], void 0, function* ({ targetDirectory }) {
|
|
31
|
+
var _b, _c, _d;
|
|
32
|
+
// Lazy so TypeScript scaffolds never load the compiler.
|
|
33
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
34
|
+
const ts = require('typescript');
|
|
35
|
+
const prettier = require('prettier');
|
|
36
|
+
/* eslint-enable @typescript-eslint/no-require-imports */
|
|
37
|
+
// The transpiler re-prints files in its own style; format the output with
|
|
38
|
+
// the app's own prettier settings so generated code matches the repo.
|
|
39
|
+
const prettierRcPath = path_1.default.join(targetDirectory, '.prettierrc');
|
|
40
|
+
const prettierOptions = fs_1.default.existsSync(prettierRcPath) ? (0, files_1.readJsonFile)(prettierRcPath) : {};
|
|
41
|
+
const compilerOptions = {
|
|
42
|
+
target: ts.ScriptTarget.ESNext,
|
|
43
|
+
module: ts.ModuleKind.ESNext, // keep import/export statements as written
|
|
44
|
+
jsx: ts.JsxEmit.Preserve,
|
|
45
|
+
removeComments: false,
|
|
46
|
+
};
|
|
47
|
+
let converted = 0;
|
|
48
|
+
for (const filePath of (0, files_1.listFilesRecursive)(targetDirectory)) {
|
|
49
|
+
if (filePath.endsWith('.d.ts')) {
|
|
50
|
+
fs_1.default.rmSync(filePath);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const isTsx = filePath.endsWith('.tsx');
|
|
54
|
+
if (!isTsx && !filePath.endsWith('.ts')) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const source = fs_1.default.readFileSync(filePath, 'utf8');
|
|
58
|
+
const { outputText } = ts.transpileModule(source, { compilerOptions, fileName: filePath });
|
|
59
|
+
// Type-only statements leave blank gaps behind — collapse runs of them.
|
|
60
|
+
const collapsed = outputText.replace(/\n{3,}/g, '\n\n');
|
|
61
|
+
const outputPath = filePath.replace(/\.tsx?$/, isTsx ? '.jsx' : '.js');
|
|
62
|
+
const output = yield prettier.format(collapsed, Object.assign(Object.assign({}, prettierOptions), { filepath: outputPath }));
|
|
63
|
+
fs_1.default.writeFileSync(outputPath, output);
|
|
64
|
+
fs_1.default.rmSync(filePath);
|
|
65
|
+
converted += 1;
|
|
66
|
+
}
|
|
67
|
+
// TypeScript build plumbing: tsconfigs, the ambient types/ dir, and the
|
|
68
|
+
// per-package tsc scripts all go. Lib packages no longer build — their
|
|
69
|
+
// package.json main points straight at src.
|
|
70
|
+
let libsRepointed = 0;
|
|
71
|
+
for (const filePath of (0, files_1.listFilesRecursive)(targetDirectory)) {
|
|
72
|
+
const baseName = path_1.default.basename(filePath);
|
|
73
|
+
if (baseName.startsWith('tsconfig') && baseName.endsWith('.json') && filePath !== path_1.default.join(targetDirectory, 'tsconfig.json')) {
|
|
74
|
+
fs_1.default.rmSync(filePath);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (baseName === 'package.json' && filePath !== path_1.default.join(targetDirectory, 'package.json')) {
|
|
78
|
+
const packageJson = (0, files_1.readJsonFile)(filePath);
|
|
79
|
+
let changed = false;
|
|
80
|
+
if ((_b = packageJson.scripts) === null || _b === void 0 ? void 0 : _b['validate-ts']) {
|
|
81
|
+
delete packageJson.scripts['validate-ts'];
|
|
82
|
+
changed = true;
|
|
83
|
+
}
|
|
84
|
+
// Lib packages (identified by their tsc build) get served from
|
|
85
|
+
// source. A tsc build with an unexpected main means the template's
|
|
86
|
+
// conventions moved — fail loudly rather than scaffold a broken app.
|
|
87
|
+
if (((_c = packageJson.scripts) === null || _c === void 0 ? void 0 : _c.build) === 'tsc -b') {
|
|
88
|
+
if (packageJson.main !== './dist/src/index.js') {
|
|
89
|
+
throw new Error(`${filePath} has a tsc build but main is "${packageJson.main}" (expected "./dist/src/index.js") — update transpileToJavaScript for the new template convention.`);
|
|
90
|
+
}
|
|
91
|
+
packageJson.main = './src/index.js';
|
|
92
|
+
delete packageJson.typings;
|
|
93
|
+
delete packageJson.scripts.build;
|
|
94
|
+
packageJson.exports = { '.': { default: './src/index.js' } };
|
|
95
|
+
packageJson.files = ['src'];
|
|
96
|
+
changed = true;
|
|
97
|
+
libsRepointed += 1;
|
|
98
|
+
}
|
|
99
|
+
if (changed) {
|
|
100
|
+
(0, files_1.writeJsonFile)(filePath, packageJson);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (converted === 0 || libsRepointed === 0) {
|
|
105
|
+
throw new Error(`JavaScript conversion looks wrong: ${converted} files transpiled, ${libsRepointed} lib packages repointed — has the template changed shape?`);
|
|
106
|
+
}
|
|
107
|
+
// The ROOT tsconfig.json stays — the qpq CLI's ts-node require hook reads
|
|
108
|
+
// its ts-node block, and allowJs makes that hook compile the app's
|
|
109
|
+
// ESM-syntax .js files (imports, __dirname) at load time.
|
|
110
|
+
fs_1.default.rmSync(path_1.default.join(targetDirectory, 'types'), { recursive: true, force: true });
|
|
111
|
+
fs_1.default.rmSync(path_1.default.join(targetDirectory, 'tsconfig.base.json'), { force: true });
|
|
112
|
+
const rootTsconfigPath = path_1.default.join(targetDirectory, 'tsconfig.json');
|
|
113
|
+
const rootTsconfig = (0, files_1.readJsonFile)(rootTsconfigPath);
|
|
114
|
+
rootTsconfig['ts-node'].compilerOptions.allowJs = true;
|
|
115
|
+
// Scope the hook to this repo — allowJs must never recompile quidproquo
|
|
116
|
+
// libs living outside node_modules (file:-linked dev setups).
|
|
117
|
+
rootTsconfig['ts-node'].scope = true;
|
|
118
|
+
rootTsconfig['ts-node'].scopeDir = '.';
|
|
119
|
+
(0, files_1.writeJsonFile)(rootTsconfigPath, rootTsconfig);
|
|
120
|
+
const rootPackageJsonPath = path_1.default.join(targetDirectory, 'package.json');
|
|
121
|
+
const rootPackageJson = (0, files_1.readJsonFile)(rootPackageJsonPath);
|
|
122
|
+
(_d = rootPackageJson.scripts) === null || _d === void 0 ? true : delete _d['validate-ts'];
|
|
123
|
+
(0, files_1.writeJsonFile)(rootPackageJsonPath, rootPackageJson);
|
|
124
|
+
console.log(` Converted ${converted} files to JavaScript.`);
|
|
22
125
|
}),
|
|
23
126
|
};
|
|
24
127
|
//# sourceMappingURL=008_transpileToJavaScript.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"008_transpileToJavaScript.js","sourceRoot":"","sources":["../../../src/steps/008_transpileToJavaScript.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oCAAyD;AAEzD,2EAA2E;AAC3E,0EAA0E;AAC1E,wDAAwD;AAC3C,QAAA,qBAAqB,GAAqB;IACrD,IAAI,EAAE,0BAA0B;IAEhC,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,KAAK,mBAAW,CAAC,UAAU;IAEnE,GAAG,EAAE,GAAS,EAAE;QACd,OAAO,CAAC,GAAG,CAAC,2EAA2E,CAAC,CAAC;IAC3F,CAAC,CAAA;CACF,CAAC","sourcesContent":["import { AppLanguage, CreateQpqAppStep } from '../types';\n\n// Placeholder for the JavaScript flavour — a later pass will transpile the\n// scaffolded TypeScript sources here. For now it's an honest no-op so the\n// language answer already threads through the pipeline.\nexport const transpileToJavaScript: CreateQpqAppStep = {\n name: 'Converting to JavaScript',\n\n shouldRun: (answers) => answers.language === AppLanguage.javascript,\n\n run: async () => {\n console.log(' JavaScript output is not available yet — generating TypeScript for now.');\n },\n};\n"]}
|
|
1
|
+
{"version":3,"file":"008_transpileToJavaScript.js","sourceRoot":"","sources":["../../../src/steps/008_transpileToJavaScript.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AAExB,wCAA+E;AAC/E,oCAAyD;AAEzD,qEAAqE;AACrE,uEAAuE;AACvE,0CAA0C;AAC1C,EAAE;AACF,0EAA0E;AAC1E,6EAA6E;AAC7E,oCAAoC;AACvB,QAAA,qBAAqB,GAAqB;IACrD,IAAI,EAAE,0BAA0B;IAEhC,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,KAAK,mBAAW,CAAC,UAAU;IAEnE,GAAG,EAAE,KAA4B,EAAE,4CAAvB,EAAE,eAAe,EAAE;;QAC7B,wDAAwD;QACxD,0DAA0D;QAC1D,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAgC,CAAC;QAChE,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAA8B,CAAC;QAClE,yDAAyD;QAEzD,0EAA0E;QAC1E,sEAAsE;QACtE,MAAM,cAAc,GAAG,cAAI,CAAC,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;QACjE,MAAM,eAAe,GAAG,YAAE,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAA,oBAAY,EAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAE1F,MAAM,eAAe,GAAyC;YAC5D,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM;YAC9B,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,2CAA2C;YACzE,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ;YACxB,cAAc,EAAE,KAAK;SACtB,CAAC;QAEF,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,KAAK,MAAM,QAAQ,IAAI,IAAA,0BAAkB,EAAC,eAAe,CAAC,EAAE,CAAC;YAC3D,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/B,YAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACpB,SAAS;YACX,CAAC;YAED,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACxC,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxC,SAAS;YACX,CAAC;YAED,MAAM,MAAM,GAAG,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACjD,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;YAE3F,wEAAwE;YACxE,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAExD,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACvE,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,SAAS,kCAAO,eAAe,KAAE,QAAQ,EAAE,UAAU,IAAG,CAAC;YAE9F,YAAE,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YACrC,YAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACpB,SAAS,IAAI,CAAC,CAAC;QACjB,CAAC;QAED,wEAAwE;QACxE,uEAAuE;QACvE,4CAA4C;QAC5C,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,KAAK,MAAM,QAAQ,IAAI,IAAA,0BAAkB,EAAC,eAAe,CAAC,EAAE,CAAC;YAC3D,MAAM,QAAQ,GAAG,cAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAEzC,IAAI,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,KAAK,cAAI,CAAC,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,EAAE,CAAC;gBAC9H,YAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACpB,SAAS;YACX,CAAC;YAED,IAAI,QAAQ,KAAK,cAAc,IAAI,QAAQ,KAAK,cAAI,CAAC,IAAI,CAAC,eAAe,EAAE,cAAc,CAAC,EAAE,CAAC;gBAC3F,MAAM,WAAW,GAAG,IAAA,oBAAY,EAAC,QAAQ,CAAC,CAAC;gBAC3C,IAAI,OAAO,GAAG,KAAK,CAAC;gBAEpB,IAAI,MAAA,WAAW,CAAC,OAAO,0CAAG,aAAa,CAAC,EAAE,CAAC;oBACzC,OAAO,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;oBAC1C,OAAO,GAAG,IAAI,CAAC;gBACjB,CAAC;gBAED,+DAA+D;gBAC/D,mEAAmE;gBACnE,qEAAqE;gBACrE,IAAI,CAAA,MAAA,WAAW,CAAC,OAAO,0CAAE,KAAK,MAAK,QAAQ,EAAE,CAAC;oBAC5C,IAAI,WAAW,CAAC,IAAI,KAAK,qBAAqB,EAAE,CAAC;wBAC/C,MAAM,IAAI,KAAK,CACb,GAAG,QAAQ,iCAAiC,WAAW,CAAC,IAAI,oGAAoG,CACjK,CAAC;oBACJ,CAAC;oBAED,WAAW,CAAC,IAAI,GAAG,gBAAgB,CAAC;oBACpC,OAAO,WAAW,CAAC,OAAO,CAAC;oBAC3B,OAAO,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC;oBACjC,WAAW,CAAC,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,EAAE,CAAC;oBAC7D,WAAW,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC;oBAC5B,OAAO,GAAG,IAAI,CAAC;oBACf,aAAa,IAAI,CAAC,CAAC;gBACrB,CAAC;gBAED,IAAI,OAAO,EAAE,CAAC;oBACZ,IAAA,qBAAa,EAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;gBACvC,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,SAAS,KAAK,CAAC,IAAI,aAAa,KAAK,CAAC,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CACb,sCAAsC,SAAS,sBAAsB,aAAa,2DAA2D,CAC9I,CAAC;QACJ,CAAC;QAED,0EAA0E;QAC1E,mEAAmE;QACnE,0DAA0D;QAC1D,YAAE,CAAC,MAAM,CAAC,cAAI,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACjF,YAAE,CAAC,MAAM,CAAC,cAAI,CAAC,IAAI,CAAC,eAAe,EAAE,oBAAoB,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAE7E,MAAM,gBAAgB,GAAG,cAAI,CAAC,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;QACrE,MAAM,YAAY,GAAG,IAAA,oBAAY,EAAC,gBAAgB,CAAC,CAAC;QACpD,YAAY,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,OAAO,GAAG,IAAI,CAAC;QACvD,wEAAwE;QACxE,8DAA8D;QAC9D,YAAY,CAAC,SAAS,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC;QACrC,YAAY,CAAC,SAAS,CAAC,CAAC,QAAQ,GAAG,GAAG,CAAC;QACvC,IAAA,qBAAa,EAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC;QAE9C,MAAM,mBAAmB,GAAG,cAAI,CAAC,IAAI,CAAC,eAAe,EAAE,cAAc,CAAC,CAAC;QACvE,MAAM,eAAe,GAAG,IAAA,oBAAY,EAAC,mBAAmB,CAAC,CAAC;QACnD,MAAA,eAAe,CAAC,OAAO,+CAAG,aAAa,CAAC,CAAC;QAChD,IAAA,qBAAa,EAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC;QAEpD,OAAO,CAAC,GAAG,CAAC,eAAe,SAAS,uBAAuB,CAAC,CAAC;IAC/D,CAAC,CAAA;CACF,CAAC","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { listFilesRecursive, readJsonFile, writeJsonFile } from '../lib/files';\nimport { AppLanguage, CreateQpqAppStep } from '../types';\n\n// Convert the scaffolded TypeScript app to JavaScript: per-file type\n// stripping (JSX preserved, comments kept), then remove the TypeScript\n// build plumbing the app no longer needs.\n//\n// The qpq toolchain runs the result as-is: the CLI's ts-node require hook\n// compiles the app's ESM-syntax .js at load time (allowJs, added below), and\n// rspack bundles .js/.jsx natively.\nexport const transpileToJavaScript: CreateQpqAppStep = {\n name: 'Converting to JavaScript',\n\n shouldRun: (answers) => answers.language === AppLanguage.javascript,\n\n run: async ({ targetDirectory }) => {\n // Lazy so TypeScript scaffolds never load the compiler.\n /* eslint-disable @typescript-eslint/no-require-imports */\n const ts = require('typescript') as typeof import('typescript');\n const prettier = require('prettier') as typeof import('prettier');\n /* eslint-enable @typescript-eslint/no-require-imports */\n\n // The transpiler re-prints files in its own style; format the output with\n // the app's own prettier settings so generated code matches the repo.\n const prettierRcPath = path.join(targetDirectory, '.prettierrc');\n const prettierOptions = fs.existsSync(prettierRcPath) ? readJsonFile(prettierRcPath) : {};\n\n const compilerOptions: import('typescript').CompilerOptions = {\n target: ts.ScriptTarget.ESNext,\n module: ts.ModuleKind.ESNext, // keep import/export statements as written\n jsx: ts.JsxEmit.Preserve,\n removeComments: false,\n };\n\n let converted = 0;\n for (const filePath of listFilesRecursive(targetDirectory)) {\n if (filePath.endsWith('.d.ts')) {\n fs.rmSync(filePath);\n continue;\n }\n\n const isTsx = filePath.endsWith('.tsx');\n if (!isTsx && !filePath.endsWith('.ts')) {\n continue;\n }\n\n const source = fs.readFileSync(filePath, 'utf8');\n const { outputText } = ts.transpileModule(source, { compilerOptions, fileName: filePath });\n\n // Type-only statements leave blank gaps behind — collapse runs of them.\n const collapsed = outputText.replace(/\\n{3,}/g, '\\n\\n');\n\n const outputPath = filePath.replace(/\\.tsx?$/, isTsx ? '.jsx' : '.js');\n const output = await prettier.format(collapsed, { ...prettierOptions, filepath: outputPath });\n\n fs.writeFileSync(outputPath, output);\n fs.rmSync(filePath);\n converted += 1;\n }\n\n // TypeScript build plumbing: tsconfigs, the ambient types/ dir, and the\n // per-package tsc scripts all go. Lib packages no longer build — their\n // package.json main points straight at src.\n let libsRepointed = 0;\n for (const filePath of listFilesRecursive(targetDirectory)) {\n const baseName = path.basename(filePath);\n\n if (baseName.startsWith('tsconfig') && baseName.endsWith('.json') && filePath !== path.join(targetDirectory, 'tsconfig.json')) {\n fs.rmSync(filePath);\n continue;\n }\n\n if (baseName === 'package.json' && filePath !== path.join(targetDirectory, 'package.json')) {\n const packageJson = readJsonFile(filePath);\n let changed = false;\n\n if (packageJson.scripts?.['validate-ts']) {\n delete packageJson.scripts['validate-ts'];\n changed = true;\n }\n\n // Lib packages (identified by their tsc build) get served from\n // source. A tsc build with an unexpected main means the template's\n // conventions moved — fail loudly rather than scaffold a broken app.\n if (packageJson.scripts?.build === 'tsc -b') {\n if (packageJson.main !== './dist/src/index.js') {\n throw new Error(\n `${filePath} has a tsc build but main is \"${packageJson.main}\" (expected \"./dist/src/index.js\") — update transpileToJavaScript for the new template convention.`,\n );\n }\n\n packageJson.main = './src/index.js';\n delete packageJson.typings;\n delete packageJson.scripts.build;\n packageJson.exports = { '.': { default: './src/index.js' } };\n packageJson.files = ['src'];\n changed = true;\n libsRepointed += 1;\n }\n\n if (changed) {\n writeJsonFile(filePath, packageJson);\n }\n }\n }\n\n if (converted === 0 || libsRepointed === 0) {\n throw new Error(\n `JavaScript conversion looks wrong: ${converted} files transpiled, ${libsRepointed} lib packages repointed — has the template changed shape?`,\n );\n }\n\n // The ROOT tsconfig.json stays — the qpq CLI's ts-node require hook reads\n // its ts-node block, and allowJs makes that hook compile the app's\n // ESM-syntax .js files (imports, __dirname) at load time.\n fs.rmSync(path.join(targetDirectory, 'types'), { recursive: true, force: true });\n fs.rmSync(path.join(targetDirectory, 'tsconfig.base.json'), { force: true });\n\n const rootTsconfigPath = path.join(targetDirectory, 'tsconfig.json');\n const rootTsconfig = readJsonFile(rootTsconfigPath);\n rootTsconfig['ts-node'].compilerOptions.allowJs = true;\n // Scope the hook to this repo — allowJs must never recompile quidproquo\n // libs living outside node_modules (file:-linked dev setups).\n rootTsconfig['ts-node'].scope = true;\n rootTsconfig['ts-node'].scopeDir = '.';\n writeJsonFile(rootTsconfigPath, rootTsconfig);\n\n const rootPackageJsonPath = path.join(targetDirectory, 'package.json');\n const rootPackageJson = readJsonFile(rootPackageJsonPath);\n delete rootPackageJson.scripts?.['validate-ts'];\n writeJsonFile(rootPackageJsonPath, rootPackageJson);\n\n console.log(` Converted ${converted} files to JavaScript.`);\n },\n};\n"]}
|
|
@@ -1,12 +1,111 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { listFilesRecursive, readJsonFile, writeJsonFile } from '../lib/files';
|
|
1
4
|
import { AppLanguage } from '../types';
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
+
// Convert the scaffolded TypeScript app to JavaScript: per-file type
|
|
6
|
+
// stripping (JSX preserved, comments kept), then remove the TypeScript
|
|
7
|
+
// build plumbing the app no longer needs.
|
|
8
|
+
//
|
|
9
|
+
// The qpq toolchain runs the result as-is: the CLI's ts-node require hook
|
|
10
|
+
// compiles the app's ESM-syntax .js at load time (allowJs, added below), and
|
|
11
|
+
// rspack bundles .js/.jsx natively.
|
|
5
12
|
export const transpileToJavaScript = {
|
|
6
13
|
name: 'Converting to JavaScript',
|
|
7
14
|
shouldRun: (answers) => answers.language === AppLanguage.javascript,
|
|
8
|
-
run: async () => {
|
|
9
|
-
|
|
15
|
+
run: async ({ targetDirectory }) => {
|
|
16
|
+
// Lazy so TypeScript scaffolds never load the compiler.
|
|
17
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
18
|
+
const ts = require('typescript');
|
|
19
|
+
const prettier = require('prettier');
|
|
20
|
+
/* eslint-enable @typescript-eslint/no-require-imports */
|
|
21
|
+
// The transpiler re-prints files in its own style; format the output with
|
|
22
|
+
// the app's own prettier settings so generated code matches the repo.
|
|
23
|
+
const prettierRcPath = path.join(targetDirectory, '.prettierrc');
|
|
24
|
+
const prettierOptions = fs.existsSync(prettierRcPath) ? readJsonFile(prettierRcPath) : {};
|
|
25
|
+
const compilerOptions = {
|
|
26
|
+
target: ts.ScriptTarget.ESNext,
|
|
27
|
+
module: ts.ModuleKind.ESNext, // keep import/export statements as written
|
|
28
|
+
jsx: ts.JsxEmit.Preserve,
|
|
29
|
+
removeComments: false,
|
|
30
|
+
};
|
|
31
|
+
let converted = 0;
|
|
32
|
+
for (const filePath of listFilesRecursive(targetDirectory)) {
|
|
33
|
+
if (filePath.endsWith('.d.ts')) {
|
|
34
|
+
fs.rmSync(filePath);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const isTsx = filePath.endsWith('.tsx');
|
|
38
|
+
if (!isTsx && !filePath.endsWith('.ts')) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const source = fs.readFileSync(filePath, 'utf8');
|
|
42
|
+
const { outputText } = ts.transpileModule(source, { compilerOptions, fileName: filePath });
|
|
43
|
+
// Type-only statements leave blank gaps behind — collapse runs of them.
|
|
44
|
+
const collapsed = outputText.replace(/\n{3,}/g, '\n\n');
|
|
45
|
+
const outputPath = filePath.replace(/\.tsx?$/, isTsx ? '.jsx' : '.js');
|
|
46
|
+
const output = await prettier.format(collapsed, { ...prettierOptions, filepath: outputPath });
|
|
47
|
+
fs.writeFileSync(outputPath, output);
|
|
48
|
+
fs.rmSync(filePath);
|
|
49
|
+
converted += 1;
|
|
50
|
+
}
|
|
51
|
+
// TypeScript build plumbing: tsconfigs, the ambient types/ dir, and the
|
|
52
|
+
// per-package tsc scripts all go. Lib packages no longer build — their
|
|
53
|
+
// package.json main points straight at src.
|
|
54
|
+
let libsRepointed = 0;
|
|
55
|
+
for (const filePath of listFilesRecursive(targetDirectory)) {
|
|
56
|
+
const baseName = path.basename(filePath);
|
|
57
|
+
if (baseName.startsWith('tsconfig') && baseName.endsWith('.json') && filePath !== path.join(targetDirectory, 'tsconfig.json')) {
|
|
58
|
+
fs.rmSync(filePath);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (baseName === 'package.json' && filePath !== path.join(targetDirectory, 'package.json')) {
|
|
62
|
+
const packageJson = readJsonFile(filePath);
|
|
63
|
+
let changed = false;
|
|
64
|
+
if (packageJson.scripts?.['validate-ts']) {
|
|
65
|
+
delete packageJson.scripts['validate-ts'];
|
|
66
|
+
changed = true;
|
|
67
|
+
}
|
|
68
|
+
// Lib packages (identified by their tsc build) get served from
|
|
69
|
+
// source. A tsc build with an unexpected main means the template's
|
|
70
|
+
// conventions moved — fail loudly rather than scaffold a broken app.
|
|
71
|
+
if (packageJson.scripts?.build === 'tsc -b') {
|
|
72
|
+
if (packageJson.main !== './dist/src/index.js') {
|
|
73
|
+
throw new Error(`${filePath} has a tsc build but main is "${packageJson.main}" (expected "./dist/src/index.js") — update transpileToJavaScript for the new template convention.`);
|
|
74
|
+
}
|
|
75
|
+
packageJson.main = './src/index.js';
|
|
76
|
+
delete packageJson.typings;
|
|
77
|
+
delete packageJson.scripts.build;
|
|
78
|
+
packageJson.exports = { '.': { default: './src/index.js' } };
|
|
79
|
+
packageJson.files = ['src'];
|
|
80
|
+
changed = true;
|
|
81
|
+
libsRepointed += 1;
|
|
82
|
+
}
|
|
83
|
+
if (changed) {
|
|
84
|
+
writeJsonFile(filePath, packageJson);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (converted === 0 || libsRepointed === 0) {
|
|
89
|
+
throw new Error(`JavaScript conversion looks wrong: ${converted} files transpiled, ${libsRepointed} lib packages repointed — has the template changed shape?`);
|
|
90
|
+
}
|
|
91
|
+
// The ROOT tsconfig.json stays — the qpq CLI's ts-node require hook reads
|
|
92
|
+
// its ts-node block, and allowJs makes that hook compile the app's
|
|
93
|
+
// ESM-syntax .js files (imports, __dirname) at load time.
|
|
94
|
+
fs.rmSync(path.join(targetDirectory, 'types'), { recursive: true, force: true });
|
|
95
|
+
fs.rmSync(path.join(targetDirectory, 'tsconfig.base.json'), { force: true });
|
|
96
|
+
const rootTsconfigPath = path.join(targetDirectory, 'tsconfig.json');
|
|
97
|
+
const rootTsconfig = readJsonFile(rootTsconfigPath);
|
|
98
|
+
rootTsconfig['ts-node'].compilerOptions.allowJs = true;
|
|
99
|
+
// Scope the hook to this repo — allowJs must never recompile quidproquo
|
|
100
|
+
// libs living outside node_modules (file:-linked dev setups).
|
|
101
|
+
rootTsconfig['ts-node'].scope = true;
|
|
102
|
+
rootTsconfig['ts-node'].scopeDir = '.';
|
|
103
|
+
writeJsonFile(rootTsconfigPath, rootTsconfig);
|
|
104
|
+
const rootPackageJsonPath = path.join(targetDirectory, 'package.json');
|
|
105
|
+
const rootPackageJson = readJsonFile(rootPackageJsonPath);
|
|
106
|
+
delete rootPackageJson.scripts?.['validate-ts'];
|
|
107
|
+
writeJsonFile(rootPackageJsonPath, rootPackageJson);
|
|
108
|
+
console.log(` Converted ${converted} files to JavaScript.`);
|
|
10
109
|
},
|
|
11
110
|
};
|
|
12
111
|
//# sourceMappingURL=008_transpileToJavaScript.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"008_transpileToJavaScript.js","sourceRoot":"","sources":["../../../src/steps/008_transpileToJavaScript.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAoB,MAAM,UAAU,CAAC;AAEzD,2EAA2E;AAC3E,0EAA0E;AAC1E,wDAAwD;AACxD,MAAM,CAAC,MAAM,qBAAqB,GAAqB;IACrD,IAAI,EAAE,0BAA0B;IAEhC,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,KAAK,WAAW,CAAC,UAAU;IAEnE,GAAG,EAAE,KAAK,IAAI,EAAE;QACd,OAAO,CAAC,GAAG,CAAC,2EAA2E,CAAC,CAAC;IAC3F,CAAC;CACF,CAAC","sourcesContent":["import { AppLanguage, CreateQpqAppStep } from '../types';\n\n// Placeholder for the JavaScript flavour — a later pass will transpile the\n// scaffolded TypeScript sources here. For now it's an honest no-op so the\n// language answer already threads through the pipeline.\nexport const transpileToJavaScript: CreateQpqAppStep = {\n name: 'Converting to JavaScript',\n\n shouldRun: (answers) => answers.language === AppLanguage.javascript,\n\n run: async () => {\n console.log(' JavaScript output is not available yet — generating TypeScript for now.');\n },\n};\n"]}
|
|
1
|
+
{"version":3,"file":"008_transpileToJavaScript.js","sourceRoot":"","sources":["../../../src/steps/008_transpileToJavaScript.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { listFilesRecursive, readJsonFile, writeJsonFile } from '../lib/files';\nimport { AppLanguage, CreateQpqAppStep } from '../types';\n\n// Convert the scaffolded TypeScript app to JavaScript: per-file type\n// stripping (JSX preserved, comments kept), then remove the TypeScript\n// build plumbing the app no longer needs.\n//\n// The qpq toolchain runs the result as-is: the CLI's ts-node require hook\n// compiles the app's ESM-syntax .js at load time (allowJs, added below), and\n// rspack bundles .js/.jsx natively.\nexport const transpileToJavaScript: CreateQpqAppStep = {\n name: 'Converting to JavaScript',\n\n shouldRun: (answers) => answers.language === AppLanguage.javascript,\n\n run: async ({ targetDirectory }) => {\n // Lazy so TypeScript scaffolds never load the compiler.\n /* eslint-disable @typescript-eslint/no-require-imports */\n const ts = require('typescript') as typeof import('typescript');\n const prettier = require('prettier') as typeof import('prettier');\n /* eslint-enable @typescript-eslint/no-require-imports */\n\n // The transpiler re-prints files in its own style; format the output with\n // the app's own prettier settings so generated code matches the repo.\n const prettierRcPath = path.join(targetDirectory, '.prettierrc');\n const prettierOptions = fs.existsSync(prettierRcPath) ? readJsonFile(prettierRcPath) : {};\n\n const compilerOptions: import('typescript').CompilerOptions = {\n target: ts.ScriptTarget.ESNext,\n module: ts.ModuleKind.ESNext, // keep import/export statements as written\n jsx: ts.JsxEmit.Preserve,\n removeComments: false,\n };\n\n let converted = 0;\n for (const filePath of listFilesRecursive(targetDirectory)) {\n if (filePath.endsWith('.d.ts')) {\n fs.rmSync(filePath);\n continue;\n }\n\n const isTsx = filePath.endsWith('.tsx');\n if (!isTsx && !filePath.endsWith('.ts')) {\n continue;\n }\n\n const source = fs.readFileSync(filePath, 'utf8');\n const { outputText } = ts.transpileModule(source, { compilerOptions, fileName: filePath });\n\n // Type-only statements leave blank gaps behind — collapse runs of them.\n const collapsed = outputText.replace(/\\n{3,}/g, '\\n\\n');\n\n const outputPath = filePath.replace(/\\.tsx?$/, isTsx ? '.jsx' : '.js');\n const output = await prettier.format(collapsed, { ...prettierOptions, filepath: outputPath });\n\n fs.writeFileSync(outputPath, output);\n fs.rmSync(filePath);\n converted += 1;\n }\n\n // TypeScript build plumbing: tsconfigs, the ambient types/ dir, and the\n // per-package tsc scripts all go. Lib packages no longer build — their\n // package.json main points straight at src.\n let libsRepointed = 0;\n for (const filePath of listFilesRecursive(targetDirectory)) {\n const baseName = path.basename(filePath);\n\n if (baseName.startsWith('tsconfig') && baseName.endsWith('.json') && filePath !== path.join(targetDirectory, 'tsconfig.json')) {\n fs.rmSync(filePath);\n continue;\n }\n\n if (baseName === 'package.json' && filePath !== path.join(targetDirectory, 'package.json')) {\n const packageJson = readJsonFile(filePath);\n let changed = false;\n\n if (packageJson.scripts?.['validate-ts']) {\n delete packageJson.scripts['validate-ts'];\n changed = true;\n }\n\n // Lib packages (identified by their tsc build) get served from\n // source. A tsc build with an unexpected main means the template's\n // conventions moved — fail loudly rather than scaffold a broken app.\n if (packageJson.scripts?.build === 'tsc -b') {\n if (packageJson.main !== './dist/src/index.js') {\n throw new Error(\n `${filePath} has a tsc build but main is \"${packageJson.main}\" (expected \"./dist/src/index.js\") — update transpileToJavaScript for the new template convention.`,\n );\n }\n\n packageJson.main = './src/index.js';\n delete packageJson.typings;\n delete packageJson.scripts.build;\n packageJson.exports = { '.': { default: './src/index.js' } };\n packageJson.files = ['src'];\n changed = true;\n libsRepointed += 1;\n }\n\n if (changed) {\n writeJsonFile(filePath, packageJson);\n }\n }\n }\n\n if (converted === 0 || libsRepointed === 0) {\n throw new Error(\n `JavaScript conversion looks wrong: ${converted} files transpiled, ${libsRepointed} lib packages repointed — has the template changed shape?`,\n );\n }\n\n // The ROOT tsconfig.json stays — the qpq CLI's ts-node require hook reads\n // its ts-node block, and allowJs makes that hook compile the app's\n // ESM-syntax .js files (imports, __dirname) at load time.\n fs.rmSync(path.join(targetDirectory, 'types'), { recursive: true, force: true });\n fs.rmSync(path.join(targetDirectory, 'tsconfig.base.json'), { force: true });\n\n const rootTsconfigPath = path.join(targetDirectory, 'tsconfig.json');\n const rootTsconfig = readJsonFile(rootTsconfigPath);\n rootTsconfig['ts-node'].compilerOptions.allowJs = true;\n // Scope the hook to this repo — allowJs must never recompile quidproquo\n // libs living outside node_modules (file:-linked dev setups).\n rootTsconfig['ts-node'].scope = true;\n rootTsconfig['ts-node'].scopeDir = '.';\n writeJsonFile(rootTsconfigPath, rootTsconfig);\n\n const rootPackageJsonPath = path.join(targetDirectory, 'package.json');\n const rootPackageJson = readJsonFile(rootPackageJsonPath);\n delete rootPackageJson.scripts?.['validate-ts'];\n writeJsonFile(rootPackageJsonPath, rootPackageJson);\n\n console.log(` Converted ${converted} files to JavaScript.`);\n },\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-qpq-app",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Scaffold a new quidproquo app — npx create-qpq-app my-app",
|
|
5
5
|
"main": "./lib/commonjs/index.js",
|
|
6
6
|
"module": "./lib/esm/index.js",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"build:esm": "tsc -p tsconfig.esm.json",
|
|
23
23
|
"build:bin-perms": "node -e \"require('fs').chmodSync('lib/commonjs/bin/createQpqApp.js', 0o755)\"",
|
|
24
24
|
"snapshot-template": "node ./scripts/snapshotTemplate.mjs",
|
|
25
|
+
"smoke-test": "node ./scripts/smokeTest.mjs",
|
|
25
26
|
"prepack": "npm run snapshot-template",
|
|
26
27
|
"lint": "npx eslint .",
|
|
27
28
|
"lint:fix": "npx eslint . --fix",
|
|
@@ -44,12 +45,13 @@
|
|
|
44
45
|
},
|
|
45
46
|
"homepage": "https://github.com/joe-coady/quidproquo#readme",
|
|
46
47
|
"dependencies": {
|
|
47
|
-
"@inquirer/prompts": "^8.5.2"
|
|
48
|
+
"@inquirer/prompts": "^8.5.2",
|
|
49
|
+
"prettier": "^3.2.5",
|
|
50
|
+
"typescript": "^5.8.2"
|
|
48
51
|
},
|
|
49
52
|
"devDependencies": {
|
|
50
53
|
"@types/node": "^22.13.13",
|
|
51
|
-
"quidproquo-tsconfig": "0.1.
|
|
52
|
-
"typescript": "^5.8.2"
|
|
54
|
+
"quidproquo-tsconfig": "0.1.6"
|
|
53
55
|
},
|
|
54
56
|
"bin": {
|
|
55
57
|
"create-qpq-app": "./lib/commonjs/bin/createQpqApp.js"
|
|
@@ -30,6 +30,20 @@ import {
|
|
|
30
30
|
|
|
31
31
|
const modulePrefix = 'todo';
|
|
32
32
|
|
|
33
|
+
// The deployed version tag — git sha when available, so a fresh checkout
|
|
34
|
+
// (or a scaffold that skipped git init) still loads.
|
|
35
|
+
const getVersionTag = (): string => {
|
|
36
|
+
try {
|
|
37
|
+
return execSync('git rev-parse --short HEAD', {
|
|
38
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
39
|
+
})
|
|
40
|
+
.toString()
|
|
41
|
+
.trim();
|
|
42
|
+
} catch {
|
|
43
|
+
return 'no-git';
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
33
47
|
// The shared config every todo service starts from — app identity, dns,
|
|
34
48
|
// auth, admin, api and caching. Each service's infrastructure.ts layers its
|
|
35
49
|
// own resources on top of this.
|
|
@@ -50,11 +64,7 @@ export const defineTodoService = (
|
|
|
50
64
|
process.env.ACTOR_NAME
|
|
51
65
|
),
|
|
52
66
|
|
|
53
|
-
defineApplicationVersion(
|
|
54
|
-
`${execSync('git rev-parse --short HEAD')
|
|
55
|
-
.toString()
|
|
56
|
-
.trim()}-${new Date().toISOString()}`
|
|
57
|
-
),
|
|
67
|
+
defineApplicationVersion(`${getVersionTag()}-${new Date().toISOString()}`),
|
|
58
68
|
|
|
59
69
|
defineDns(domainName),
|
|
60
70
|
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
"compilerOptions": {
|
|
5
5
|
"jsx": "react-jsx",
|
|
6
6
|
"module": "commonjs",
|
|
7
|
+
// This repo is the create-qpq-app template; its JavaScript flavour is
|
|
8
|
+
// produced by per-file transpilation, which only supports
|
|
9
|
+
// isolatedModules-compatible TypeScript. Keep this on.
|
|
10
|
+
"isolatedModules": true,
|
|
7
11
|
"rootDir": ".",
|
|
8
12
|
"declaration": false,
|
|
9
13
|
"emitDecoratorMetadata": true,
|