@travetto/scaffold 2.1.1 → 2.2.0

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.
@@ -12,6 +12,7 @@ import { Feature, FEATURES } from './lib/features';
12
12
  export class ScaffoldPlugin extends BasePlugin {
13
13
  name = 'scaffold';
14
14
 
15
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
15
16
  getOptions() {
16
17
  return {
17
18
  template: this.option({ def: 'todo', desc: 'Template' }),
@@ -20,11 +21,11 @@ export class ScaffoldPlugin extends BasePlugin {
20
21
  };
21
22
  }
22
23
 
23
- getArgs() {
24
+ getArgs(): string {
24
25
  return '[name]';
25
26
  }
26
27
 
27
- async #getName(name?: string) {
28
+ async #getName(name?: string): Promise<string> {
28
29
  if (!name) {
29
30
  const res = await enquirer.prompt<{ name: string }>([
30
31
  {
@@ -39,14 +40,15 @@ export class ScaffoldPlugin extends BasePlugin {
39
40
  }
40
41
 
41
42
  async #chooseFeature(feature: Feature): Promise<Feature | undefined> {
42
- const res = await enquirer.prompt<{ choice: string }>({
43
+ const choice: (Parameters<typeof enquirer['prompt']>[0] & { type: 'select' }) = {
43
44
  type: 'select' as const,
44
45
  name: 'choice',
45
46
  message: 'Please select one',
46
47
  initial: feature.default,
47
- choices: feature.choices!.map(x => x.title),
48
- } as Parameters<typeof enquirer['prompt']>[0]);
48
+ choices: feature.choices!.map(x => x.title).filter((x?: string): x is string => !!x),
49
+ };
49
50
 
51
+ const res = await enquirer.prompt<{ choice: string }>(choice);
50
52
  return feature.choices?.find(x => x.title === res.choice);
51
53
  }
52
54
 
@@ -79,11 +81,13 @@ export class ScaffoldPlugin extends BasePlugin {
79
81
  }
80
82
  }
81
83
 
82
- async action(name?: string) {
84
+ async action(name?: string): Promise<void> {
83
85
  try {
84
86
  name = await this.#getName(name);
85
87
  } catch (err) {
86
- console.error('Failed to provide correct input', err.message);
88
+ if (err instanceof Error) {
89
+ console.error('Failed to provide correct input', err.message);
90
+ }
87
91
  process.exit(1);
88
92
  }
89
93
 
@@ -100,7 +104,9 @@ export class ScaffoldPlugin extends BasePlugin {
100
104
  await ctx.addDependency(dep);
101
105
  }
102
106
  } catch (err) {
103
- console.error('Failed to provide correct input', err.message);
107
+ if (err instanceof Error) {
108
+ console.error('Failed to provide correct input', err.message);
109
+ }
104
110
  process.exit(1);
105
111
  }
106
112
 
@@ -2,7 +2,7 @@ import * as path from 'path';
2
2
  import * as fs from 'fs/promises';
3
3
  import * as mustache from 'mustache';
4
4
 
5
- import { EnvUtil, ExecUtil, FsUtil, PathUtil } from '@travetto/boot';
5
+ import { EnvUtil, ExecUtil, ExecutionResult, FsUtil, PathUtil } from '@travetto/boot';
6
6
  import { version } from '@travetto/boot/package.json';
7
7
 
8
8
  import { Feature } from './features';
@@ -12,7 +12,7 @@ type Listing = Record<string, ListingEntry>;
12
12
 
13
13
  export class Context {
14
14
 
15
- static #meetsRequirement(modules: string[], desired: string[]) {
15
+ static #meetsRequirement(modules: string[], desired: string[]): boolean {
16
16
  let valid = true;
17
17
  for (const mod of desired) {
18
18
  if (mod.endsWith('-')) {
@@ -46,43 +46,44 @@ export class Context {
46
46
  this.#targetDir = PathUtil.resolveUnix(targetDir);
47
47
  }
48
48
 
49
- get modules() {
49
+ get modules(): Record<string, boolean> {
50
50
  if (!this.#modules) {
51
51
  this.#modules = this.#frameworkDependencies.map(x => x.split('/')).reduce((acc, [, v]) => ({ ...acc, [v]: true }), {});
52
52
  }
53
53
  return this.#modules;
54
54
  }
55
55
 
56
- get frameworkDependencies() {
56
+ get frameworkDependencies(): string[] {
57
57
  return this.#frameworkDependencies;
58
58
  }
59
59
 
60
- get peerDependencies() {
60
+ get peerDependencies(): string[] {
61
61
  return this.#peerDependencies;
62
62
  }
63
63
 
64
- get moduleNames() {
64
+ get moduleNames(): string[] {
65
65
  return [...Object.keys(this.modules)].filter(x => !x.includes('-'));
66
66
  }
67
67
 
68
- source(file?: string) {
68
+ source(file?: string): string {
69
69
  return PathUtil.resolveUnix(__dirname, '..', '..', 'templates', this.#template, ...file ? [file] : []);
70
70
  }
71
71
 
72
- destination(file?: string) {
72
+ destination(file?: string): string {
73
73
  return PathUtil.resolveUnix(this.#targetDir, ...file ? [file] : []);
74
74
  }
75
75
 
76
- get sourceListing() {
76
+ get sourceListing(): Promise<Listing> {
77
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
77
78
  return import(this.source('listing.json')) as Promise<Listing>;
78
79
  }
79
80
 
80
- async resolvedSourceListing() {
81
+ async resolvedSourceListing(): Promise<[string, ListingEntry][]> {
81
82
  return Object.entries(await this.sourceListing)
82
83
  .filter(([, conf]) => !conf.requires || Context.#meetsRequirement(this.#frameworkDependencies, conf.requires));
83
84
  }
84
85
 
85
- async initialize() {
86
+ async initialize(): Promise<void> {
86
87
  let base = this.destination();
87
88
  while (base) {
88
89
  if (await FsUtil.exists(`${base}/package.json`)) {
@@ -96,7 +97,7 @@ export class Context {
96
97
  }
97
98
  }
98
99
 
99
- async template(file: string, { rename }: ListingEntry) {
100
+ async template(file: string, { rename }: ListingEntry): Promise<void> {
100
101
  const contents = await fs.readFile(this.source(file), 'utf-8');
101
102
  const out = this.destination(rename ?? file);
102
103
  const rendered = mustache.render(contents, this).replace(/^\s*(\/\/|#)\s*\n/gsm, '');
@@ -104,13 +105,13 @@ export class Context {
104
105
  await fs.writeFile(out, rendered, 'utf8');
105
106
  }
106
107
 
107
- async templateResolvedFiles() {
108
+ async templateResolvedFiles(): Promise<void> {
108
109
  for (const [key, config] of await this.resolvedSourceListing()) {
109
110
  await this.template(key, config);
110
111
  }
111
112
  }
112
113
 
113
- async addDependency(feat: Feature) {
114
+ async addDependency(feat: Feature): Promise<void> {
114
115
  if (feat.npm.startsWith('@travetto')) {
115
116
  this.#frameworkDependencies.push(feat.npm);
116
117
  } else {
@@ -122,7 +123,7 @@ export class Context {
122
123
  }
123
124
  }
124
125
 
125
- exec(cmd: string, args: string[]) {
126
+ exec(cmd: string, args: string[]): Promise<ExecutionResult> {
126
127
  return ExecUtil.spawn(cmd, args, { cwd: this.destination(), stdio: [0, 1, 2], isolatedEnv: true }).result;
127
128
  }
128
129
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@travetto/scaffold",
3
3
  "displayName": "App Scaffold",
4
- "version": "2.1.1",
4
+ "version": "2.2.0",
5
5
  "description": "App Scaffold for the Travetto framework",
6
6
  "keywords": [
7
7
  "generator",
@@ -32,13 +32,13 @@
32
32
  "trv-scaffold": "./bin/trv-scaffold.js"
33
33
  },
34
34
  "dependencies": {
35
- "@travetto/boot": "^2.1.1",
36
- "@travetto/cli": "^2.1.1",
35
+ "@travetto/boot": "^2.2.0",
36
+ "@travetto/cli": "^2.2.0",
37
37
  "mustache": "^4.2.0",
38
38
  "enquirer": "^2.3.6"
39
39
  },
40
40
  "devDependencies": {
41
- "@types/mustache": "^4.1.2"
41
+ "@types/mustache": "^4.1.3"
42
42
  },
43
43
  "docDependencies": {
44
44
  "@travetto/auth-rest": true,
@@ -24,7 +24,9 @@
24
24
  ],
25
25
  "rules": {
26
26
  "@typescript-eslint/array-type": "error",
27
- "@typescript-eslint/explicit-function-return-type": "off",
27
+ "@typescript-eslint/explicit-function-return-type": [
28
+ "off"
29
+ ],
28
30
  "@typescript-eslint/no-non-null-assertion": "off",
29
31
  "@typescript-eslint/no-explicit-any": "warn",
30
32
  "@typescript-eslint/explicit-member-accessibility": [
@@ -39,10 +41,14 @@
39
41
  2,
40
42
  {
41
43
  "ignoredNodes": [
44
+ "PropertyDefinition[decorators]",
45
+ "TSUnionType",
46
+ "TSTypeParameterInstantiation",
42
47
  "FunctionExpression > .params[decorators.length > 0]",
43
48
  "FunctionExpression > .params > :matches(Decorator, :not(:first-child))",
44
49
  "ClassBody.body > PropertyDefinition[decorators.length > 0] > .key"
45
- ]
50
+ ],
51
+ "SwitchCase": 1
46
52
  }
47
53
  ],
48
54
  "@typescript-eslint/member-delimiter-style": [
@@ -209,6 +215,28 @@
209
215
  "PascalCase",
210
216
  "camelCase"
211
217
  ]
218
+ },
219
+ {
220
+ "selector": "objectLiteralProperty",
221
+ "modifiers": [
222
+ "requiresQuotes"
223
+ ],
224
+ "format": null,
225
+ "custom": {
226
+ "regex": ".*",
227
+ "match": true
228
+ }
229
+ },
230
+ {
231
+ "selector": "objectLiteralMethod",
232
+ "modifiers": [
233
+ "requiresQuotes"
234
+ ],
235
+ "format": null,
236
+ "custom": {
237
+ "regex": ".*",
238
+ "match": true
239
+ }
212
240
  }
213
241
  ],
214
242
  "curly": "error",
@@ -297,6 +325,12 @@
297
325
  ]
298
326
  }
299
327
  }
328
+ ],
329
+ "@typescript-eslint/consistent-type-assertions": [
330
+ "warn",
331
+ {
332
+ "assertionStyle": "never"
333
+ }
300
334
  ]
301
335
  },
302
336
  "overrides": [