create-lwr 0.6.0 → 0.6.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/build/es/index.js +47 -122
- package/build/es/types.d.ts +26 -0
- package/build/es/types.js +2 -0
- package/build/es/utils.d.ts +3 -4
- package/build/es/utils.js +119 -5
- package/package.json +3 -3
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 {
|
|
6
|
-
import prompts from 'prompts';
|
|
7
|
-
import { isEmpty, isValidPackageName, toValidPackageName, emptyDir, copy, pkgFromUserAgent, } from './utils.js';
|
|
5
|
+
import { emptyDir, copy, pkgFromUserAgent, promptForAnswers } 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,71 @@ 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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
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
|
-
|
|
120
|
-
const {
|
|
121
|
-
const
|
|
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(
|
|
40
|
+
emptyDir(projectRoot);
|
|
124
41
|
}
|
|
125
|
-
else if (!fs.existsSync(
|
|
126
|
-
fs.mkdirSync(
|
|
42
|
+
else if (!fs.existsSync(projectRoot)) {
|
|
43
|
+
fs.mkdirSync(projectRoot, { recursive: true });
|
|
127
44
|
}
|
|
128
45
|
// determine template
|
|
129
|
-
template =
|
|
130
|
-
console.log(`\nScaffolding project in ${
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
+
write(projectRoot, templateDir, 'package.json', JSON.stringify(pkg, null, 2));
|
|
149
71
|
const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent);
|
|
150
72
|
const pkgManager = pkgInfo ? pkgInfo.name : 'npm';
|
|
73
|
+
return pkgManager;
|
|
74
|
+
}
|
|
75
|
+
function logResult(projectRoot, pkgManager) {
|
|
151
76
|
console.log(`\nDone. Now run:\n`);
|
|
152
|
-
if (
|
|
153
|
-
console.log(` cd ${path.relative(cwd,
|
|
77
|
+
if (projectRoot !== cwd) {
|
|
78
|
+
console.log(` cd ${path.relative(cwd, projectRoot)}`);
|
|
154
79
|
}
|
|
155
80
|
switch (pkgManager) {
|
|
156
81
|
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
|
package/build/es/utils.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
export declare
|
|
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 promptForAnswers(metadata: ProjectMetadata): Promise<AnswersWithMetadata>;
|
|
11
10
|
//# 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
|
-
|
|
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
|
-
|
|
38
|
+
function isValidPackageName(projectName) {
|
|
7
39
|
return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(projectName);
|
|
8
40
|
}
|
|
9
|
-
|
|
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
|
-
|
|
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,83 @@ export function pkgFromUserAgent(userAgent) {
|
|
|
50
85
|
version: pkgSpecArr[1],
|
|
51
86
|
};
|
|
52
87
|
}
|
|
88
|
+
// Gather project information from the user in the terminal
|
|
89
|
+
export async function promptForAnswers(metadata) {
|
|
90
|
+
const results = await prompts([
|
|
91
|
+
{
|
|
92
|
+
// Get the project name, used as the LWR project directory and saved as metadata.targetDir
|
|
93
|
+
type: metadata.targetDir ? null : 'text',
|
|
94
|
+
name: 'projectName',
|
|
95
|
+
message: 'Project directory name:',
|
|
96
|
+
initial: metadata.defaultProjectName,
|
|
97
|
+
onState: (state) => (metadata.targetDir = state.value.trim() || metadata.defaultProjectName),
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
// If the targetDir is not empty, ask if the current contents should be deleted (i.e. overwritten)
|
|
101
|
+
type: () => !fs.existsSync(metadata.targetDir) || isDirEmpty(metadata.targetDir)
|
|
102
|
+
? null
|
|
103
|
+
: 'confirm',
|
|
104
|
+
name: 'overwrite',
|
|
105
|
+
message: () => (metadata.targetDir === '.'
|
|
106
|
+
? 'Current directory'
|
|
107
|
+
: `Target directory "${metadata.targetDir}"`) +
|
|
108
|
+
` is not empty. Remove existing files and continue?`,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
// If the current contents SHOULD NOT be overwritten, throw an error and exit
|
|
112
|
+
type: (_, { overwrite } = {}) => {
|
|
113
|
+
if (overwrite === false) {
|
|
114
|
+
throw new Error(red('✖') + ' Operation cancelled');
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
},
|
|
118
|
+
name: 'overwriteChecker',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
// If the projectName/targetDir is not a valid package.json[name], prompt for a new one
|
|
122
|
+
type: () => (isValidPackageName(metadata.targetDir) ? null : 'text'),
|
|
123
|
+
name: 'packageName',
|
|
124
|
+
message: 'Package name (used in package.json):',
|
|
125
|
+
initial: () => toValidPackageName(metadata.targetDir),
|
|
126
|
+
validate: (dir) => isValidPackageName(dir) || 'Invalid package.json name',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
// Select a project type, if the user has not passed in a "--template"
|
|
130
|
+
type: metadata.template && TEMPLATES.includes(metadata.template) ? null : 'select',
|
|
131
|
+
name: 'projectType',
|
|
132
|
+
message: typeof metadata.template === 'string' && !TEMPLATES.includes(metadata.template)
|
|
133
|
+
? `"${metadata.template}" isn't a valid template. Please choose from below: `
|
|
134
|
+
: 'Select the type of project:',
|
|
135
|
+
initial: 0,
|
|
136
|
+
choices: PROJECTS.map((project_type) => {
|
|
137
|
+
const frameworkColor = project_type.color;
|
|
138
|
+
return {
|
|
139
|
+
title: frameworkColor(project_type.name),
|
|
140
|
+
value: project_type,
|
|
141
|
+
};
|
|
142
|
+
}),
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
// If the user picked a project type (i.e. "project_type") in the previous prompt, now choose a template
|
|
146
|
+
type: (project_type) => (project_type && project_type.templates ? 'select' : null),
|
|
147
|
+
name: 'template',
|
|
148
|
+
message: 'Select a project template:',
|
|
149
|
+
choices: (project_type) => project_type.templates.map((template) => {
|
|
150
|
+
const templateColor = template.color;
|
|
151
|
+
return {
|
|
152
|
+
title: templateColor(template.display || template.name),
|
|
153
|
+
value: template.name,
|
|
154
|
+
};
|
|
155
|
+
}),
|
|
156
|
+
},
|
|
157
|
+
], {
|
|
158
|
+
onCancel: () => {
|
|
159
|
+
throw new Error(red('✖') + ' Operation cancelled');
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
return {
|
|
163
|
+
results,
|
|
164
|
+
metadata: metadata, // possible mutation of metadata in prompts
|
|
165
|
+
};
|
|
166
|
+
}
|
|
53
167
|
//# 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-
|
|
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.
|
|
24
|
+
"version": "0.6.1",
|
|
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": "
|
|
42
|
+
"gitHead": "4d7c44dfae958fe24ef1c94b0f60aa2b15e12f24"
|
|
43
43
|
}
|