@citolab/tspci 2.9.7 → 2.9.10
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 +24 -0
- package/package.json +6 -5
- package/preset/base/package.json +2 -1
- package/preset/preact/src/interaction.tsx +14 -10
- package/preset/tailwind/src/styles.css +25 -5
- package/scripts/test-init-local.sh +49 -1
- package/scripts/test-init-matrix.sh +49 -0
- package/src/cli.js +26 -3
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,30 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [2.9.10](/compare/v2.9.9...v2.9.10) (2026-03-11)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @citolab/tspci
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [2.9.9](/compare/v2.9.8...v2.9.9) (2026-03-11)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @citolab/tspci
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## [2.9.8](/compare/v2.9.7...v2.9.8) (2026-03-11)
|
|
23
|
+
|
|
24
|
+
**Note:** Version bump only for package @citolab/tspci
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
6
30
|
## [2.9.7](/compare/v2.9.6...v2.9.7) (2026-03-09)
|
|
7
31
|
|
|
8
32
|
**Note:** Version bump only for package @citolab/tspci
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@citolab/tspci",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.10",
|
|
4
4
|
"description": "an opiniated typescript ims-pci builder with tao integration",
|
|
5
5
|
"author": "patrick <patrick.deklein@cito.nl>",
|
|
6
6
|
"repository": "@citolab/tspci",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@rollup/plugin-json": "^6.1.0",
|
|
26
26
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
27
27
|
"@rollup/plugin-replace": "^6.0.3",
|
|
28
|
-
"@rollup/plugin-terser": "^0.
|
|
28
|
+
"@rollup/plugin-terser": "^1.0.0",
|
|
29
29
|
"@rollup/plugin-typescript": "^12.3.0",
|
|
30
30
|
"@tailwindcss/nesting": "0.0.0-insiders.565cd3e",
|
|
31
31
|
"@tailwindcss/postcss": "^4.1.18",
|
|
@@ -40,9 +40,10 @@
|
|
|
40
40
|
"postcss": "^8.5.6",
|
|
41
41
|
"postcss-import": "^16.1.1",
|
|
42
42
|
"postcss-load-config": "^6.0.1",
|
|
43
|
-
"rollup": "^4.
|
|
43
|
+
"rollup": "^4.59.0",
|
|
44
44
|
"rollup-plugin-livereload": "^2.0.5",
|
|
45
|
-
"tailwindcss": "^4.1.18"
|
|
45
|
+
"tailwindcss": "^4.1.18",
|
|
46
|
+
"tslib": "^2.8.1"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
49
|
"@types/node": "^25.1.0",
|
|
@@ -53,5 +54,5 @@
|
|
|
53
54
|
"access": "public",
|
|
54
55
|
"registry": "https://registry.npmjs.org/"
|
|
55
56
|
},
|
|
56
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "5d514e4e118dd152f455964a08bc9bed43cb774b"
|
|
57
58
|
}
|
package/preset/base/package.json
CHANGED
|
@@ -20,22 +20,26 @@ const Interaction = ({ config, dom, store }: { config: PropTypes; dom: Document
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
return <div className="pci-container">
|
|
23
|
-
<h1>{config.title}</h1>
|
|
23
|
+
<h1 className="title">{config.title}</h1>
|
|
24
24
|
<div className="body">
|
|
25
|
-
<img width={config.width} height={+config.height} src={procenten} />
|
|
25
|
+
<img className="body-image" width={config.width} height={+config.height} src={procenten} alt="Percentages visual" />
|
|
26
26
|
</div>
|
|
27
27
|
<div className="interaction">
|
|
28
|
-
<label htmlFor="
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
<label className="prompt" htmlFor="percentage-input">{config.prompt}</label>
|
|
29
|
+
<div className="answer-row">
|
|
30
|
+
<input className="answer-input"
|
|
31
|
+
id="percentage-input"
|
|
32
|
+
type="number"
|
|
33
|
+
value={state.input}
|
|
34
|
+
onInput={handleInput}
|
|
35
|
+
onPaste={() => setEventHandled(false)}
|
|
36
|
+
onKeyDown={() => setEventHandled(false)}
|
|
37
|
+
min="0" max="100" />
|
|
38
|
+
<span className="answer-suffix">%</span>
|
|
39
|
+
</div>
|
|
35
40
|
</div>
|
|
36
41
|
</div>;
|
|
37
42
|
};
|
|
38
43
|
|
|
39
44
|
|
|
40
45
|
export default Interaction;
|
|
41
|
-
|
|
@@ -1,10 +1,30 @@
|
|
|
1
1
|
@import "tailwindcss";
|
|
2
|
+
@source "./**/*.{html,js,ts,jsx,tsx}";
|
|
3
|
+
@source "../*.xml";
|
|
2
4
|
.pci-container {
|
|
3
|
-
@apply
|
|
5
|
+
@apply mx-auto flex w-full max-w-xl flex-col items-center gap-5 rounded-2xl border border-slate-200 bg-white p-6 shadow-lg;
|
|
4
6
|
}
|
|
5
|
-
|
|
6
|
-
@apply text-
|
|
7
|
+
.title {
|
|
8
|
+
@apply text-center text-2xl font-semibold tracking-tight text-slate-800;
|
|
7
9
|
}
|
|
8
|
-
|
|
9
|
-
@apply
|
|
10
|
+
.body {
|
|
11
|
+
@apply flex w-full justify-center;
|
|
12
|
+
}
|
|
13
|
+
.body-image {
|
|
14
|
+
@apply rounded-xl border border-slate-200 bg-slate-50 p-2;
|
|
15
|
+
}
|
|
16
|
+
.interaction {
|
|
17
|
+
@apply w-full rounded-xl border border-slate-200 bg-slate-50 p-4;
|
|
18
|
+
}
|
|
19
|
+
.prompt {
|
|
20
|
+
@apply mb-2 block text-sm font-medium text-slate-700;
|
|
21
|
+
}
|
|
22
|
+
.answer-row {
|
|
23
|
+
@apply flex items-center gap-2;
|
|
24
|
+
}
|
|
25
|
+
.answer-input {
|
|
26
|
+
@apply w-28 rounded-lg border border-slate-300 bg-white px-3 py-2 text-lg font-medium text-slate-900 shadow-sm outline-none transition focus:border-amber-500 focus:ring-2 focus:ring-amber-200;
|
|
27
|
+
}
|
|
28
|
+
.answer-suffix {
|
|
29
|
+
@apply text-sm font-semibold uppercase tracking-wide text-slate-500;
|
|
10
30
|
}
|
|
@@ -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
|
@@ -22,6 +22,24 @@ const __dirname = path.dirname(__filename);
|
|
|
22
22
|
const PACKAGE_ROOT_PATH = process.cwd();
|
|
23
23
|
const PACKAGE_DIST_PATH = path.join(PACKAGE_ROOT_PATH, "dist");
|
|
24
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
|
+
};
|
|
25
43
|
|
|
26
44
|
const getDevIndexHtmlSourceCandidates = (target = "IMS") => {
|
|
27
45
|
const projectSource = path.join(PACKAGE_ROOT_PATH, "src/index.html");
|
|
@@ -98,6 +116,10 @@ const watchBuild = (devServer = false, target = "IMS") => {
|
|
|
98
116
|
console.log("starting build");
|
|
99
117
|
}
|
|
100
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
|
+
}
|
|
101
123
|
console.log("ERROR", event);
|
|
102
124
|
}
|
|
103
125
|
});
|
|
@@ -337,6 +359,7 @@ const run = async () => {
|
|
|
337
359
|
const packageJson = path.join(destinationFolder, "package.json");
|
|
338
360
|
const packageJsonContent = fs.readFileSync(packageJson, "utf8");
|
|
339
361
|
let packageJsonContentJson = JSON.parse(packageJsonContent);
|
|
362
|
+
ensureRequiredDevDependencies(packageJsonContentJson);
|
|
340
363
|
|
|
341
364
|
const kebabCasedProjectName = pciName.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
342
365
|
packageJsonContentJson.name = kebabCasedProjectName;
|
|
@@ -443,9 +466,9 @@ const run = async () => {
|
|
|
443
466
|
execSync("npm install", { cwd: destinationFolder, stdio: [0, 1, 2] });
|
|
444
467
|
execSync("npm install", { cwd: destinationFolder, stdio: [0, 1, 2] }); // Somehow this to prevent the fsevents.watch is not a function error
|
|
445
468
|
console.log(chalk.green(`📦 Done!`));
|
|
446
|
-
console.log(
|
|
447
|
-
console.log(
|
|
448
|
-
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")}`);
|
|
449
472
|
|
|
450
473
|
return;
|
|
451
474
|
} else {
|