create-thingworx-widget2 1.0.2 → 1.0.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.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- 'use strict';
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: '\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',
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 = (...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}`);
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
- `${c.bold}${c.blue} ████████╗██╗ ██╗██╗███╗ ██╗ ██████╗ ██╗ ██╗ ██████╗ ██████╗ ██╗ ██╗${c.reset}`
33
- );
34
- log(
35
- `${c.blue} ██╔══╝██║ ██║██║████╗ ██║██╔════╝ ██║ ██║██╔═══██╗██╔══██╗╚██╗██╔╝${c.reset}`
36
- );
37
- log(
38
- `${c.blue} ██║ ███████║██║██╔██╗ ██║██║ ███╗██║ █╗ ██║██║ ██║██████╔╝ ╚███╔╝${c.reset}`
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((resolve) => {
59
- const hint = defaultVal ? `${c.dim}(${defaultVal})${c.reset} ` : '';
60
- rl.question(` ${c.cyan}?${c.reset} ${question} ${hint}: `, (ans) => {
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 = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
73
- return pkg.main || 'index.js';
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] = '*'; // user can pin versions manually
73
+ deps[dep] = "*"; // user can pin versions manually
88
74
  }
89
75
 
90
76
  const devDeps = {
91
- '@babel/core': '^7.0.0-beta.46',
92
- '@babel/preset-env': '^7.0.0-beta.46',
93
- '@types/jquery': '^3.3.1',
94
- '@types/node': '^8.10.11',
95
- 'babel-plugin-remove-import-export': '^1.1.0',
96
- del: '^5.0.0',
97
- 'delete-empty': '^3.0.0',
98
- eslint: '^10.4.1',
99
- 'eslint-config-prettier': '^10.1.8',
100
- 'form-data': '^4.0.5',
101
- gulp: '^5.0.1',
102
- 'gulp-babel': '^8.0.0',
103
- 'gulp-concat': '^2.6.1',
104
- 'gulp-terser': '^1.2.0',
105
- 'gulp-zip': '^5.0.0',
106
- prettier: '^3.8.3',
107
- undici: '^7.26.0',
108
- xml2js: '^0.6.2',
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: cfg.packageName.toLowerCase().replace(/\s+/g, '-'),
113
- packageName: cfg.packageName,
114
- moduleName: cfg.moduleName,
115
- version: cfg.version,
116
- description: cfg.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: cfg.twxUser,
104
+ thingworxUser: cfg.twxUser,
119
105
  thingworxPassword: cfg.twxPassword,
120
- author: cfg.author,
106
+ author: cfg.author,
121
107
  minimumThingWorxVersion: cfg.minTwxVersion,
122
- homepage: '',
123
- autoUpdate: { gitHubURL: '' },
124
- repository: { type: 'git', url: '' },
108
+ homepage: "",
109
+ autoUpdate: { gitHubURL: "" },
110
+ repository: { type: "git", url: "" },
125
111
  scripts: {
126
- test: 'echo "Error: no test specified" && exit 1',
127
- build: 'gulp',
128
- buildProduction: 'gulp --p',
129
- upload: 'gulp upload',
130
- uploadProduction: 'gulp upload --p',
131
- format: 'prettier --write src/**/*.js',
132
- 'format:check': 'prettier --check src/**/*.js',
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: 'MIT',
135
- files: ['lib', 'build', 'LICENSE'],
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, 'package.json'), JSON.stringify(content, null, 4));
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 = cfg.packageName;
145
- const jsIde = `ide\\${wName}.ide.js`;
146
- const jsRuntime = `runtime\\${wName}.runtime.js`;
147
- const cssIde = `assets\\styles\\${wName}.ide.css`;
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
- .map(
153
- (dep) =>
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 + '\n' : ''}
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, 'metadata.xml'), content);
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, 'gulpfile.js'), content);
473
+ fs.writeFileSync(path.join(root, "gulpfile.js"), content);
478
474
  }
479
475
 
480
476
  function writeIdeJs(root, cfg) {
@@ -551,7 +547,7 @@ TW.IDE.Widgets.${wName} = function () {
551
547
 
552
548
  this.renderHtml = function () {
553
549
  return [
554
- '<div class="${wName.toLowerCase()}-ide-wrapper">',
550
+ '<div class="widget-content ${wName.toLowerCase()}-ide-wrapper">',
555
551
  ' <span class="${wName.toLowerCase()}-ide-label">📊 ${cfg.moduleName}</span>',
556
552
  '</div>',
557
553
  ].join('');
@@ -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, 'src', 'ide');
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 = wName.toLowerCase();
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
- .map((d) => ` // ${d} (from node_modules → copied to build as ${d}.js)`)
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, 'src', 'runtime');
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, 'src', 'assets', 'styles');
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, 'src', 'assets', 'styles');
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, '.eslintrc'), content);
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, '.prettierrc'), content);
827
+ fs.writeFileSync(path.join(root, ".prettierrc"), content);
835
828
  }
836
829
 
837
830
  function writePrettierIgnore(root) {
838
- fs.writeFileSync(
839
- path.join(root, '.prettierignore'),
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
- path.join(root, '.gitignore'),
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
- .map((dep) => {
858
- const mainFile =
859
- resolveDepMain(dep) || '(see node_modules/' + dep + '/package.json → main)';
860
- return `| \`${dep}\` | \`node_modules/${dep}/${mainFile}\` |`;
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, 'README.md'), content);
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, 'src', 'ide'),
994
- path.join(root, 'src', 'runtime'),
995
- path.join(root, 'src', 'assets', 'styles'),
996
- path.join(root, 'src', 'assets', 'images'),
997
- path.join(root, 'src', 'lib'),
998
- ].forEach((d) => fs.mkdirSync(d, { recursive: true }));
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
- path.join(root, 'src', 'lib', 'A.js'),
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
- 'package.json',
1029
- 'gulpfile.js',
1030
- 'metadata.xml',
1031
- '.eslintrc',
1032
- '.prettierrc',
1033
- '.prettierignore',
1034
- '.gitignore',
1035
- 'README.md',
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
- 'src/lib/A.js',
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 = i === files.length - 1;
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: process.stdin,
1061
- output: process.stdout,
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
- rl,
1071
- 'Widget package name (PascalCase, e.g. MyChartWidget)',
1072
- 'MyWidget'
1073
- );
1074
- const moduleName = await prompt(rl, 'Display name in Composer', packageName);
1075
- const description = await prompt(rl, 'Short description', `${moduleName} for ThingWorx`);
1076
- const version = await prompt(rl, 'Version', '1.0.0');
1077
- const author = await prompt(rl, 'Author / vendor', 'YourCompany');
1078
- const minTwxVer = await prompt(rl, 'Minimum ThingWorx version', '9.0.0');
1079
- const twxServer = await prompt(rl, 'ThingWorx server URL', 'http://localhost:8085');
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, 'Dependencies', 'echarts');
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((d) => d.trim())
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
- `Scaffolding ${c.bold}${packageName}${c.reset} with deps: ${c.yellow}${extraDeps.join(', ') || '(none)'}${c.reset}`
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('package.json');
1096
+ ok("package.json");
1119
1097
  ok("gulpfile.js (Gulp 5 + undici — no deprecated 'request')");
1120
- ok('metadata.xml (with dep FileResource stubs + inline instructions)');
1121
- ok('.eslintrc');
1122
- ok('.prettierrc');
1123
- ok('.prettierignore');
1124
- ok('.gitignore');
1125
- ok('README.md (dep resolution guide included)');
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('src/lib/A.js');
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((dep) => {
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
- ` ${c.cyan} npm run upload${c.reset} ${c.dim}# build + push to ThingWorx${c.reset}`
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); });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-thingworx-widget2",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Scaffold a ThingWorx custom widget project — like npm create vite@latest but for ThingWorx.",
5
5
  "keywords": [
6
6
  "thingworx",