@jsenv/cli 0.0.3 → 0.0.6
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 +7 -0
- package/jsenv_cli.js +358 -0
- package/package.json +7 -5
- package/template-node-package/.eslintignore +2 -0
- package/template-node-package/.eslintrc.cjs +102 -0
- package/template-node-package/.jsenv/jsenv_tests_output.txt +8 -0
- package/template-node-package/.prettierrc.yml +2 -0
- package/template-node-package/package.json +23 -0
- package/template-node-package/scripts/test.mjs +25 -0
- package/template-node-package/src/main.js +8 -0
- package/template-node-package/src/message.js +11 -0
- package/template-node-package/tests/message.test.mjs +21 -0
- package/template-web/.eslintignore +3 -0
- package/template-web/.eslintrc.cjs +138 -0
- package/template-web/.prettierrc.yml +2 -0
- package/template-web/babel.config.cjs +3 -0
- package/template-web/package.json +33 -0
- package/template-web/scripts/build.mjs +21 -0
- package/template-web/scripts/build_serve.mjs +16 -0
- package/template-web/scripts/dev.mjs +15 -0
- package/template-web/scripts/test.mjs +29 -0
- package/template-web/src/app/animals.js +11 -0
- package/template-web/src/app/counter.js +11 -0
- package/template-web/src/index.html +27 -0
- package/template-web/src/jsenv_logo.svg +140 -0
- package/template-web/src/main.css +4 -0
- package/template-web/src/main.js +31 -0
- package/template-web/src/tests/animals.test.html +32 -0
- package/template-web/src/tests/app.test.mjs +26 -0
- package/template-web-components/.eslintignore +3 -0
- package/template-web-components/.eslintrc.cjs +138 -0
- package/template-web-components/.prettierrc.yml +2 -0
- package/template-web-components/babel.config.cjs +3 -0
- package/template-web-components/package.json +35 -0
- package/template-web-components/scripts/build.mjs +21 -0
- package/template-web-components/scripts/build_serve.mjs +16 -0
- package/template-web-components/scripts/dev.mjs +15 -0
- package/template-web-components/scripts/test.mjs +29 -0
- package/template-web-components/src/app/animals.js +11 -0
- package/template-web-components/src/app/app_custom_element.css +4 -0
- package/template-web-components/src/app/app_custom_element.js +31 -0
- package/template-web-components/src/app/counter.js +11 -0
- package/template-web-components/src/app/custom_elements_redefine.js +5 -0
- package/template-web-components/src/index.html +27 -0
- package/template-web-components/src/jsenv_logo.svg +140 -0
- package/template-web-components/src/main.js +11 -0
- package/template-web-components/src/tests/animals.test.html +32 -0
- package/template-web-components/src/tests/app.test.mjs +26 -0
- package/template-web-preact/.eslintignore +3 -0
- package/template-web-preact/.eslintrc.cjs +175 -0
- package/template-web-preact/.prettierrc.yml +2 -0
- package/template-web-preact/babel.config.cjs +11 -0
- package/template-web-preact/package.json +40 -0
- package/template-web-preact/scripts/build.mjs +23 -0
- package/template-web-preact/scripts/build_serve.mjs +16 -0
- package/template-web-preact/scripts/dev.mjs +21 -0
- package/template-web-preact/scripts/test.mjs +28 -0
- package/template-web-preact/src/app/animals.js +11 -0
- package/template-web-preact/src/app/app.css +42 -0
- package/template-web-preact/src/app/app.jsx +52 -0
- package/template-web-preact/src/app/counter.jsx +20 -0
- package/template-web-preact/src/index.html +28 -0
- package/template-web-preact/src/main.jsx +5 -0
- package/template-web-preact/src/preact_logo.svg +6 -0
- package/template-web-preact/src/tests/animals.test.html +32 -0
- package/template-web-preact/src/tests/app.test.mjs +26 -0
- package/template-web-react/.eslintignore +3 -0
- package/template-web-react/.eslintrc.cjs +175 -0
- package/template-web-react/.prettierrc.yml +2 -0
- package/template-web-react/babel.config.cjs +12 -0
- package/template-web-react/package.json +41 -0
- package/template-web-react/scripts/build.mjs +23 -0
- package/template-web-react/scripts/build_serve.mjs +16 -0
- package/template-web-react/scripts/dev.mjs +21 -0
- package/template-web-react/scripts/test.mjs +28 -0
- package/template-web-react/src/app/animals.js +11 -0
- package/template-web-react/src/app/app.css +42 -0
- package/template-web-react/src/app/app.jsx +55 -0
- package/template-web-react/src/app/counter.jsx +19 -0
- package/template-web-react/src/index.html +28 -0
- package/template-web-react/src/main.jsx +14 -0
- package/template-web-react/src/react_logo.svg +7 -0
- package/template-web-react/src/tests/animals.test.html +32 -0
- package/template-web-react/src/tests/app.test.mjs +26 -0
- package/src/command_build.mjs +0 -185
- package/src/command_dev.mjs +0 -38
- package/src/command_preview.mjs +0 -22
- package/src/command_test.mjs +0 -59
- package/src/jsenv_cli.mjs +0 -66
- package/src/package_installer.js +0 -122
package/README.md
ADDED
package/jsenv_cli.js
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// see https://docs.npmjs.com/cli/v8/commands/npm-init#description
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
existsSync,
|
|
7
|
+
readdirSync,
|
|
8
|
+
mkdirSync,
|
|
9
|
+
statSync,
|
|
10
|
+
writeFileSync,
|
|
11
|
+
readFileSync,
|
|
12
|
+
} from "node:fs";
|
|
13
|
+
import { relative } from "node:path";
|
|
14
|
+
import { parseArgs } from "node:util";
|
|
15
|
+
import { pathToFileURL, fileURLToPath } from "node:url";
|
|
16
|
+
import { execSync } from "node:child_process";
|
|
17
|
+
|
|
18
|
+
import prompts from "prompts";
|
|
19
|
+
import { createTaskLog, UNICODE } from "@jsenv/humanize";
|
|
20
|
+
import { urlToRelativeUrl, ensurePathnameTrailingSlash } from "@jsenv/urls";
|
|
21
|
+
|
|
22
|
+
// not using readdir to control order
|
|
23
|
+
const availableTemplateNameArray = [
|
|
24
|
+
"web",
|
|
25
|
+
"web-components",
|
|
26
|
+
"web-react",
|
|
27
|
+
"web-preact",
|
|
28
|
+
"node-package",
|
|
29
|
+
];
|
|
30
|
+
const options = {
|
|
31
|
+
help: {
|
|
32
|
+
type: "boolean",
|
|
33
|
+
},
|
|
34
|
+
web: {
|
|
35
|
+
type: "boolean",
|
|
36
|
+
},
|
|
37
|
+
["web-components"]: {
|
|
38
|
+
type: "boolean",
|
|
39
|
+
},
|
|
40
|
+
["web-react"]: {
|
|
41
|
+
type: "boolean",
|
|
42
|
+
},
|
|
43
|
+
["web-preact"]: {
|
|
44
|
+
type: "boolean",
|
|
45
|
+
},
|
|
46
|
+
["node-package"]: {
|
|
47
|
+
type: "boolean",
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
const { values, positionals } = parseArgs({
|
|
51
|
+
options,
|
|
52
|
+
allowPositionals: true,
|
|
53
|
+
});
|
|
54
|
+
if (values.help) {
|
|
55
|
+
console.log(`@jsenv/cli: Init jsenv in a directory.
|
|
56
|
+
|
|
57
|
+
Usage: npx @jsenv/cli <dir> [options]
|
|
58
|
+
|
|
59
|
+
https://github.com/jsenv/core/tree/main/packages/related/cli
|
|
60
|
+
|
|
61
|
+
<dir> Where to install jsenv files; Otherwise you'll be prompted to select.
|
|
62
|
+
|
|
63
|
+
Options:
|
|
64
|
+
--help Display this message.
|
|
65
|
+
--web Consider directory as "web" project; Otherwise you'll be prompted to select.
|
|
66
|
+
--web-components Consider directory as "web-components" project; Otherwise you'll be prompted to select.
|
|
67
|
+
--web-react Consider directory as "web-react" project; Otherwise you'll be prompted to select.
|
|
68
|
+
--web-preact Consider directory as "web-preact" project; Otherwise you'll be prompted to select.
|
|
69
|
+
--node-package Consider directory as "node-package" project; Otherwise you'll be prompted to select.
|
|
70
|
+
`);
|
|
71
|
+
process.exit(0);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
console.log("Welcome in jsenv CLI");
|
|
75
|
+
const commands = [];
|
|
76
|
+
const cwdUrl = ensurePathnameTrailingSlash(pathToFileURL(process.cwd()));
|
|
77
|
+
let directoryUrl;
|
|
78
|
+
dir: {
|
|
79
|
+
const directoryPathFromArg = positionals[0];
|
|
80
|
+
if (directoryPathFromArg) {
|
|
81
|
+
directoryUrl = ensurePathnameTrailingSlash(
|
|
82
|
+
new URL(directoryPathFromArg, cwdUrl),
|
|
83
|
+
);
|
|
84
|
+
console.log(`${UNICODE.OK} Enter a directory: ${directoryPathFromArg}`);
|
|
85
|
+
break dir;
|
|
86
|
+
}
|
|
87
|
+
const result = await prompts(
|
|
88
|
+
{
|
|
89
|
+
type: "text",
|
|
90
|
+
name: "directory",
|
|
91
|
+
message: "Enter a directory:",
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
onCancel: () => {
|
|
95
|
+
console.log("Aborted, can be resumed any time");
|
|
96
|
+
process.exit(0);
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
);
|
|
100
|
+
directoryUrl = ensurePathnameTrailingSlash(new URL(result.directory, cwdUrl));
|
|
101
|
+
}
|
|
102
|
+
if (directoryUrl.href !== cwdUrl.href) {
|
|
103
|
+
const dir = relative(fileURLToPath(cwdUrl), fileURLToPath(directoryUrl));
|
|
104
|
+
commands.push({
|
|
105
|
+
label: `cd ${dir}`,
|
|
106
|
+
run: () => {
|
|
107
|
+
process.chdir(dir);
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
let templateName;
|
|
112
|
+
template: {
|
|
113
|
+
const templateNameFromArg = availableTemplateNameArray.find(
|
|
114
|
+
(availableTemplateName) => values[availableTemplateName],
|
|
115
|
+
);
|
|
116
|
+
if (templateNameFromArg) {
|
|
117
|
+
templateName = templateNameFromArg;
|
|
118
|
+
console.log(`${UNICODE.OK} Select a template: ${templateNameFromArg}`);
|
|
119
|
+
break template;
|
|
120
|
+
}
|
|
121
|
+
const result = await prompts(
|
|
122
|
+
[
|
|
123
|
+
{
|
|
124
|
+
type: "select",
|
|
125
|
+
name: "templateName",
|
|
126
|
+
message: "Select a template:",
|
|
127
|
+
initial: 0,
|
|
128
|
+
choices: availableTemplateNameArray.map((availableTemplateName) => {
|
|
129
|
+
return {
|
|
130
|
+
title: availableTemplateName,
|
|
131
|
+
value: availableTemplateName,
|
|
132
|
+
};
|
|
133
|
+
}),
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
{
|
|
137
|
+
onCancel: () => {
|
|
138
|
+
console.log("Aborted, can be resumed any time");
|
|
139
|
+
process.exit(0);
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
);
|
|
143
|
+
templateName = result.templateName;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
write_files: {
|
|
147
|
+
const writeFilesTask = createTaskLog(`init jsenv in "${directoryUrl}"`);
|
|
148
|
+
const mergeTwoIgnoreFileContents = (left, right) => {
|
|
149
|
+
const leftLines = String(left)
|
|
150
|
+
.split("\n")
|
|
151
|
+
.map((l) => l.trim());
|
|
152
|
+
const rightLines = String(right)
|
|
153
|
+
.split("\n")
|
|
154
|
+
.map((l) => l.trim());
|
|
155
|
+
let finalContent = left;
|
|
156
|
+
for (const rightLine of rightLines) {
|
|
157
|
+
if (!leftLines.includes(rightLine)) {
|
|
158
|
+
finalContent += "\n";
|
|
159
|
+
finalContent += rightLine;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return finalContent;
|
|
163
|
+
};
|
|
164
|
+
const overrideHandlers = {
|
|
165
|
+
"package.json": (existingContent, templateContent) => {
|
|
166
|
+
const existingPackage = JSON.parse(existingContent);
|
|
167
|
+
const templatePackage = JSON.parse(templateContent);
|
|
168
|
+
const override = (left, right, allowedKeys) => {
|
|
169
|
+
if (right === null) {
|
|
170
|
+
return left === undefined ? null : left;
|
|
171
|
+
}
|
|
172
|
+
if (Array.isArray(right)) {
|
|
173
|
+
if (Array.isArray(left)) {
|
|
174
|
+
for (const valueFromRight of right) {
|
|
175
|
+
if (!left.includes(valueFromRight)) {
|
|
176
|
+
left.push(valueFromRight);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return left;
|
|
180
|
+
}
|
|
181
|
+
return left === undefined ? right : left;
|
|
182
|
+
}
|
|
183
|
+
if (typeof right === "object") {
|
|
184
|
+
if (left && typeof left === "object") {
|
|
185
|
+
const keysToVisit = allowedKeys || Object.keys(right);
|
|
186
|
+
for (const keyToVisit of keysToVisit) {
|
|
187
|
+
const rightValue = right[keyToVisit];
|
|
188
|
+
if (rightValue === undefined) {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
const leftValue = left[keyToVisit];
|
|
192
|
+
left[keyToVisit] = override(leftValue, rightValue);
|
|
193
|
+
}
|
|
194
|
+
return left;
|
|
195
|
+
}
|
|
196
|
+
return left === undefined ? right : left;
|
|
197
|
+
}
|
|
198
|
+
return left === undefined ? right : left;
|
|
199
|
+
};
|
|
200
|
+
const existingDependencies = existingPackage.dependencies
|
|
201
|
+
? { ...existingPackage.dependencies }
|
|
202
|
+
: {};
|
|
203
|
+
const existingDevDependencies = existingPackage.devDependencies
|
|
204
|
+
? { ...existingPackage.devDependencies }
|
|
205
|
+
: {};
|
|
206
|
+
override(existingPackage, templatePackage, [
|
|
207
|
+
"scripts",
|
|
208
|
+
"dependencies",
|
|
209
|
+
"devDependencies",
|
|
210
|
+
]);
|
|
211
|
+
const finalDependencies = existingPackage.dependencies || {};
|
|
212
|
+
const finalDevDependencies = existingPackage.devDependencies || {};
|
|
213
|
+
if (
|
|
214
|
+
JSON.stringify(existingDependencies) !==
|
|
215
|
+
JSON.stringify(finalDependencies) ||
|
|
216
|
+
JSON.stringify(existingDevDependencies) !==
|
|
217
|
+
JSON.stringify(finalDevDependencies)
|
|
218
|
+
) {
|
|
219
|
+
commands.push({
|
|
220
|
+
label: "npm install",
|
|
221
|
+
run: () => {
|
|
222
|
+
console.log("npm install");
|
|
223
|
+
execSync("npm install", {
|
|
224
|
+
stdio: [0, 1, 2],
|
|
225
|
+
});
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
if (existingContent.startsWith("{\n")) {
|
|
230
|
+
return JSON.stringify(existingPackage, null, " ");
|
|
231
|
+
}
|
|
232
|
+
return JSON.stringify(existingPackage);
|
|
233
|
+
},
|
|
234
|
+
".gitignore": mergeTwoIgnoreFileContents,
|
|
235
|
+
".eslintignore": mergeTwoIgnoreFileContents,
|
|
236
|
+
};
|
|
237
|
+
const templateSourceDirectoryUrl = new URL(
|
|
238
|
+
`./template-${templateName}/`,
|
|
239
|
+
import.meta.url,
|
|
240
|
+
);
|
|
241
|
+
const copyDirectoryContent = (fromDirectoryUrl, toDirectoryUrl) => {
|
|
242
|
+
if (!existsSync(toDirectoryUrl)) {
|
|
243
|
+
mkdirSync(toDirectoryUrl, { recursive: true });
|
|
244
|
+
}
|
|
245
|
+
const directoryEntryNameArray = readdirSync(fromDirectoryUrl);
|
|
246
|
+
for (const directoryEntryName of directoryEntryNameArray) {
|
|
247
|
+
if (
|
|
248
|
+
directoryEntryName === ".jsenv" ||
|
|
249
|
+
directoryEntryName === "dist" ||
|
|
250
|
+
directoryEntryName === "node_modules"
|
|
251
|
+
) {
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
const fromUrl = new URL(directoryEntryName, fromDirectoryUrl);
|
|
255
|
+
const toUrl = new URL(
|
|
256
|
+
directoryEntryName === "_gitignore" ? ".gitignore" : directoryEntryName,
|
|
257
|
+
toDirectoryUrl,
|
|
258
|
+
);
|
|
259
|
+
const fromStat = statSync(fromUrl);
|
|
260
|
+
if (fromStat.isDirectory()) {
|
|
261
|
+
if (directoryEntryName === "src" || directoryEntryName === "tests") {
|
|
262
|
+
// copy src and tests if they don't exists
|
|
263
|
+
if (existsSync(toUrl)) {
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
// for web the presence of index.html or main.html at the root
|
|
267
|
+
// prevent src/ content from being copied
|
|
268
|
+
if (templateName.startsWith("web")) {
|
|
269
|
+
if (existsSync(new URL("./index.html", directoryUrl))) {
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
if (existsSync(new URL("./main.html", directoryUrl))) {
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
copyDirectoryContent(
|
|
278
|
+
ensurePathnameTrailingSlash(fromUrl),
|
|
279
|
+
ensurePathnameTrailingSlash(toUrl),
|
|
280
|
+
);
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
if (!existsSync(toUrl)) {
|
|
284
|
+
if (directoryEntryName === "package.json") {
|
|
285
|
+
commands.push({
|
|
286
|
+
label: "npm install",
|
|
287
|
+
run: () => {
|
|
288
|
+
console.log("npm install");
|
|
289
|
+
execSync("npm install", {
|
|
290
|
+
stdio: [0, 1, 2],
|
|
291
|
+
});
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
writeFileSync(toUrl, readFileSync(fromUrl));
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
const relativeUrl = urlToRelativeUrl(fromUrl, templateSourceDirectoryUrl);
|
|
299
|
+
const overrideHandler = overrideHandlers[relativeUrl];
|
|
300
|
+
if (!overrideHandler) {
|
|
301
|
+
// when there is no handler the file is kept as is
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
const existingContent = readFileSync(toUrl);
|
|
305
|
+
const templateContent = readFileSync(fromUrl);
|
|
306
|
+
const finalContent = overrideHandler(
|
|
307
|
+
String(existingContent),
|
|
308
|
+
String(templateContent),
|
|
309
|
+
);
|
|
310
|
+
writeFileSync(toUrl, finalContent);
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
copyDirectoryContent(
|
|
314
|
+
new URL(templateSourceDirectoryUrl),
|
|
315
|
+
new URL(directoryUrl),
|
|
316
|
+
);
|
|
317
|
+
writeFilesTask.done();
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
run_commands: {
|
|
321
|
+
if (commands.length === 0) {
|
|
322
|
+
break run_commands;
|
|
323
|
+
}
|
|
324
|
+
let message;
|
|
325
|
+
if (commands.length === 1) {
|
|
326
|
+
console.log(`----- 1 command to run -----
|
|
327
|
+
${commands[0].label}
|
|
328
|
+
---------------------------`);
|
|
329
|
+
// we can't run cd for the parent terminal
|
|
330
|
+
// so we'll just print the command in that case
|
|
331
|
+
// and user will have to run it if he want to go into the
|
|
332
|
+
// directory
|
|
333
|
+
if (commands[0].label.startsWith("cd")) {
|
|
334
|
+
console.log("Done, thank you");
|
|
335
|
+
process.exit(0);
|
|
336
|
+
}
|
|
337
|
+
message = "Can we run the command";
|
|
338
|
+
} else {
|
|
339
|
+
console.log(`----- ${commands.length} commands to run -----
|
|
340
|
+
${commands.map((c) => c.label).join("\n")}
|
|
341
|
+
-----------------------------`);
|
|
342
|
+
message = "Can we run the commands";
|
|
343
|
+
}
|
|
344
|
+
const { value } = await prompts({
|
|
345
|
+
type: "confirm",
|
|
346
|
+
name: "value",
|
|
347
|
+
message,
|
|
348
|
+
initial: true,
|
|
349
|
+
});
|
|
350
|
+
if (!value) {
|
|
351
|
+
console.log("Done, thank you");
|
|
352
|
+
process.exit(0);
|
|
353
|
+
}
|
|
354
|
+
for (const command of commands) {
|
|
355
|
+
await command.run();
|
|
356
|
+
}
|
|
357
|
+
console.log("Done, thank you");
|
|
358
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Command Line Interface for jsenv",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -20,13 +20,15 @@
|
|
|
20
20
|
},
|
|
21
21
|
"type": "module",
|
|
22
22
|
"bin": {
|
|
23
|
-
"jsenv": "
|
|
23
|
+
"jsenv": "jsenv_cli.js"
|
|
24
24
|
},
|
|
25
25
|
"files": [
|
|
26
|
-
"./
|
|
26
|
+
"./jsenv_cli.js",
|
|
27
|
+
"./template-*/**"
|
|
27
28
|
],
|
|
28
29
|
"dependencies": {
|
|
29
|
-
"
|
|
30
|
-
"@jsenv/
|
|
30
|
+
"@jsenv/humanize": "1.2.4",
|
|
31
|
+
"@jsenv/urls": "2.3.0",
|
|
32
|
+
"prompts": "2.4.2"
|
|
31
33
|
}
|
|
32
34
|
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file uses "@jsenv/eslint-config" to configure ESLint
|
|
3
|
+
* See https://github.com/jsenv/eslint-config#eslint-config----
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
composeEslintConfig,
|
|
8
|
+
eslintConfigBase,
|
|
9
|
+
eslintConfigForPrettier,
|
|
10
|
+
eslintConfigToPreferExplicitGlobals,
|
|
11
|
+
jsenvEslintRules,
|
|
12
|
+
jsenvEslintRulesForImport,
|
|
13
|
+
} = require("@jsenv/eslint-config");
|
|
14
|
+
|
|
15
|
+
const eslintConfig = composeEslintConfig(
|
|
16
|
+
eslintConfigBase,
|
|
17
|
+
|
|
18
|
+
// enable top level await
|
|
19
|
+
{
|
|
20
|
+
parserOptions: {
|
|
21
|
+
ecmaVersion: 2022,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
// Files in this repository are all meant to be executed in Node.js
|
|
26
|
+
// and we want to tell this to ESLint.
|
|
27
|
+
// As a result ESLint can consider `window` as undefined
|
|
28
|
+
// and `global` as an existing global variable.
|
|
29
|
+
{
|
|
30
|
+
env: {
|
|
31
|
+
node: true,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
// Reuse jsenv eslint rules
|
|
36
|
+
{
|
|
37
|
+
rules: {
|
|
38
|
+
...jsenvEslintRules,
|
|
39
|
+
// Example of code changing the ESLint configuration to enable a rule:
|
|
40
|
+
// 'prefer-const': ['error']
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
// Enable import plugin
|
|
45
|
+
{
|
|
46
|
+
plugins: ["import"],
|
|
47
|
+
settings: {
|
|
48
|
+
"import/resolver": {
|
|
49
|
+
"@jsenv/eslint-import-resolver": {
|
|
50
|
+
rootDirectoryUrl: __dirname,
|
|
51
|
+
packageConditions: ["node", "import"],
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
"import/extensions": [".js", ".mjs"],
|
|
55
|
+
},
|
|
56
|
+
rules: jsenvEslintRulesForImport,
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
// package is "type": "module" so:
|
|
60
|
+
// 1. disable commonjs globals by default
|
|
61
|
+
// 2. Re-enable commonjs into *.cjs files
|
|
62
|
+
{
|
|
63
|
+
globals: {
|
|
64
|
+
__filename: "off",
|
|
65
|
+
__dirname: "off",
|
|
66
|
+
require: "off",
|
|
67
|
+
exports: "off",
|
|
68
|
+
},
|
|
69
|
+
overrides: [
|
|
70
|
+
{
|
|
71
|
+
files: ["**/*.cjs"],
|
|
72
|
+
env: {
|
|
73
|
+
commonjs: true,
|
|
74
|
+
},
|
|
75
|
+
// inside *.cjs files. restore commonJS "globals"
|
|
76
|
+
globals: {
|
|
77
|
+
__filename: true,
|
|
78
|
+
__dirname: true,
|
|
79
|
+
require: true,
|
|
80
|
+
exports: true,
|
|
81
|
+
},
|
|
82
|
+
// inside *.cjs files, use commonjs module resolution
|
|
83
|
+
settings: {
|
|
84
|
+
"import/resolver": {
|
|
85
|
+
"@jsenv/eslint-import-resolver": {
|
|
86
|
+
rootDirectoryUrl: __dirname,
|
|
87
|
+
packageConditions: ["node", "require"],
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
eslintConfigToPreferExplicitGlobals,
|
|
96
|
+
|
|
97
|
+
// We are using prettier, disable all eslint rules
|
|
98
|
+
// already handled by prettier.
|
|
99
|
+
eslintConfigForPrettier,
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
module.exports = eslintConfig;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
------------- 1 execution ready -------------
|
|
2
|
+
directory: /Users/damien.maillard/dev/perso/jsenv-core/packages/related/create-jsenv/demo-node-package
|
|
3
|
+
---------------------------------------------
|
|
4
|
+
✔ 1/1 tests/message.test.mjs [0.02s] (all completed)
|
|
5
|
+
------------- 1 execution done --------------
|
|
6
|
+
status: all completed
|
|
7
|
+
duration: 0.1s (setup: 0.004s, execution: 0.1s, teardown: 0s)
|
|
8
|
+
---------------------------------------------
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jsenv-template-node-package",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./src/main.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "node ./scripts/test.mjs",
|
|
11
|
+
"test:coverage": "npm run test -- --coverage"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@jsenv/assert": "4.1.4",
|
|
15
|
+
"@jsenv/core": "39.2.1",
|
|
16
|
+
"@jsenv/eslint-config": "16.5.2",
|
|
17
|
+
"@jsenv/eslint-import-resolver": "8.1.2",
|
|
18
|
+
"@jsenv/test": "3.3.11",
|
|
19
|
+
"eslint": "8.56.0",
|
|
20
|
+
"eslint-plugin-import": "2.29.1",
|
|
21
|
+
"prettier": "3.3.3"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Execute all test files
|
|
3
|
+
* - npm test
|
|
4
|
+
* - npm test:coverage
|
|
5
|
+
* Read more in https://github.com/jsenv/core/tree/main/packages/test#jsenvtest-
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { executeTestPlan, nodeWorkerThread } from "@jsenv/test";
|
|
9
|
+
|
|
10
|
+
await executeTestPlan({
|
|
11
|
+
rootDirectoryUrl: new URL("../", import.meta.url),
|
|
12
|
+
testPlan: {
|
|
13
|
+
"./tests/**/*.test.mjs": {
|
|
14
|
+
node: {
|
|
15
|
+
runtime: nodeWorkerThread(),
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
coverage: process.argv.includes("--coverage")
|
|
20
|
+
? {
|
|
21
|
+
methodForNodeJs: "Profiler",
|
|
22
|
+
}
|
|
23
|
+
: false,
|
|
24
|
+
githubCheck: false,
|
|
25
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is the entry point of this codebase
|
|
3
|
+
* - It is responsible to export the documented API
|
|
4
|
+
* - It should be kept simple (just re-export) to help reader to
|
|
5
|
+
* discover codebase progressively
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export { getMessage, getMessageAsync } from "./message.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file test the public exports of "jsenv-template-node"
|
|
3
|
+
* - It illustrates how to test code
|
|
4
|
+
* - It illustrates how to use top level await to test code
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { assert } from "@jsenv/assert";
|
|
8
|
+
|
|
9
|
+
import { getMessage, getMessageAsync } from "jsenv-template-node-package";
|
|
10
|
+
|
|
11
|
+
{
|
|
12
|
+
const actual = getMessage();
|
|
13
|
+
const expect = "Hello dev!";
|
|
14
|
+
assert({ actual, expect });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
{
|
|
18
|
+
const actual = await getMessageAsync();
|
|
19
|
+
const expect = "Hello dev async!";
|
|
20
|
+
assert({ actual, expect });
|
|
21
|
+
}
|