@schalkneethling/miyagi-core 4.3.0 → 4.4.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.md +48 -1
- package/bin/miyagi.js +9 -1
- package/index.js +2 -2
- package/lib/cli/component.js +23 -5
- package/lib/cli/doctor.js +153 -0
- package/lib/cli/drupal-assets.js +44 -7
- package/lib/cli/index.js +2 -0
- package/lib/cli/lint.js +71 -27
- package/lib/cli/run.js +281 -0
- package/lib/config.js +10 -0
- package/lib/default-config.js +1 -1
- package/lib/errors.js +31 -0
- package/lib/index.js +7 -151
- package/lib/init/args.js +161 -93
- package/lib/init/engines.js +13 -4
- package/lib/init/index.js +26 -10
- package/lib/init/watcher.js +15 -12
- package/lib/state/helpers.js +14 -9
- package/package.json +3 -3
package/lib/init/args.js
CHANGED
|
@@ -6,101 +6,169 @@
|
|
|
6
6
|
import yargs from "yargs";
|
|
7
7
|
import { hideBin } from "yargs/helpers";
|
|
8
8
|
import pkgJson from "../../package.json" with { type: "json" };
|
|
9
|
+
import { EXIT_CODES, MiyagiError } from "../errors.js";
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
* @param {object} handlers
|
|
13
|
+
* @param {string[]} [argv]
|
|
14
|
+
* @returns {object}
|
|
15
|
+
*/
|
|
16
|
+
export default function createCli(handlers, argv = process.argv) {
|
|
17
|
+
let result;
|
|
18
|
+
|
|
19
|
+
const commandHandler = (handler) => async (args) => {
|
|
20
|
+
result = await handler(args);
|
|
21
|
+
return result;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const cli = yargs(hideBin(argv))
|
|
25
|
+
.scriptName("miyagi")
|
|
26
|
+
.option("verbose", {
|
|
27
|
+
alias: "v",
|
|
13
28
|
description:
|
|
14
29
|
"Logging additional information — helpful mainly in case of errors.",
|
|
15
30
|
type: "boolean",
|
|
31
|
+
global: true,
|
|
32
|
+
})
|
|
33
|
+
.command(
|
|
34
|
+
"start",
|
|
35
|
+
"Starts the miyagi server",
|
|
36
|
+
(builder) =>
|
|
37
|
+
builder
|
|
38
|
+
.option("watch-report", {
|
|
39
|
+
description: "Enable watch report output on startup.",
|
|
40
|
+
type: "boolean",
|
|
41
|
+
})
|
|
42
|
+
.option("watch-report-format", {
|
|
43
|
+
description: "Set watch report format.",
|
|
44
|
+
type: "string",
|
|
45
|
+
choices: ["pretty", "summary", "json"],
|
|
46
|
+
})
|
|
47
|
+
.option("watch-report-no-color", {
|
|
48
|
+
description: "Disable colors in watch report output.",
|
|
49
|
+
type: "boolean",
|
|
50
|
+
}),
|
|
51
|
+
commandHandler(handlers.start),
|
|
52
|
+
)
|
|
53
|
+
.command(
|
|
54
|
+
"build",
|
|
55
|
+
"Creates a static build of all your components",
|
|
56
|
+
(builder) =>
|
|
57
|
+
builder.option("folder", {
|
|
58
|
+
description: "The folder where your static build files will be saved",
|
|
59
|
+
type: "string",
|
|
60
|
+
}),
|
|
61
|
+
commandHandler(handlers.build),
|
|
62
|
+
)
|
|
63
|
+
.command(
|
|
64
|
+
"new <component>",
|
|
65
|
+
"Creates a new component folder (including template, CSS, JS, documentation, mocks, and schema files)",
|
|
66
|
+
(builder) =>
|
|
67
|
+
builder
|
|
68
|
+
.positional("component", {
|
|
69
|
+
description: "The component path to create",
|
|
70
|
+
type: "string",
|
|
71
|
+
})
|
|
72
|
+
.option("skip", {
|
|
73
|
+
description:
|
|
74
|
+
"files that will not be created\n(space separated list of tpl, css, js, docs, mocks, schema)",
|
|
75
|
+
type: "array",
|
|
76
|
+
})
|
|
77
|
+
.option("only", {
|
|
78
|
+
description:
|
|
79
|
+
"tells miyagi to only created the passes file types\n(space separated list of tpl, css, js, docs, mocks, schema)",
|
|
80
|
+
type: "array",
|
|
81
|
+
}),
|
|
82
|
+
commandHandler(handlers.new),
|
|
83
|
+
)
|
|
84
|
+
.command(
|
|
85
|
+
"mocks <component>",
|
|
86
|
+
"Creates a mock data file with dummy content based on the schema file",
|
|
87
|
+
(builder) =>
|
|
88
|
+
builder.positional("component", {
|
|
89
|
+
description: "The component path to generate mock data for",
|
|
90
|
+
type: "string",
|
|
91
|
+
}),
|
|
92
|
+
commandHandler(handlers.mocks),
|
|
93
|
+
)
|
|
94
|
+
.command(
|
|
95
|
+
"lint [component]",
|
|
96
|
+
"Validates if the component's mock data matches its JSON schema",
|
|
97
|
+
(builder) =>
|
|
98
|
+
builder.positional("component", {
|
|
99
|
+
description: "Optional component path to lint",
|
|
100
|
+
type: "string",
|
|
101
|
+
}),
|
|
102
|
+
commandHandler(handlers.lint),
|
|
103
|
+
)
|
|
104
|
+
.command(
|
|
105
|
+
"drupal-assets",
|
|
106
|
+
"Resolves Drupal *.libraries.yml dependencies and updates component $assets in mock files",
|
|
107
|
+
(builder) =>
|
|
108
|
+
builder
|
|
109
|
+
.option("engine", {
|
|
110
|
+
alias: "e",
|
|
111
|
+
description: "Engine to use for asset resolution",
|
|
112
|
+
type: "string",
|
|
113
|
+
choices: ["drupal"],
|
|
114
|
+
default: "drupal",
|
|
115
|
+
})
|
|
116
|
+
.option("config", {
|
|
117
|
+
description: "Path to .miyagi-assets.js config file",
|
|
118
|
+
type: "string",
|
|
119
|
+
default: ".miyagi-assets.js",
|
|
120
|
+
})
|
|
121
|
+
.option("libraries", {
|
|
122
|
+
alias: "l",
|
|
123
|
+
description: "Path to *.libraries.yml (overrides config)",
|
|
124
|
+
type: "string",
|
|
125
|
+
})
|
|
126
|
+
.option("components", {
|
|
127
|
+
alias: "c",
|
|
128
|
+
description: "Library names to process (space-separated)",
|
|
129
|
+
type: "array",
|
|
130
|
+
})
|
|
131
|
+
.option("ignore-prefixes", {
|
|
132
|
+
description:
|
|
133
|
+
'Dependency prefixes to skip (e.g. "core" to ignore core/jquery)',
|
|
134
|
+
type: "array",
|
|
135
|
+
})
|
|
136
|
+
.option("dry-run", {
|
|
137
|
+
description: "Print resolved $assets without writing files",
|
|
138
|
+
type: "boolean",
|
|
139
|
+
default: false,
|
|
140
|
+
}),
|
|
141
|
+
commandHandler(handlers.drupalAssets),
|
|
142
|
+
)
|
|
143
|
+
.command(
|
|
144
|
+
"doctor",
|
|
145
|
+
"Checks your miyagi environment and config for common setup issues",
|
|
146
|
+
() => {},
|
|
147
|
+
commandHandler(handlers.doctor),
|
|
148
|
+
)
|
|
149
|
+
.help()
|
|
150
|
+
.version(pkgJson.version)
|
|
151
|
+
.alias("help", "h")
|
|
152
|
+
.strictCommands()
|
|
153
|
+
.demandCommand()
|
|
154
|
+
.exitProcess(false)
|
|
155
|
+
.fail((message, error) => {
|
|
156
|
+
if (error) {
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
throw new MiyagiError(message || "CLI parsing failed.", {
|
|
161
|
+
code: EXIT_CODES.CLI_USAGE_ERROR,
|
|
162
|
+
});
|
|
163
|
+
})
|
|
164
|
+
.epilogue(
|
|
165
|
+
"Please check https://docs.miyagi.dev/configuration/options/ for all options",
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
cli,
|
|
170
|
+
getResult() {
|
|
171
|
+
return result;
|
|
16
172
|
},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
type: "boolean",
|
|
20
|
-
},
|
|
21
|
-
"watch-report-format": {
|
|
22
|
-
description: "Set watch report format.",
|
|
23
|
-
type: "string",
|
|
24
|
-
choices: ["pretty", "summary", "json"],
|
|
25
|
-
},
|
|
26
|
-
"watch-report-no-color": {
|
|
27
|
-
description: "Disable colors in watch report output.",
|
|
28
|
-
type: "boolean",
|
|
29
|
-
},
|
|
30
|
-
})
|
|
31
|
-
.command("build", "Creates a static build of all your components", {
|
|
32
|
-
folder: {
|
|
33
|
-
description: "The folder where your static build files will be saved",
|
|
34
|
-
type: "string",
|
|
35
|
-
},
|
|
36
|
-
})
|
|
37
|
-
.command(
|
|
38
|
-
"new",
|
|
39
|
-
"Creates a new component folder (including template, CSS, JS, documentation, mocks, and schema files)",
|
|
40
|
-
{
|
|
41
|
-
skip: {
|
|
42
|
-
description:
|
|
43
|
-
"files that will not be created\n(space separated list of tpl, css, js, docs, mocks, schema)",
|
|
44
|
-
type: "array",
|
|
45
|
-
},
|
|
46
|
-
only: {
|
|
47
|
-
description:
|
|
48
|
-
"tells miyagi to only created the passes file types\n(space separated list of tpl, css, js, docs, mocks, schema)",
|
|
49
|
-
type: "array",
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
)
|
|
53
|
-
.command(
|
|
54
|
-
"mocks",
|
|
55
|
-
"Creates a mock data file with dummy content based on the schema file",
|
|
56
|
-
)
|
|
57
|
-
.command(
|
|
58
|
-
"lint",
|
|
59
|
-
"Validates if the component's mock data matches its JSON schema",
|
|
60
|
-
)
|
|
61
|
-
.command(
|
|
62
|
-
"drupal-assets",
|
|
63
|
-
"Resolves Drupal *.libraries.yml dependencies and updates component $assets in mock files",
|
|
64
|
-
{
|
|
65
|
-
engine: {
|
|
66
|
-
alias: "e",
|
|
67
|
-
description: "Engine to use for asset resolution",
|
|
68
|
-
type: "string",
|
|
69
|
-
choices: ["drupal"],
|
|
70
|
-
default: "drupal",
|
|
71
|
-
},
|
|
72
|
-
config: {
|
|
73
|
-
description: "Path to .miyagi-assets.js config file",
|
|
74
|
-
type: "string",
|
|
75
|
-
default: ".miyagi-assets.js",
|
|
76
|
-
},
|
|
77
|
-
libraries: {
|
|
78
|
-
alias: "l",
|
|
79
|
-
description: "Path to *.libraries.yml (overrides config)",
|
|
80
|
-
type: "string",
|
|
81
|
-
},
|
|
82
|
-
components: {
|
|
83
|
-
alias: "c",
|
|
84
|
-
description: "Library names to process (space-separated)",
|
|
85
|
-
type: "array",
|
|
86
|
-
},
|
|
87
|
-
"ignore-prefixes": {
|
|
88
|
-
description:
|
|
89
|
-
'Dependency prefixes to skip (e.g. "core" to ignore core/jquery)',
|
|
90
|
-
type: "array",
|
|
91
|
-
},
|
|
92
|
-
"dry-run": {
|
|
93
|
-
description: "Print resolved $assets without writing files",
|
|
94
|
-
type: "boolean",
|
|
95
|
-
default: false,
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
)
|
|
99
|
-
.help()
|
|
100
|
-
.version(pkgJson.version)
|
|
101
|
-
.alias("help", "h")
|
|
102
|
-
.alias("verbose", "v")
|
|
103
|
-
.demandCommand()
|
|
104
|
-
.epilogue(
|
|
105
|
-
"Please check https://docs.miyagi.dev/configuration/options/ for all options",
|
|
106
|
-
);
|
|
173
|
+
};
|
|
174
|
+
}
|
package/lib/init/engines.js
CHANGED
|
@@ -7,6 +7,7 @@ import fs from "fs";
|
|
|
7
7
|
import { t } from "../i18n/index.js";
|
|
8
8
|
import log from "../logger.js";
|
|
9
9
|
import * as helpers from "../helpers.js";
|
|
10
|
+
import { EXIT_CODES, MiyagiError } from "../errors.js";
|
|
10
11
|
import TwingCache from "./twing/cache.js";
|
|
11
12
|
import * as twingFunctions from "./twing/functions.js";
|
|
12
13
|
|
|
@@ -41,8 +42,12 @@ async function setUserEngine() {
|
|
|
41
42
|
const { engine } = global.config;
|
|
42
43
|
|
|
43
44
|
if (!engine.render) {
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
const message = "No render function has beend defined.";
|
|
46
|
+
log("error", message);
|
|
47
|
+
throw new MiyagiError(message, {
|
|
48
|
+
code: EXIT_CODES.CONFIG_ERROR,
|
|
49
|
+
logged: true,
|
|
50
|
+
});
|
|
46
51
|
}
|
|
47
52
|
|
|
48
53
|
try {
|
|
@@ -51,8 +56,12 @@ async function setUserEngine() {
|
|
|
51
56
|
async (name, context, cb) => await engine.render({ name, context, cb }),
|
|
52
57
|
);
|
|
53
58
|
} catch (e) {
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
const message = t("settingEngineFailed");
|
|
60
|
+
log("error", message, e);
|
|
61
|
+
throw new MiyagiError(message, {
|
|
62
|
+
code: EXIT_CODES.CONFIG_ERROR,
|
|
63
|
+
logged: true,
|
|
64
|
+
});
|
|
56
65
|
}
|
|
57
66
|
}
|
|
58
67
|
|
package/lib/init/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import appConfig from "../default-config.js";
|
|
|
12
12
|
import { t } from "../i18n/index.js";
|
|
13
13
|
import build from "../build/index.js";
|
|
14
14
|
import log from "../logger.js";
|
|
15
|
+
import { EXIT_CODES } from "../errors.js";
|
|
15
16
|
import setEngines from "./engines.js";
|
|
16
17
|
import setRouter from "./router.js";
|
|
17
18
|
import setState from "../state/index.js";
|
|
@@ -50,15 +51,24 @@ export default async function init(mergedConfig) {
|
|
|
50
51
|
setViews();
|
|
51
52
|
|
|
52
53
|
if (global.config.isBuild) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
54
|
+
try {
|
|
55
|
+
const message = await build();
|
|
56
|
+
log("success", message);
|
|
57
|
+
return {
|
|
58
|
+
success: true,
|
|
59
|
+
code: EXIT_CODES.SUCCESS,
|
|
60
|
+
shouldExit: true,
|
|
61
|
+
message,
|
|
62
|
+
};
|
|
63
|
+
} catch (error) {
|
|
64
|
+
log("error", error);
|
|
65
|
+
return {
|
|
66
|
+
success: false,
|
|
67
|
+
code: EXIT_CODES.GENERAL_ERROR,
|
|
68
|
+
shouldExit: true,
|
|
69
|
+
message: String(error),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
62
72
|
}
|
|
63
73
|
|
|
64
74
|
const { server, port: actualPort } = await startServer(
|
|
@@ -69,7 +79,13 @@ export default async function init(mergedConfig) {
|
|
|
69
79
|
|
|
70
80
|
log("success", `${t("serverStarted").replace("{{port}}", actualPort)}\n`);
|
|
71
81
|
|
|
72
|
-
return
|
|
82
|
+
return {
|
|
83
|
+
success: true,
|
|
84
|
+
code: EXIT_CODES.SUCCESS,
|
|
85
|
+
shouldExit: false,
|
|
86
|
+
server,
|
|
87
|
+
port: actualPort,
|
|
88
|
+
};
|
|
73
89
|
}
|
|
74
90
|
|
|
75
91
|
/**
|
package/lib/init/watcher.js
CHANGED
|
@@ -161,18 +161,21 @@ function printWatchReport(report, watchConfig) {
|
|
|
161
161
|
` ${colorize("grey", "Diagnostics:", useColors)} sources=${report.meta.sourceCount
|
|
162
162
|
}, ignores=${report.meta.ignoreCount}`,
|
|
163
163
|
);
|
|
164
|
-
console.info(` ${colorize("grey", "Resolved sources:", useColors)}`);
|
|
165
164
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
165
|
+
if (watchConfig?.debug?.logResolvedSources) {
|
|
166
|
+
console.info(` ${colorize("grey", "Resolved sources:", useColors)}`);
|
|
167
|
+
|
|
168
|
+
for (const source of report.sources) {
|
|
169
|
+
const stateLabel = source.exists ? "exists" : "missing";
|
|
170
|
+
const stateColor = source.exists ? "green" : "yellow";
|
|
171
|
+
console.info(
|
|
172
|
+
` - ${source.id} (${source.type}) ${source.resolvedPath} [${colorize(
|
|
173
|
+
stateColor,
|
|
174
|
+
stateLabel,
|
|
175
|
+
useColors,
|
|
176
|
+
)}]`,
|
|
177
|
+
);
|
|
178
|
+
}
|
|
176
179
|
}
|
|
177
180
|
|
|
178
181
|
console.info(` ${colorize("grey", "Ignored patterns:", useColors)}`);
|
|
@@ -628,6 +631,7 @@ export default function Watcher(server) {
|
|
|
628
631
|
|
|
629
632
|
isProcessing = true;
|
|
630
633
|
try {
|
|
634
|
+
log("info", t("updatingStarted"));
|
|
631
635
|
const events = snapshotPendingEvents(pendingByPath);
|
|
632
636
|
pendingByPath.clear();
|
|
633
637
|
await handleFileChange(events);
|
|
@@ -713,7 +717,6 @@ export default function Watcher(server) {
|
|
|
713
717
|
log("info", `watch:event=${eventType} path=${changedPath}`);
|
|
714
718
|
}
|
|
715
719
|
|
|
716
|
-
log("info", t("updatingStarted"));
|
|
717
720
|
enqueueEvent(eventType, changedPath);
|
|
718
721
|
});
|
|
719
722
|
|
package/lib/state/helpers.js
CHANGED
|
@@ -7,6 +7,7 @@ import path from "path";
|
|
|
7
7
|
import log from "../logger.js";
|
|
8
8
|
import { t } from "../i18n/index.js";
|
|
9
9
|
import { readdir } from "node:fs/promises";
|
|
10
|
+
import { EXIT_CODES, MiyagiError } from "../errors.js";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* @param {string|null} dir - the directory in which to look for files
|
|
@@ -25,17 +26,21 @@ async function getFiles(dir, ignores, configPath, type, check) {
|
|
|
25
26
|
});
|
|
26
27
|
} catch (error) {
|
|
27
28
|
if (error.code === "ENOENT") {
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
const message = t("srcFolderNotFound")
|
|
30
|
+
.replaceAll("{{directory}}", dir)
|
|
31
|
+
.replaceAll("{{type}}", type)
|
|
32
|
+
.replaceAll("{{config}}", configPath);
|
|
33
|
+
log("error", message);
|
|
34
|
+
throw new MiyagiError(message, {
|
|
35
|
+
code: EXIT_CODES.CONFIG_ERROR,
|
|
36
|
+
logged: true,
|
|
37
|
+
});
|
|
36
38
|
} else {
|
|
37
39
|
log("error", error.toString(), error);
|
|
38
|
-
|
|
40
|
+
throw new MiyagiError(error.toString(), {
|
|
41
|
+
code: EXIT_CODES.GENERAL_ERROR,
|
|
42
|
+
logged: true,
|
|
43
|
+
});
|
|
39
44
|
}
|
|
40
45
|
}
|
|
41
46
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schalkneethling/miyagi-core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "miyagi is a component development tool for JavaScript template engines.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "Schalk Neethling <schalkneethling@duck.com>, Michael Großklaus <mail@mgrossklaus.de> (https://www.mgrossklaus.de)",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@eslint/js": "^9.39.2",
|
|
55
55
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
56
|
-
"@rollup/plugin-terser": "^0.
|
|
56
|
+
"@rollup/plugin-terser": "^1.0.0",
|
|
57
57
|
"@types/js-yaml": "^4.0.9",
|
|
58
58
|
"@types/node": "^25.3.3",
|
|
59
59
|
"@types/yargs": "^17.0.35",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"cssnano": "^7.1.2",
|
|
62
62
|
"eslint": "^9.39.0",
|
|
63
63
|
"eslint-plugin-jsdoc": "^62.5.4",
|
|
64
|
-
"globals": "^
|
|
64
|
+
"globals": "^17.4.0",
|
|
65
65
|
"gulp": "^5.0.1",
|
|
66
66
|
"gulp-postcss": "^10.0.0",
|
|
67
67
|
"postcss": "^8.5.6",
|