create-lwr 0.6.0 → 0.6.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.
package/build/es/index.js CHANGED
@@ -2,9 +2,7 @@
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
4
  import minimist from 'minimist';
5
- import { green, blue, red } from 'kolorist';
6
- import prompts from 'prompts';
7
- import { isEmpty, isValidPackageName, toValidPackageName, emptyDir, copy, pkgFromUserAgent, } from './utils.js';
5
+ import { emptyDir, copy, pkgFromUserAgent, promptForAnswers, updateLwrVersion } from './utils.js';
8
6
  import { dirname } from 'path';
9
7
  import { fileURLToPath } from 'url';
10
8
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -13,144 +11,73 @@ const argv = minimist(process.argv.slice(2), { string: ['_'] });
13
11
  const renameFiles = {
14
12
  _gitignore: '.gitignore',
15
13
  };
16
- const PROJECTS = [
17
- {
18
- name: 'Static Site',
19
- color: green,
20
- variants: [
21
- {
22
- name: 'markdown-static-site',
23
- display: 'Markdown Static Site',
24
- color: green,
25
- },
26
- ],
27
- },
28
- {
29
- name: 'Single Page App',
30
- color: green,
31
- variants: [
32
- {
33
- name: 'lwc',
34
- display: 'LWC',
35
- color: green,
36
- },
37
- {
38
- name: 'lwc-ts',
39
- display: 'LWC (TypeScript)',
40
- color: blue,
41
- },
42
- ],
43
- },
44
- ];
45
- const TEMPLATES = PROJECTS.map((f) => (f.variants && f.variants.map((v) => v.name)) || [f.name]).reduce((a, b) => a.concat(b), []);
46
14
  export async function init() {
47
- let targetDir = argv._[0];
48
- let template = argv.template || argv.t;
49
- const defaultProjectName = !targetDir ? 'lwr-project' : targetDir;
50
- let result = {};
15
+ const targetDir = argv._[0];
16
+ const metadata = {
17
+ targetDir,
18
+ template: argv.template || argv.t,
19
+ defaultProjectName: !targetDir ? 'lwr-project' : targetDir,
20
+ };
21
+ let userFeedback = {};
51
22
  try {
52
- result = await prompts([
53
- {
54
- type: targetDir ? null : 'text',
55
- name: 'projectName',
56
- message: 'Project name:',
57
- initial: defaultProjectName,
58
- onState: (state) => (targetDir = state.value.trim() || defaultProjectName),
59
- },
60
- {
61
- type: () => (!fs.existsSync(targetDir) || isEmpty(targetDir) ? null : 'confirm'),
62
- name: 'overwrite',
63
- message: () => (targetDir === '.' ? 'Current directory' : `Target directory "${targetDir}"`) +
64
- ` is not empty. Remove existing files and continue?`,
65
- },
66
- {
67
- type: (_, { overwrite } = {}) => {
68
- if (overwrite === false) {
69
- throw new Error(red('✖') + ' Operation cancelled');
70
- }
71
- return null;
72
- },
73
- name: 'overwriteChecker',
74
- },
75
- {
76
- type: () => (isValidPackageName(targetDir) ? null : 'text'),
77
- name: 'packageName',
78
- message: 'Package name:',
79
- initial: () => toValidPackageName(targetDir),
80
- validate: (dir) => isValidPackageName(dir) || 'Invalid package.json name',
81
- },
82
- {
83
- type: template && TEMPLATES.includes(template) ? null : 'select',
84
- name: 'projectType',
85
- message: typeof template === 'string' && !TEMPLATES.includes(template)
86
- ? `"${template}" isn't a valid template. Please choose from below: `
87
- : 'Select a type of project:',
88
- initial: 0,
89
- choices: PROJECTS.map((project_type) => {
90
- const frameworkColor = project_type.color;
91
- return {
92
- title: frameworkColor(project_type.name),
93
- value: project_type,
94
- };
95
- }),
96
- },
97
- {
98
- type: (project_type) => project_type && project_type.variants ? 'select' : null,
99
- name: 'variant',
100
- message: 'Select a variant:',
101
- choices: (project_type) => project_type.variants.map((variant) => {
102
- const variantColor = variant.color;
103
- return {
104
- title: variantColor(variant.display || variant.name),
105
- value: variant.name,
106
- };
107
- }),
108
- },
109
- ], {
110
- onCancel: () => {
111
- throw new Error(red('✖') + ' Operation cancelled');
112
- },
113
- });
23
+ userFeedback = await promptForAnswers(metadata);
114
24
  }
115
25
  catch (cancelled) {
116
26
  console.log(cancelled.message);
117
27
  return;
118
28
  }
119
- // user choice associated with prompts
120
- const { projectType, overwrite, packageName, variant } = result;
121
- const root = path.join(cwd, targetDir);
29
+ const { results: { overwrite, packageName, template }, } = userFeedback;
30
+ const { metadata: revisedMetadata } = userFeedback;
31
+ const projectRoot = path.join(cwd, revisedMetadata.targetDir);
32
+ createRootDir(projectRoot, revisedMetadata, overwrite, template);
33
+ const templateDir = path.join(__dirname, '../../', `template-${revisedMetadata.template}`);
34
+ writeFiles(projectRoot, templateDir);
35
+ const pkgManager = writePackageFile(projectRoot, templateDir, packageName, revisedMetadata);
36
+ logResult(projectRoot, pkgManager);
37
+ }
38
+ function createRootDir(projectRoot, metadata, overwrite, template) {
122
39
  if (overwrite) {
123
- emptyDir(root);
40
+ emptyDir(projectRoot);
124
41
  }
125
- else if (!fs.existsSync(root)) {
126
- fs.mkdirSync(root);
42
+ else if (!fs.existsSync(projectRoot)) {
43
+ fs.mkdirSync(projectRoot, { recursive: true });
127
44
  }
128
45
  // determine template
129
- template = variant || projectType || template;
130
- console.log(`\nScaffolding project in ${root}...`);
131
- const templateDir = path.join(__dirname, '../../', `template-${template}`);
132
- const write = (file, content) => {
133
- const targetPath = renameFiles[file] ? path.join(root, renameFiles[file]) : path.join(root, file);
134
- if (content) {
135
- fs.writeFileSync(targetPath, content);
136
- }
137
- else {
138
- copy(path.join(templateDir, file), targetPath);
139
- }
140
- };
46
+ metadata.template = template || metadata.template;
47
+ console.log(`\nScaffolding project in ${projectRoot}...`);
48
+ }
49
+ const write = (projectRoot, templateDir, file, content) => {
50
+ const targetPath = renameFiles[file]
51
+ ? path.join(projectRoot, renameFiles[file])
52
+ : path.join(projectRoot, file);
53
+ if (content) {
54
+ fs.writeFileSync(targetPath, content);
55
+ }
56
+ else {
57
+ copy(path.join(templateDir, file), targetPath);
58
+ }
59
+ };
60
+ function writeFiles(projectRoot, templateDir) {
141
61
  const files = fs.readdirSync(templateDir);
142
62
  for (const file of files.filter((f) => f !== 'package.json')) {
143
- write(file);
63
+ write(projectRoot, templateDir, file);
144
64
  }
65
+ }
66
+ function writePackageFile(projectRoot, templateDir, packageName, metadata) {
145
67
  // modify package json name
146
68
  const pkg = JSON.parse(fs.readFileSync(path.join(templateDir, `package.json`), 'utf-8'));
147
- pkg.name = packageName || targetDir;
148
- write('package.json', JSON.stringify(pkg, null, 2));
69
+ pkg.name = packageName || metadata.targetDir;
70
+ // Set the target lwr package version equal to this create-lwr package version
71
+ updateLwrVersion(templateDir, pkg);
72
+ write(projectRoot, templateDir, 'package.json', JSON.stringify(pkg, null, 2));
149
73
  const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent);
150
74
  const pkgManager = pkgInfo ? pkgInfo.name : 'npm';
75
+ return pkgManager;
76
+ }
77
+ function logResult(projectRoot, pkgManager) {
151
78
  console.log(`\nDone. Now run:\n`);
152
- if (root !== cwd) {
153
- console.log(` cd ${path.relative(cwd, root)}`);
79
+ if (projectRoot !== cwd) {
80
+ console.log(` cd ${path.relative(cwd, projectRoot)}`);
154
81
  }
155
82
  switch (pkgManager) {
156
83
  case 'yarn':
@@ -0,0 +1,26 @@
1
+ export interface ProjectTemplate {
2
+ name: string;
3
+ display: string;
4
+ color: any;
5
+ }
6
+ export interface ProjectType {
7
+ name: string;
8
+ color: any;
9
+ templates: ProjectTemplate[];
10
+ }
11
+ export interface ProjectMetadata {
12
+ targetDir?: string;
13
+ template?: string;
14
+ defaultProjectName: string;
15
+ }
16
+ export declare type NormalizedProjectMetadata = Required<ProjectMetadata>;
17
+ export interface Answers {
18
+ overwrite: boolean;
19
+ packageName: string;
20
+ template: string;
21
+ }
22
+ export interface AnswersWithMetadata {
23
+ results: Answers;
24
+ metadata: NormalizedProjectMetadata;
25
+ }
26
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -1,11 +1,15 @@
1
- export declare function isEmpty(path: string): boolean;
2
- export declare function isValidPackageName(projectName: string): boolean;
3
- export declare function toValidPackageName(projectName: string): string;
1
+ import { AnswersWithMetadata, ProjectType, ProjectMetadata } from './types';
2
+ export declare const PROJECTS: ProjectType[];
4
3
  export declare function emptyDir(dir: string): void;
5
4
  export declare function copy(src: string, dest: string): void;
6
- export declare function copyDir(srcDir: string, destDir: string): void;
7
5
  export declare function pkgFromUserAgent(userAgent: string | undefined): {
8
6
  name: string;
9
7
  version: string;
10
8
  } | undefined;
9
+ export declare function updateLwrVersion(templateDir: string, pkg: {
10
+ dependencies?: {
11
+ lwr?: string;
12
+ };
13
+ }): void;
14
+ export declare function promptForAnswers(metadata: ProjectMetadata): Promise<AnswersWithMetadata>;
11
15
  //# sourceMappingURL=utils.d.ts.map
package/build/es/utils.js CHANGED
@@ -1,12 +1,44 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- export function isEmpty(path) {
3
+ import { red, green, blue } from 'kolorist';
4
+ import prompts from 'prompts';
5
+ export const PROJECTS = [
6
+ {
7
+ name: 'Static Site',
8
+ color: green,
9
+ templates: [
10
+ {
11
+ name: 'markdown-static-site',
12
+ display: 'Markdown Static Site',
13
+ color: green,
14
+ },
15
+ ],
16
+ },
17
+ {
18
+ name: 'Single Page App',
19
+ color: green,
20
+ templates: [
21
+ {
22
+ name: 'lwc',
23
+ display: 'LWC',
24
+ color: green,
25
+ },
26
+ {
27
+ name: 'lwc-ts',
28
+ display: 'LWC (TypeScript)',
29
+ color: blue,
30
+ },
31
+ ],
32
+ },
33
+ ];
34
+ const TEMPLATES = PROJECTS.map((t) => (t.templates && t.templates.map((t) => t.name)) || [t.name]).reduce((a, b) => a.concat(b), []);
35
+ function isDirEmpty(path) {
4
36
  return fs.readdirSync(path).length === 0;
5
37
  }
6
- export function isValidPackageName(projectName) {
38
+ function isValidPackageName(projectName) {
7
39
  return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(projectName);
8
40
  }
9
- export function toValidPackageName(projectName) {
41
+ function toValidPackageName(projectName) {
10
42
  return projectName
11
43
  .trim()
12
44
  .toLowerCase()
@@ -14,15 +46,17 @@ export function toValidPackageName(projectName) {
14
46
  .replace(/^[._]/, '')
15
47
  .replace(/[^a-z0-9-~]+/g, '-');
16
48
  }
49
+ // Recursively empty the given directory
17
50
  export function emptyDir(dir) {
18
51
  if (!fs.existsSync(dir)) {
19
52
  return;
20
53
  }
21
54
  for (const file of fs.readdirSync(dir)) {
22
55
  const abs = path.resolve(dir, file);
23
- fs.rmSync(abs);
56
+ fs.rmSync(abs, { recursive: true, force: true });
24
57
  }
25
58
  }
59
+ // Copy a directory or file to a new destination
26
60
  export function copy(src, dest) {
27
61
  const stat = fs.statSync(src);
28
62
  if (stat.isDirectory()) {
@@ -32,7 +66,8 @@ export function copy(src, dest) {
32
66
  fs.copyFileSync(src, dest);
33
67
  }
34
68
  }
35
- export function copyDir(srcDir, destDir) {
69
+ /* istanbul ignore next */
70
+ function copyDir(srcDir, destDir) {
36
71
  fs.mkdirSync(destDir, { recursive: true });
37
72
  for (const file of fs.readdirSync(srcDir)) {
38
73
  const srcFile = path.resolve(srcDir, file);
@@ -50,4 +85,93 @@ export function pkgFromUserAgent(userAgent) {
50
85
  version: pkgSpecArr[1],
51
86
  };
52
87
  }
88
+ export function updateLwrVersion(templateDir, pkg) {
89
+ const createLwrPkg = JSON.parse(fs.readFileSync(path.join(templateDir, `../package.json`), 'utf-8'));
90
+ const version = createLwrPkg.version;
91
+ if (!pkg.dependencies) {
92
+ pkg.dependencies = { lwr: version };
93
+ }
94
+ else {
95
+ pkg.dependencies.lwr = version;
96
+ }
97
+ }
98
+ // Gather project information from the user in the terminal
99
+ export async function promptForAnswers(metadata) {
100
+ const results = await prompts([
101
+ {
102
+ // Get the project name, used as the LWR project directory and saved as metadata.targetDir
103
+ type: metadata.targetDir ? null : 'text',
104
+ name: 'projectName',
105
+ message: 'Project directory name:',
106
+ initial: metadata.defaultProjectName,
107
+ onState: (state) => (metadata.targetDir = state.value.trim() || metadata.defaultProjectName),
108
+ },
109
+ {
110
+ // If the targetDir is not empty, ask if the current contents should be deleted (i.e. overwritten)
111
+ type: () => !fs.existsSync(metadata.targetDir) || isDirEmpty(metadata.targetDir)
112
+ ? null
113
+ : 'confirm',
114
+ name: 'overwrite',
115
+ message: () => (metadata.targetDir === '.'
116
+ ? 'Current directory'
117
+ : `Target directory "${metadata.targetDir}"`) +
118
+ ` is not empty. Remove existing files and continue?`,
119
+ },
120
+ {
121
+ // If the current contents SHOULD NOT be overwritten, throw an error and exit
122
+ type: (_, { overwrite } = {}) => {
123
+ if (overwrite === false) {
124
+ throw new Error(red('✖') + ' Operation cancelled');
125
+ }
126
+ return null;
127
+ },
128
+ name: 'overwriteChecker',
129
+ },
130
+ {
131
+ // If the projectName/targetDir is not a valid package.json[name], prompt for a new one
132
+ type: () => (isValidPackageName(metadata.targetDir) ? null : 'text'),
133
+ name: 'packageName',
134
+ message: 'Package name (used in package.json):',
135
+ initial: () => toValidPackageName(metadata.targetDir),
136
+ validate: (dir) => isValidPackageName(dir) || 'Invalid package.json name',
137
+ },
138
+ {
139
+ // Select a project type, if the user has not passed in a "--template"
140
+ type: metadata.template && TEMPLATES.includes(metadata.template) ? null : 'select',
141
+ name: 'projectType',
142
+ message: typeof metadata.template === 'string' && !TEMPLATES.includes(metadata.template)
143
+ ? `"${metadata.template}" isn't a valid template. Please choose from below: `
144
+ : 'Select the type of project:',
145
+ initial: 0,
146
+ choices: PROJECTS.map((project_type) => {
147
+ const frameworkColor = project_type.color;
148
+ return {
149
+ title: frameworkColor(project_type.name),
150
+ value: project_type,
151
+ };
152
+ }),
153
+ },
154
+ {
155
+ // If the user picked a project type (i.e. "project_type") in the previous prompt, now choose a template
156
+ type: (project_type) => (project_type && project_type.templates ? 'select' : null),
157
+ name: 'template',
158
+ message: 'Select a project template:',
159
+ choices: (project_type) => project_type.templates.map((template) => {
160
+ const templateColor = template.color;
161
+ return {
162
+ title: templateColor(template.display || template.name),
163
+ value: template.name,
164
+ };
165
+ }),
166
+ },
167
+ ], {
168
+ onCancel: () => {
169
+ throw new Error(red('✖') + ' Operation cancelled');
170
+ },
171
+ });
172
+ return {
173
+ results,
174
+ metadata: metadata, // possible mutation of metadata in prompts
175
+ };
176
+ }
53
177
  //# sourceMappingURL=utils.js.map
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "url": "https://github.com/salesforce/lwr/issues"
11
11
  },
12
12
  "bin": {
13
- "create-lwc": "build/es/index.js"
13
+ "create-lwr": "build/es/index.js"
14
14
  },
15
15
  "scripts": {
16
16
  "local:bin": "node ./build/es/index.js"
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "type": "module",
23
23
  "types": "build/es/index.d.ts",
24
- "version": "0.6.0",
24
+ "version": "0.6.4",
25
25
  "module": "build/es/index.js",
26
26
  "main": "build/cjs/index.cjs",
27
27
  "files": [
@@ -39,5 +39,5 @@
39
39
  "minimist": "^1.2.5",
40
40
  "prompts": "^2.4.1"
41
41
  },
42
- "gitHead": "31769655f0155ad7e54cf37bccdf72d0baaf44ab"
42
+ "gitHead": "80b73fe4558dc3db0afcdbe80eb17f5a1464e34e"
43
43
  }
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "lwc": "2.5.8",
16
- "lwr": "0.6.0-alpha.14"
16
+ "lwr": "0.6.1"
17
17
  },
18
18
  "engines": {
19
19
  "node": ">=14.15.4 <17"
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "lwc": "2.5.8",
16
- "lwr": "0.6.0-alpha.14"
16
+ "lwr": "0.6.1"
17
17
  },
18
18
  "engines": {
19
19
  "node": ">=14.15.4 <17"
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "lwc": "2.5.8",
16
- "lwr": "0.6.0-alpha.14"
16
+ "lwr": "0.6.1"
17
17
  },
18
18
  "engines": {
19
19
  "node": ">=14.15.4 <17"