milkee 3.1.2 → 3.1.3-dev.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.
- package/README-ja.md +4 -0
- package/README.md +4 -0
- package/dist/commands/compile.js +7 -7
- package/dist/commands/plugin.js +41 -41
- package/dist/commands/setup.js +6 -6
- package/dist/lib/checks.js +1 -1
- package/dist/lib/plugins.js +2 -2
- package/dist/main.js +3 -3
- package/dist/options/confirm.js +3 -3
- package/dist/options/copy.js +5 -5
- package/dist/options/refresh.js +9 -9
- package/docs/PLUGIN-ja.md +1 -1
- package/docs/PLUGIN.md +1 -1
- package/package.json +3 -3
- package/.prettierrc.json +0 -3
- package/test/integration/setup.cli.test.js +0 -36
- package/test/setup.js +0 -113
- package/test/unit/checks.test.js +0 -38
- package/test/unit/copy.test.js +0 -50
- package/test/unit/plugins.test.js +0 -50
- package/test/unit/refresh.test.js +0 -63
- package/test/unit/sandbox-windows.test.js +0 -14
- package/test/unit/setup.test.js +0 -70
- package/test/unit/src.smoke.test.js +0 -56
- package/test/unit/utils.test.js +0 -41
- package/vitest.config.mjs +0 -14
package/README-ja.md
CHANGED
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/milkee)
|
|
6
6
|
[](./LICENSE)
|
|
7
7
|
|
|
8
|
+
<a href="https://www.buymeacoffee.com/devuloper" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>
|
|
9
|
+
|
|
10
|
+
<a href='https://ko-fi.com/E1E41LY2C9' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi6.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
|
|
11
|
+
|
|
8
12
|
[English](./README.md) | **日本語**
|
|
9
13
|
|
|
10
14
|
[](https://milkee.org)
|
package/README.md
CHANGED
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/milkee)
|
|
6
6
|
[](./LICENSE)
|
|
7
7
|
|
|
8
|
+
<a href="https://www.buymeacoffee.com/devuloper" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>
|
|
9
|
+
|
|
10
|
+
<a href='https://ko-fi.com/E1E41LY2C9' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi6.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
|
|
11
|
+
|
|
8
12
|
**English** | [日本語](./README-ja.md)
|
|
9
13
|
|
|
10
14
|
[](https://milkee.org)
|
package/dist/commands/compile.js
CHANGED
|
@@ -28,7 +28,7 @@ compile = async function() {
|
|
|
28
28
|
var action, backupFiles, cl, compilerProcess, config, debounceTimeout, enabledOptions, enabledOptionsList, error, execCommand, execCommandParts, execOtherOptionStrings, installCmd, lastError, milkee, milkeeOptions, options, spawnArgs, summary, toContinue;
|
|
29
29
|
cl = (await checkLatest());
|
|
30
30
|
if (cl) {
|
|
31
|
-
action = (await consola.prompt(
|
|
31
|
+
action = (await consola.prompt('Do you want to update now?', {
|
|
32
32
|
type: 'select',
|
|
33
33
|
options: [
|
|
34
34
|
{
|
|
@@ -50,7 +50,7 @@ compile = async function() {
|
|
|
50
50
|
}));
|
|
51
51
|
if (action && action !== 'skip') {
|
|
52
52
|
installCmd = action === 'global' ? 'npm i -g milkee@latest' : 'npm i -D milkee@latest';
|
|
53
|
-
consola.start(
|
|
53
|
+
consola.start('Updating milkee...');
|
|
54
54
|
await new Promise(function(resolve) {
|
|
55
55
|
var cp;
|
|
56
56
|
cp = spawn(installCmd, {
|
|
@@ -59,10 +59,10 @@ compile = async function() {
|
|
|
59
59
|
});
|
|
60
60
|
return cp.on('close', resolve);
|
|
61
61
|
});
|
|
62
|
-
consola.success(
|
|
62
|
+
consola.success('Update finished! Please run the command again.');
|
|
63
63
|
process.exit(0);
|
|
64
64
|
} else if (action === 'skip') {
|
|
65
|
-
consola.info(
|
|
65
|
+
consola.info('Skipped!');
|
|
66
66
|
} else if (!action) {
|
|
67
67
|
process.exit(1);
|
|
68
68
|
}
|
|
@@ -157,7 +157,7 @@ compile = async function() {
|
|
|
157
157
|
summary.push(`Options: ${enabledOptionsList}`);
|
|
158
158
|
}
|
|
159
159
|
consola.box({
|
|
160
|
-
title:
|
|
160
|
+
title: 'Milkee Compilation Summary',
|
|
161
161
|
message: summary.join('\n')
|
|
162
162
|
});
|
|
163
163
|
if (milkeeOptions.confirm) {
|
|
@@ -181,7 +181,7 @@ compile = async function() {
|
|
|
181
181
|
consola.start(`Watching for changes in \`${config.entry}\`...`);
|
|
182
182
|
consola.info(`Executing: coffee ${spawnArgs.join(' ')}`);
|
|
183
183
|
if (milkeeOptions.refresh) {
|
|
184
|
-
consola.warn(
|
|
184
|
+
consola.warn('Refresh backup is disabled in watch mode (backups are cleared immediately).');
|
|
185
185
|
clearBackups(backupFiles);
|
|
186
186
|
}
|
|
187
187
|
compilerProcess = spawn('coffee', spawnArgs, {
|
|
@@ -210,7 +210,7 @@ compile = async function() {
|
|
|
210
210
|
}
|
|
211
211
|
return debounceTimeout = setTimeout(function() {
|
|
212
212
|
if (lastError) {
|
|
213
|
-
consola.warn(
|
|
213
|
+
consola.warn('Compilation failed, plugins skipped.');
|
|
214
214
|
} else {
|
|
215
215
|
consola.success('Compilation successful (watch mode).');
|
|
216
216
|
runPlugins(config, {...(config.options || {})}, '(watch mode)', '');
|
package/dist/commands/plugin.js
CHANGED
|
@@ -128,11 +128,11 @@ updatePackageJson = function() {
|
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
131
|
-
consola.success(
|
|
131
|
+
consola.success('Updated `package.json`');
|
|
132
132
|
return true;
|
|
133
133
|
} catch (error1) {
|
|
134
134
|
error = error1;
|
|
135
|
-
consola.error(
|
|
135
|
+
consola.error('Failed to update package.json:', error);
|
|
136
136
|
return false;
|
|
137
137
|
}
|
|
138
138
|
};
|
|
@@ -142,16 +142,16 @@ initPackageJson = function() {
|
|
|
142
142
|
var error, pkgPath;
|
|
143
143
|
pkgPath = path.join(CWD, 'package.json');
|
|
144
144
|
if (!fs.existsSync(pkgPath)) {
|
|
145
|
-
consola.start(
|
|
145
|
+
consola.start('Initializing package.json...');
|
|
146
146
|
try {
|
|
147
147
|
execSync('npm init', {
|
|
148
148
|
cwd: CWD,
|
|
149
149
|
stdio: 'inherit'
|
|
150
150
|
});
|
|
151
|
-
consola.success(
|
|
151
|
+
consola.success('Created `package.json`');
|
|
152
152
|
} catch (error1) {
|
|
153
153
|
error = error1;
|
|
154
|
-
consola.error(
|
|
154
|
+
consola.error('Failed to create package.json:', error);
|
|
155
155
|
return false;
|
|
156
156
|
}
|
|
157
157
|
}
|
|
@@ -176,11 +176,11 @@ generateReadme = function() {
|
|
|
176
176
|
readme = readme.replace(/\{\{name\}\}/g, name);
|
|
177
177
|
readme = readme.replace(/\{\{description\}\}/g, description);
|
|
178
178
|
fs.writeFileSync(readmePath, readme);
|
|
179
|
-
consola.success(
|
|
179
|
+
consola.success('Created `README.md`');
|
|
180
180
|
return true;
|
|
181
181
|
} catch (error1) {
|
|
182
182
|
error = error1;
|
|
183
|
-
consola.error(
|
|
183
|
+
consola.error('Failed to create README.md:', error);
|
|
184
184
|
return false;
|
|
185
185
|
}
|
|
186
186
|
};
|
|
@@ -188,41 +188,41 @@ generateReadme = function() {
|
|
|
188
188
|
// Main plugin setup function
|
|
189
189
|
plugin = async function() {
|
|
190
190
|
var confirmed, destPath, doc, error, i, j, k, l, len, len1, len2, len3, overwrite, pkgPath, readmePath, template;
|
|
191
|
-
consola.box(
|
|
192
|
-
consola.info(
|
|
193
|
-
consola.info(
|
|
194
|
-
consola.info(
|
|
191
|
+
consola.box('Milkee Plugin Setup');
|
|
192
|
+
consola.info('This will set up your project as a Milkee plugin.');
|
|
193
|
+
consola.info('');
|
|
194
|
+
consola.info('The following actions will be performed:');
|
|
195
195
|
pkgPath = path.join(CWD, 'package.json');
|
|
196
196
|
if (!fs.existsSync(pkgPath)) {
|
|
197
|
-
consola.info(
|
|
197
|
+
consola.info(' 0. Initialize package.json (npm init)');
|
|
198
198
|
}
|
|
199
|
-
consola.info(
|
|
200
|
-
consola.info(
|
|
199
|
+
consola.info(' 1. Install dependencies (consola, coffeescript, milkee)');
|
|
200
|
+
consola.info(' 2. Create template files:');
|
|
201
201
|
for (i = 0, len = TEMPLATES.length; i < len; i++) {
|
|
202
202
|
template = TEMPLATES[i];
|
|
203
203
|
consola.info(` - ${template.dest}`);
|
|
204
204
|
}
|
|
205
|
-
consola.info(
|
|
205
|
+
consola.info(' 3. Copy docs:');
|
|
206
206
|
for (j = 0, len1 = DOCS.length; j < len1; j++) {
|
|
207
207
|
doc = DOCS[j];
|
|
208
208
|
consola.info(` - ${doc.dest}`);
|
|
209
209
|
}
|
|
210
|
-
consola.info(
|
|
211
|
-
consola.info(
|
|
212
|
-
consola.info(
|
|
210
|
+
consola.info(' 4. Update package.json (main, scripts, keywords)');
|
|
211
|
+
consola.info(' 5. Generate README.md');
|
|
212
|
+
consola.info('');
|
|
213
213
|
// Confirm before proceeding
|
|
214
214
|
confirmed = (await confirmContinue());
|
|
215
215
|
if (!confirmed) {
|
|
216
216
|
return;
|
|
217
217
|
}
|
|
218
|
-
consola.info(
|
|
218
|
+
consola.info('');
|
|
219
219
|
// Initialize package.json if not exists
|
|
220
220
|
if (!initPackageJson()) {
|
|
221
221
|
return;
|
|
222
222
|
}
|
|
223
223
|
try {
|
|
224
224
|
// Install dependencies
|
|
225
|
-
consola.start(
|
|
225
|
+
consola.start('Installing dependencies...');
|
|
226
226
|
execSync('npm install consola', {
|
|
227
227
|
cwd: CWD,
|
|
228
228
|
stdio: 'inherit'
|
|
@@ -231,21 +231,21 @@ plugin = async function() {
|
|
|
231
231
|
cwd: CWD,
|
|
232
232
|
stdio: 'inherit'
|
|
233
233
|
});
|
|
234
|
-
consola.success(
|
|
234
|
+
consola.success('Dependencies installed!');
|
|
235
235
|
} catch (error1) {
|
|
236
236
|
error = error1;
|
|
237
|
-
consola.error(
|
|
237
|
+
consola.error('Failed to install dependencies:', error);
|
|
238
238
|
return;
|
|
239
239
|
}
|
|
240
|
-
consola.info(
|
|
240
|
+
consola.info('');
|
|
241
241
|
// Create template files
|
|
242
|
-
consola.start(
|
|
242
|
+
consola.start('Creating template files...');
|
|
243
243
|
for (k = 0, len2 = TEMPLATES.length; k < len2; k++) {
|
|
244
244
|
template = TEMPLATES[k];
|
|
245
245
|
destPath = path.join(CWD, template.dest);
|
|
246
246
|
if (fs.existsSync(destPath)) {
|
|
247
247
|
overwrite = (await consola.prompt(`${template.dest} already exists. Overwrite?`, {
|
|
248
|
-
type:
|
|
248
|
+
type: 'confirm'
|
|
249
249
|
}));
|
|
250
250
|
if (!overwrite) {
|
|
251
251
|
consola.info(`Skipped \`${template.dest}\``);
|
|
@@ -254,15 +254,15 @@ plugin = async function() {
|
|
|
254
254
|
}
|
|
255
255
|
copyTemplate(template.src, template.dest);
|
|
256
256
|
}
|
|
257
|
-
consola.info(
|
|
257
|
+
consola.info('');
|
|
258
258
|
// Copy docs
|
|
259
|
-
consola.start(
|
|
259
|
+
consola.start('Copying docs...');
|
|
260
260
|
for (l = 0, len3 = DOCS.length; l < len3; l++) {
|
|
261
261
|
doc = DOCS[l];
|
|
262
262
|
destPath = path.join(CWD, doc.dest);
|
|
263
263
|
if (fs.existsSync(destPath)) {
|
|
264
264
|
overwrite = (await consola.prompt(`${doc.dest} already exists. Overwrite?`, {
|
|
265
|
-
type:
|
|
265
|
+
type: 'confirm'
|
|
266
266
|
}));
|
|
267
267
|
if (!overwrite) {
|
|
268
268
|
consola.info(`Skipped \`${doc.dest}\``);
|
|
@@ -271,32 +271,32 @@ plugin = async function() {
|
|
|
271
271
|
}
|
|
272
272
|
copyDocs(doc.src, doc.dest);
|
|
273
273
|
}
|
|
274
|
-
consola.info(
|
|
274
|
+
consola.info('');
|
|
275
275
|
// Update package.json
|
|
276
|
-
consola.start(
|
|
276
|
+
consola.start('Updating package.json...');
|
|
277
277
|
updatePackageJson();
|
|
278
|
-
consola.info(
|
|
278
|
+
consola.info('');
|
|
279
279
|
// Generate README.md
|
|
280
280
|
readmePath = path.join(CWD, 'README.md');
|
|
281
281
|
if (fs.existsSync(readmePath)) {
|
|
282
|
-
overwrite = (await consola.prompt(
|
|
283
|
-
type:
|
|
282
|
+
overwrite = (await consola.prompt('README.md already exists. Overwrite?', {
|
|
283
|
+
type: 'confirm'
|
|
284
284
|
}));
|
|
285
285
|
if (overwrite) {
|
|
286
286
|
generateReadme();
|
|
287
287
|
} else {
|
|
288
|
-
consola.info(
|
|
288
|
+
consola.info('Skipped `README.md`');
|
|
289
289
|
}
|
|
290
290
|
} else {
|
|
291
291
|
generateReadme();
|
|
292
292
|
}
|
|
293
|
-
consola.info(
|
|
294
|
-
consola.success(
|
|
295
|
-
consola.info(
|
|
296
|
-
consola.info(
|
|
297
|
-
consola.info(
|
|
298
|
-
consola.info(
|
|
299
|
-
return consola.info(
|
|
293
|
+
consola.info('');
|
|
294
|
+
consola.success('Milkee plugin setup complete!');
|
|
295
|
+
consola.info('');
|
|
296
|
+
consola.info('Next steps:');
|
|
297
|
+
consola.info(' 1. Edit `src/main.coffee` to implement your plugin');
|
|
298
|
+
consola.info(' 2. Run `npm run build` to compile');
|
|
299
|
+
return consola.info(' 3. Test your plugin locally');
|
|
300
300
|
};
|
|
301
301
|
|
|
302
302
|
module.exports = plugin;
|
package/dist/commands/setup.js
CHANGED
|
@@ -15,23 +15,23 @@ consola = require('consola');
|
|
|
15
15
|
setup = async function() {
|
|
16
16
|
var CONFIG_TEMPLATE, TEMPLATE_PATH, check, error, pstat, stat;
|
|
17
17
|
checkCoffee();
|
|
18
|
-
pstat =
|
|
19
|
-
stat =
|
|
18
|
+
pstat = 'created';
|
|
19
|
+
stat = 'create';
|
|
20
20
|
if (fs.existsSync(CONFIG_PATH)) {
|
|
21
21
|
consola.warn(`\`${CONFIG_FILE}\` already exists in this directory.`);
|
|
22
22
|
check = (await consola.prompt(`Do you want to reset \`${CONFIG_FILE}\`?`, {
|
|
23
|
-
type:
|
|
23
|
+
type: 'confirm'
|
|
24
24
|
}));
|
|
25
25
|
if (!check) {
|
|
26
|
-
consola.info(
|
|
26
|
+
consola.info('Cancelled.');
|
|
27
27
|
return;
|
|
28
28
|
} else {
|
|
29
29
|
fs.rmSync(CONFIG_PATH, {
|
|
30
30
|
recursive: true,
|
|
31
31
|
force: true
|
|
32
32
|
});
|
|
33
|
-
pstat =
|
|
34
|
-
stat =
|
|
33
|
+
pstat = 'reset';
|
|
34
|
+
stat = 'reset';
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
try {
|
package/dist/lib/checks.js
CHANGED
|
@@ -20,7 +20,7 @@ checkLatest = async function() {
|
|
|
20
20
|
res = (await isPackageLatest(pkg));
|
|
21
21
|
if (res.success && !res.isLatest) {
|
|
22
22
|
consola.box({
|
|
23
|
-
title:
|
|
23
|
+
title: 'A new version is now available!',
|
|
24
24
|
message: `${res.currentVersion} --> \`${res.latestVersion}\`\n\n# global installation\n\`npm i -g milkee@latest\`\n# or local installation\n\`npm i -D milkee@latest\``
|
|
25
25
|
});
|
|
26
26
|
return true;
|
package/dist/lib/plugins.js
CHANGED
|
@@ -29,10 +29,10 @@ executePlugins = function(config, compilationResult) {
|
|
|
29
29
|
consola.warn(`Invalid plugin definition skipped (expected a function, got ${typeof pluginFn}).`);
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
|
-
return consola.success(
|
|
32
|
+
return consola.success('Plugins executed successfully.');
|
|
33
33
|
} catch (error1) {
|
|
34
34
|
error = error1;
|
|
35
|
-
return consola.error(
|
|
35
|
+
return consola.error('An error occurred during plugin execution:', error);
|
|
36
36
|
}
|
|
37
37
|
})();
|
|
38
38
|
};
|
package/dist/main.js
CHANGED
|
@@ -15,15 +15,15 @@ plugin = require('./commands/plugin');
|
|
|
15
15
|
|
|
16
16
|
argv = yargs(hideBin(process.argv)).scriptName('milkee').usage('$0 [command]').option('setup', {
|
|
17
17
|
alias: 's',
|
|
18
|
-
describe:
|
|
18
|
+
describe: 'Generate a default config file',
|
|
19
19
|
type: 'boolean'
|
|
20
20
|
}).option('compile', {
|
|
21
21
|
alias: 'c',
|
|
22
|
-
describe:
|
|
22
|
+
describe: 'Compile CoffeeScript (default)',
|
|
23
23
|
type: 'boolean'
|
|
24
24
|
}).option('plugin', {
|
|
25
25
|
alias: 'p',
|
|
26
|
-
describe:
|
|
26
|
+
describe: 'Set up a new Milkee plugin project',
|
|
27
27
|
type: 'boolean'
|
|
28
28
|
}).version('version', pkg.version).alias('v', 'version').help('help').alias('h', 'help').argv;
|
|
29
29
|
|
package/dist/options/confirm.js
CHANGED
|
@@ -6,11 +6,11 @@ consola = require('consola');
|
|
|
6
6
|
// Confirm processing
|
|
7
7
|
confirmContinue = async function() {
|
|
8
8
|
var toContinue;
|
|
9
|
-
toContinue = (await consola.prompt(
|
|
10
|
-
type:
|
|
9
|
+
toContinue = (await consola.prompt('Do you want to continue?', {
|
|
10
|
+
type: 'confirm'
|
|
11
11
|
}));
|
|
12
12
|
if (!toContinue) {
|
|
13
|
-
consola.info(
|
|
13
|
+
consola.info('Canceled.');
|
|
14
14
|
return false;
|
|
15
15
|
}
|
|
16
16
|
return true;
|
package/dist/options/copy.js
CHANGED
|
@@ -18,7 +18,7 @@ executeCopy = function(config) {
|
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
20
|
if ((ref = config.options) != null ? ref.join : void 0) {
|
|
21
|
-
consola.info(
|
|
21
|
+
consola.info('Copy skipped (join option is enabled)');
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
24
|
if (!fs.existsSync(outputPath)) {
|
|
@@ -27,10 +27,10 @@ executeCopy = function(config) {
|
|
|
27
27
|
}
|
|
28
28
|
stat = fs.statSync(entryPath);
|
|
29
29
|
if (!stat.isDirectory()) {
|
|
30
|
-
consola.info(
|
|
30
|
+
consola.info('Copy skipped (entry is not a directory)');
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
|
-
consola.start(
|
|
33
|
+
consola.start('Copying non-coffee files...');
|
|
34
34
|
try {
|
|
35
35
|
copyNonCoffeeFiles = function(srcDir, destDir) {
|
|
36
36
|
var destItemPath, i, item, items, len, parentDir, results, srcItemPath;
|
|
@@ -68,10 +68,10 @@ executeCopy = function(config) {
|
|
|
68
68
|
return results;
|
|
69
69
|
};
|
|
70
70
|
copyNonCoffeeFiles(entryPath, outputPath);
|
|
71
|
-
return consola.success(
|
|
71
|
+
return consola.success('Non-coffee files copied successfully!');
|
|
72
72
|
} catch (error1) {
|
|
73
73
|
error = error1;
|
|
74
|
-
consola.error(
|
|
74
|
+
consola.error('Failed to copy non-coffee files:', error);
|
|
75
75
|
throw error;
|
|
76
76
|
}
|
|
77
77
|
};
|
package/dist/options/refresh.js
CHANGED
|
@@ -20,9 +20,9 @@ executeRefresh = function(config, backupFiles) {
|
|
|
20
20
|
hash = crypto.randomBytes(4).toString('hex');
|
|
21
21
|
try {
|
|
22
22
|
if (stat.isDirectory()) {
|
|
23
|
-
consola.info(
|
|
23
|
+
consola.info('Executing: Refresh');
|
|
24
24
|
items = fs.readdirSync(targetDir);
|
|
25
|
-
consola.start(
|
|
25
|
+
consola.start('Backing up files...');
|
|
26
26
|
for (i = 0, len = items.length; i < len; i++) {
|
|
27
27
|
item = items[i];
|
|
28
28
|
originalPath = path.join(targetDir, item);
|
|
@@ -36,7 +36,7 @@ executeRefresh = function(config, backupFiles) {
|
|
|
36
36
|
}
|
|
37
37
|
return consola.success(`Files backed up with hash \`${hash}\``);
|
|
38
38
|
} else {
|
|
39
|
-
consola.info(
|
|
39
|
+
consola.info('Executing: Refresh (Single File)');
|
|
40
40
|
originalPath = targetDir;
|
|
41
41
|
fileName = path.basename(originalPath);
|
|
42
42
|
dirName = path.dirname(originalPath);
|
|
@@ -51,18 +51,18 @@ executeRefresh = function(config, backupFiles) {
|
|
|
51
51
|
}
|
|
52
52
|
} catch (error1) {
|
|
53
53
|
error = error1;
|
|
54
|
-
consola.error(
|
|
54
|
+
consola.error('Failed to create backups during refresh:', error);
|
|
55
55
|
throw error;
|
|
56
56
|
}
|
|
57
57
|
} else {
|
|
58
|
-
return consola.info(
|
|
58
|
+
return consola.info('Refresh skipped.');
|
|
59
59
|
}
|
|
60
60
|
};
|
|
61
61
|
|
|
62
62
|
// Restore backup files
|
|
63
63
|
restoreBackups = function(backupFiles) {
|
|
64
64
|
var backup, e, i, len;
|
|
65
|
-
consola.info(
|
|
65
|
+
consola.info('Restoring previous files...');
|
|
66
66
|
if (backupFiles.length > 0) {
|
|
67
67
|
for (i = 0, len = backupFiles.length; i < len; i++) {
|
|
68
68
|
backup = backupFiles[i];
|
|
@@ -80,9 +80,9 @@ restoreBackups = function(backupFiles) {
|
|
|
80
80
|
consola.warn(`Failed to restore ${backup.original}`);
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
-
return consola.success(
|
|
83
|
+
return consola.success('Restored!');
|
|
84
84
|
} else {
|
|
85
|
-
return consola.info(
|
|
85
|
+
return consola.info('No files found to restore.');
|
|
86
86
|
}
|
|
87
87
|
};
|
|
88
88
|
|
|
@@ -90,7 +90,7 @@ restoreBackups = function(backupFiles) {
|
|
|
90
90
|
clearBackups = function(backupFiles) {
|
|
91
91
|
var backup, e, i, len, results;
|
|
92
92
|
if (backupFiles.length > 0) {
|
|
93
|
-
consola.start(
|
|
93
|
+
consola.start('Cleaning up backups...');
|
|
94
94
|
results = [];
|
|
95
95
|
for (i = 0, len = backupFiles.length; i < len; i++) {
|
|
96
96
|
backup = backupFiles[i];
|
package/docs/PLUGIN-ja.md
CHANGED
|
@@ -131,7 +131,7 @@ npm publish --access public
|
|
|
131
131
|
### 命名規則 & キーワード
|
|
132
132
|
|
|
133
133
|
- 名前: `milkee-plugin-xxx` または `@yourname/milkee-plugin-xxx`
|
|
134
|
-
- キーワード(自動追加): `milkee`, `coffeescript`, `coffee`, `
|
|
134
|
+
- キーワード(自動追加): `milkee`, `coffeescript`, `coffee`, `plugin`, `milkee-plugin`
|
|
135
135
|
|
|
136
136
|
### エラーハンドリング
|
|
137
137
|
|
package/docs/PLUGIN.md
CHANGED
|
@@ -131,7 +131,7 @@ npm publish --access public
|
|
|
131
131
|
### Naming & Keywords
|
|
132
132
|
|
|
133
133
|
- Name: `milkee-plugin-xxx` or `@yourname/milkee-plugin-xxx`
|
|
134
|
-
- Keywords (auto-added): `milkee`, `coffeescript`, `coffee`, `
|
|
134
|
+
- Keywords (auto-added): `milkee`, `coffeescript`, `coffee`, `plugin`, `milkee-plugin`
|
|
135
135
|
|
|
136
136
|
### Error Handling
|
|
137
137
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "milkee",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.3-dev.0",
|
|
4
4
|
"description": "A simple CoffeeScript build tool with coffee.config.cjs",
|
|
5
5
|
"main": "dist/main.js",
|
|
6
6
|
"bin": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"coverage": "vitest --run --coverage",
|
|
13
13
|
"checkversion": "ncu",
|
|
14
14
|
"build": "coffee --output dist/ --compile --bare src/",
|
|
15
|
-
"format": "
|
|
15
|
+
"format": "cprettier ./src/",
|
|
16
16
|
"deprecate:dev": "node ./scripts/deprecate-dev-versions.js"
|
|
17
17
|
},
|
|
18
18
|
"repository": {
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"coffeescript": "^2.7.0",
|
|
51
51
|
"dotenv": "^17.2.3",
|
|
52
52
|
"execa": "^9.6.1",
|
|
53
|
+
"milkee-plugin-prettier": "^1.0.0",
|
|
53
54
|
"npm-check-updates": "^19.3.1",
|
|
54
|
-
"prettier": "^3.8.0",
|
|
55
55
|
"vitest": "^4.0.17"
|
|
56
56
|
}
|
|
57
57
|
}
|
package/.prettierrc.json
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const os = require("os");
|
|
4
|
-
const { execFile } = require("child_process");
|
|
5
|
-
|
|
6
|
-
describe("cli setup integration", () => {
|
|
7
|
-
it("runs `--setup` and creates coffee.config.cjs", async () => {
|
|
8
|
-
const dir = createTestDir("cli");
|
|
9
|
-
|
|
10
|
-
// run the setup command directly via CoffeeScript so we don't require the ESM-only `yargs` in `main`
|
|
11
|
-
const scriptPath = require("path").join(
|
|
12
|
-
process.cwd(),
|
|
13
|
-
"src",
|
|
14
|
-
"commands",
|
|
15
|
-
"setup.coffee",
|
|
16
|
-
);
|
|
17
|
-
const csRegister = require.resolve("coffeescript/register");
|
|
18
|
-
await new Promise((resolve, reject) => {
|
|
19
|
-
// -r <abs> -> preload CoffeeScript via absolute path so child process can find it
|
|
20
|
-
execFile(
|
|
21
|
-
"node",
|
|
22
|
-
["-r", csRegister, "-e", `require(${JSON.stringify(scriptPath)})()`],
|
|
23
|
-
{ cwd: dir },
|
|
24
|
-
(err) => {
|
|
25
|
-
if (err) return reject(err);
|
|
26
|
-
resolve();
|
|
27
|
-
},
|
|
28
|
-
);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const cfgPath = path.join(dir, "coffee.config.cjs");
|
|
32
|
-
expect(fs.existsSync(cfgPath)).toBe(true);
|
|
33
|
-
|
|
34
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
35
|
-
});
|
|
36
|
-
});
|
package/test/setup.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
// Register CoffeeScript so tests can require .coffee files
|
|
2
|
-
require("coffeescript/register");
|
|
3
|
-
|
|
4
|
-
// Test sandbox guard: prevent accidental writes outside a temporary sandbox
|
|
5
|
-
const fs = require("fs");
|
|
6
|
-
const path = require("path");
|
|
7
|
-
const os = require("os");
|
|
8
|
-
|
|
9
|
-
const SANDBOX = fs.mkdtempSync(path.join(os.tmpdir(), "milkee-test-sandbox-"));
|
|
10
|
-
process.env.TEST_SANDBOX = SANDBOX;
|
|
11
|
-
globalThis.TEST_SANDBOX = SANDBOX;
|
|
12
|
-
|
|
13
|
-
function stripExtendedPrefix(s) {
|
|
14
|
-
if (typeof s !== "string") return s;
|
|
15
|
-
// Remove Windows extended path prefix like '\\?\\' or '\?\\'
|
|
16
|
-
let out = s.replace(/^\\+\?\\/, "");
|
|
17
|
-
// If we still have a leading backslash before a drive letter (e.g. '\C:\...'), remove it
|
|
18
|
-
out = out.replace(/^\\+([A-Za-z]:)/, "$1");
|
|
19
|
-
return out;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Allowlist: sandbox + system temp + node_modules + any additional paths via TEST_WRITE_ALLOW
|
|
23
|
-
const allowed = [
|
|
24
|
-
path.resolve(stripExtendedPrefix(SANDBOX)),
|
|
25
|
-
path.resolve(stripExtendedPrefix(os.tmpdir())),
|
|
26
|
-
path.resolve(stripExtendedPrefix(process.cwd()), "node_modules"),
|
|
27
|
-
];
|
|
28
|
-
if (process.env.TEST_WRITE_ALLOW) {
|
|
29
|
-
process.env.TEST_WRITE_ALLOW.split(",").forEach((p) => {
|
|
30
|
-
if (p) allowed.push(path.resolve(stripExtendedPrefix(p)));
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function resolveSafe(p) {
|
|
35
|
-
if (!p) return p;
|
|
36
|
-
// accept Buffers as well
|
|
37
|
-
if (Buffer.isBuffer(p)) p = p.toString();
|
|
38
|
-
// strip Windows extended path prefix if present
|
|
39
|
-
if (typeof p === "string") {
|
|
40
|
-
p = stripExtendedPrefix(p);
|
|
41
|
-
}
|
|
42
|
-
if (!path.isAbsolute(p)) p = path.join(process.cwd(), String(p));
|
|
43
|
-
return path.resolve(p);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function isAllowed(p) {
|
|
47
|
-
const rp = resolveSafe(p);
|
|
48
|
-
return allowed.some(
|
|
49
|
-
(prefix) => rp === prefix || rp.startsWith(prefix + path.sep),
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function makeGuard(orig, checkIndex = 0) {
|
|
54
|
-
return function (...args) {
|
|
55
|
-
const target = args[checkIndex];
|
|
56
|
-
if (!isAllowed(target)) {
|
|
57
|
-
throw new Error(
|
|
58
|
-
`Test attempted to modify outside sandbox: ${target} (sandbox=${SANDBOX})`,
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
return orig.apply(this, args);
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Patch common fs methods that write or modify the FS
|
|
66
|
-
const writeSyncMethods = [
|
|
67
|
-
"writeFileSync",
|
|
68
|
-
"appendFileSync",
|
|
69
|
-
"copyFileSync",
|
|
70
|
-
"mkdirSync",
|
|
71
|
-
"rmSync",
|
|
72
|
-
"rmdirSync",
|
|
73
|
-
"renameSync",
|
|
74
|
-
"unlinkSync",
|
|
75
|
-
];
|
|
76
|
-
for (const m of writeSyncMethods) {
|
|
77
|
-
if (typeof fs[m] === "function") fs[m] = makeGuard(fs[m], 0);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Async versions
|
|
81
|
-
if (typeof fs.writeFile === "function") {
|
|
82
|
-
const orig = fs.writeFile;
|
|
83
|
-
fs.writeFile = function (file, ...rest) {
|
|
84
|
-
if (!isAllowed(file)) {
|
|
85
|
-
const cb = rest.find((r) => typeof r === "function");
|
|
86
|
-
const err = new Error(
|
|
87
|
-
`Test attempted to modify outside sandbox: ${file} (sandbox=${SANDBOX})`,
|
|
88
|
-
);
|
|
89
|
-
if (cb) return process.nextTick(() => cb(err));
|
|
90
|
-
throw err;
|
|
91
|
-
}
|
|
92
|
-
return orig.apply(this, [file, ...rest]);
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
if (fs.promises && typeof fs.promises.writeFile === "function") {
|
|
96
|
-
const orig = fs.promises.writeFile;
|
|
97
|
-
fs.promises.writeFile = function (file, ...rest) {
|
|
98
|
-
if (!isAllowed(file))
|
|
99
|
-
throw new Error(
|
|
100
|
-
`Test attempted to modify outside sandbox: ${file} (sandbox=${SANDBOX})`,
|
|
101
|
-
);
|
|
102
|
-
return orig.apply(this, [file, ...rest]);
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Helper for tests to create safe temp dirs
|
|
107
|
-
globalThis.createTestDir = function (name = "") {
|
|
108
|
-
const dir = path.join(SANDBOX, name || String(Date.now()));
|
|
109
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
110
|
-
return dir;
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
console.info(`[test setup] test sandbox: ${SANDBOX}`);
|
package/test/unit/checks.test.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const consola = require("consola");
|
|
4
|
-
|
|
5
|
-
// We re-require the checks module inside tests to allow us to mock dependencies
|
|
6
|
-
// that it captures at require-time.
|
|
7
|
-
|
|
8
|
-
describe("checks", () => {
|
|
9
|
-
afterEach(() => {
|
|
10
|
-
vi.restoreAllMocks();
|
|
11
|
-
vi.resetModules();
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it("checkLatest returns true and shows box when not latest", async () => {
|
|
15
|
-
vi.mock("is-package-latest", () => ({
|
|
16
|
-
isPackageLatest: async () => ({
|
|
17
|
-
success: true,
|
|
18
|
-
isLatest: false,
|
|
19
|
-
currentVersion: "1.0.0",
|
|
20
|
-
latestVersion: "1.2.0",
|
|
21
|
-
}),
|
|
22
|
-
}));
|
|
23
|
-
const { checkLatest } = require("../../src/lib/checks.coffee");
|
|
24
|
-
|
|
25
|
-
vi.spyOn(consola, "box").mockImplementation(() => {});
|
|
26
|
-
|
|
27
|
-
const res = await checkLatest();
|
|
28
|
-
expect(res).toBe(true);
|
|
29
|
-
expect(consola.box).toHaveBeenCalled();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it("checkCoffee reads package.json and does not warn when coffeescript present", async () => {
|
|
33
|
-
const { checkCoffee } = require("../../src/lib/checks.coffee");
|
|
34
|
-
vi.spyOn(consola, "warn").mockImplementation(() => {});
|
|
35
|
-
await checkCoffee();
|
|
36
|
-
expect(consola.warn).not.toHaveBeenCalled();
|
|
37
|
-
});
|
|
38
|
-
});
|
package/test/unit/copy.test.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const os = require("os");
|
|
4
|
-
|
|
5
|
-
const executeCopy = require("../../src/options/copy.coffee");
|
|
6
|
-
|
|
7
|
-
function createTree(base) {
|
|
8
|
-
fs.mkdirSync(base, { recursive: true });
|
|
9
|
-
fs.writeFileSync(path.join(base, "a.coffee"), "c");
|
|
10
|
-
fs.writeFileSync(path.join(base, "b.txt"), "b");
|
|
11
|
-
fs.mkdirSync(path.join(base, "sub"), { recursive: true });
|
|
12
|
-
fs.writeFileSync(path.join(base, "sub", "c.md"), "c");
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
describe("copy", () => {
|
|
16
|
-
it("copies non-coffee files recursively", () => {
|
|
17
|
-
const base = createTestDir("copy");
|
|
18
|
-
const entry = path.join(base, "entry");
|
|
19
|
-
const out = path.join(base, "out");
|
|
20
|
-
createTree(entry);
|
|
21
|
-
fs.mkdirSync(out, { recursive: true });
|
|
22
|
-
|
|
23
|
-
// preconditions
|
|
24
|
-
expect(fs.existsSync(entry)).toBe(true);
|
|
25
|
-
expect(fs.existsSync(path.join(entry, "b.txt"))).toBe(true);
|
|
26
|
-
|
|
27
|
-
// use absolute paths (sandboxed)
|
|
28
|
-
executeCopy({ entry, output: out });
|
|
29
|
-
|
|
30
|
-
expect(fs.existsSync(path.join(out, "b.txt"))).toBe(true);
|
|
31
|
-
expect(fs.existsSync(path.join(out, "sub", "c.md"))).toBe(true);
|
|
32
|
-
expect(fs.existsSync(path.join(out, "a.coffee"))).toBe(false);
|
|
33
|
-
|
|
34
|
-
fs.rmSync(base, { recursive: true, force: true });
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("skips when join option is enabled", () => {
|
|
38
|
-
const base = createTestDir("copy");
|
|
39
|
-
const entry = path.join(base, "entry");
|
|
40
|
-
const out = path.join(base, "out");
|
|
41
|
-
createTree(entry);
|
|
42
|
-
fs.mkdirSync(out, { recursive: true });
|
|
43
|
-
|
|
44
|
-
executeCopy({ entry, output: out, options: { join: true } });
|
|
45
|
-
|
|
46
|
-
expect(fs.existsSync(path.join(out, "b.txt"))).toBe(false);
|
|
47
|
-
|
|
48
|
-
fs.rmSync(base, { recursive: true, force: true });
|
|
49
|
-
});
|
|
50
|
-
});
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
|
|
3
|
-
const path = require("path");
|
|
4
|
-
|
|
5
|
-
const plugins = require("../../src/lib/plugins.coffee");
|
|
6
|
-
|
|
7
|
-
describe("plugins", () => {
|
|
8
|
-
it("runPlugins executes provided plugin functions", async () => {
|
|
9
|
-
let called = false;
|
|
10
|
-
const tempDir = createTestDir("plugins");
|
|
11
|
-
// create a dummy compiled file
|
|
12
|
-
const compiled = path.join(tempDir, "out.js");
|
|
13
|
-
fs.writeFileSync(compiled, "x");
|
|
14
|
-
|
|
15
|
-
const config = {
|
|
16
|
-
output: tempDir,
|
|
17
|
-
milkee: {
|
|
18
|
-
plugins: [
|
|
19
|
-
(res) => {
|
|
20
|
-
called = true;
|
|
21
|
-
return Promise.resolve();
|
|
22
|
-
},
|
|
23
|
-
],
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
|
-
plugins.runPlugins(config, {});
|
|
27
|
-
|
|
28
|
-
// wait a tick for async IIFE to run
|
|
29
|
-
await new Promise((r) => setTimeout(r, 10));
|
|
30
|
-
expect(called).toBe(true);
|
|
31
|
-
|
|
32
|
-
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("warns on invalid plugin entries", async () => {
|
|
36
|
-
const tempDir = fs.mkdtempSync(
|
|
37
|
-
path.join(require("os").tmpdir(), "milkee-plugins-"),
|
|
38
|
-
);
|
|
39
|
-
const consola = require("consola");
|
|
40
|
-
vi.spyOn(consola, "warn").mockImplementation(() => {});
|
|
41
|
-
|
|
42
|
-
const config = { output: tempDir, milkee: { plugins: ["not-fn"] } };
|
|
43
|
-
plugins.runPlugins(config, {});
|
|
44
|
-
await new Promise((r) => setTimeout(r, 10));
|
|
45
|
-
|
|
46
|
-
expect(consola.warn).toHaveBeenCalled();
|
|
47
|
-
|
|
48
|
-
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
49
|
-
});
|
|
50
|
-
});
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const os = require("os");
|
|
4
|
-
|
|
5
|
-
const {
|
|
6
|
-
executeRefresh,
|
|
7
|
-
restoreBackups,
|
|
8
|
-
clearBackups,
|
|
9
|
-
} = require("../../src/options/refresh.coffee");
|
|
10
|
-
|
|
11
|
-
describe("refresh", () => {
|
|
12
|
-
it("backs up directory files and restores them", () => {
|
|
13
|
-
const base = createTestDir("refresh");
|
|
14
|
-
const dir = path.join(base, "out");
|
|
15
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
16
|
-
const a = path.join(dir, "a.txt");
|
|
17
|
-
const b = path.join(dir, "b.txt");
|
|
18
|
-
fs.writeFileSync(a, "1");
|
|
19
|
-
fs.writeFileSync(b, "2");
|
|
20
|
-
|
|
21
|
-
const backupFiles = [];
|
|
22
|
-
// preconditions
|
|
23
|
-
expect(fs.existsSync(dir)).toBe(true);
|
|
24
|
-
expect(fs.existsSync(a)).toBe(true);
|
|
25
|
-
|
|
26
|
-
executeRefresh({ output: dir }, backupFiles);
|
|
27
|
-
|
|
28
|
-
expect(backupFiles.length).toBe(2);
|
|
29
|
-
for (const binfo of backupFiles) {
|
|
30
|
-
expect(fs.existsSync(binfo.backup)).toBe(true);
|
|
31
|
-
expect(fs.existsSync(binfo.original)).toBe(false);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// restore
|
|
35
|
-
restoreBackups(backupFiles);
|
|
36
|
-
for (const binfo of backupFiles) {
|
|
37
|
-
expect(fs.existsSync(binfo.original)).toBe(true);
|
|
38
|
-
expect(fs.existsSync(binfo.backup)).toBe(false);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// cleanup
|
|
42
|
-
fs.rmSync(base, { recursive: true, force: true });
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it("clearBackups removes backup files", () => {
|
|
46
|
-
const base = createTestDir("refresh");
|
|
47
|
-
const dir = path.join(base, "out");
|
|
48
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
49
|
-
const a = path.join(dir, "a.txt");
|
|
50
|
-
fs.writeFileSync(a, "1");
|
|
51
|
-
|
|
52
|
-
const backupFiles = [];
|
|
53
|
-
executeRefresh({ output: dir }, backupFiles);
|
|
54
|
-
expect(backupFiles.length).toBeGreaterThan(0);
|
|
55
|
-
|
|
56
|
-
clearBackups(backupFiles);
|
|
57
|
-
for (const binfo of backupFiles) {
|
|
58
|
-
expect(fs.existsSync(binfo.backup)).toBe(false);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
fs.rmSync(base, { recursive: true, force: true });
|
|
62
|
-
});
|
|
63
|
-
});
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
|
|
4
|
-
describe("sandbox Windows extended path handling", () => {
|
|
5
|
-
it("allows writes when path uses \\?\\ prefix (Windows only)", () => {
|
|
6
|
-
if (process.platform !== "win32") return;
|
|
7
|
-
const dir = createTestDir("win-prefix");
|
|
8
|
-
// simulate Windows extended path prefix
|
|
9
|
-
// use Windows extended path prefix with doubled backslashes
|
|
10
|
-
const prefixed = "\\\\?\\\\" + path.join(dir, "file.txt");
|
|
11
|
-
expect(() => fs.writeFileSync(prefixed, "ok")).not.toThrow();
|
|
12
|
-
expect(fs.existsSync(path.join(dir, "file.txt"))).toBe(true);
|
|
13
|
-
});
|
|
14
|
-
});
|
package/test/unit/setup.test.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const os = require("os");
|
|
4
|
-
|
|
5
|
-
const setup = require("../../src/commands/setup.coffee");
|
|
6
|
-
const checks = require("../../src/lib/checks.coffee");
|
|
7
|
-
const { CONFIG_FILE } = require("../../src/lib/constants.coffee");
|
|
8
|
-
|
|
9
|
-
describe("setup", () => {
|
|
10
|
-
let cwd;
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
cwd = process.cwd();
|
|
13
|
-
vi.spyOn(checks, "checkCoffee").mockImplementation(() => {});
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
afterEach(() => {
|
|
17
|
-
process.chdir(cwd);
|
|
18
|
-
vi.restoreAllMocks();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("creates config file when not present", async () => {
|
|
22
|
-
const dir = fs.mkdtempSync(
|
|
23
|
-
path.join(require("os").tmpdir(), "milkee-setup-"),
|
|
24
|
-
);
|
|
25
|
-
process.chdir(dir);
|
|
26
|
-
|
|
27
|
-
// re-require to ensure constants.CWD is captured from the new cwd
|
|
28
|
-
delete require.cache[require.resolve("../../src/lib/constants.coffee")];
|
|
29
|
-
delete require.cache[require.resolve("../../src/commands/setup.coffee")];
|
|
30
|
-
const setupLocal = require("../../src/commands/setup.coffee");
|
|
31
|
-
|
|
32
|
-
// run setup
|
|
33
|
-
await setupLocal();
|
|
34
|
-
|
|
35
|
-
const cfgPath = path.join(dir, CONFIG_FILE);
|
|
36
|
-
expect(fs.existsSync(cfgPath)).toBe(true);
|
|
37
|
-
|
|
38
|
-
try {
|
|
39
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
40
|
-
} catch (e) {
|
|
41
|
-
/* ignore */
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it("does not overwrite when prompt says no", async () => {
|
|
46
|
-
const dir = fs.mkdtempSync(
|
|
47
|
-
path.join(require("os").tmpdir(), "milkee-setup-"),
|
|
48
|
-
);
|
|
49
|
-
process.chdir(dir);
|
|
50
|
-
|
|
51
|
-
const cfgPath = path.join(dir, CONFIG_FILE);
|
|
52
|
-
fs.writeFileSync(cfgPath, "original");
|
|
53
|
-
|
|
54
|
-
const consola = require("consola");
|
|
55
|
-
vi.spyOn(consola, "prompt").mockResolvedValue(false);
|
|
56
|
-
|
|
57
|
-
delete require.cache[require.resolve("../../src/lib/constants.coffee")];
|
|
58
|
-
delete require.cache[require.resolve("../../src/commands/setup.coffee")];
|
|
59
|
-
const setupLocal = require("../../src/commands/setup.coffee");
|
|
60
|
-
|
|
61
|
-
await setupLocal();
|
|
62
|
-
|
|
63
|
-
expect(fs.readFileSync(cfgPath, "utf-8")).toBe("original");
|
|
64
|
-
|
|
65
|
-
// try cleanup; ignore errors
|
|
66
|
-
try {
|
|
67
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
68
|
-
} catch (e) {}
|
|
69
|
-
});
|
|
70
|
-
});
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
|
|
4
|
-
function collectCoffeeFiles(dir) {
|
|
5
|
-
let out = [];
|
|
6
|
-
const items = fs.readdirSync(dir);
|
|
7
|
-
for (const item of items) {
|
|
8
|
-
const itemPath = path.join(dir, item);
|
|
9
|
-
const stat = fs.statSync(itemPath);
|
|
10
|
-
if (stat.isDirectory()) {
|
|
11
|
-
out = out.concat(collectCoffeeFiles(itemPath));
|
|
12
|
-
} else if (stat.isFile() && itemPath.endsWith(".coffee")) {
|
|
13
|
-
out.push(itemPath);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
return out;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const SRC_DIR = path.join(__dirname, "../../src");
|
|
20
|
-
let files = [];
|
|
21
|
-
try {
|
|
22
|
-
files = collectCoffeeFiles(SRC_DIR);
|
|
23
|
-
} catch (e) {
|
|
24
|
-
// If src missing for some reason, test will fail explicitly below
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Exclude main.coffee and compile.coffee to avoid executing CLI/long-running flows on require
|
|
28
|
-
files = files.filter((f) => {
|
|
29
|
-
const excluded = [
|
|
30
|
-
path.join("src", "main.coffee"),
|
|
31
|
-
path.join("src", "commands", "compile.coffee"),
|
|
32
|
-
];
|
|
33
|
-
return !excluded.some((e) => f.endsWith(e));
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
if (files.length === 0) {
|
|
37
|
-
it("has .coffee files under src", () => {
|
|
38
|
-
throw new Error("No .coffee files found under src");
|
|
39
|
-
});
|
|
40
|
-
} else {
|
|
41
|
-
describe("smoke: require all src .coffee files", () => {
|
|
42
|
-
for (const file of files) {
|
|
43
|
-
const rel = path.relative(process.cwd(), file);
|
|
44
|
-
it(`require ${rel}`, () => {
|
|
45
|
-
// clear cache to make require deterministic
|
|
46
|
-
try {
|
|
47
|
-
delete require.cache[require.resolve(file)];
|
|
48
|
-
} catch (e) {}
|
|
49
|
-
expect(() => {
|
|
50
|
-
const mod = require(file);
|
|
51
|
-
expect(mod).not.toBeUndefined();
|
|
52
|
-
}).not.toThrow();
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
}
|
package/test/unit/utils.test.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const os = require("os");
|
|
4
|
-
|
|
5
|
-
const utils = require("../../src/lib/utils.coffee");
|
|
6
|
-
|
|
7
|
-
describe("utils", () => {
|
|
8
|
-
it("sleep resolves after given time", async () => {
|
|
9
|
-
vi.useFakeTimers();
|
|
10
|
-
const p = utils.sleep(100);
|
|
11
|
-
vi.advanceTimersByTime(100);
|
|
12
|
-
await vi.runAllTimersAsync();
|
|
13
|
-
await expect(p).resolves.toBeUndefined();
|
|
14
|
-
vi.useRealTimers();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("getCompiledFiles finds .js and .js.map files recursively", () => {
|
|
18
|
-
// create directory inside test sandbox
|
|
19
|
-
const dir = createTestDir("utils");
|
|
20
|
-
const fileA = path.join(dir, "a.js");
|
|
21
|
-
const fileB = path.join(dir, "b.js.map");
|
|
22
|
-
const fileC = path.join(dir, "c.txt");
|
|
23
|
-
const subdir = path.join(dir, "sub");
|
|
24
|
-
fs.mkdirSync(subdir);
|
|
25
|
-
const fileD = path.join(subdir, "d.js");
|
|
26
|
-
fs.writeFileSync(fileA, "console.log(1)");
|
|
27
|
-
fs.writeFileSync(fileB, "map");
|
|
28
|
-
fs.writeFileSync(fileC, "no");
|
|
29
|
-
fs.writeFileSync(fileD, "console.log(2)");
|
|
30
|
-
const res = utils.getCompiledFiles(dir);
|
|
31
|
-
expect(res).toEqual(expect.arrayContaining([fileA, fileB, fileD]));
|
|
32
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("returns empty if path does not exist", () => {
|
|
36
|
-
const res = utils.getCompiledFiles(
|
|
37
|
-
path.join(os.tmpdir(), "nonexistent-" + Date.now()),
|
|
38
|
-
);
|
|
39
|
-
expect(res).toEqual([]);
|
|
40
|
-
});
|
|
41
|
-
});
|
package/vitest.config.mjs
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vitest/config';
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
environment: 'node',
|
|
6
|
-
globals: true,
|
|
7
|
-
setupFiles: './test/setup.js',
|
|
8
|
-
},
|
|
9
|
-
coverage: {
|
|
10
|
-
provider: 'v8',
|
|
11
|
-
reporter: ['text', 'lcov'],
|
|
12
|
-
exclude: ['**/*.coffee'],
|
|
13
|
-
},
|
|
14
|
-
});
|