mn-rails-cli 0.1.1 → 0.1.2
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/dist/index.cjs +78 -68
- package/dist/index.js +77 -68
- package/package.json +11 -11
- package/LICENSE +0 -21
package/dist/index.cjs
CHANGED
|
@@ -27,10 +27,17 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
27
|
var import_commander = require("commander");
|
|
28
28
|
|
|
29
29
|
// src/commands/new.ts
|
|
30
|
-
var
|
|
30
|
+
var import_fs_extra = __toESM(require("fs-extra"), 1);
|
|
31
|
+
var import_fs = require("fs");
|
|
31
32
|
var path = __toESM(require("path"), 1);
|
|
33
|
+
var import_url = require("url");
|
|
32
34
|
var import_chalk = __toESM(require("chalk"), 1);
|
|
33
35
|
var import_inquirer = __toESM(require("inquirer"), 1);
|
|
36
|
+
var import_meta = {};
|
|
37
|
+
var { ensureDirSync, writeJSONSync, copySync } = import_fs_extra.default;
|
|
38
|
+
var __filename = (0, import_url.fileURLToPath)(import_meta.url);
|
|
39
|
+
var __dirname = path.dirname(__filename);
|
|
40
|
+
var TEMPLATES_ROOT = path.resolve(__dirname, "../src/templates");
|
|
34
41
|
async function newCommand(name, options = {}) {
|
|
35
42
|
try {
|
|
36
43
|
let projectName = name;
|
|
@@ -58,15 +65,15 @@ async function newCommand(name, options = {}) {
|
|
|
58
65
|
process.exit(1);
|
|
59
66
|
}
|
|
60
67
|
const projectPath = path.resolve(process.cwd(), projectName);
|
|
61
|
-
if (
|
|
68
|
+
if ((0, import_fs.existsSync)(projectPath)) {
|
|
62
69
|
console.error(import_chalk.default.red(`Error: Directory "${projectName}" already exists`));
|
|
63
70
|
process.exit(1);
|
|
64
71
|
}
|
|
65
72
|
console.log(import_chalk.default.blue(`Creating new plugin project: ${projectName}...`));
|
|
66
|
-
|
|
73
|
+
ensureDirSync(projectPath);
|
|
67
74
|
const templateName = options.template || "basic";
|
|
68
|
-
const templatePath = path.resolve(
|
|
69
|
-
if (!
|
|
75
|
+
const templatePath = path.resolve(TEMPLATES_ROOT, templateName);
|
|
76
|
+
if (!(0, import_fs.existsSync)(templatePath)) {
|
|
70
77
|
console.warn(import_chalk.default.yellow(`Template "${templateName}" not found, using basic template`));
|
|
71
78
|
await createBasicTemplate(projectPath, projectName);
|
|
72
79
|
} else {
|
|
@@ -85,7 +92,7 @@ Next steps:`));
|
|
|
85
92
|
}
|
|
86
93
|
async function createBasicTemplate(projectPath, projectName) {
|
|
87
94
|
const dirs = ["src", "src/controllers", "src/views"];
|
|
88
|
-
dirs.forEach((dir) =>
|
|
95
|
+
dirs.forEach((dir) => ensureDirSync(path.join(projectPath, dir)));
|
|
89
96
|
const packageJson = {
|
|
90
97
|
name: projectName,
|
|
91
98
|
version: "0.1.0",
|
|
@@ -103,7 +110,7 @@ async function createBasicTemplate(projectPath, projectName) {
|
|
|
103
110
|
typescript: "^5.3.3"
|
|
104
111
|
}
|
|
105
112
|
};
|
|
106
|
-
|
|
113
|
+
writeJSONSync(path.join(projectPath, "package.json"), packageJson, { spaces: 2 });
|
|
107
114
|
const tsconfig = {
|
|
108
115
|
extends: "mn-rails-core/tsconfig.json",
|
|
109
116
|
compilerOptions: {
|
|
@@ -112,14 +119,14 @@ async function createBasicTemplate(projectPath, projectName) {
|
|
|
112
119
|
},
|
|
113
120
|
include: ["src/**/*"]
|
|
114
121
|
};
|
|
115
|
-
|
|
122
|
+
writeJSONSync(path.join(projectPath, "tsconfig.json"), tsconfig, { spaces: 2 });
|
|
116
123
|
const config = `export default {
|
|
117
124
|
// Plugin configuration
|
|
118
125
|
name: '${projectName}',
|
|
119
126
|
version: '0.1.0',
|
|
120
127
|
};
|
|
121
128
|
`;
|
|
122
|
-
|
|
129
|
+
(0, import_fs.writeFileSync)(path.join(projectPath, "mn-rails.config.js"), config);
|
|
123
130
|
const indexContent = `import { App, MN } from 'mn-rails-core';
|
|
124
131
|
import MainController from './controllers/MainController.js';
|
|
125
132
|
|
|
@@ -139,7 +146,7 @@ class Plugin extends App {
|
|
|
139
146
|
|
|
140
147
|
export default new Plugin();
|
|
141
148
|
`;
|
|
142
|
-
|
|
149
|
+
(0, import_fs.writeFileSync)(path.join(projectPath, "src/index.ts"), indexContent);
|
|
143
150
|
const controllerContent = `import { Controller, MN } from 'mn-rails-core';
|
|
144
151
|
|
|
145
152
|
export default class MainController extends Controller {
|
|
@@ -196,7 +203,7 @@ export default class MainController extends Controller {
|
|
|
196
203
|
};
|
|
197
204
|
}
|
|
198
205
|
`;
|
|
199
|
-
|
|
206
|
+
(0, import_fs.writeFileSync)(path.join(projectPath, "src/controllers/MainController.ts"), controllerContent);
|
|
200
207
|
const helloWorldView = `<!DOCTYPE html>
|
|
201
208
|
<html>
|
|
202
209
|
<head>
|
|
@@ -336,7 +343,7 @@ export default class MainController extends Controller {
|
|
|
336
343
|
</body>
|
|
337
344
|
</html>
|
|
338
345
|
`;
|
|
339
|
-
|
|
346
|
+
(0, import_fs.writeFileSync)(path.join(projectPath, "src/views/HelloWorld.html"), helloWorldView);
|
|
340
347
|
const readme = `# ${projectName}
|
|
341
348
|
|
|
342
349
|
A MarginNote plugin built with MN Rails.
|
|
@@ -352,10 +359,10 @@ mn-rails build
|
|
|
352
359
|
|
|
353
360
|
MIT
|
|
354
361
|
`;
|
|
355
|
-
|
|
362
|
+
(0, import_fs.writeFileSync)(path.join(projectPath, "README.md"), readme);
|
|
356
363
|
}
|
|
357
364
|
async function copyTemplate(templatePath, projectPath, projectName) {
|
|
358
|
-
const files =
|
|
365
|
+
const files = (0, import_fs.readdirSync)(templatePath, { withFileTypes: true });
|
|
359
366
|
for (const file of files) {
|
|
360
367
|
const srcPath = path.join(templatePath, file.name);
|
|
361
368
|
let destPath = path.join(projectPath, file.name);
|
|
@@ -363,31 +370,32 @@ async function copyTemplate(templatePath, projectPath, projectName) {
|
|
|
363
370
|
destPath = destPath.replace(".template", "");
|
|
364
371
|
}
|
|
365
372
|
if (file.isDirectory()) {
|
|
366
|
-
|
|
373
|
+
copySync(srcPath, destPath);
|
|
367
374
|
} else {
|
|
368
|
-
let content =
|
|
375
|
+
let content = (0, import_fs.readFileSync)(srcPath, "utf-8");
|
|
369
376
|
const projectTitle = projectName.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
370
377
|
content = content.replace(/\{\{PROJECT_NAME\}\}/g, projectName).replace(/\{\{PROJECT_TITLE\}\}/g, projectTitle);
|
|
371
|
-
|
|
378
|
+
(0, import_fs.writeFileSync)(destPath, content);
|
|
372
379
|
}
|
|
373
380
|
}
|
|
374
381
|
const dirs = ["src", "src/controllers", "src/views"];
|
|
375
382
|
dirs.forEach((dir) => {
|
|
376
383
|
const dirPath = path.join(projectPath, dir);
|
|
377
|
-
if (!
|
|
378
|
-
|
|
384
|
+
if (!(0, import_fs.existsSync)(dirPath)) {
|
|
385
|
+
ensureDirSync(dirPath);
|
|
379
386
|
}
|
|
380
387
|
});
|
|
381
388
|
}
|
|
382
389
|
|
|
383
390
|
// src/commands/build.ts
|
|
384
391
|
var path5 = __toESM(require("path"), 1);
|
|
385
|
-
var
|
|
392
|
+
var import_fs4 = require("fs");
|
|
386
393
|
var import_chalk3 = __toESM(require("chalk"), 1);
|
|
387
394
|
|
|
388
395
|
// src/build/index.ts
|
|
389
396
|
var path4 = __toESM(require("path"), 1);
|
|
390
|
-
var
|
|
397
|
+
var import_fs_extra2 = __toESM(require("fs-extra"), 1);
|
|
398
|
+
var import_fs3 = require("fs");
|
|
391
399
|
var import_child_process = require("child_process");
|
|
392
400
|
var import_chalk2 = __toESM(require("chalk"), 1);
|
|
393
401
|
|
|
@@ -680,7 +688,8 @@ function generateCompanionCode(options) {
|
|
|
680
688
|
}
|
|
681
689
|
|
|
682
690
|
// src/build/type-generator.ts
|
|
683
|
-
var
|
|
691
|
+
var fs = __toESM(require("fs-extra"), 1);
|
|
692
|
+
var import_fs2 = require("fs");
|
|
684
693
|
var path3 = __toESM(require("path"), 1);
|
|
685
694
|
var import_ts_morph = require("ts-morph");
|
|
686
695
|
function extractActionsType(objectLiteral, sourceFile) {
|
|
@@ -770,10 +779,10 @@ function formatActionSignature(sig) {
|
|
|
770
779
|
async function parseAllControllers(projectRoot, onWarn) {
|
|
771
780
|
const srcDir = path3.join(projectRoot, "src");
|
|
772
781
|
const controllersDir = path3.join(srcDir, "controllers");
|
|
773
|
-
if (!
|
|
782
|
+
if (!(0, import_fs2.existsSync)(controllersDir)) {
|
|
774
783
|
return [];
|
|
775
784
|
}
|
|
776
|
-
const controllerFiles =
|
|
785
|
+
const controllerFiles = (0, import_fs2.readdirSync)(controllersDir).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
|
|
777
786
|
if (controllerFiles.length === 0) {
|
|
778
787
|
return [];
|
|
779
788
|
}
|
|
@@ -862,19 +871,20 @@ async function generateTypes(options) {
|
|
|
862
871
|
lines.push("}");
|
|
863
872
|
lines.push("");
|
|
864
873
|
const output = outputPath || path3.join(projectRoot, "src", "bridge-types.ts");
|
|
865
|
-
await
|
|
866
|
-
await
|
|
874
|
+
await fs.ensureDir(path3.dirname(output));
|
|
875
|
+
await fs.writeFile(output, lines.join("\n"), "utf-8");
|
|
867
876
|
}
|
|
868
877
|
|
|
869
878
|
// src/build/index.ts
|
|
870
879
|
async function buildPlugin(projectRoot, options = {}) {
|
|
880
|
+
const { removeSync, ensureDirSync: ensureDirSync2, copySync: copySync2, writeJSONSync: writeJSONSync2 } = import_fs_extra2.default;
|
|
871
881
|
const srcDir = path4.join(projectRoot, "src");
|
|
872
882
|
const distDir = path4.join(projectRoot, "dist");
|
|
873
|
-
if (!
|
|
883
|
+
if (!(0, import_fs3.existsSync)(srcDir)) {
|
|
874
884
|
throw new Error("src directory not found");
|
|
875
885
|
}
|
|
876
|
-
if (
|
|
877
|
-
|
|
886
|
+
if ((0, import_fs3.existsSync)(distDir)) {
|
|
887
|
+
removeSync(distDir);
|
|
878
888
|
}
|
|
879
889
|
let typeDefinitionsForInjection = null;
|
|
880
890
|
try {
|
|
@@ -901,23 +911,23 @@ async function buildPlugin(projectRoot, options = {}) {
|
|
|
901
911
|
}
|
|
902
912
|
const config = await loadConfig(projectRoot);
|
|
903
913
|
const addonDir = path4.join(projectRoot, "dist", "addon");
|
|
904
|
-
|
|
914
|
+
ensureDirSync2(addonDir);
|
|
905
915
|
const copyFiles = (src, dest) => {
|
|
906
|
-
const entries =
|
|
916
|
+
const entries = (0, import_fs3.readdirSync)(src, { withFileTypes: true });
|
|
907
917
|
for (const entry of entries) {
|
|
908
918
|
const srcPath = path4.join(src, entry.name);
|
|
909
919
|
const destPath = path4.join(dest, entry.name);
|
|
910
920
|
if (entry.isDirectory()) {
|
|
911
|
-
|
|
921
|
+
ensureDirSync2(destPath);
|
|
912
922
|
copyFiles(srcPath, destPath);
|
|
913
923
|
} else if (entry.name.endsWith(".js") || entry.name.endsWith(".d.ts")) {
|
|
914
|
-
|
|
924
|
+
copySync2(srcPath, destPath);
|
|
915
925
|
}
|
|
916
926
|
}
|
|
917
927
|
};
|
|
918
928
|
const collectFilesByExt = (dir, ext, base = "") => {
|
|
919
929
|
const results = [];
|
|
920
|
-
const entries =
|
|
930
|
+
const entries = (0, import_fs3.readdirSync)(dir, { withFileTypes: true });
|
|
921
931
|
for (const e of entries) {
|
|
922
932
|
const rel = base ? `${base}/${e.name}` : e.name;
|
|
923
933
|
if (e.isDirectory()) {
|
|
@@ -929,26 +939,26 @@ async function buildPlugin(projectRoot, options = {}) {
|
|
|
929
939
|
return results;
|
|
930
940
|
};
|
|
931
941
|
const copyViewsExcept = (src, dest, skipExts) => {
|
|
932
|
-
const entries =
|
|
942
|
+
const entries = (0, import_fs3.readdirSync)(src, { withFileTypes: true });
|
|
933
943
|
for (const entry of entries) {
|
|
934
944
|
const srcPath = path4.join(src, entry.name);
|
|
935
945
|
const destPath = path4.join(dest, entry.name);
|
|
936
946
|
if (entry.isDirectory()) {
|
|
937
|
-
|
|
947
|
+
ensureDirSync2(destPath);
|
|
938
948
|
copyViewsExcept(srcPath, destPath, skipExts);
|
|
939
949
|
} else {
|
|
940
950
|
const skip = skipExts.some((ext) => entry.name.endsWith(ext));
|
|
941
951
|
if (!skip) {
|
|
942
|
-
|
|
952
|
+
copySync2(srcPath, destPath);
|
|
943
953
|
}
|
|
944
954
|
}
|
|
945
955
|
}
|
|
946
956
|
};
|
|
947
957
|
copyFiles(distDir, addonDir);
|
|
948
958
|
const srcViewsDir = path4.join(projectRoot, "src", "views");
|
|
949
|
-
if (
|
|
959
|
+
if ((0, import_fs3.existsSync)(srcViewsDir)) {
|
|
950
960
|
const addonViewsDir = path4.join(addonDir, "views");
|
|
951
|
-
|
|
961
|
+
ensureDirSync2(addonViewsDir);
|
|
952
962
|
let typeDefinitions = null;
|
|
953
963
|
try {
|
|
954
964
|
typeDefinitions = await generateTypesForInjection(
|
|
@@ -965,7 +975,7 @@ async function buildPlugin(projectRoot, options = {}) {
|
|
|
965
975
|
const inputPath = path4.join(srcViewsDir, rel);
|
|
966
976
|
const outRel = rel.replace(/\.jsx$/, ".js");
|
|
967
977
|
const outputPath = path4.join(addonViewsDir, outRel);
|
|
968
|
-
|
|
978
|
+
ensureDirSync2(path4.dirname(outputPath));
|
|
969
979
|
await esbuild.build({
|
|
970
980
|
entryPoints: [inputPath],
|
|
971
981
|
bundle: false,
|
|
@@ -975,14 +985,14 @@ async function buildPlugin(projectRoot, options = {}) {
|
|
|
975
985
|
jsx: "transform"
|
|
976
986
|
});
|
|
977
987
|
if (typeDefinitions) {
|
|
978
|
-
let content =
|
|
988
|
+
let content = (0, import_fs3.readFileSync)(outputPath, "utf-8");
|
|
979
989
|
const typeComment = `/**
|
|
980
990
|
* @typedef {Object} BridgeActions
|
|
981
991
|
${typeDefinitions.split("\n").filter((l) => l.trim() && !l.startsWith("//")).map((l) => ` * ${l}`).join("\n")}
|
|
982
992
|
*/
|
|
983
993
|
`;
|
|
984
994
|
content = typeComment + content;
|
|
985
|
-
|
|
995
|
+
(0, import_fs3.writeFileSync)(outputPath, content, "utf-8");
|
|
986
996
|
}
|
|
987
997
|
}
|
|
988
998
|
console.log(import_chalk2.default.blue(`\u2713 Compiled ${jsxFiles.length} JSX file(s)`));
|
|
@@ -995,9 +1005,9 @@ ${typeDefinitions.split("\n").filter((l) => l.trim() && !l.startsWith("//")).map
|
|
|
995
1005
|
const inputPath = path4.join(srcViewsDir, rel);
|
|
996
1006
|
const outRel = rel.replace(/\.vue$/, ".js");
|
|
997
1007
|
const outputPath = path4.join(addonViewsDir, outRel);
|
|
998
|
-
|
|
1008
|
+
ensureDirSync2(path4.dirname(outputPath));
|
|
999
1009
|
try {
|
|
1000
|
-
const source =
|
|
1010
|
+
const source = (0, import_fs3.readFileSync)(inputPath, "utf-8");
|
|
1001
1011
|
const { descriptor, errors } = parse(source, { filename: inputPath });
|
|
1002
1012
|
if (errors.length > 0) {
|
|
1003
1013
|
console.warn(import_chalk2.default.yellow(`Vue parse warnings for ${rel}:`));
|
|
@@ -1043,7 +1053,7 @@ export default { render,`
|
|
|
1043
1053
|
if (descriptor.styles && descriptor.styles.length > 0) {
|
|
1044
1054
|
const styleContent = descriptor.styles.map((style) => style.content).join("\n");
|
|
1045
1055
|
const stylePath = outputPath.replace(/\.js$/, ".css");
|
|
1046
|
-
|
|
1056
|
+
(0, import_fs3.writeFileSync)(stylePath, styleContent, "utf-8");
|
|
1047
1057
|
}
|
|
1048
1058
|
const result = await esbuild.transform(scriptCode, {
|
|
1049
1059
|
loader: descriptor.script?.lang === "ts" || descriptor.scriptSetup?.lang === "ts" ? "ts" : "js",
|
|
@@ -1059,7 +1069,7 @@ ${typeDefinitions.split("\n").filter((l) => l.trim() && !l.startsWith("//")).map
|
|
|
1059
1069
|
`;
|
|
1060
1070
|
compiledCode = typeComment + compiledCode;
|
|
1061
1071
|
}
|
|
1062
|
-
|
|
1072
|
+
(0, import_fs3.writeFileSync)(outputPath, compiledCode, "utf-8");
|
|
1063
1073
|
} catch (error) {
|
|
1064
1074
|
console.error(import_chalk2.default.red(`Failed to compile Vue file ${rel}: ${error instanceof Error ? error.message : String(error)}`));
|
|
1065
1075
|
}
|
|
@@ -1073,7 +1083,7 @@ ${typeDefinitions.split("\n").filter((l) => l.trim() && !l.startsWith("//")).map
|
|
|
1073
1083
|
);
|
|
1074
1084
|
}
|
|
1075
1085
|
if (srcPath.endsWith(".js") || srcPath.endsWith(".ts")) {
|
|
1076
|
-
let content =
|
|
1086
|
+
let content = (0, import_fs3.readFileSync)(srcPath, "utf-8");
|
|
1077
1087
|
if (srcPath.endsWith(".ts") && typeDefinitions) {
|
|
1078
1088
|
content = typeDefinitions + "\n\n" + content;
|
|
1079
1089
|
} else if (srcPath.endsWith(".js") && typeDefinitions) {
|
|
@@ -1084,18 +1094,18 @@ ${typeDefinitions.split("\n").filter((l) => l.trim() && !l.startsWith("//")).map
|
|
|
1084
1094
|
`;
|
|
1085
1095
|
content = typeComment + content;
|
|
1086
1096
|
}
|
|
1087
|
-
|
|
1097
|
+
(0, import_fs3.writeFileSync)(destPath, content, "utf-8");
|
|
1088
1098
|
} else {
|
|
1089
|
-
|
|
1099
|
+
copySync2(srcPath, destPath);
|
|
1090
1100
|
}
|
|
1091
1101
|
};
|
|
1092
1102
|
const copyViewsWithTypeInjection = (src, dest, skipExts) => {
|
|
1093
|
-
const entries =
|
|
1103
|
+
const entries = (0, import_fs3.readdirSync)(src, { withFileTypes: true });
|
|
1094
1104
|
for (const entry of entries) {
|
|
1095
1105
|
const srcPath = path4.join(src, entry.name);
|
|
1096
1106
|
const destPath = path4.join(dest, entry.name);
|
|
1097
1107
|
if (entry.isDirectory()) {
|
|
1098
|
-
|
|
1108
|
+
ensureDirSync2(destPath);
|
|
1099
1109
|
copyViewsWithTypeInjection(srcPath, destPath, skipExts);
|
|
1100
1110
|
} else {
|
|
1101
1111
|
const skip = skipExts.some((ext) => entry.name.endsWith(ext));
|
|
@@ -1110,8 +1120,8 @@ ${typeDefinitions.split("\n").filter((l) => l.trim() && !l.startsWith("//")).map
|
|
|
1110
1120
|
}
|
|
1111
1121
|
const indexFile = path4.join(addonDir, "index.js");
|
|
1112
1122
|
const mainFile = path4.join(addonDir, "main.js");
|
|
1113
|
-
if (
|
|
1114
|
-
let mainContent =
|
|
1123
|
+
if ((0, import_fs3.existsSync)(indexFile)) {
|
|
1124
|
+
let mainContent = (0, import_fs3.readFileSync)(indexFile, "utf-8");
|
|
1115
1125
|
if (options.devMode && options.devServerUrl) {
|
|
1116
1126
|
const companionCode = generateCompanionCode({
|
|
1117
1127
|
serverUrl: options.devServerUrl
|
|
@@ -1119,8 +1129,8 @@ ${typeDefinitions.split("\n").filter((l) => l.trim() && !l.startsWith("//")).map
|
|
|
1119
1129
|
mainContent = companionCode + "\n" + mainContent;
|
|
1120
1130
|
console.log(import_chalk2.default.blue("\u2713 Debug companion injected"));
|
|
1121
1131
|
}
|
|
1122
|
-
|
|
1123
|
-
|
|
1132
|
+
(0, import_fs3.writeFileSync)(mainFile, mainContent);
|
|
1133
|
+
removeSync(indexFile);
|
|
1124
1134
|
}
|
|
1125
1135
|
if (typeDefinitionsForInjection) {
|
|
1126
1136
|
const typesFile = path4.join(addonDir, "bridge-types.js");
|
|
@@ -1132,7 +1142,7 @@ ${jsdocTypes}
|
|
|
1132
1142
|
* @typedef {BridgeActions} bridge
|
|
1133
1143
|
*/
|
|
1134
1144
|
`;
|
|
1135
|
-
|
|
1145
|
+
(0, import_fs3.writeFileSync)(typesFile, typesCode, "utf-8");
|
|
1136
1146
|
}
|
|
1137
1147
|
const addonJson = {
|
|
1138
1148
|
key: config.name || path4.basename(projectRoot),
|
|
@@ -1141,7 +1151,7 @@ ${jsdocTypes}
|
|
|
1141
1151
|
author: config.author || "",
|
|
1142
1152
|
main: "main.js"
|
|
1143
1153
|
};
|
|
1144
|
-
|
|
1154
|
+
writeJSONSync2(path4.join(addonDir, "addon.json"), addonJson, { spaces: 2 });
|
|
1145
1155
|
const addonName = `${addonJson.key}-${addonJson.version}.mnaddon`;
|
|
1146
1156
|
const addonPath = path4.join(projectRoot, addonName);
|
|
1147
1157
|
try {
|
|
@@ -1160,7 +1170,7 @@ async function buildCommand(options = {}) {
|
|
|
1160
1170
|
try {
|
|
1161
1171
|
const projectRoot = process.cwd();
|
|
1162
1172
|
const configPath = path5.join(projectRoot, "mn-rails.config.js");
|
|
1163
|
-
if (!
|
|
1173
|
+
if (!(0, import_fs4.existsSync)(configPath)) {
|
|
1164
1174
|
console.error(import_chalk3.default.red("Error: mn-rails.config.js not found. Are you in a plugin project?"));
|
|
1165
1175
|
process.exit(1);
|
|
1166
1176
|
}
|
|
@@ -1180,6 +1190,8 @@ async function buildCommand(options = {}) {
|
|
|
1180
1190
|
// src/commands/dev.ts
|
|
1181
1191
|
var import_chalk7 = __toESM(require("chalk"), 1);
|
|
1182
1192
|
var path8 = __toESM(require("path"), 1);
|
|
1193
|
+
var fs2 = __toESM(require("fs-extra"), 1);
|
|
1194
|
+
var import_fs6 = require("fs");
|
|
1183
1195
|
|
|
1184
1196
|
// src/dev/server.ts
|
|
1185
1197
|
var import_ws = require("ws");
|
|
@@ -1441,14 +1453,14 @@ var import_chalk6 = __toESM(require("chalk"), 1);
|
|
|
1441
1453
|
|
|
1442
1454
|
// src/dev/code-loader.ts
|
|
1443
1455
|
var path7 = __toESM(require("path"), 1);
|
|
1444
|
-
var
|
|
1456
|
+
var import_fs5 = require("fs");
|
|
1445
1457
|
function loadPluginCode(projectRoot) {
|
|
1446
1458
|
try {
|
|
1447
1459
|
const mainFile = path7.join(projectRoot, "dist", "addon", "main.js");
|
|
1448
|
-
if (!
|
|
1460
|
+
if (!(0, import_fs5.existsSync)(mainFile)) {
|
|
1449
1461
|
return null;
|
|
1450
1462
|
}
|
|
1451
|
-
let code =
|
|
1463
|
+
let code = (0, import_fs5.readFileSync)(mainFile, "utf-8");
|
|
1452
1464
|
const companionEndMarker = "})();";
|
|
1453
1465
|
const companionIndex = code.indexOf(companionEndMarker);
|
|
1454
1466
|
if (companionIndex !== -1) {
|
|
@@ -1601,8 +1613,7 @@ async function devCommand(options = {}) {
|
|
|
1601
1613
|
console.log(import_chalk7.default.blue("Starting development server..."));
|
|
1602
1614
|
const configPath = path8.join(projectRoot, "mn-rails.config.js");
|
|
1603
1615
|
try {
|
|
1604
|
-
|
|
1605
|
-
if (!fs6.existsSync(configPath)) {
|
|
1616
|
+
if (!(0, import_fs6.existsSync)(configPath)) {
|
|
1606
1617
|
console.error(import_chalk7.default.red("Error: mn-rails.config.js not found. Are you in a plugin project?"));
|
|
1607
1618
|
process.exit(1);
|
|
1608
1619
|
}
|
|
@@ -1636,18 +1647,17 @@ async function devCommand(options = {}) {
|
|
|
1636
1647
|
}
|
|
1637
1648
|
if (isFirstBuild) {
|
|
1638
1649
|
isFirstBuild = false;
|
|
1639
|
-
const fs6 = await import("fs-extra");
|
|
1640
1650
|
const addonDir = path8.join(projectRoot, "dist", "addon");
|
|
1641
1651
|
const addonJsonPath = path8.join(addonDir, "addon.json");
|
|
1642
|
-
if (
|
|
1643
|
-
const addonJson =
|
|
1652
|
+
if ((0, import_fs6.existsSync)(addonJsonPath)) {
|
|
1653
|
+
const addonJson = fs2.readJSONSync(addonJsonPath);
|
|
1644
1654
|
const addonName = `${addonJson.key}-${addonJson.version}.mnaddon`;
|
|
1645
1655
|
const addonPath = path8.join(projectRoot, addonName);
|
|
1646
1656
|
console.log(import_chalk7.default.green("\n\u2713 Initial build completed!"));
|
|
1647
1657
|
console.log(import_chalk7.default.cyan("\n\u{1F4E6} Plugin Information:"));
|
|
1648
1658
|
console.log(import_chalk7.default.white(` Name: ${addonJson.title || addonJson.key}`));
|
|
1649
1659
|
console.log(import_chalk7.default.white(` Version: ${addonJson.version}`));
|
|
1650
|
-
if (
|
|
1660
|
+
if ((0, import_fs6.existsSync)(addonPath)) {
|
|
1651
1661
|
console.log(import_chalk7.default.cyan(`
|
|
1652
1662
|
\u{1F4C1} Plugin file: ${addonPath}`));
|
|
1653
1663
|
} else {
|
|
@@ -1658,7 +1668,7 @@ async function devCommand(options = {}) {
|
|
|
1658
1668
|
console.log(import_chalk7.default.white(" 1. Open MarginNote app"));
|
|
1659
1669
|
console.log(import_chalk7.default.white(" 2. Go to Settings > Add-ons"));
|
|
1660
1670
|
console.log(import_chalk7.default.white(' 3. Tap "Import Add-on" or drag the .mnaddon file'));
|
|
1661
|
-
if (
|
|
1671
|
+
if ((0, import_fs6.existsSync)(addonPath)) {
|
|
1662
1672
|
console.log(import_chalk7.default.white(` 4. Select: ${addonName}`));
|
|
1663
1673
|
} else {
|
|
1664
1674
|
console.log(import_chalk7.default.white(` 4. Select the addon directory: ${addonDir}`));
|
package/dist/index.js
CHANGED
|
@@ -4,10 +4,16 @@
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/new.ts
|
|
7
|
-
import
|
|
7
|
+
import fsExtra from "fs-extra";
|
|
8
|
+
import { existsSync, readdirSync, readFileSync, writeFileSync } from "fs";
|
|
8
9
|
import * as path from "path";
|
|
10
|
+
import { fileURLToPath } from "url";
|
|
9
11
|
import chalk from "chalk";
|
|
10
12
|
import inquirer from "inquirer";
|
|
13
|
+
var { ensureDirSync, writeJSONSync, copySync } = fsExtra;
|
|
14
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
var __dirname = path.dirname(__filename);
|
|
16
|
+
var TEMPLATES_ROOT = path.resolve(__dirname, "../src/templates");
|
|
11
17
|
async function newCommand(name, options = {}) {
|
|
12
18
|
try {
|
|
13
19
|
let projectName = name;
|
|
@@ -35,15 +41,15 @@ async function newCommand(name, options = {}) {
|
|
|
35
41
|
process.exit(1);
|
|
36
42
|
}
|
|
37
43
|
const projectPath = path.resolve(process.cwd(), projectName);
|
|
38
|
-
if (
|
|
44
|
+
if (existsSync(projectPath)) {
|
|
39
45
|
console.error(chalk.red(`Error: Directory "${projectName}" already exists`));
|
|
40
46
|
process.exit(1);
|
|
41
47
|
}
|
|
42
48
|
console.log(chalk.blue(`Creating new plugin project: ${projectName}...`));
|
|
43
|
-
|
|
49
|
+
ensureDirSync(projectPath);
|
|
44
50
|
const templateName = options.template || "basic";
|
|
45
|
-
const templatePath = path.resolve(
|
|
46
|
-
if (!
|
|
51
|
+
const templatePath = path.resolve(TEMPLATES_ROOT, templateName);
|
|
52
|
+
if (!existsSync(templatePath)) {
|
|
47
53
|
console.warn(chalk.yellow(`Template "${templateName}" not found, using basic template`));
|
|
48
54
|
await createBasicTemplate(projectPath, projectName);
|
|
49
55
|
} else {
|
|
@@ -62,7 +68,7 @@ Next steps:`));
|
|
|
62
68
|
}
|
|
63
69
|
async function createBasicTemplate(projectPath, projectName) {
|
|
64
70
|
const dirs = ["src", "src/controllers", "src/views"];
|
|
65
|
-
dirs.forEach((dir) =>
|
|
71
|
+
dirs.forEach((dir) => ensureDirSync(path.join(projectPath, dir)));
|
|
66
72
|
const packageJson = {
|
|
67
73
|
name: projectName,
|
|
68
74
|
version: "0.1.0",
|
|
@@ -80,7 +86,7 @@ async function createBasicTemplate(projectPath, projectName) {
|
|
|
80
86
|
typescript: "^5.3.3"
|
|
81
87
|
}
|
|
82
88
|
};
|
|
83
|
-
|
|
89
|
+
writeJSONSync(path.join(projectPath, "package.json"), packageJson, { spaces: 2 });
|
|
84
90
|
const tsconfig = {
|
|
85
91
|
extends: "mn-rails-core/tsconfig.json",
|
|
86
92
|
compilerOptions: {
|
|
@@ -89,14 +95,14 @@ async function createBasicTemplate(projectPath, projectName) {
|
|
|
89
95
|
},
|
|
90
96
|
include: ["src/**/*"]
|
|
91
97
|
};
|
|
92
|
-
|
|
98
|
+
writeJSONSync(path.join(projectPath, "tsconfig.json"), tsconfig, { spaces: 2 });
|
|
93
99
|
const config = `export default {
|
|
94
100
|
// Plugin configuration
|
|
95
101
|
name: '${projectName}',
|
|
96
102
|
version: '0.1.0',
|
|
97
103
|
};
|
|
98
104
|
`;
|
|
99
|
-
|
|
105
|
+
writeFileSync(path.join(projectPath, "mn-rails.config.js"), config);
|
|
100
106
|
const indexContent = `import { App, MN } from 'mn-rails-core';
|
|
101
107
|
import MainController from './controllers/MainController.js';
|
|
102
108
|
|
|
@@ -116,7 +122,7 @@ class Plugin extends App {
|
|
|
116
122
|
|
|
117
123
|
export default new Plugin();
|
|
118
124
|
`;
|
|
119
|
-
|
|
125
|
+
writeFileSync(path.join(projectPath, "src/index.ts"), indexContent);
|
|
120
126
|
const controllerContent = `import { Controller, MN } from 'mn-rails-core';
|
|
121
127
|
|
|
122
128
|
export default class MainController extends Controller {
|
|
@@ -173,7 +179,7 @@ export default class MainController extends Controller {
|
|
|
173
179
|
};
|
|
174
180
|
}
|
|
175
181
|
`;
|
|
176
|
-
|
|
182
|
+
writeFileSync(path.join(projectPath, "src/controllers/MainController.ts"), controllerContent);
|
|
177
183
|
const helloWorldView = `<!DOCTYPE html>
|
|
178
184
|
<html>
|
|
179
185
|
<head>
|
|
@@ -313,7 +319,7 @@ export default class MainController extends Controller {
|
|
|
313
319
|
</body>
|
|
314
320
|
</html>
|
|
315
321
|
`;
|
|
316
|
-
|
|
322
|
+
writeFileSync(path.join(projectPath, "src/views/HelloWorld.html"), helloWorldView);
|
|
317
323
|
const readme = `# ${projectName}
|
|
318
324
|
|
|
319
325
|
A MarginNote plugin built with MN Rails.
|
|
@@ -329,10 +335,10 @@ mn-rails build
|
|
|
329
335
|
|
|
330
336
|
MIT
|
|
331
337
|
`;
|
|
332
|
-
|
|
338
|
+
writeFileSync(path.join(projectPath, "README.md"), readme);
|
|
333
339
|
}
|
|
334
340
|
async function copyTemplate(templatePath, projectPath, projectName) {
|
|
335
|
-
const files =
|
|
341
|
+
const files = readdirSync(templatePath, { withFileTypes: true });
|
|
336
342
|
for (const file of files) {
|
|
337
343
|
const srcPath = path.join(templatePath, file.name);
|
|
338
344
|
let destPath = path.join(projectPath, file.name);
|
|
@@ -340,31 +346,32 @@ async function copyTemplate(templatePath, projectPath, projectName) {
|
|
|
340
346
|
destPath = destPath.replace(".template", "");
|
|
341
347
|
}
|
|
342
348
|
if (file.isDirectory()) {
|
|
343
|
-
|
|
349
|
+
copySync(srcPath, destPath);
|
|
344
350
|
} else {
|
|
345
|
-
let content =
|
|
351
|
+
let content = readFileSync(srcPath, "utf-8");
|
|
346
352
|
const projectTitle = projectName.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
347
353
|
content = content.replace(/\{\{PROJECT_NAME\}\}/g, projectName).replace(/\{\{PROJECT_TITLE\}\}/g, projectTitle);
|
|
348
|
-
|
|
354
|
+
writeFileSync(destPath, content);
|
|
349
355
|
}
|
|
350
356
|
}
|
|
351
357
|
const dirs = ["src", "src/controllers", "src/views"];
|
|
352
358
|
dirs.forEach((dir) => {
|
|
353
359
|
const dirPath = path.join(projectPath, dir);
|
|
354
|
-
if (!
|
|
355
|
-
|
|
360
|
+
if (!existsSync(dirPath)) {
|
|
361
|
+
ensureDirSync(dirPath);
|
|
356
362
|
}
|
|
357
363
|
});
|
|
358
364
|
}
|
|
359
365
|
|
|
360
366
|
// src/commands/build.ts
|
|
361
367
|
import * as path5 from "path";
|
|
362
|
-
import
|
|
368
|
+
import { existsSync as existsSync4 } from "fs";
|
|
363
369
|
import chalk3 from "chalk";
|
|
364
370
|
|
|
365
371
|
// src/build/index.ts
|
|
366
372
|
import * as path4 from "path";
|
|
367
|
-
import
|
|
373
|
+
import fsExtra2 from "fs-extra";
|
|
374
|
+
import { existsSync as existsSync3, readdirSync as readdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
368
375
|
import { execSync } from "child_process";
|
|
369
376
|
import chalk2 from "chalk";
|
|
370
377
|
|
|
@@ -657,7 +664,8 @@ function generateCompanionCode(options) {
|
|
|
657
664
|
}
|
|
658
665
|
|
|
659
666
|
// src/build/type-generator.ts
|
|
660
|
-
import * as
|
|
667
|
+
import * as fs from "fs-extra";
|
|
668
|
+
import { existsSync as existsSync2, readdirSync as readdirSync2 } from "fs";
|
|
661
669
|
import * as path3 from "path";
|
|
662
670
|
import { Project } from "ts-morph";
|
|
663
671
|
function extractActionsType(objectLiteral, sourceFile) {
|
|
@@ -747,10 +755,10 @@ function formatActionSignature(sig) {
|
|
|
747
755
|
async function parseAllControllers(projectRoot, onWarn) {
|
|
748
756
|
const srcDir = path3.join(projectRoot, "src");
|
|
749
757
|
const controllersDir = path3.join(srcDir, "controllers");
|
|
750
|
-
if (!
|
|
758
|
+
if (!existsSync2(controllersDir)) {
|
|
751
759
|
return [];
|
|
752
760
|
}
|
|
753
|
-
const controllerFiles =
|
|
761
|
+
const controllerFiles = readdirSync2(controllersDir).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
|
|
754
762
|
if (controllerFiles.length === 0) {
|
|
755
763
|
return [];
|
|
756
764
|
}
|
|
@@ -839,19 +847,20 @@ async function generateTypes(options) {
|
|
|
839
847
|
lines.push("}");
|
|
840
848
|
lines.push("");
|
|
841
849
|
const output = outputPath || path3.join(projectRoot, "src", "bridge-types.ts");
|
|
842
|
-
await
|
|
843
|
-
await
|
|
850
|
+
await fs.ensureDir(path3.dirname(output));
|
|
851
|
+
await fs.writeFile(output, lines.join("\n"), "utf-8");
|
|
844
852
|
}
|
|
845
853
|
|
|
846
854
|
// src/build/index.ts
|
|
847
855
|
async function buildPlugin(projectRoot, options = {}) {
|
|
856
|
+
const { removeSync, ensureDirSync: ensureDirSync2, copySync: copySync2, writeJSONSync: writeJSONSync2 } = fsExtra2;
|
|
848
857
|
const srcDir = path4.join(projectRoot, "src");
|
|
849
858
|
const distDir = path4.join(projectRoot, "dist");
|
|
850
|
-
if (!
|
|
859
|
+
if (!existsSync3(srcDir)) {
|
|
851
860
|
throw new Error("src directory not found");
|
|
852
861
|
}
|
|
853
|
-
if (
|
|
854
|
-
|
|
862
|
+
if (existsSync3(distDir)) {
|
|
863
|
+
removeSync(distDir);
|
|
855
864
|
}
|
|
856
865
|
let typeDefinitionsForInjection = null;
|
|
857
866
|
try {
|
|
@@ -878,23 +887,23 @@ async function buildPlugin(projectRoot, options = {}) {
|
|
|
878
887
|
}
|
|
879
888
|
const config = await loadConfig(projectRoot);
|
|
880
889
|
const addonDir = path4.join(projectRoot, "dist", "addon");
|
|
881
|
-
|
|
890
|
+
ensureDirSync2(addonDir);
|
|
882
891
|
const copyFiles = (src, dest) => {
|
|
883
|
-
const entries =
|
|
892
|
+
const entries = readdirSync3(src, { withFileTypes: true });
|
|
884
893
|
for (const entry of entries) {
|
|
885
894
|
const srcPath = path4.join(src, entry.name);
|
|
886
895
|
const destPath = path4.join(dest, entry.name);
|
|
887
896
|
if (entry.isDirectory()) {
|
|
888
|
-
|
|
897
|
+
ensureDirSync2(destPath);
|
|
889
898
|
copyFiles(srcPath, destPath);
|
|
890
899
|
} else if (entry.name.endsWith(".js") || entry.name.endsWith(".d.ts")) {
|
|
891
|
-
|
|
900
|
+
copySync2(srcPath, destPath);
|
|
892
901
|
}
|
|
893
902
|
}
|
|
894
903
|
};
|
|
895
904
|
const collectFilesByExt = (dir, ext, base = "") => {
|
|
896
905
|
const results = [];
|
|
897
|
-
const entries =
|
|
906
|
+
const entries = readdirSync3(dir, { withFileTypes: true });
|
|
898
907
|
for (const e of entries) {
|
|
899
908
|
const rel = base ? `${base}/${e.name}` : e.name;
|
|
900
909
|
if (e.isDirectory()) {
|
|
@@ -906,26 +915,26 @@ async function buildPlugin(projectRoot, options = {}) {
|
|
|
906
915
|
return results;
|
|
907
916
|
};
|
|
908
917
|
const copyViewsExcept = (src, dest, skipExts) => {
|
|
909
|
-
const entries =
|
|
918
|
+
const entries = readdirSync3(src, { withFileTypes: true });
|
|
910
919
|
for (const entry of entries) {
|
|
911
920
|
const srcPath = path4.join(src, entry.name);
|
|
912
921
|
const destPath = path4.join(dest, entry.name);
|
|
913
922
|
if (entry.isDirectory()) {
|
|
914
|
-
|
|
923
|
+
ensureDirSync2(destPath);
|
|
915
924
|
copyViewsExcept(srcPath, destPath, skipExts);
|
|
916
925
|
} else {
|
|
917
926
|
const skip = skipExts.some((ext) => entry.name.endsWith(ext));
|
|
918
927
|
if (!skip) {
|
|
919
|
-
|
|
928
|
+
copySync2(srcPath, destPath);
|
|
920
929
|
}
|
|
921
930
|
}
|
|
922
931
|
}
|
|
923
932
|
};
|
|
924
933
|
copyFiles(distDir, addonDir);
|
|
925
934
|
const srcViewsDir = path4.join(projectRoot, "src", "views");
|
|
926
|
-
if (
|
|
935
|
+
if (existsSync3(srcViewsDir)) {
|
|
927
936
|
const addonViewsDir = path4.join(addonDir, "views");
|
|
928
|
-
|
|
937
|
+
ensureDirSync2(addonViewsDir);
|
|
929
938
|
let typeDefinitions = null;
|
|
930
939
|
try {
|
|
931
940
|
typeDefinitions = await generateTypesForInjection(
|
|
@@ -942,7 +951,7 @@ async function buildPlugin(projectRoot, options = {}) {
|
|
|
942
951
|
const inputPath = path4.join(srcViewsDir, rel);
|
|
943
952
|
const outRel = rel.replace(/\.jsx$/, ".js");
|
|
944
953
|
const outputPath = path4.join(addonViewsDir, outRel);
|
|
945
|
-
|
|
954
|
+
ensureDirSync2(path4.dirname(outputPath));
|
|
946
955
|
await esbuild.build({
|
|
947
956
|
entryPoints: [inputPath],
|
|
948
957
|
bundle: false,
|
|
@@ -952,14 +961,14 @@ async function buildPlugin(projectRoot, options = {}) {
|
|
|
952
961
|
jsx: "transform"
|
|
953
962
|
});
|
|
954
963
|
if (typeDefinitions) {
|
|
955
|
-
let content =
|
|
964
|
+
let content = readFileSync2(outputPath, "utf-8");
|
|
956
965
|
const typeComment = `/**
|
|
957
966
|
* @typedef {Object} BridgeActions
|
|
958
967
|
${typeDefinitions.split("\n").filter((l) => l.trim() && !l.startsWith("//")).map((l) => ` * ${l}`).join("\n")}
|
|
959
968
|
*/
|
|
960
969
|
`;
|
|
961
970
|
content = typeComment + content;
|
|
962
|
-
|
|
971
|
+
writeFileSync2(outputPath, content, "utf-8");
|
|
963
972
|
}
|
|
964
973
|
}
|
|
965
974
|
console.log(chalk2.blue(`\u2713 Compiled ${jsxFiles.length} JSX file(s)`));
|
|
@@ -972,9 +981,9 @@ ${typeDefinitions.split("\n").filter((l) => l.trim() && !l.startsWith("//")).map
|
|
|
972
981
|
const inputPath = path4.join(srcViewsDir, rel);
|
|
973
982
|
const outRel = rel.replace(/\.vue$/, ".js");
|
|
974
983
|
const outputPath = path4.join(addonViewsDir, outRel);
|
|
975
|
-
|
|
984
|
+
ensureDirSync2(path4.dirname(outputPath));
|
|
976
985
|
try {
|
|
977
|
-
const source =
|
|
986
|
+
const source = readFileSync2(inputPath, "utf-8");
|
|
978
987
|
const { descriptor, errors } = parse(source, { filename: inputPath });
|
|
979
988
|
if (errors.length > 0) {
|
|
980
989
|
console.warn(chalk2.yellow(`Vue parse warnings for ${rel}:`));
|
|
@@ -1020,7 +1029,7 @@ export default { render,`
|
|
|
1020
1029
|
if (descriptor.styles && descriptor.styles.length > 0) {
|
|
1021
1030
|
const styleContent = descriptor.styles.map((style) => style.content).join("\n");
|
|
1022
1031
|
const stylePath = outputPath.replace(/\.js$/, ".css");
|
|
1023
|
-
|
|
1032
|
+
writeFileSync2(stylePath, styleContent, "utf-8");
|
|
1024
1033
|
}
|
|
1025
1034
|
const result = await esbuild.transform(scriptCode, {
|
|
1026
1035
|
loader: descriptor.script?.lang === "ts" || descriptor.scriptSetup?.lang === "ts" ? "ts" : "js",
|
|
@@ -1036,7 +1045,7 @@ ${typeDefinitions.split("\n").filter((l) => l.trim() && !l.startsWith("//")).map
|
|
|
1036
1045
|
`;
|
|
1037
1046
|
compiledCode = typeComment + compiledCode;
|
|
1038
1047
|
}
|
|
1039
|
-
|
|
1048
|
+
writeFileSync2(outputPath, compiledCode, "utf-8");
|
|
1040
1049
|
} catch (error) {
|
|
1041
1050
|
console.error(chalk2.red(`Failed to compile Vue file ${rel}: ${error instanceof Error ? error.message : String(error)}`));
|
|
1042
1051
|
}
|
|
@@ -1050,7 +1059,7 @@ ${typeDefinitions.split("\n").filter((l) => l.trim() && !l.startsWith("//")).map
|
|
|
1050
1059
|
);
|
|
1051
1060
|
}
|
|
1052
1061
|
if (srcPath.endsWith(".js") || srcPath.endsWith(".ts")) {
|
|
1053
|
-
let content =
|
|
1062
|
+
let content = readFileSync2(srcPath, "utf-8");
|
|
1054
1063
|
if (srcPath.endsWith(".ts") && typeDefinitions) {
|
|
1055
1064
|
content = typeDefinitions + "\n\n" + content;
|
|
1056
1065
|
} else if (srcPath.endsWith(".js") && typeDefinitions) {
|
|
@@ -1061,18 +1070,18 @@ ${typeDefinitions.split("\n").filter((l) => l.trim() && !l.startsWith("//")).map
|
|
|
1061
1070
|
`;
|
|
1062
1071
|
content = typeComment + content;
|
|
1063
1072
|
}
|
|
1064
|
-
|
|
1073
|
+
writeFileSync2(destPath, content, "utf-8");
|
|
1065
1074
|
} else {
|
|
1066
|
-
|
|
1075
|
+
copySync2(srcPath, destPath);
|
|
1067
1076
|
}
|
|
1068
1077
|
};
|
|
1069
1078
|
const copyViewsWithTypeInjection = (src, dest, skipExts) => {
|
|
1070
|
-
const entries =
|
|
1079
|
+
const entries = readdirSync3(src, { withFileTypes: true });
|
|
1071
1080
|
for (const entry of entries) {
|
|
1072
1081
|
const srcPath = path4.join(src, entry.name);
|
|
1073
1082
|
const destPath = path4.join(dest, entry.name);
|
|
1074
1083
|
if (entry.isDirectory()) {
|
|
1075
|
-
|
|
1084
|
+
ensureDirSync2(destPath);
|
|
1076
1085
|
copyViewsWithTypeInjection(srcPath, destPath, skipExts);
|
|
1077
1086
|
} else {
|
|
1078
1087
|
const skip = skipExts.some((ext) => entry.name.endsWith(ext));
|
|
@@ -1087,8 +1096,8 @@ ${typeDefinitions.split("\n").filter((l) => l.trim() && !l.startsWith("//")).map
|
|
|
1087
1096
|
}
|
|
1088
1097
|
const indexFile = path4.join(addonDir, "index.js");
|
|
1089
1098
|
const mainFile = path4.join(addonDir, "main.js");
|
|
1090
|
-
if (
|
|
1091
|
-
let mainContent =
|
|
1099
|
+
if (existsSync3(indexFile)) {
|
|
1100
|
+
let mainContent = readFileSync2(indexFile, "utf-8");
|
|
1092
1101
|
if (options.devMode && options.devServerUrl) {
|
|
1093
1102
|
const companionCode = generateCompanionCode({
|
|
1094
1103
|
serverUrl: options.devServerUrl
|
|
@@ -1096,8 +1105,8 @@ ${typeDefinitions.split("\n").filter((l) => l.trim() && !l.startsWith("//")).map
|
|
|
1096
1105
|
mainContent = companionCode + "\n" + mainContent;
|
|
1097
1106
|
console.log(chalk2.blue("\u2713 Debug companion injected"));
|
|
1098
1107
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1108
|
+
writeFileSync2(mainFile, mainContent);
|
|
1109
|
+
removeSync(indexFile);
|
|
1101
1110
|
}
|
|
1102
1111
|
if (typeDefinitionsForInjection) {
|
|
1103
1112
|
const typesFile = path4.join(addonDir, "bridge-types.js");
|
|
@@ -1109,7 +1118,7 @@ ${jsdocTypes}
|
|
|
1109
1118
|
* @typedef {BridgeActions} bridge
|
|
1110
1119
|
*/
|
|
1111
1120
|
`;
|
|
1112
|
-
|
|
1121
|
+
writeFileSync2(typesFile, typesCode, "utf-8");
|
|
1113
1122
|
}
|
|
1114
1123
|
const addonJson = {
|
|
1115
1124
|
key: config.name || path4.basename(projectRoot),
|
|
@@ -1118,7 +1127,7 @@ ${jsdocTypes}
|
|
|
1118
1127
|
author: config.author || "",
|
|
1119
1128
|
main: "main.js"
|
|
1120
1129
|
};
|
|
1121
|
-
|
|
1130
|
+
writeJSONSync2(path4.join(addonDir, "addon.json"), addonJson, { spaces: 2 });
|
|
1122
1131
|
const addonName = `${addonJson.key}-${addonJson.version}.mnaddon`;
|
|
1123
1132
|
const addonPath = path4.join(projectRoot, addonName);
|
|
1124
1133
|
try {
|
|
@@ -1137,7 +1146,7 @@ async function buildCommand(options = {}) {
|
|
|
1137
1146
|
try {
|
|
1138
1147
|
const projectRoot = process.cwd();
|
|
1139
1148
|
const configPath = path5.join(projectRoot, "mn-rails.config.js");
|
|
1140
|
-
if (!
|
|
1149
|
+
if (!existsSync4(configPath)) {
|
|
1141
1150
|
console.error(chalk3.red("Error: mn-rails.config.js not found. Are you in a plugin project?"));
|
|
1142
1151
|
process.exit(1);
|
|
1143
1152
|
}
|
|
@@ -1157,6 +1166,8 @@ async function buildCommand(options = {}) {
|
|
|
1157
1166
|
// src/commands/dev.ts
|
|
1158
1167
|
import chalk7 from "chalk";
|
|
1159
1168
|
import * as path8 from "path";
|
|
1169
|
+
import * as fs2 from "fs-extra";
|
|
1170
|
+
import { existsSync as existsSync6 } from "fs";
|
|
1160
1171
|
|
|
1161
1172
|
// src/dev/server.ts
|
|
1162
1173
|
import { WebSocketServer, WebSocket } from "ws";
|
|
@@ -1418,14 +1429,14 @@ import chalk6 from "chalk";
|
|
|
1418
1429
|
|
|
1419
1430
|
// src/dev/code-loader.ts
|
|
1420
1431
|
import * as path7 from "path";
|
|
1421
|
-
import
|
|
1432
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
1422
1433
|
function loadPluginCode(projectRoot) {
|
|
1423
1434
|
try {
|
|
1424
1435
|
const mainFile = path7.join(projectRoot, "dist", "addon", "main.js");
|
|
1425
|
-
if (!
|
|
1436
|
+
if (!existsSync5(mainFile)) {
|
|
1426
1437
|
return null;
|
|
1427
1438
|
}
|
|
1428
|
-
let code =
|
|
1439
|
+
let code = readFileSync3(mainFile, "utf-8");
|
|
1429
1440
|
const companionEndMarker = "})();";
|
|
1430
1441
|
const companionIndex = code.indexOf(companionEndMarker);
|
|
1431
1442
|
if (companionIndex !== -1) {
|
|
@@ -1578,8 +1589,7 @@ async function devCommand(options = {}) {
|
|
|
1578
1589
|
console.log(chalk7.blue("Starting development server..."));
|
|
1579
1590
|
const configPath = path8.join(projectRoot, "mn-rails.config.js");
|
|
1580
1591
|
try {
|
|
1581
|
-
|
|
1582
|
-
if (!fs6.existsSync(configPath)) {
|
|
1592
|
+
if (!existsSync6(configPath)) {
|
|
1583
1593
|
console.error(chalk7.red("Error: mn-rails.config.js not found. Are you in a plugin project?"));
|
|
1584
1594
|
process.exit(1);
|
|
1585
1595
|
}
|
|
@@ -1613,18 +1623,17 @@ async function devCommand(options = {}) {
|
|
|
1613
1623
|
}
|
|
1614
1624
|
if (isFirstBuild) {
|
|
1615
1625
|
isFirstBuild = false;
|
|
1616
|
-
const fs6 = await import("fs-extra");
|
|
1617
1626
|
const addonDir = path8.join(projectRoot, "dist", "addon");
|
|
1618
1627
|
const addonJsonPath = path8.join(addonDir, "addon.json");
|
|
1619
|
-
if (
|
|
1620
|
-
const addonJson =
|
|
1628
|
+
if (existsSync6(addonJsonPath)) {
|
|
1629
|
+
const addonJson = fs2.readJSONSync(addonJsonPath);
|
|
1621
1630
|
const addonName = `${addonJson.key}-${addonJson.version}.mnaddon`;
|
|
1622
1631
|
const addonPath = path8.join(projectRoot, addonName);
|
|
1623
1632
|
console.log(chalk7.green("\n\u2713 Initial build completed!"));
|
|
1624
1633
|
console.log(chalk7.cyan("\n\u{1F4E6} Plugin Information:"));
|
|
1625
1634
|
console.log(chalk7.white(` Name: ${addonJson.title || addonJson.key}`));
|
|
1626
1635
|
console.log(chalk7.white(` Version: ${addonJson.version}`));
|
|
1627
|
-
if (
|
|
1636
|
+
if (existsSync6(addonPath)) {
|
|
1628
1637
|
console.log(chalk7.cyan(`
|
|
1629
1638
|
\u{1F4C1} Plugin file: ${addonPath}`));
|
|
1630
1639
|
} else {
|
|
@@ -1635,7 +1644,7 @@ async function devCommand(options = {}) {
|
|
|
1635
1644
|
console.log(chalk7.white(" 1. Open MarginNote app"));
|
|
1636
1645
|
console.log(chalk7.white(" 2. Go to Settings > Add-ons"));
|
|
1637
1646
|
console.log(chalk7.white(' 3. Tap "Import Add-on" or drag the .mnaddon file'));
|
|
1638
|
-
if (
|
|
1647
|
+
if (existsSync6(addonPath)) {
|
|
1639
1648
|
console.log(chalk7.white(` 4. Select: ${addonName}`));
|
|
1640
1649
|
} else {
|
|
1641
1650
|
console.log(chalk7.white(` 4. Select the addon directory: ${addonDir}`));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mn-rails-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "CLI tool for MN Rails framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -25,31 +25,31 @@
|
|
|
25
25
|
"src/templates",
|
|
26
26
|
"README.md"
|
|
27
27
|
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --outDir dist",
|
|
30
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --outDir dist --watch",
|
|
31
|
+
"clean": "rm -rf dist"
|
|
32
|
+
},
|
|
28
33
|
"dependencies": {
|
|
29
|
-
"mn-rails-core": "^0.1.
|
|
34
|
+
"mn-rails-core": "^0.1.2",
|
|
30
35
|
"@vue/compiler-sfc": "^3.5.27",
|
|
31
36
|
"chalk": "^5.3.0",
|
|
32
|
-
"chokidar": "^
|
|
37
|
+
"chokidar": "^5.0.0",
|
|
33
38
|
"commander": "^11.1.0",
|
|
34
39
|
"consola": "^3.4.2",
|
|
35
40
|
"cosmiconfig": "^9.0.0",
|
|
36
41
|
"esbuild": "^0.27.2",
|
|
37
42
|
"fs-extra": "^11.2.0",
|
|
38
|
-
"inquirer": "^
|
|
43
|
+
"inquirer": "^13.2.1",
|
|
39
44
|
"ts-morph": "^27.0.2",
|
|
40
45
|
"ws": "^8.16.0"
|
|
41
46
|
},
|
|
42
47
|
"devDependencies": {
|
|
43
48
|
"@types/fs-extra": "^11.0.4",
|
|
44
49
|
"@types/inquirer": "^9.0.7",
|
|
45
|
-
"@types/node": "^
|
|
50
|
+
"@types/node": "^25.0.10",
|
|
46
51
|
"@types/ws": "^8.5.10",
|
|
47
52
|
"tsup": "^8.0.1",
|
|
48
53
|
"typescript": "^5.3.3"
|
|
49
|
-
},
|
|
50
|
-
"scripts": {
|
|
51
|
-
"build": "tsup src/index.ts --format cjs,esm --dts --outDir dist",
|
|
52
|
-
"dev": "tsup src/index.ts --format cjs,esm --dts --outDir dist --watch",
|
|
53
|
-
"clean": "rm -rf dist"
|
|
54
54
|
}
|
|
55
|
-
}
|
|
55
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024 Temsys-Shen
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|