create-thingworx-widget2 1.0.2 → 1.0.3
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/bin/create-thingworx-widget.js +168 -197
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
"use strict";
|
|
4
4
|
|
|
5
5
|
import fs from 'fs';
|
|
6
6
|
import path from 'path';
|
|
@@ -9,56 +9,42 @@ import { execSync } from 'child_process';
|
|
|
9
9
|
|
|
10
10
|
// ─── ANSI colours ────────────────────────────────────────────────────────────
|
|
11
11
|
const c = {
|
|
12
|
-
reset:
|
|
13
|
-
bold:
|
|
14
|
-
cyan:
|
|
15
|
-
green:
|
|
16
|
-
yellow:
|
|
17
|
-
red:
|
|
18
|
-
dim:
|
|
19
|
-
blue:
|
|
12
|
+
reset: "\x1b[0m",
|
|
13
|
+
bold: "\x1b[1m",
|
|
14
|
+
cyan: "\x1b[36m",
|
|
15
|
+
green: "\x1b[32m",
|
|
16
|
+
yellow: "\x1b[33m",
|
|
17
|
+
red: "\x1b[31m",
|
|
18
|
+
dim: "\x1b[2m",
|
|
19
|
+
blue: "\x1b[34m",
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
const log
|
|
23
|
-
const info = (msg)
|
|
24
|
-
const ok
|
|
25
|
-
const warn = (msg)
|
|
26
|
-
const fail = (msg)
|
|
22
|
+
const log = (...a) => console.log(...a);
|
|
23
|
+
const info = (msg) => log(` ${c.cyan}>${c.reset} ${msg}`);
|
|
24
|
+
const ok = (msg) => log(` ${c.green}✔${c.reset} ${msg}`);
|
|
25
|
+
const warn = (msg) => log(` ${c.yellow}!${c.reset} ${msg}`);
|
|
26
|
+
const fail = (msg) => log(` ${c.red}✖${c.reset} ${msg}`);
|
|
27
27
|
|
|
28
28
|
// ─── Banner ───────────────────────────────────────────────────────────────────
|
|
29
29
|
function banner() {
|
|
30
|
-
log(
|
|
31
|
-
log(
|
|
32
|
-
|
|
33
|
-
);
|
|
34
|
-
log(
|
|
35
|
-
|
|
36
|
-
);
|
|
37
|
-
log(
|
|
38
|
-
|
|
39
|
-
);
|
|
40
|
-
log(
|
|
41
|
-
`${c.blue} ██║ ██╔══██║██║██║╚██╗██║██║ ██║██║███╗██║██║ ██║██╔══██╗ ██╔██╗${c.reset}`
|
|
42
|
-
);
|
|
43
|
-
log(
|
|
44
|
-
`${c.blue} ██║ ██║ ██║██║██║ ╚████║╚██████╔╝╚███╔███╔╝╚██████╔╝██║ ██║██╔╝ ██╗${c.reset}`
|
|
45
|
-
);
|
|
46
|
-
log(
|
|
47
|
-
`${c.blue} ╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══╝╚══╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝${c.reset}`
|
|
48
|
-
);
|
|
49
|
-
log('');
|
|
50
|
-
log(
|
|
51
|
-
`${c.bold} ThingWorx Widget Scaffolder${c.reset} ${c.dim}— Gulp 5 · Babel · undici · External Dependencies${c.reset}`
|
|
52
|
-
);
|
|
53
|
-
log('');
|
|
30
|
+
log("");
|
|
31
|
+
log(`${c.bold}${c.blue} ████████╗██╗ ██╗██╗███╗ ██╗ ██████╗ ██╗ ██╗ ██████╗ ██████╗ ██╗ ██╗${c.reset}`);
|
|
32
|
+
log(`${c.blue} ██╔══╝██║ ██║██║████╗ ██║██╔════╝ ██║ ██║██╔═══██╗██╔══██╗╚██╗██╔╝${c.reset}`);
|
|
33
|
+
log(`${c.blue} ██║ ███████║██║██╔██╗ ██║██║ ███╗██║ █╗ ██║██║ ██║██████╔╝ ╚███╔╝${c.reset}`);
|
|
34
|
+
log(`${c.blue} ██║ ██╔══██║██║██║╚██╗██║██║ ██║██║███╗██║██║ ██║██╔══██╗ ██╔██╗${c.reset}`);
|
|
35
|
+
log(`${c.blue} ██║ ██║ ██║██║██║ ╚████║╚██████╔╝╚███╔███╔╝╚██████╔╝██║ ██║██╔╝ ██╗${c.reset}`);
|
|
36
|
+
log(`${c.blue} ╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══╝╚══╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝${c.reset}`);
|
|
37
|
+
log("");
|
|
38
|
+
log(`${c.bold} ThingWorx Widget Scaffolder${c.reset} ${c.dim}— Gulp 5 · Babel · undici · External Dependencies${c.reset}`);
|
|
39
|
+
log("");
|
|
54
40
|
}
|
|
55
41
|
|
|
56
42
|
// ─── Prompt helpers ───────────────────────────────────────────────────────────
|
|
57
43
|
function prompt(rl, question, defaultVal) {
|
|
58
|
-
return new Promise(
|
|
59
|
-
const hint = defaultVal ? `${c.dim}(${defaultVal})${c.reset} ` :
|
|
60
|
-
rl.question(` ${c.cyan}?${c.reset} ${question} ${hint}: `,
|
|
61
|
-
resolve(ans.trim() || defaultVal ||
|
|
44
|
+
return new Promise(resolve => {
|
|
45
|
+
const hint = defaultVal ? `${c.dim}(${defaultVal})${c.reset} ` : "";
|
|
46
|
+
rl.question(` ${c.cyan}?${c.reset} ${question} ${hint}: `, ans => {
|
|
47
|
+
resolve(ans.trim() || defaultVal || "");
|
|
62
48
|
});
|
|
63
49
|
});
|
|
64
50
|
}
|
|
@@ -69,8 +55,8 @@ function prompt(rl, question, defaultVal) {
|
|
|
69
55
|
function resolveDepMain(dep) {
|
|
70
56
|
try {
|
|
71
57
|
const pkgPath = require.resolve(`${dep}/package.json`, { paths: [process.cwd()] });
|
|
72
|
-
const pkg
|
|
73
|
-
return pkg.main ||
|
|
58
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
59
|
+
return pkg.main || "index.js";
|
|
74
60
|
} catch (_) {
|
|
75
61
|
return null; // not installed yet — that's fine
|
|
76
62
|
}
|
|
@@ -84,76 +70,73 @@ function writePackageJson(root, cfg) {
|
|
|
84
70
|
// Build dependencies object: echarts always + extra deps from user input
|
|
85
71
|
const deps = {};
|
|
86
72
|
for (const dep of cfg.extraDeps) {
|
|
87
|
-
deps[dep] =
|
|
73
|
+
deps[dep] = "*"; // user can pin versions manually
|
|
88
74
|
}
|
|
89
75
|
|
|
90
76
|
const devDeps = {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
del:
|
|
97
|
-
|
|
98
|
-
eslint:
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
gulp:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
prettier:
|
|
107
|
-
undici:
|
|
108
|
-
xml2js:
|
|
77
|
+
"@babel/core": "^7.0.0-beta.46",
|
|
78
|
+
"@babel/preset-env": "^7.0.0-beta.46",
|
|
79
|
+
"@types/jquery": "^3.3.1",
|
|
80
|
+
"@types/node": "^8.10.11",
|
|
81
|
+
"babel-plugin-remove-import-export": "^1.1.0",
|
|
82
|
+
"del": "^5.0.0",
|
|
83
|
+
"delete-empty": "^3.0.0",
|
|
84
|
+
"eslint": "^10.4.1",
|
|
85
|
+
"eslint-config-prettier": "^10.1.8",
|
|
86
|
+
"form-data": "^4.0.5",
|
|
87
|
+
"gulp": "^5.0.1",
|
|
88
|
+
"gulp-babel": "^8.0.0",
|
|
89
|
+
"gulp-concat": "^2.6.1",
|
|
90
|
+
"gulp-terser": "^1.2.0",
|
|
91
|
+
"gulp-zip": "^5.0.0",
|
|
92
|
+
"prettier": "^3.8.3",
|
|
93
|
+
"undici": "^7.26.0",
|
|
94
|
+
"xml2js": "^0.6.2",
|
|
109
95
|
};
|
|
110
96
|
|
|
111
97
|
const content = {
|
|
112
|
-
name:
|
|
113
|
-
packageName:
|
|
114
|
-
moduleName:
|
|
115
|
-
version:
|
|
116
|
-
description:
|
|
98
|
+
name: cfg.packageName.toLowerCase().replace(/\s+/g, "-"),
|
|
99
|
+
packageName: cfg.packageName,
|
|
100
|
+
moduleName: cfg.moduleName,
|
|
101
|
+
version: cfg.version,
|
|
102
|
+
description: cfg.description,
|
|
117
103
|
thingworxServer: cfg.twxServer,
|
|
118
|
-
thingworxUser:
|
|
104
|
+
thingworxUser: cfg.twxUser,
|
|
119
105
|
thingworxPassword: cfg.twxPassword,
|
|
120
|
-
author:
|
|
106
|
+
author: cfg.author,
|
|
121
107
|
minimumThingWorxVersion: cfg.minTwxVersion,
|
|
122
|
-
homepage:
|
|
123
|
-
autoUpdate:
|
|
124
|
-
repository:
|
|
108
|
+
homepage: "",
|
|
109
|
+
autoUpdate: { gitHubURL: "" },
|
|
110
|
+
repository: { type: "git", url: "" },
|
|
125
111
|
scripts: {
|
|
126
|
-
test:
|
|
127
|
-
build:
|
|
128
|
-
buildProduction:
|
|
129
|
-
upload:
|
|
130
|
-
uploadProduction:
|
|
131
|
-
format:
|
|
132
|
-
|
|
112
|
+
test: "echo \"Error: no test specified\" && exit 1",
|
|
113
|
+
build: "gulp",
|
|
114
|
+
buildProduction: "gulp --p",
|
|
115
|
+
upload: "gulp upload",
|
|
116
|
+
uploadProduction: "gulp upload --p",
|
|
117
|
+
format: "prettier --write src/**/*.js",
|
|
118
|
+
"format:check": "prettier --check src/**/*.js",
|
|
133
119
|
},
|
|
134
|
-
license:
|
|
135
|
-
files: [
|
|
120
|
+
license: "MIT",
|
|
121
|
+
files: ["lib", "build", "LICENSE"],
|
|
136
122
|
devDependencies: devDeps,
|
|
137
123
|
dependencies: deps,
|
|
138
124
|
};
|
|
139
125
|
|
|
140
|
-
fs.writeFileSync(path.join(root,
|
|
126
|
+
fs.writeFileSync(path.join(root, "package.json"), JSON.stringify(content, null, 4));
|
|
141
127
|
}
|
|
142
128
|
|
|
143
129
|
function writeMetadataXml(root, cfg) {
|
|
144
|
-
const wName
|
|
145
|
-
const jsIde
|
|
146
|
-
const jsRuntime
|
|
147
|
-
const cssIde
|
|
130
|
+
const wName = cfg.packageName;
|
|
131
|
+
const jsIde = `ide\\${wName}.ide.js`;
|
|
132
|
+
const jsRuntime = `runtime\\${wName}.runtime.js`;
|
|
133
|
+
const cssIde = `assets\\styles\\${wName}.ide.css`;
|
|
148
134
|
const cssRuntime = `assets\\styles\\${wName}.runtime.css`;
|
|
149
135
|
|
|
150
136
|
// Build one FileResource line per extra dependency
|
|
151
|
-
const depLines = cfg.extraDeps
|
|
152
|
-
.
|
|
153
|
-
|
|
154
|
-
` <FileResource type="JS" file="${dep}.js"\n description="" isDevelopment="false" isRuntime="true"/>`
|
|
155
|
-
)
|
|
156
|
-
.join('\n');
|
|
137
|
+
const depLines = cfg.extraDeps.map(dep =>
|
|
138
|
+
` <FileResource type="JS" file="${dep}.js"\n description="" isDevelopment="false" isRuntime="true"/>`
|
|
139
|
+
).join("\n");
|
|
157
140
|
|
|
158
141
|
const content = `<?xml version="1.0" encoding="UTF-8"?>
|
|
159
142
|
<Entities>
|
|
@@ -180,7 +163,7 @@ function writeMetadataXml(root, cfg) {
|
|
|
180
163
|
description="" isDevelopment="false" isRuntime="true"/>
|
|
181
164
|
<FileResource type="JS" file="${jsRuntime}"
|
|
182
165
|
description="" isDevelopment="false" isRuntime="true"/>
|
|
183
|
-
${depLines ? depLines +
|
|
166
|
+
${depLines ? depLines + "\n" : ""}
|
|
184
167
|
<!--
|
|
185
168
|
EXTERNAL DEPENDENCIES NOTE:
|
|
186
169
|
Each library listed above must be manually added to metadata.xml.
|
|
@@ -197,7 +180,7 @@ ${depLines ? depLines + '\n' : ''}
|
|
|
197
180
|
</Widgets>
|
|
198
181
|
</Entities>
|
|
199
182
|
`;
|
|
200
|
-
fs.writeFileSync(path.join(root,
|
|
183
|
+
fs.writeFileSync(path.join(root, "metadata.xml"), content);
|
|
201
184
|
}
|
|
202
185
|
|
|
203
186
|
function writeGulpfile(root, cfg) {
|
|
@@ -319,6 +302,11 @@ async function prepareBuild(cb) {
|
|
|
319
302
|
|
|
320
303
|
const fileResources = metadataXML.Entities.Widgets[0].Widget[0].UIResources[0].FileResource;
|
|
321
304
|
|
|
305
|
+
// Dependency JS files (from package.json "dependencies") must NOT be concat'd —
|
|
306
|
+
// they are copied as-is and must survive the production build unchanged.
|
|
307
|
+
const depFileNames = Object.keys(packageJson.dependencies || {}).map(dep => \`\${dep}.js\`);
|
|
308
|
+
const depResources = fileResources.filter(r => r.$.type === 'JS' && depFileNames.includes(r.$.file));
|
|
309
|
+
|
|
322
310
|
const fileGroups = [
|
|
323
311
|
{ isDevelopment: true, isRuntime: true, extension: 'min' },
|
|
324
312
|
{ isDevelopment: false, isRuntime: true, extension: 'runtime' },
|
|
@@ -327,6 +315,8 @@ async function prepareBuild(cb) {
|
|
|
327
315
|
|
|
328
316
|
for (const group of fileGroups) {
|
|
329
317
|
group.files = fileResources.filter(r => {
|
|
318
|
+
// Never concat dependency files — they are kept as standalone entries
|
|
319
|
+
if (depFileNames.includes(r.$.file)) return false;
|
|
330
320
|
const include =
|
|
331
321
|
(group.isDevelopment ? r.$.isDevelopment === 'true' : r.$.isDevelopment !== 'true') &&
|
|
332
322
|
(group.isRuntime ? r.$.isRuntime === 'true' : r.$.isRuntime !== 'true') &&
|
|
@@ -339,9 +329,15 @@ async function prepareBuild(cb) {
|
|
|
339
329
|
}).map(r => r.$.file);
|
|
340
330
|
}
|
|
341
331
|
|
|
332
|
+
// Keep only non-JS entries (CSS etc.) — dep + concat JS entries are added back below
|
|
342
333
|
metadataXML.Entities.Widgets[0].Widget[0].UIResources[0].FileResource =
|
|
343
334
|
fileResources.filter(r => r.$.type !== 'JS' || !r.$.file);
|
|
344
335
|
|
|
336
|
+
// Re-add dependency entries unchanged — they must always load as separate files
|
|
337
|
+
for (const depRes of depResources) {
|
|
338
|
+
metadataXML.Entities.Widgets[0].Widget[0].UIResources[0].FileResource.push(depRes);
|
|
339
|
+
}
|
|
340
|
+
|
|
345
341
|
for (const group of fileGroups) {
|
|
346
342
|
if (!group.files.length) continue;
|
|
347
343
|
const name = \`\${packageJson.packageName}.\${group.extension}\`;
|
|
@@ -474,7 +470,7 @@ async function upload(cb) {
|
|
|
474
470
|
exports.default = series(cleanBuildDir, copy, prepareBuild);
|
|
475
471
|
exports.upload = series(cleanBuildDir, copy, prepareBuild, upload);
|
|
476
472
|
`;
|
|
477
|
-
fs.writeFileSync(path.join(root,
|
|
473
|
+
fs.writeFileSync(path.join(root, "gulpfile.js"), content);
|
|
478
474
|
}
|
|
479
475
|
|
|
480
476
|
function writeIdeJs(root, cfg) {
|
|
@@ -562,23 +558,20 @@ TW.IDE.Widgets.${wName} = function () {
|
|
|
562
558
|
this.beforeDestroy = function () { /* clean up IDE resources */ };
|
|
563
559
|
};
|
|
564
560
|
`;
|
|
565
|
-
const ideDir = path.join(root,
|
|
561
|
+
const ideDir = path.join(root, "src", "ide");
|
|
566
562
|
fs.mkdirSync(ideDir, { recursive: true });
|
|
567
563
|
fs.writeFileSync(path.join(ideDir, `${wName}.ide.js`), content);
|
|
568
564
|
}
|
|
569
565
|
|
|
570
566
|
function writeRuntimeJs(root, cfg) {
|
|
571
567
|
const wName = cfg.packageName;
|
|
572
|
-
const wLow
|
|
568
|
+
const wLow = wName.toLowerCase();
|
|
573
569
|
|
|
574
570
|
// Build dep-awareness comment
|
|
575
571
|
const depComment = cfg.extraDeps.length
|
|
576
572
|
? `\n // External dependencies available as globals (loaded via metadata.xml):\n` +
|
|
577
|
-
cfg.extraDeps
|
|
578
|
-
|
|
579
|
-
.join('\n') +
|
|
580
|
-
'\n'
|
|
581
|
-
: '';
|
|
573
|
+
cfg.extraDeps.map(d => ` // ${d} (from node_modules → copied to build as ${d}.js)`).join("\n") + "\n"
|
|
574
|
+
: "";
|
|
582
575
|
|
|
583
576
|
const content = `/* ── ${wName} — Runtime (Mashup) ── */
|
|
584
577
|
|
|
@@ -683,7 +676,7 @@ ${depComment}
|
|
|
683
676
|
}
|
|
684
677
|
};
|
|
685
678
|
`;
|
|
686
|
-
const runtimeDir = path.join(root,
|
|
679
|
+
const runtimeDir = path.join(root, "src", "runtime");
|
|
687
680
|
fs.mkdirSync(runtimeDir, { recursive: true });
|
|
688
681
|
fs.writeFileSync(path.join(runtimeDir, `${wName}.runtime.js`), content);
|
|
689
682
|
}
|
|
@@ -712,7 +705,7 @@ function writeIdeCss(root, cfg) {
|
|
|
712
705
|
letter-spacing: 0.5px;
|
|
713
706
|
}
|
|
714
707
|
`;
|
|
715
|
-
const stylesDir = path.join(root,
|
|
708
|
+
const stylesDir = path.join(root, "src", "assets", "styles");
|
|
716
709
|
fs.mkdirSync(stylesDir, { recursive: true });
|
|
717
710
|
fs.writeFileSync(path.join(stylesDir, `${cfg.packageName}.ide.css`), content);
|
|
718
711
|
}
|
|
@@ -769,7 +762,7 @@ function writeRuntimeCss(root, cfg) {
|
|
|
769
762
|
text-align: center;
|
|
770
763
|
}
|
|
771
764
|
`;
|
|
772
|
-
const stylesDir = path.join(root,
|
|
765
|
+
const stylesDir = path.join(root, "src", "assets", "styles");
|
|
773
766
|
fs.mkdirSync(stylesDir, { recursive: true });
|
|
774
767
|
fs.writeFileSync(path.join(stylesDir, `${cfg.packageName}.runtime.css`), content);
|
|
775
768
|
}
|
|
@@ -796,7 +789,7 @@ function writeEslintrc(root) {
|
|
|
796
789
|
}
|
|
797
790
|
}
|
|
798
791
|
`;
|
|
799
|
-
fs.writeFileSync(path.join(root,
|
|
792
|
+
fs.writeFileSync(path.join(root, ".eslintrc"), content);
|
|
800
793
|
}
|
|
801
794
|
|
|
802
795
|
function writePrettierrc(root) {
|
|
@@ -831,21 +824,17 @@ function writePrettierrc(root) {
|
|
|
831
824
|
]
|
|
832
825
|
}
|
|
833
826
|
`;
|
|
834
|
-
fs.writeFileSync(path.join(root,
|
|
827
|
+
fs.writeFileSync(path.join(root, ".prettierrc"), content);
|
|
835
828
|
}
|
|
836
829
|
|
|
837
830
|
function writePrettierIgnore(root) {
|
|
838
|
-
fs.writeFileSync(
|
|
839
|
-
|
|
840
|
-
`build/\nzip/\nlib/\nnode_modules/\n*.min.js\n`
|
|
841
|
-
);
|
|
831
|
+
fs.writeFileSync(path.join(root, ".prettierignore"),
|
|
832
|
+
`build/\nzip/\nlib/\nnode_modules/\n*.min.js\n`);
|
|
842
833
|
}
|
|
843
834
|
|
|
844
835
|
function writeGitignore(root) {
|
|
845
|
-
fs.writeFileSync(
|
|
846
|
-
|
|
847
|
-
`node_modules/\nbuild/\nzip/\nlib/\n*.log\n.DS_Store\n`
|
|
848
|
-
);
|
|
836
|
+
fs.writeFileSync(path.join(root, ".gitignore"),
|
|
837
|
+
`node_modules/\nbuild/\nzip/\nlib/\n*.log\n.DS_Store\n`);
|
|
849
838
|
}
|
|
850
839
|
|
|
851
840
|
function writeReadme(root, cfg) {
|
|
@@ -853,14 +842,11 @@ function writeReadme(root, cfg) {
|
|
|
853
842
|
|
|
854
843
|
// Build dep table rows
|
|
855
844
|
const depRows = cfg.extraDeps.length
|
|
856
|
-
? cfg.extraDeps
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
})
|
|
862
|
-
.join('\n')
|
|
863
|
-
: '| _(none)_ | — |';
|
|
845
|
+
? cfg.extraDeps.map(dep => {
|
|
846
|
+
const mainFile = resolveDepMain(dep) || "(see node_modules/" + dep + "/package.json → main)";
|
|
847
|
+
return `| \`${dep}\` | \`node_modules/${dep}/${mainFile}\` |`;
|
|
848
|
+
}).join("\n")
|
|
849
|
+
: "| _(none)_ | — |";
|
|
864
850
|
|
|
865
851
|
const content = `# ${cfg.moduleName} — ThingWorx Custom Widget
|
|
866
852
|
|
|
@@ -973,7 +959,7 @@ node -e "const p = require('echarts/package.json'); console.log(p.main)"
|
|
|
973
959
|
- Zips \`build/\` → \`zip/${wName}-dev|min-<version>.zip\`
|
|
974
960
|
4. **\`upload\`** (optional) — POSTs the zip to ThingWorx via the Extension Package Uploader servlet using \`undici\`
|
|
975
961
|
`;
|
|
976
|
-
fs.writeFileSync(path.join(root,
|
|
962
|
+
fs.writeFileSync(path.join(root, "README.md"), content);
|
|
977
963
|
}
|
|
978
964
|
|
|
979
965
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -990,12 +976,12 @@ async function scaffold(cfg) {
|
|
|
990
976
|
// Create all directories upfront
|
|
991
977
|
[
|
|
992
978
|
root,
|
|
993
|
-
path.join(root,
|
|
994
|
-
path.join(root,
|
|
995
|
-
path.join(root,
|
|
996
|
-
path.join(root,
|
|
997
|
-
path.join(root,
|
|
998
|
-
].forEach(
|
|
979
|
+
path.join(root, "src", "ide"),
|
|
980
|
+
path.join(root, "src", "runtime"),
|
|
981
|
+
path.join(root, "src", "assets", "styles"),
|
|
982
|
+
path.join(root, "src", "assets", "images"),
|
|
983
|
+
path.join(root, "src", "lib"),
|
|
984
|
+
].forEach(d => fs.mkdirSync(d, { recursive: true }));
|
|
999
985
|
|
|
1000
986
|
writePackageJson(root, cfg);
|
|
1001
987
|
writeMetadataXml(root, cfg);
|
|
@@ -1011,10 +997,8 @@ async function scaffold(cfg) {
|
|
|
1011
997
|
writeReadme(root, cfg);
|
|
1012
998
|
|
|
1013
999
|
// Placeholder lib/A.js (mirrors sample project)
|
|
1014
|
-
fs.writeFileSync(
|
|
1015
|
-
|
|
1016
|
-
`/* Shared utilities — add reusable helpers here */\n`
|
|
1017
|
-
);
|
|
1000
|
+
fs.writeFileSync(path.join(root, "src", "lib", "A.js"),
|
|
1001
|
+
`/* Shared utilities — add reusable helpers here */\n`);
|
|
1018
1002
|
|
|
1019
1003
|
return root;
|
|
1020
1004
|
}
|
|
@@ -1025,26 +1009,26 @@ async function scaffold(cfg) {
|
|
|
1025
1009
|
function printTree(root, cfg) {
|
|
1026
1010
|
const wName = cfg.packageName;
|
|
1027
1011
|
const files = [
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1012
|
+
"package.json",
|
|
1013
|
+
"gulpfile.js",
|
|
1014
|
+
"metadata.xml",
|
|
1015
|
+
".eslintrc",
|
|
1016
|
+
".prettierrc",
|
|
1017
|
+
".prettierignore",
|
|
1018
|
+
".gitignore",
|
|
1019
|
+
"README.md",
|
|
1036
1020
|
`src/ide/${wName}.ide.js`,
|
|
1037
1021
|
`src/runtime/${wName}.runtime.js`,
|
|
1038
1022
|
`src/assets/styles/${wName}.ide.css`,
|
|
1039
1023
|
`src/assets/styles/${wName}.runtime.css`,
|
|
1040
|
-
|
|
1024
|
+
"src/lib/A.js",
|
|
1041
1025
|
];
|
|
1042
1026
|
|
|
1043
|
-
log(
|
|
1027
|
+
log("");
|
|
1044
1028
|
log(` ${c.bold}${wName}/${c.reset}`);
|
|
1045
1029
|
files.forEach((f, i) => {
|
|
1046
|
-
const last
|
|
1047
|
-
const prefix = last ?
|
|
1030
|
+
const last = i === files.length - 1;
|
|
1031
|
+
const prefix = last ? "└──" : "├──";
|
|
1048
1032
|
log(` ${c.dim}${prefix}${c.reset} ${f}`);
|
|
1049
1033
|
});
|
|
1050
1034
|
log(` ${c.dim}└── node_modules/ (after npm install)${c.reset}`);
|
|
@@ -1057,41 +1041,37 @@ async function main() {
|
|
|
1057
1041
|
banner();
|
|
1058
1042
|
|
|
1059
1043
|
const rl = readline.createInterface({
|
|
1060
|
-
input:
|
|
1061
|
-
output:
|
|
1044
|
+
input: process.stdin,
|
|
1045
|
+
output: process.stdout,
|
|
1062
1046
|
terminal: process.stdin.isTTY,
|
|
1063
1047
|
});
|
|
1064
1048
|
|
|
1065
1049
|
log(`${c.bold} Let's set up your ThingWorx widget!${c.reset}`);
|
|
1066
1050
|
log(` ${c.dim}Press Enter to accept defaults shown in (parentheses).${c.reset}`);
|
|
1067
|
-
log(
|
|
1068
|
-
|
|
1069
|
-
const packageName = await prompt(
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
);
|
|
1074
|
-
const
|
|
1075
|
-
const
|
|
1076
|
-
const
|
|
1077
|
-
const
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
const twxUser = await prompt(rl, 'ThingWorx username', 'Administrator');
|
|
1081
|
-
const twxPassword = await prompt(rl, 'ThingWorx password', 'yourpassword');
|
|
1082
|
-
|
|
1083
|
-
log('');
|
|
1051
|
+
log("");
|
|
1052
|
+
|
|
1053
|
+
const packageName = await prompt(rl, "Widget package name (PascalCase, e.g. MyChartWidget)", "MyWidget");
|
|
1054
|
+
const moduleName = await prompt(rl, "Display name in Composer", packageName);
|
|
1055
|
+
const description = await prompt(rl, "Short description", `${moduleName} for ThingWorx`);
|
|
1056
|
+
const version = await prompt(rl, "Version", "1.0.0");
|
|
1057
|
+
const author = await prompt(rl, "Author / vendor", "YourCompany");
|
|
1058
|
+
const minTwxVer = await prompt(rl, "Minimum ThingWorx version", "9.0.0");
|
|
1059
|
+
const twxServer = await prompt(rl, "ThingWorx server URL", "http://localhost:8085");
|
|
1060
|
+
const twxUser = await prompt(rl, "ThingWorx username", "Administrator");
|
|
1061
|
+
const twxPassword = await prompt(rl, "ThingWorx password", "yourpassword");
|
|
1062
|
+
|
|
1063
|
+
log("");
|
|
1084
1064
|
log(` ${c.cyan}?${c.reset} External npm dependencies to install (space-separated).`);
|
|
1085
1065
|
log(` ${c.dim} These will be auto-copied to build/ and added to package.json.${c.reset}`);
|
|
1086
1066
|
log(` ${c.dim} You must still add each one to metadata.xml manually (see README).${c.reset}`);
|
|
1087
1067
|
log(` ${c.dim} Example: echarts datatable xyz${c.reset}`);
|
|
1088
|
-
const depsRaw = await prompt(rl,
|
|
1068
|
+
const depsRaw = await prompt(rl, "Dependencies", "echarts");
|
|
1089
1069
|
|
|
1090
1070
|
rl.close();
|
|
1091
1071
|
|
|
1092
1072
|
const extraDeps = depsRaw
|
|
1093
1073
|
.split(/\s+/)
|
|
1094
|
-
.map(
|
|
1074
|
+
.map(d => d.trim())
|
|
1095
1075
|
.filter(Boolean);
|
|
1096
1076
|
|
|
1097
1077
|
const cfg = {
|
|
@@ -1107,56 +1087,47 @@ async function main() {
|
|
|
1107
1087
|
extraDeps,
|
|
1108
1088
|
};
|
|
1109
1089
|
|
|
1110
|
-
log(
|
|
1111
|
-
info(
|
|
1112
|
-
|
|
1113
|
-
);
|
|
1114
|
-
log('');
|
|
1090
|
+
log("");
|
|
1091
|
+
info(`Scaffolding ${c.bold}${packageName}${c.reset} with deps: ${c.yellow}${extraDeps.join(", ") || "(none)"}${c.reset}`);
|
|
1092
|
+
log("");
|
|
1115
1093
|
|
|
1116
1094
|
const root = await scaffold(cfg);
|
|
1117
1095
|
|
|
1118
|
-
ok(
|
|
1096
|
+
ok("package.json");
|
|
1119
1097
|
ok("gulpfile.js (Gulp 5 + undici — no deprecated 'request')");
|
|
1120
|
-
ok(
|
|
1121
|
-
ok(
|
|
1122
|
-
ok(
|
|
1123
|
-
ok(
|
|
1124
|
-
ok(
|
|
1125
|
-
ok(
|
|
1098
|
+
ok("metadata.xml (with dep FileResource stubs + inline instructions)");
|
|
1099
|
+
ok(".eslintrc");
|
|
1100
|
+
ok(".prettierrc");
|
|
1101
|
+
ok(".prettierignore");
|
|
1102
|
+
ok(".gitignore");
|
|
1103
|
+
ok("README.md (dep resolution guide included)");
|
|
1126
1104
|
ok(`src/ide/${packageName}.ide.js`);
|
|
1127
1105
|
ok(`src/runtime/${packageName}.runtime.js`);
|
|
1128
1106
|
ok(`src/assets/styles/${packageName}.ide.css`);
|
|
1129
1107
|
ok(`src/assets/styles/${packageName}.runtime.css`);
|
|
1130
|
-
ok(
|
|
1108
|
+
ok("src/lib/A.js");
|
|
1131
1109
|
|
|
1132
1110
|
printTree(root, cfg);
|
|
1133
1111
|
|
|
1134
|
-
log(
|
|
1112
|
+
log("");
|
|
1135
1113
|
log(` ${c.bold}${c.green}✨ Done!${c.reset} Your widget is ready.`);
|
|
1136
|
-
log(
|
|
1114
|
+
log("");
|
|
1137
1115
|
log(` ${c.dim}Next steps:${c.reset}`);
|
|
1138
1116
|
log(` ${c.cyan} cd ${packageName}${c.reset}`);
|
|
1139
1117
|
log(` ${c.cyan} npm install${c.reset}`);
|
|
1140
1118
|
if (extraDeps.length) {
|
|
1141
|
-
log(
|
|
1119
|
+
log("");
|
|
1142
1120
|
log(` ${c.yellow} ⚠️ External dependencies — manual metadata.xml step required:${c.reset}`);
|
|
1143
|
-
extraDeps.forEach(
|
|
1144
|
-
log(
|
|
1145
|
-
` ${c.yellow} • Add <FileResource type="JS" file="${dep}.js" isDevelopment="false" isRuntime="true"/> to metadata.xml${c.reset}`
|
|
1146
|
-
);
|
|
1121
|
+
extraDeps.forEach(dep => {
|
|
1122
|
+
log(` ${c.yellow} • Add <FileResource type="JS" file="${dep}.js" isDevelopment="false" isRuntime="true"/> to metadata.xml${c.reset}`);
|
|
1147
1123
|
});
|
|
1148
1124
|
log(` ${c.dim} See README.md → "External Dependencies" for the full guide.${c.reset}`);
|
|
1149
1125
|
}
|
|
1150
|
-
log(
|
|
1126
|
+
log("");
|
|
1151
1127
|
log(` ${c.cyan} npm run build${c.reset} ${c.dim}# dev build${c.reset}`);
|
|
1152
1128
|
log(` ${c.cyan} npm run buildProduction${c.reset} ${c.dim}# minified build + zip${c.reset}`);
|
|
1153
|
-
log(
|
|
1154
|
-
|
|
1155
|
-
);
|
|
1156
|
-
log('');
|
|
1129
|
+
log(` ${c.cyan} npm run upload${c.reset} ${c.dim}# build + push to ThingWorx${c.reset}`);
|
|
1130
|
+
log("");
|
|
1157
1131
|
}
|
|
1158
1132
|
|
|
1159
|
-
main().catch((e)
|
|
1160
|
-
fail(String(e));
|
|
1161
|
-
process.exit(1);
|
|
1162
|
-
});
|
|
1133
|
+
main().catch(e => { fail(String(e)); process.exit(1); });
|