@citolab/tspci 2.8.4 → 2.9.9
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/CHANGELOG.md +83 -0
- package/package.json +6 -5
- package/preset/base/package.json +2 -1
- package/preset/javascript/src/index.js +1 -0
- package/preset/preact/src/index.tsx +16 -0
- package/preset/typescript/src/index.ts +1 -0
- package/public/index.html +798 -323
- package/scripts/test-init-local.sh +49 -1
- package/scripts/test-init-matrix.sh +49 -0
- package/src/cli.js +83 -35
|
@@ -46,6 +46,19 @@ node -e "
|
|
|
46
46
|
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8');
|
|
47
47
|
" "${TARGET_DIR}/package.json" "file:${PACK_PATH}"
|
|
48
48
|
|
|
49
|
+
echo "Verifying generated package.json contains required dev dependencies..."
|
|
50
|
+
node -e "
|
|
51
|
+
const fs = require('fs');
|
|
52
|
+
const pkgPath = process.argv[1];
|
|
53
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
54
|
+
const hasTslib = Boolean(pkg.devDependencies && pkg.devDependencies.tslib);
|
|
55
|
+
if (!hasTslib) {
|
|
56
|
+
console.error('ERROR: expected devDependency \"tslib\" in generated package.json');
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
console.log('OK: required devDependency \"tslib\" is present');
|
|
60
|
+
" "${TARGET_DIR}/package.json"
|
|
61
|
+
|
|
49
62
|
echo ""
|
|
50
63
|
echo "Generated files:"
|
|
51
64
|
find "${TARGET_DIR}" -maxdepth 3 -type f | sort
|
|
@@ -68,7 +81,6 @@ echo ""
|
|
|
68
81
|
echo "Installing dependencies in generated project..."
|
|
69
82
|
(cd "${TARGET_DIR}" && npm install --cache "${NPM_CACHE_DIR}" --workspaces=false)
|
|
70
83
|
|
|
71
|
-
echo ""
|
|
72
84
|
echo "Running production build smoke test..."
|
|
73
85
|
node -e "
|
|
74
86
|
const { spawnSync } = require('child_process');
|
|
@@ -76,6 +88,7 @@ node -e "
|
|
|
76
88
|
const result = spawnSync('npm', ['run', 'prod'], {
|
|
77
89
|
cwd: targetDir,
|
|
78
90
|
stdio: 'inherit',
|
|
91
|
+
shell: process.platform === 'win32',
|
|
79
92
|
timeout: 180000
|
|
80
93
|
});
|
|
81
94
|
if (result.error) {
|
|
@@ -99,6 +112,41 @@ if [[ ! -f "${DIST_TYPES}" ]]; then
|
|
|
99
112
|
exit 1
|
|
100
113
|
fi
|
|
101
114
|
|
|
115
|
+
echo "Running dev startup smoke test (timeout 20s)..."
|
|
116
|
+
node -e "
|
|
117
|
+
const { spawn } = require('child_process');
|
|
118
|
+
const targetDir = process.argv[1];
|
|
119
|
+
const child = spawn('npm', ['run', 'dev'], {
|
|
120
|
+
cwd: targetDir,
|
|
121
|
+
shell: process.platform === 'win32'
|
|
122
|
+
});
|
|
123
|
+
let logs = '';
|
|
124
|
+
const onData = (chunk) => {
|
|
125
|
+
logs += chunk.toString();
|
|
126
|
+
};
|
|
127
|
+
child.stdout.on('data', onData);
|
|
128
|
+
child.stderr.on('data', onData);
|
|
129
|
+
child.on('error', (err) => {
|
|
130
|
+
console.error(err.message);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
});
|
|
133
|
+
setTimeout(() => {
|
|
134
|
+
child.kill('SIGTERM');
|
|
135
|
+
const hasReady = logs.includes('Ready for changes');
|
|
136
|
+
const missingTslib = logs.includes(\"Could not find module 'tslib'\");
|
|
137
|
+
if (missingTslib) {
|
|
138
|
+
console.error('ERROR: dev startup failed due to missing tslib');
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
if (!hasReady) {
|
|
142
|
+
console.error('ERROR: dev startup did not reach \"Ready for changes\" within timeout');
|
|
143
|
+
console.error(logs);
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
process.exit(0);
|
|
147
|
+
}, 20000);
|
|
148
|
+
" "${TARGET_DIR}"
|
|
149
|
+
|
|
102
150
|
echo ""
|
|
103
151
|
echo "OK: found expected entry file: ${EXPECTED_FILE}"
|
|
104
152
|
echo "OK: production build output exists: ${DIST_JS}"
|
|
@@ -88,6 +88,17 @@ create_project() {
|
|
|
88
88
|
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
89
89
|
' "${project_dir}/package.json" "$(npm_path "${TSPCI_TGZ}")" "$(npm_path "${PREACT_STORE_TGZ}")"
|
|
90
90
|
|
|
91
|
+
node -e '
|
|
92
|
+
const fs = require("fs");
|
|
93
|
+
const pkgPath = process.argv[1];
|
|
94
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
95
|
+
const hasTslib = Boolean(pkg.devDependencies && pkg.devDependencies.tslib);
|
|
96
|
+
if (!hasTslib) {
|
|
97
|
+
console.error("ERROR: expected devDependency \"tslib\" in generated package.json");
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
' "${project_dir}/package.json"
|
|
101
|
+
|
|
91
102
|
(cd "${project_dir}" && npm install --cache "${NPM_CACHE_DIR}" --workspaces=false)
|
|
92
103
|
}
|
|
93
104
|
|
|
@@ -105,6 +116,43 @@ run_base_build() {
|
|
|
105
116
|
assert_file "${project_dir}/dist/index.js"
|
|
106
117
|
}
|
|
107
118
|
|
|
119
|
+
run_dev_start_smoke() {
|
|
120
|
+
local project_dir="$1"
|
|
121
|
+
node -e '
|
|
122
|
+
const { spawn } = require("child_process");
|
|
123
|
+
const targetDir = process.argv[1];
|
|
124
|
+
const child = spawn("npm", ["run", "dev"], {
|
|
125
|
+
cwd: targetDir,
|
|
126
|
+
shell: process.platform === "win32"
|
|
127
|
+
});
|
|
128
|
+
let logs = "";
|
|
129
|
+
const onData = (chunk) => {
|
|
130
|
+
logs += chunk.toString();
|
|
131
|
+
};
|
|
132
|
+
child.stdout.on("data", onData);
|
|
133
|
+
child.stderr.on("data", onData);
|
|
134
|
+
child.on("error", (err) => {
|
|
135
|
+
console.error(err.message);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
});
|
|
138
|
+
setTimeout(() => {
|
|
139
|
+
child.kill("SIGTERM");
|
|
140
|
+
const hasReady = logs.includes("Ready for changes");
|
|
141
|
+
const missingTslib = logs.includes("Could not find module '\''tslib'\''");
|
|
142
|
+
if (missingTslib) {
|
|
143
|
+
console.error("ERROR: dev startup failed due to missing tslib");
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
if (!hasReady) {
|
|
147
|
+
console.error("ERROR: dev startup did not reach \"Ready for changes\" within timeout");
|
|
148
|
+
console.error(logs);
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
process.exit(0);
|
|
152
|
+
}, 20000);
|
|
153
|
+
' "${project_dir}"
|
|
154
|
+
}
|
|
155
|
+
|
|
108
156
|
echo "Scenario 1: vanilla PCI creates and builds"
|
|
109
157
|
create_project "VanillaPci" "javascript" "Vanilla PCI matrix test"
|
|
110
158
|
assert_file "${TEST_ROOT}/VanillaPci/src/index.js"
|
|
@@ -114,6 +162,7 @@ echo "Scenario 2: TypeScript PCI (without tailwind/preact) creates and builds"
|
|
|
114
162
|
create_project "TypeScriptPci" "typescript" "TypeScript PCI matrix test"
|
|
115
163
|
assert_file "${TEST_ROOT}/TypeScriptPci/src/index.ts"
|
|
116
164
|
run_base_build "${TEST_ROOT}/TypeScriptPci"
|
|
165
|
+
run_dev_start_smoke "${TEST_ROOT}/TypeScriptPci"
|
|
117
166
|
|
|
118
167
|
echo "Scenario 3: TypeScript + tailwind PCI creates and builds"
|
|
119
168
|
create_project "TypeScriptTailwindPci" "preact+tailwind" "TypeScript + tailwind PCI matrix test"
|
package/src/cli.js
CHANGED
|
@@ -9,7 +9,8 @@ import fs from "fs";
|
|
|
9
9
|
import os from "os";
|
|
10
10
|
import clear from "clear";
|
|
11
11
|
import figlet from "figlet";
|
|
12
|
-
import
|
|
12
|
+
import chokidar from "chokidar";
|
|
13
|
+
import { select } from "@inquirer/prompts";
|
|
13
14
|
|
|
14
15
|
const args = process.argv.slice(2);
|
|
15
16
|
|
|
@@ -21,6 +22,70 @@ const __dirname = path.dirname(__filename);
|
|
|
21
22
|
const PACKAGE_ROOT_PATH = process.cwd();
|
|
22
23
|
const PACKAGE_DIST_PATH = path.join(PACKAGE_ROOT_PATH, "dist");
|
|
23
24
|
const NODE_MODULES = path.join(process.cwd(), "node_modules");
|
|
25
|
+
const REQUIRED_DEV_DEPENDENCIES = {
|
|
26
|
+
tslib: "^2.8.1",
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const ensureRequiredDevDependencies = (packageJson) => {
|
|
30
|
+
packageJson.devDependencies = packageJson.devDependencies || {};
|
|
31
|
+
for (const [name, version] of Object.entries(REQUIRED_DEV_DEPENDENCIES)) {
|
|
32
|
+
if (!packageJson.devDependencies[name]) {
|
|
33
|
+
packageJson.devDependencies[name] = version;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const isMissingTslibError = (event) => {
|
|
39
|
+
const error = event?.error;
|
|
40
|
+
const message = [error?.message, error?.toString?.(), event?.message].filter(Boolean).join("\n");
|
|
41
|
+
return message.includes("Could not find module 'tslib'");
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const getDevIndexHtmlSourceCandidates = (target = "IMS") => {
|
|
45
|
+
const projectSource = path.join(PACKAGE_ROOT_PATH, "src/index.html");
|
|
46
|
+
const templateSource =
|
|
47
|
+
target === "IMS"
|
|
48
|
+
? path.join(__dirname, "../public/index.html")
|
|
49
|
+
: path.join(NODE_MODULES, `@citolab/tspci-${target}/public/index.html`);
|
|
50
|
+
return { projectSource, templateSource };
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const resolveActiveDevIndexHtmlSource = (target = "IMS") => {
|
|
54
|
+
const { projectSource, templateSource } = getDevIndexHtmlSourceCandidates(target);
|
|
55
|
+
return fs.existsSync(projectSource) ? projectSource : templateSource;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const copyDevIndexHtmlToDist = (target = "IMS", reason = "initial") => {
|
|
59
|
+
const source = resolveActiveDevIndexHtmlSource(target);
|
|
60
|
+
if (!fs.existsSync(source)) {
|
|
61
|
+
throw new Error(`No index.html template found for dev mode. Expected: ${source}`);
|
|
62
|
+
}
|
|
63
|
+
fs.copyFileSync(source, path.join(PACKAGE_DIST_PATH, "index.html"));
|
|
64
|
+
console.log(`index.html copied to dist (${reason}) from ${source}`);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const watchDevIndexHtmlSources = (target = "IMS") => {
|
|
68
|
+
const { projectSource, templateSource } = getDevIndexHtmlSourceCandidates(target);
|
|
69
|
+
const watcher = chokidar.watch([projectSource, templateSource], {
|
|
70
|
+
ignoreInitial: true,
|
|
71
|
+
awaitWriteFinish: {
|
|
72
|
+
stabilityThreshold: 120,
|
|
73
|
+
pollInterval: 20,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
watcher.on("all", (event, changedPath) => {
|
|
78
|
+
try {
|
|
79
|
+
copyDevIndexHtmlToDist(target, `${event}: ${changedPath}`);
|
|
80
|
+
} catch (err) {
|
|
81
|
+
console.error(`Failed to refresh index.html after ${event} on ${changedPath}`, err);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const closeWatcher = () => watcher.close();
|
|
86
|
+
process.on("SIGINT", closeWatcher);
|
|
87
|
+
process.on("SIGTERM", closeWatcher);
|
|
88
|
+
};
|
|
24
89
|
|
|
25
90
|
// https://rollupjs.org/guide/en/#programmatically-loading-a-config-file
|
|
26
91
|
const watchBuild = (devServer = false, target = "IMS") => {
|
|
@@ -36,27 +101,8 @@ const watchBuild = (devServer = false, target = "IMS") => {
|
|
|
36
101
|
}
|
|
37
102
|
if (devServer) {
|
|
38
103
|
try {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
path.join(PACKAGE_ROOT_PATH, "src/index.html"),
|
|
42
|
-
path.join(PACKAGE_DIST_PATH, "index.html"),
|
|
43
|
-
(err) => {
|
|
44
|
-
if (err) throw err;
|
|
45
|
-
console.log("using index.html found in src/index.html, copied to dist");
|
|
46
|
-
}
|
|
47
|
-
);
|
|
48
|
-
} else {
|
|
49
|
-
let fileToCopy;
|
|
50
|
-
if (target == "IMS") {
|
|
51
|
-
fileToCopy = path.join(__dirname, `../public/index.html`);
|
|
52
|
-
} else {
|
|
53
|
-
fileToCopy = path.join(NODE_MODULES, `@citolab/tspci-${target}/public/index.html`);
|
|
54
|
-
}
|
|
55
|
-
fs.copyFile(fileToCopy, path.join(PACKAGE_DIST_PATH, "index.html"), (err) => {
|
|
56
|
-
if (err) throw err;
|
|
57
|
-
console.log("using index.html was copied to /dist folder pci");
|
|
58
|
-
});
|
|
59
|
-
}
|
|
104
|
+
copyDevIndexHtmlToDist(target);
|
|
105
|
+
watchDevIndexHtmlSources(target);
|
|
60
106
|
} catch (err) {
|
|
61
107
|
console.error(err);
|
|
62
108
|
}
|
|
@@ -70,6 +116,10 @@ const watchBuild = (devServer = false, target = "IMS") => {
|
|
|
70
116
|
console.log("starting build");
|
|
71
117
|
}
|
|
72
118
|
if (event.code == "ERROR") {
|
|
119
|
+
if (isMissingTslibError(event)) {
|
|
120
|
+
console.log(chalk.red("ERROR: Missing dependency 'tslib'"));
|
|
121
|
+
console.log(chalk.yellow("Install it in your PCI project: npm install --save-dev tslib"));
|
|
122
|
+
}
|
|
73
123
|
console.log("ERROR", event);
|
|
74
124
|
}
|
|
75
125
|
});
|
|
@@ -110,16 +160,13 @@ const prodBuild = async () => {
|
|
|
110
160
|
});
|
|
111
161
|
};
|
|
112
162
|
|
|
113
|
-
function selectOptions(prompt, options) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
default: options[0],
|
|
121
|
-
},
|
|
122
|
-
]);
|
|
163
|
+
async function selectOptions(prompt, options) {
|
|
164
|
+
const value = await select({
|
|
165
|
+
message: prompt,
|
|
166
|
+
choices: options.map((o) => ({ value: o })),
|
|
167
|
+
default: options[0],
|
|
168
|
+
});
|
|
169
|
+
return { value };
|
|
123
170
|
}
|
|
124
171
|
|
|
125
172
|
function askOption(prompt) {
|
|
@@ -312,6 +359,7 @@ const run = async () => {
|
|
|
312
359
|
const packageJson = path.join(destinationFolder, "package.json");
|
|
313
360
|
const packageJsonContent = fs.readFileSync(packageJson, "utf8");
|
|
314
361
|
let packageJsonContentJson = JSON.parse(packageJsonContent);
|
|
362
|
+
ensureRequiredDevDependencies(packageJsonContentJson);
|
|
315
363
|
|
|
316
364
|
const kebabCasedProjectName = pciName.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
317
365
|
packageJsonContentJson.name = kebabCasedProjectName;
|
|
@@ -418,9 +466,9 @@ const run = async () => {
|
|
|
418
466
|
execSync("npm install", { cwd: destinationFolder, stdio: [0, 1, 2] });
|
|
419
467
|
execSync("npm install", { cwd: destinationFolder, stdio: [0, 1, 2] }); // Somehow this to prevent the fsevents.watch is not a function error
|
|
420
468
|
console.log(chalk.green(`📦 Done!`));
|
|
421
|
-
console.log(
|
|
422
|
-
console.log(
|
|
423
|
-
console.log(
|
|
469
|
+
console.log(`Navigate to ${chalk.bold(destinationFolder)} or open this folder (e.g. with vscode).`);
|
|
470
|
+
console.log(`Start the dev server with: ${chalk.bold("npm run dev")}`);
|
|
471
|
+
console.log(`Add support for TAO with: ${chalk.bold("npm run tspci -- add --target tao")}`);
|
|
424
472
|
|
|
425
473
|
return;
|
|
426
474
|
} else {
|