sn-typescript-util 1.4.2 → 1.5.1

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/README.md CHANGED
@@ -29,7 +29,7 @@ Using TypeScript, the CLI provides an enhanced developer workflow.
29
29
 
30
30
  - [Node.js](https://nodejs.org/)
31
31
  - [ServiceNow Extension for VS Code](https://marketplace.visualstudio.com/items?itemName=ServiceNow.now-vscode)
32
- - An [imported application](https://docs.servicenow.com/bundle/vancouver-application-development/page/build/applications/task/vscode-import-application.html) in VS Code
32
+ - An [imported application](https://docs.servicenow.com/bundle/washingtondc-application-development/page/build/applications/task/vscode-import-application.html) in VS Code
33
33
 
34
34
  **[Back to top](#table-of-contents)**
35
35
 
@@ -59,7 +59,7 @@ After installation & setup, simply run the TypeScript compiler `--watch` command
59
59
  tsc --watch
60
60
  ```
61
61
 
62
- Any JavaScript ES2015 (ES6) code added will get converted down to ES5 and moved to the `src` directory. Then changes are ready to sync with the target instance using the ServiceNow Extension for VS Code.
62
+ The TypeScript will get transpiled to ES5 (or other ECMAScript target) and moved to the `src` directory. Then changes are ready to sync with the target instance using the ServiceNow Extension for VS Code.
63
63
 
64
64
  **[Back to top](#table-of-contents)**
65
65
 
package/bin/snts.js CHANGED
@@ -3,21 +3,63 @@ import { $ } from 'execa';
3
3
  import { Command } from 'commander';
4
4
  import { execFile } from 'node:child_process';
5
5
  import path from 'path';
6
- import { readFileSync, writeFileSync } from 'fs';
6
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
7
7
  import { fileURLToPath } from 'url';
8
- import { bold, cyan, gray, magenta, red } from 'colorette';
9
- import { intro, outro, spinner } from '@clack/prompts';
8
+ import { bold, cyan, gray, green, magenta, red } from 'colorette';
9
+ import { confirm, intro, outro, select, spinner } from '@clack/prompts';
10
+ async function addFile(sourcefile, sourceDir, targetFile, targetDir, message) {
11
+ if (await confirmFile(message)) {
12
+ const file = await getTargetPath(targetFile, targetDir);
13
+ const filePath = getFilePath(sourcefile, sourceDir);
14
+ createFile(file, filePath);
15
+ }
16
+ }
17
+ async function addInterfaceFile() {
18
+ return await addFile(
19
+ 'base-table.ts',
20
+ 'scripts/templates',
21
+ 'BaseTable.ts',
22
+ 'ts/Types',
23
+ `${getConstants().confirmInterfaceMsg}`
24
+ );
25
+ }
26
+ async function addPrettierFile() {
27
+ return await addFile(
28
+ '.prettierrc.json',
29
+ 'scripts/templates',
30
+ '.prettierrc.json',
31
+ null,
32
+ `${getConstants().confirmPrettierMsg}`
33
+ );
34
+ }
35
+ async function confirmFile(msg) {
36
+ return await confirm({
37
+ message: `${msg}`
38
+ });
39
+ }
40
+ async function createFile(file, path) {
41
+ const template = readFileSync(path, 'utf8');
42
+ return await writeFile(file, template);
43
+ }
10
44
  async function createTemplate(file, path) {
11
45
  const project = await getProject();
12
46
  const template = readFileSync(path, 'utf8');
13
- const updatedContent = template.replace(/@project/g, project);
14
- return await writeFile(file, updatedContent);
47
+ const data = template.replace(/@project/g, project);
48
+ return await writeFile(file, data);
15
49
  }
16
50
  async function doBuild() {
17
- const s = startPrompts('Installing configs', 'Build started');
51
+ introPrompt(`${bold(magenta(getConstants().projectName))}: Build`);
52
+ const esVersion = await getConfigTypes();
53
+ await addInterfaceFile();
54
+ await addPrettierFile();
55
+ await initGitRepo();
56
+ const s = startPrompts('Installing config(s)', null);
18
57
  const filePath = getFilePath('tsconfig.json', 'scripts/templates');
19
58
  await createTemplate('tsconfig.json', filePath);
20
- stopPrompt(s, 'Configs installed');
59
+ const template = readFileSync('tsconfig.json', 'utf8');
60
+ const data = template.replace(/@version/g, esVersion);
61
+ await writeFile('tsconfig.json', data);
62
+ stopPrompt(s, `The ${cyan('tsconfig.json')} file was bootstrapped.`);
21
63
  runSync();
22
64
  }
23
65
  async function doClean() {
@@ -43,16 +85,37 @@ async function doSync() {
43
85
  return stdout;
44
86
  });
45
87
  }
88
+ function getConfigTargets() {
89
+ return [
90
+ { value: 'es5', label: 'ES5', hint: 'recommended' },
91
+ { value: 'es6', label: 'ES2015', hint: 'ES6' },
92
+ { value: 'es2021', label: 'ES2021' }
93
+ ];
94
+ }
95
+ async function getConfigTypes() {
96
+ return select({
97
+ message: 'Please pick a ECMAScript target.',
98
+ options: getConfigTargets()
99
+ });
100
+ }
46
101
  function getConstants() {
47
102
  let Constants;
48
103
  (function (Constants) {
49
104
  Constants['projectName'] = 'SN TypeScript Util';
50
105
  Constants['projectDescription'] =
51
106
  'is a TS utility for ServiceNow developers using VS Code.';
107
+ Constants[
108
+ (Constants['confirmInterfaceMsg'] =
109
+ `Add a ${cyan('BaseTable.ts')} interface with global default fields?`)
110
+ ] = 'confirmInterfaceMsg';
111
+ Constants[
112
+ (Constants['confirmPrettierMsg'] =
113
+ `Add a ${cyan('.prettierrc.json')} default config?`)
114
+ ] = 'confirmPrettierMsg';
52
115
  Constants['errorMsg'] =
53
116
  'No active application detected. Please create a project with the ServiceNow Extension for VS Code.';
54
117
  Constants['docsUrl'] =
55
- 'https://docs.servicenow.com/bundle/vancouver-application-development/page/build/applications/task/create-project.html';
118
+ 'https://docs.servicenow.com/bundle/washingtondc-application-development/page/build/applications/task/create-project.html';
56
119
  Constants['buildOption'] =
57
120
  'Build project utility files & package dependencies';
58
121
  Constants['compileOption'] =
@@ -76,7 +139,7 @@ function getErrorMsg() {
76
139
  const msg = `${constants.errorMsg}\n\n${constants.docsUrl}`;
77
140
  return console.error(bold(red(msg)));
78
141
  }
79
- function getFilePath(file, dir = 'scripts/build') {
142
+ function getFilePath(file, dir) {
80
143
  const fileName = fileURLToPath(import.meta.url);
81
144
  const dirName = path.dirname(fileName);
82
145
  return `${path.join(dirName, `../${dir}`)}/${file}`;
@@ -110,6 +173,12 @@ async function getProject() {
110
173
  const workspace = await getWorkspace();
111
174
  return workspace.ACTIVE_APPLICATION;
112
175
  }
176
+ async function getTargetPath(file, dir) {
177
+ const project = await getProject();
178
+ const path = dir ? `${project}/${dir}/` : '.';
179
+ dir && !existsSync(path) && mkdirSync(path, { recursive: true });
180
+ return `${path}/${file}`;
181
+ }
113
182
  async function getVersion() {
114
183
  const info = await getPackageInfo();
115
184
  return info.version;
@@ -157,6 +226,10 @@ async function init() {
157
226
  program.usage(cyan('[options]'));
158
227
  return doOptions(program);
159
228
  }
229
+ async function initGitRepo() {
230
+ const msg = `Initialize a new git repository?`;
231
+ return (await confirmFile(msg)) && (await $`git init`);
232
+ }
160
233
  function introPrompt(msg) {
161
234
  return intro(msg);
162
235
  }
@@ -165,10 +238,14 @@ function parseOptions(program) {
165
238
  return options && Object.keys(program.opts()).toString();
166
239
  }
167
240
  async function runSync() {
241
+ const project = await getProject();
168
242
  const s = startPrompts('Syncing', null);
169
243
  return await execFile(getFilePath('sync.sh', 'scripts/build'), (stdout) => {
170
- stopPrompt(s, 'Sync completed');
171
- outro('Completed');
244
+ stopPrompt(
245
+ s,
246
+ `TypeScript files constructed in the ${cyan(project + '/ts')} directory.`
247
+ );
248
+ outro(`${green('Done!')}`);
172
249
  return stdout;
173
250
  });
174
251
  }
package/bun.lockb CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sn-typescript-util",
3
- "version": "1.4.2",
3
+ "version": "1.5.1",
4
4
  "description": "A TypeScript utility for ServiceNow developers using VS Code",
5
5
  "bin": {
6
6
  "snts": "bin/snts.js"
@@ -27,15 +27,15 @@
27
27
  "@clack/prompts": "^0.7.0",
28
28
  "colorette": "^2.0.20",
29
29
  "commander": "^12.0.0",
30
- "execa": "^8.0.1",
30
+ "execa": "^9.1.0",
31
31
  "typescript": "^5.4.5"
32
32
  },
33
33
  "devDependencies": {
34
- "@eslint/js": "^9.0.0",
34
+ "@eslint/js": "^9.3.0",
35
35
  "@types/commander": "^2.12.2",
36
- "bun-types": "^1.1.3",
37
- "eslint": "^9.0.0",
36
+ "bun-types": "^1.1.8",
37
+ "eslint": "^9.3.0",
38
38
  "prettier": "^3.2.5",
39
- "typescript-eslint": "^7.7.0"
39
+ "typescript-eslint": "^7.9.0"
40
40
  }
41
41
  }
package/scripts/snts.ts CHANGED
@@ -4,25 +4,78 @@ import { $ } from 'execa';
4
4
  import { Command } from 'commander';
5
5
  import { execFile } from 'node:child_process';
6
6
  import path from 'path';
7
- import { readFileSync, writeFileSync } from 'fs';
7
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
8
8
  import { fileURLToPath } from 'url';
9
- import { bold, cyan, gray, magenta, red } from 'colorette';
10
- import { intro, outro, spinner } from '@clack/prompts';
9
+ import { bold, cyan, gray, green, magenta, red } from 'colorette';
10
+ import { confirm, intro, outro, select, spinner } from '@clack/prompts';
11
11
  import { Options } from './types/options.js';
12
12
  import { Workspace } from './types/workspace.js';
13
13
 
14
+ async function addFile(
15
+ sourcefile: string,
16
+ sourceDir: string,
17
+ targetFile: string,
18
+ targetDir: string | any,
19
+ message: string
20
+ ) {
21
+ if (await confirmFile(message)) {
22
+ const file = await getTargetPath(targetFile, targetDir);
23
+ const filePath = getFilePath(sourcefile, sourceDir);
24
+ createFile(file, filePath);
25
+ }
26
+ }
27
+
28
+ async function addInterfaceFile() {
29
+ return await addFile(
30
+ 'base-table.ts',
31
+ 'scripts/templates',
32
+ 'BaseTable.ts',
33
+ 'ts/Types',
34
+ `${getConstants().confirmInterfaceMsg}`
35
+ );
36
+ }
37
+
38
+ async function addPrettierFile() {
39
+ return await addFile(
40
+ '.prettierrc.json',
41
+ 'scripts/templates',
42
+ '.prettierrc.json',
43
+ null,
44
+ `${getConstants().confirmPrettierMsg}`
45
+ );
46
+ }
47
+
48
+ async function confirmFile(msg: string) {
49
+ return await confirm({
50
+ message: `${msg}`
51
+ });
52
+ }
53
+
54
+ async function createFile(file: string, path: string): Promise<void> {
55
+ const template = readFileSync(path, 'utf8');
56
+ return await writeFile(file, template);
57
+ }
58
+
14
59
  async function createTemplate(file: string, path: string): Promise<void> {
15
60
  const project = await getProject();
16
61
  const template = readFileSync(path, 'utf8');
17
- const updatedContent = template.replace(/@project/g, project);
18
- return await writeFile(file, updatedContent);
62
+ const data = template.replace(/@project/g, project);
63
+ return await writeFile(file, data);
19
64
  }
20
65
 
21
66
  async function doBuild() {
22
- const s = startPrompts('Installing configs', 'Build started');
67
+ introPrompt(`${bold(magenta(getConstants().projectName))}: Build`);
68
+ const esVersion: any = await getConfigTypes();
69
+ await addInterfaceFile();
70
+ await addPrettierFile();
71
+ await initGitRepo();
72
+ const s = startPrompts('Installing config(s)', null);
23
73
  const filePath = getFilePath('tsconfig.json', 'scripts/templates');
24
74
  await createTemplate('tsconfig.json', filePath);
25
- stopPrompt(s, 'Configs installed');
75
+ const template = readFileSync('tsconfig.json', 'utf8');
76
+ const data = template.replace(/@version/g, esVersion);
77
+ await writeFile('tsconfig.json', data);
78
+ stopPrompt(s, `The ${cyan('tsconfig.json')} file was bootstrapped.`);
26
79
  runSync();
27
80
  }
28
81
 
@@ -56,12 +109,29 @@ async function doSync() {
56
109
  );
57
110
  }
58
111
 
112
+ function getConfigTargets() {
113
+ return [
114
+ { value: 'es5', label: 'ES5', hint: 'recommended' },
115
+ { value: 'es6', label: 'ES2015', hint: 'ES6' },
116
+ { value: 'es2021', label: 'ES2021' }
117
+ ];
118
+ }
119
+
120
+ async function getConfigTypes() {
121
+ return select({
122
+ message: 'Please pick a ECMAScript target.',
123
+ options: getConfigTargets()
124
+ });
125
+ }
126
+
59
127
  function getConstants() {
60
128
  enum Constants {
61
129
  projectName = 'SN TypeScript Util',
62
130
  projectDescription = 'is a TS utility for ServiceNow developers using VS Code.',
131
+ confirmInterfaceMsg = `Add a ${cyan('BaseTable.ts')} interface with global default fields?`,
132
+ confirmPrettierMsg = `Add a ${cyan('.prettierrc.json')} default config?`,
63
133
  errorMsg = 'No active application detected. Please create a project with the ServiceNow Extension for VS Code.',
64
- docsUrl = 'https://docs.servicenow.com/bundle/vancouver-application-development/page/build/applications/task/create-project.html',
134
+ docsUrl = 'https://docs.servicenow.com/bundle/washingtondc-application-development/page/build/applications/task/create-project.html',
65
135
  buildOption = 'Build project utility files & package dependencies',
66
136
  compileOption = 'Compile TypeScript files to JavaScript & move to src',
67
137
  helpOption = 'Display help for command',
@@ -85,7 +155,7 @@ function getErrorMsg() {
85
155
  return console.error(bold(red(msg)));
86
156
  }
87
157
 
88
- function getFilePath(file: string, dir: string = 'scripts/build') {
158
+ function getFilePath(file: string, dir: string) {
89
159
  const fileName = fileURLToPath(import.meta.url);
90
160
  const dirName = path.dirname(fileName);
91
161
  return `${path.join(dirName, `../${dir}`)}/${file}`;
@@ -123,6 +193,13 @@ async function getProject() {
123
193
  return workspace.ACTIVE_APPLICATION;
124
194
  }
125
195
 
196
+ async function getTargetPath(file: string, dir: string) {
197
+ const project = await getProject();
198
+ const path = dir ? `${project}/${dir}/` : '.';
199
+ dir && !existsSync(path) && mkdirSync(path, { recursive: true });
200
+ return `${path}/${file}`;
201
+ }
202
+
126
203
  async function getVersion() {
127
204
  const info = await getPackageInfo();
128
205
  return info.version;
@@ -181,6 +258,11 @@ async function init() {
181
258
  return doOptions(program);
182
259
  }
183
260
 
261
+ async function initGitRepo() {
262
+ const msg = `Initialize a new git repository?`;
263
+ return (await confirmFile(msg)) && (await $`git init`);
264
+ }
265
+
184
266
  function introPrompt(msg: string) {
185
267
  return intro(msg);
186
268
  }
@@ -191,12 +273,16 @@ function parseOptions(program: Command) {
191
273
  }
192
274
 
193
275
  async function runSync() {
276
+ const project = await getProject();
194
277
  const s = startPrompts('Syncing', null);
195
278
  return await execFile(
196
279
  getFilePath('sync.sh', 'scripts/build'),
197
280
  (stdout: unknown) => {
198
- stopPrompt(s, 'Sync completed');
199
- outro('Completed');
281
+ stopPrompt(
282
+ s,
283
+ `TypeScript files constructed in the ${cyan(project + '/ts')} directory.`
284
+ );
285
+ outro(`${green('Done!')}`);
200
286
  return stdout;
201
287
  }
202
288
  );
@@ -0,0 +1,8 @@
1
+ interface BaseTable {
2
+ readonly sys_created_on?: Date;
3
+ readonly sys_created_by?: string;
4
+ readonly sys_id?: string;
5
+ readonly sys_mod_count?: number;
6
+ readonly sys_updated_by?: string;
7
+ readonly sys_updated_on?: Date;
8
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "es5",
3
+ "target": "@version",
4
4
  "outDir": "@project/src",
5
5
  "baseUrl": ".",
6
6
  "skipLibCheck": true