@worldware/msg-cli 0.0.4 → 0.1.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.
Files changed (39) hide show
  1. package/dist/chunk-4Q2252JQ.mjs +50 -0
  2. package/dist/chunk-DBC2Y6VQ.mjs +167 -0
  3. package/dist/chunk-KKYCVD5M.mjs +136 -0
  4. package/dist/commands/create/project.cjs +293 -0
  5. package/dist/commands/create/project.d.mts +22 -0
  6. package/dist/commands/create/project.d.ts +22 -0
  7. package/dist/commands/create/project.mjs +151 -0
  8. package/dist/commands/create/resource.cjs +355 -0
  9. package/dist/commands/create/resource.d.mts +22 -0
  10. package/dist/commands/create/resource.d.ts +22 -0
  11. package/dist/commands/create/resource.mjs +143 -0
  12. package/dist/commands/init.cjs +259 -0
  13. package/dist/commands/init.d.mts +20 -0
  14. package/dist/commands/init.d.ts +20 -0
  15. package/dist/commands/init.mjs +133 -0
  16. package/dist/lib/create-project-helpers.cjs +163 -0
  17. package/dist/lib/create-project-helpers.d.mts +50 -0
  18. package/dist/lib/create-project-helpers.d.ts +50 -0
  19. package/dist/lib/create-project-helpers.mjs +14 -0
  20. package/dist/lib/create-resource-helpers.cjs +225 -0
  21. package/dist/lib/create-resource-helpers.d.mts +55 -0
  22. package/dist/lib/create-resource-helpers.d.ts +55 -0
  23. package/dist/lib/create-resource-helpers.mjs +15 -0
  24. package/dist/lib/init-helpers.cjs +203 -0
  25. package/dist/lib/init-helpers.d.mts +100 -0
  26. package/dist/lib/init-helpers.d.ts +100 -0
  27. package/dist/lib/init-helpers.mjs +30 -0
  28. package/dist/lib/utilities.cjs +203 -0
  29. package/dist/lib/utilities.d.mts +59 -0
  30. package/dist/lib/utilities.d.ts +59 -0
  31. package/dist/lib/utilities.mjs +172 -0
  32. package/package.json +7 -4
  33. package/dist/commands/create/project.js +0 -160
  34. package/dist/commands/create/resource.js +0 -169
  35. package/dist/commands/init.js +0 -131
  36. package/dist/lib/create-project-helpers.js +0 -112
  37. package/dist/lib/create-resource-helpers.js +0 -178
  38. package/dist/lib/init-helpers.js +0 -219
  39. package/dist/lib/utilities.js +0 -286
@@ -0,0 +1,50 @@
1
+ import { PackageJson } from './init-helpers.js';
2
+
3
+ /** Minimal type for MsgProject-like data we read from an existing project file. */
4
+ interface MsgProjectFileData {
5
+ project?: {
6
+ name?: string;
7
+ version?: number;
8
+ };
9
+ locales?: {
10
+ sourceLocale?: string;
11
+ pseudoLocale?: string;
12
+ targetLocales?: Record<string, string[]>;
13
+ };
14
+ loader?: unknown;
15
+ }
16
+ /**
17
+ * Calculates the relative path from the i18n projects directory to the l10n translations directory.
18
+ * @param projectsDir - Absolute path to i18n/projects (e.g. root/i18n/projects)
19
+ * @param translationsDir - Absolute path to l10n/translations (e.g. root/l10n/translations)
20
+ * @returns Relative path string from projects to translations, suitable for import()
21
+ */
22
+ declare function calculateRelativePath(projectsDir: string, translationsDir: string): string;
23
+ /**
24
+ * Imports an existing MsgProject module from the projects directory.
25
+ * @param projectsDir - Absolute path to i18n/projects
26
+ * @param projectName - Name of the project (file name without extension)
27
+ * @returns The default export (MsgProject instance or data) or undefined if not found
28
+ */
29
+ declare function importMsgProjectFile(projectsDir: string, projectName: string): Promise<MsgProjectFileData | undefined>;
30
+ /**
31
+ * Writes an MsgProject file to the projects directory.
32
+ * @param filePath - Absolute path of the file to write (including extension)
33
+ * @param content - Full file content string
34
+ */
35
+ declare function writeMsgProjectFile(filePath: string, content: string): void;
36
+ /**
37
+ * Loads package.json from the given directory (walking up to find it).
38
+ * Requires directories.i18n and directories.l10n.
39
+ * @param cwd - Directory to start from (e.g. process.cwd())
40
+ * @returns Parsed package.json with directories.i18n and directories.l10n
41
+ * @throws Error if package.json not found or missing directories.i18n / directories.l10n
42
+ */
43
+ declare function loadPackageJsonForCreateProject(cwd: string): PackageJson & {
44
+ directories: {
45
+ i18n: string;
46
+ l10n: string;
47
+ };
48
+ };
49
+
50
+ export { type MsgProjectFileData, calculateRelativePath, importMsgProjectFile, loadPackageJsonForCreateProject, writeMsgProjectFile };
@@ -0,0 +1,14 @@
1
+ import {
2
+ calculateRelativePath,
3
+ importMsgProjectFile,
4
+ loadPackageJsonForCreateProject,
5
+ writeMsgProjectFile
6
+ } from "../chunk-4Q2252JQ.mjs";
7
+ import "../chunk-KKYCVD5M.mjs";
8
+ import "../chunk-DBC2Y6VQ.mjs";
9
+ export {
10
+ calculateRelativePath,
11
+ importMsgProjectFile,
12
+ loadPackageJsonForCreateProject,
13
+ writeMsgProjectFile
14
+ };
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/lib/create-resource-helpers.ts
21
+ var create_resource_helpers_exports = {};
22
+ __export(create_resource_helpers_exports, {
23
+ dynamicImportFromUrl: () => dynamicImportFromUrl,
24
+ generateMsgResourceContent: () => generateMsgResourceContent,
25
+ importMsgProjectForResource: () => importMsgProjectForResource,
26
+ readPackageJsonForCreateResource: () => readPackageJsonForCreateResource,
27
+ writeMsgResourceFile: () => writeMsgResourceFile
28
+ });
29
+ module.exports = __toCommonJS(create_resource_helpers_exports);
30
+ var import_fs2 = require("fs");
31
+ var import_module = require("module");
32
+ var import_path2 = require("path");
33
+ var import_url = require("url");
34
+
35
+ // src/lib/init-helpers.ts
36
+ var import_fs = require("fs");
37
+ var import_path = require("path");
38
+ function findPackageJsonPath(cwd) {
39
+ let dir = cwd;
40
+ for (; ; ) {
41
+ const p = (0, import_path.join)(dir, "package.json");
42
+ if ((0, import_fs.existsSync)(p)) return p;
43
+ const parent = (0, import_path.dirname)(dir);
44
+ if (parent === dir) return null;
45
+ dir = parent;
46
+ }
47
+ }
48
+ function readPackageJson(pkgPath) {
49
+ const raw = (0, import_fs.readFileSync)(pkgPath, "utf-8");
50
+ try {
51
+ const parsed = JSON.parse(raw);
52
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
53
+ throw new Error("package.json must be a JSON object");
54
+ }
55
+ return parsed;
56
+ } catch (err) {
57
+ if (err instanceof SyntaxError) {
58
+ throw new Error("Invalid package.json: " + err.message);
59
+ }
60
+ throw err;
61
+ }
62
+ }
63
+ function loadPackageJsonForMsg(cwd, options) {
64
+ const pkgPath = findPackageJsonPath(cwd);
65
+ if (!pkgPath) {
66
+ throw new Error("package.json not found. Run this command from the project root.");
67
+ }
68
+ let pkg;
69
+ try {
70
+ pkg = readPackageJson(pkgPath);
71
+ } catch (err) {
72
+ const msg = err instanceof Error ? err.message : "package.json could not be parsed.";
73
+ throw new Error(msg);
74
+ }
75
+ const dirs = pkg.directories;
76
+ if (!dirs || typeof dirs !== "object" || !dirs.i18n) {
77
+ throw new Error("package.json must contain directories.i18n. Run 'msg init' first.");
78
+ }
79
+ if (options?.requireL10n && !dirs.l10n) {
80
+ throw new Error(
81
+ "package.json must contain directories.i18n and directories.l10n. Run 'msg init' first."
82
+ );
83
+ }
84
+ const rootDir = (0, import_path.dirname)(pkgPath);
85
+ const useTypeScript = (0, import_fs.existsSync)((0, import_path.join)(rootDir, "tsconfig.json"));
86
+ const isEsm = pkg.type === "module";
87
+ return {
88
+ pkgPath,
89
+ rootDir,
90
+ pkg,
91
+ i18nDir: dirs.i18n,
92
+ l10nDir: dirs.l10n,
93
+ isEsm,
94
+ useTypeScript
95
+ };
96
+ }
97
+
98
+ // src/lib/create-resource-helpers.ts
99
+ async function dynamicImportFromUrl(url) {
100
+ try {
101
+ return await import(
102
+ /* @vite-ignore */
103
+ url
104
+ );
105
+ } catch (err) {
106
+ const msg = err instanceof Error ? err.message : String(err);
107
+ const useRequire = msg.includes("dynamic import callback") || msg.includes("ERR_VM_DYNAMIC_IMPORT");
108
+ if (useRequire) {
109
+ try {
110
+ const path = url.startsWith("file:") ? (0, import_url.fileURLToPath)(url) : url;
111
+ const base = (0, import_url.pathToFileURL)(process.cwd()).href;
112
+ const req = (0, import_module.createRequire)(base);
113
+ const mod = req(path);
114
+ return Promise.resolve(mod ?? {});
115
+ } catch {
116
+ }
117
+ }
118
+ throw err;
119
+ }
120
+ }
121
+ function readPackageJsonForCreateResource(cwd) {
122
+ const ctx = loadPackageJsonForMsg(cwd);
123
+ return {
124
+ i18nDir: ctx.i18nDir,
125
+ isEsm: ctx.isEsm,
126
+ useTypeScript: ctx.useTypeScript
127
+ };
128
+ }
129
+ function dirFromSourceLocale(sourceLocale) {
130
+ const lang = sourceLocale.split("-")[0]?.toLowerCase() ?? "";
131
+ return lang === "ar" || lang === "he" ? "rtl" : "ltr";
132
+ }
133
+ async function importMsgProjectForResource(projectsDir, projectName) {
134
+ const basePath = (0, import_path2.join)(projectsDir, projectName);
135
+ const exts = [".ts", ".js"];
136
+ for (const ext of exts) {
137
+ const p = `${basePath}${ext}`;
138
+ if ((0, import_fs2.existsSync)(p)) {
139
+ try {
140
+ const url = (0, import_url.pathToFileURL)(p).href;
141
+ const mod = await dynamicImportFromUrl(url);
142
+ const data = mod?.default ?? mod;
143
+ const sourceLocale = data?.locales?.sourceLocale;
144
+ if (!sourceLocale || typeof sourceLocale !== "string") {
145
+ throw new Error(
146
+ `Project file must export a default with locales.sourceLocale (got ${typeof data?.locales?.sourceLocale}).`
147
+ );
148
+ }
149
+ return {
150
+ sourceLocale,
151
+ dir: dirFromSourceLocale(sourceLocale)
152
+ };
153
+ } catch (err) {
154
+ const message = err instanceof Error ? err.message : String(err);
155
+ throw new Error(
156
+ `Project file '${projectName}${ext}' could not be loaded: ${message}`
157
+ );
158
+ }
159
+ }
160
+ }
161
+ return void 0;
162
+ }
163
+ function generateMsgResourceContent(params) {
164
+ const { title, projectName, sourceLocale, dir, isEsm } = params;
165
+ const projectImport = isEsm ? `../projects/${projectName}.js` : `../projects/${projectName}`;
166
+ const messagesBlock = ` messages: [
167
+ {
168
+ key: 'example.message',
169
+ value: 'Example message.',
170
+ notes: [
171
+ { type: 'description', content: 'This is an example message. You can delete it.' }
172
+ ]
173
+ }
174
+ ]`;
175
+ const titleStr = `'${title.replace(/'/g, "\\'")}'`;
176
+ const langStr = `'${sourceLocale.replace(/'/g, "\\'")}'`;
177
+ const dirStr = `'${dir}'`;
178
+ if (isEsm) {
179
+ return `import { MsgResource } from '@worldware/msg';
180
+ import project from '${projectImport}';
181
+
182
+ export default MsgResource.create({
183
+ title: ${titleStr},
184
+ attributes: {
185
+ lang: ${langStr},
186
+ dir: ${dirStr}
187
+ },
188
+ notes: [
189
+ { type: 'DESCRIPTION', content: 'This is a generated file. Replace this description with your own.' }
190
+ ],
191
+ ${messagesBlock}
192
+ }, project);
193
+ `;
194
+ }
195
+ return `const { MsgResource } = require('@worldware/msg');
196
+ const project = require('${projectImport}');
197
+
198
+ module.exports = MsgResource.create({
199
+ title: ${titleStr},
200
+ attributes: {
201
+ lang: ${langStr},
202
+ dir: ${dirStr}
203
+ },
204
+ notes: [
205
+ { type: 'DESCRIPTION', content: 'This is a generated file. Replace this description with your own.' }
206
+ ],
207
+ ${messagesBlock}
208
+ }, project);
209
+ `;
210
+ }
211
+ function writeMsgResourceFile(filePath, content) {
212
+ const dir = (0, import_path2.dirname)(filePath);
213
+ if (!(0, import_fs2.existsSync)(dir)) {
214
+ (0, import_fs2.mkdirSync)(dir, { recursive: true });
215
+ }
216
+ (0, import_fs2.writeFileSync)(filePath, content, "utf-8");
217
+ }
218
+ // Annotate the CommonJS export names for ESM import in node:
219
+ 0 && (module.exports = {
220
+ dynamicImportFromUrl,
221
+ generateMsgResourceContent,
222
+ importMsgProjectForResource,
223
+ readPackageJsonForCreateResource,
224
+ writeMsgResourceFile
225
+ });
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Dynamically import a module from a file URL.
3
+ * Tries native import() first; on VM/runner errors (e.g. Vitest "dynamic import
4
+ * callback was not specified") falls back to require() so CJS files load.
5
+ */
6
+ declare function dynamicImportFromUrl(url: string): Promise<Record<string, unknown>>;
7
+ /** Result of reading package.json for create-resource (i18n dir, module type). */
8
+ interface PackageJsonForCreateResource {
9
+ i18nDir: string;
10
+ isEsm: boolean;
11
+ useTypeScript: boolean;
12
+ }
13
+ /** Minimal type for MsgProject-like data we read to get sourceLocale and dir. */
14
+ interface MsgProjectForResource {
15
+ locales?: {
16
+ sourceLocale?: string;
17
+ };
18
+ }
19
+ /**
20
+ * Reads package.json and returns i18n directory and module type info.
21
+ * @param cwd - Directory to start from (e.g. process.cwd())
22
+ * @returns Object with i18nDir, isEsm, useTypeScript
23
+ * @throws Error if package.json not found or missing directories.i18n
24
+ */
25
+ declare function readPackageJsonForCreateResource(cwd: string): PackageJsonForCreateResource;
26
+ /**
27
+ * Imports the MsgProject module and returns sourceLocale and dir (ltr/rtl).
28
+ * @param projectsDir - Absolute path to i18n/projects
29
+ * @param projectName - Name of the project file (without extension)
30
+ * @returns Object with sourceLocale and dir, or undefined if project not found
31
+ */
32
+ declare function importMsgProjectForResource(projectsDir: string, projectName: string): Promise<{
33
+ sourceLocale: string;
34
+ dir: "ltr" | "rtl";
35
+ } | undefined>;
36
+ /**
37
+ * Generates the MsgResource file content as a string.
38
+ * @param params - Title, projectName, sourceLocale, dir, and isEsm
39
+ * @returns The generated file content
40
+ */
41
+ declare function generateMsgResourceContent(params: {
42
+ title: string;
43
+ projectName: string;
44
+ sourceLocale: string;
45
+ dir: "ltr" | "rtl";
46
+ isEsm: boolean;
47
+ }): string;
48
+ /**
49
+ * Writes the MsgResource content to file.
50
+ * @param filePath - Absolute path of the file to write (including extension)
51
+ * @param content - Full file content string
52
+ */
53
+ declare function writeMsgResourceFile(filePath: string, content: string): void;
54
+
55
+ export { type MsgProjectForResource, type PackageJsonForCreateResource, dynamicImportFromUrl, generateMsgResourceContent, importMsgProjectForResource, readPackageJsonForCreateResource, writeMsgResourceFile };
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Dynamically import a module from a file URL.
3
+ * Tries native import() first; on VM/runner errors (e.g. Vitest "dynamic import
4
+ * callback was not specified") falls back to require() so CJS files load.
5
+ */
6
+ declare function dynamicImportFromUrl(url: string): Promise<Record<string, unknown>>;
7
+ /** Result of reading package.json for create-resource (i18n dir, module type). */
8
+ interface PackageJsonForCreateResource {
9
+ i18nDir: string;
10
+ isEsm: boolean;
11
+ useTypeScript: boolean;
12
+ }
13
+ /** Minimal type for MsgProject-like data we read to get sourceLocale and dir. */
14
+ interface MsgProjectForResource {
15
+ locales?: {
16
+ sourceLocale?: string;
17
+ };
18
+ }
19
+ /**
20
+ * Reads package.json and returns i18n directory and module type info.
21
+ * @param cwd - Directory to start from (e.g. process.cwd())
22
+ * @returns Object with i18nDir, isEsm, useTypeScript
23
+ * @throws Error if package.json not found or missing directories.i18n
24
+ */
25
+ declare function readPackageJsonForCreateResource(cwd: string): PackageJsonForCreateResource;
26
+ /**
27
+ * Imports the MsgProject module and returns sourceLocale and dir (ltr/rtl).
28
+ * @param projectsDir - Absolute path to i18n/projects
29
+ * @param projectName - Name of the project file (without extension)
30
+ * @returns Object with sourceLocale and dir, or undefined if project not found
31
+ */
32
+ declare function importMsgProjectForResource(projectsDir: string, projectName: string): Promise<{
33
+ sourceLocale: string;
34
+ dir: "ltr" | "rtl";
35
+ } | undefined>;
36
+ /**
37
+ * Generates the MsgResource file content as a string.
38
+ * @param params - Title, projectName, sourceLocale, dir, and isEsm
39
+ * @returns The generated file content
40
+ */
41
+ declare function generateMsgResourceContent(params: {
42
+ title: string;
43
+ projectName: string;
44
+ sourceLocale: string;
45
+ dir: "ltr" | "rtl";
46
+ isEsm: boolean;
47
+ }): string;
48
+ /**
49
+ * Writes the MsgResource content to file.
50
+ * @param filePath - Absolute path of the file to write (including extension)
51
+ * @param content - Full file content string
52
+ */
53
+ declare function writeMsgResourceFile(filePath: string, content: string): void;
54
+
55
+ export { type MsgProjectForResource, type PackageJsonForCreateResource, dynamicImportFromUrl, generateMsgResourceContent, importMsgProjectForResource, readPackageJsonForCreateResource, writeMsgResourceFile };
@@ -0,0 +1,15 @@
1
+ import {
2
+ dynamicImportFromUrl,
3
+ generateMsgResourceContent,
4
+ importMsgProjectForResource,
5
+ readPackageJsonForCreateResource,
6
+ writeMsgResourceFile
7
+ } from "../chunk-KKYCVD5M.mjs";
8
+ import "../chunk-DBC2Y6VQ.mjs";
9
+ export {
10
+ dynamicImportFromUrl,
11
+ generateMsgResourceContent,
12
+ importMsgProjectForResource,
13
+ readPackageJsonForCreateResource,
14
+ writeMsgResourceFile
15
+ };
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/lib/init-helpers.ts
21
+ var init_helpers_exports = {};
22
+ __export(init_helpers_exports, {
23
+ DEFAULT_I18N_DIR: () => DEFAULT_I18N_DIR,
24
+ DEFAULT_L10N_DIR: () => DEFAULT_L10N_DIR,
25
+ addDirectoriesToPackageJson: () => addDirectoriesToPackageJson,
26
+ addImportAliasesToPackageJson: () => addImportAliasesToPackageJson,
27
+ addScriptsToPackageJson: () => addScriptsToPackageJson,
28
+ addTsconfigPaths: () => addTsconfigPaths,
29
+ ensureDirectoriesWithGitkeep: () => ensureDirectoriesWithGitkeep,
30
+ findPackageJsonPath: () => findPackageJsonPath,
31
+ isAlreadyInitialized: () => isAlreadyInitialized,
32
+ loadPackageJsonForMsg: () => loadPackageJsonForMsg,
33
+ readPackageJson: () => readPackageJson,
34
+ validatePaths: () => validatePaths,
35
+ writePackageJson: () => writePackageJson
36
+ });
37
+ module.exports = __toCommonJS(init_helpers_exports);
38
+ var import_fs = require("fs");
39
+ var import_path = require("path");
40
+ var DEFAULT_I18N_DIR = "src/i18n";
41
+ var DEFAULT_L10N_DIR = "res/l10n";
42
+ function findPackageJsonPath(cwd) {
43
+ let dir = cwd;
44
+ for (; ; ) {
45
+ const p = (0, import_path.join)(dir, "package.json");
46
+ if ((0, import_fs.existsSync)(p)) return p;
47
+ const parent = (0, import_path.dirname)(dir);
48
+ if (parent === dir) return null;
49
+ dir = parent;
50
+ }
51
+ }
52
+ function readPackageJson(pkgPath) {
53
+ const raw = (0, import_fs.readFileSync)(pkgPath, "utf-8");
54
+ try {
55
+ const parsed = JSON.parse(raw);
56
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
57
+ throw new Error("package.json must be a JSON object");
58
+ }
59
+ return parsed;
60
+ } catch (err) {
61
+ if (err instanceof SyntaxError) {
62
+ throw new Error("Invalid package.json: " + err.message);
63
+ }
64
+ throw err;
65
+ }
66
+ }
67
+ function loadPackageJsonForMsg(cwd, options) {
68
+ const pkgPath = findPackageJsonPath(cwd);
69
+ if (!pkgPath) {
70
+ throw new Error("package.json not found. Run this command from the project root.");
71
+ }
72
+ let pkg;
73
+ try {
74
+ pkg = readPackageJson(pkgPath);
75
+ } catch (err) {
76
+ const msg = err instanceof Error ? err.message : "package.json could not be parsed.";
77
+ throw new Error(msg);
78
+ }
79
+ const dirs = pkg.directories;
80
+ if (!dirs || typeof dirs !== "object" || !dirs.i18n) {
81
+ throw new Error("package.json must contain directories.i18n. Run 'msg init' first.");
82
+ }
83
+ if (options?.requireL10n && !dirs.l10n) {
84
+ throw new Error(
85
+ "package.json must contain directories.i18n and directories.l10n. Run 'msg init' first."
86
+ );
87
+ }
88
+ const rootDir = (0, import_path.dirname)(pkgPath);
89
+ const useTypeScript = (0, import_fs.existsSync)((0, import_path.join)(rootDir, "tsconfig.json"));
90
+ const isEsm = pkg.type === "module";
91
+ return {
92
+ pkgPath,
93
+ rootDir,
94
+ pkg,
95
+ i18nDir: dirs.i18n,
96
+ l10nDir: dirs.l10n,
97
+ isEsm,
98
+ useTypeScript
99
+ };
100
+ }
101
+ function writePackageJson(pkgPath, pkg) {
102
+ const json = JSON.stringify(pkg, null, 2) + "\n";
103
+ (0, import_fs.writeFileSync)(pkgPath, json, "utf-8");
104
+ }
105
+ function validatePaths(rootDir, i18nDir, l10nDir) {
106
+ const trimmedI18n = i18nDir.trim();
107
+ const trimmedL10n = l10nDir.trim();
108
+ if (!trimmedI18n) return { valid: false, error: "i18n directory path cannot be empty" };
109
+ if (!trimmedL10n) return { valid: false, error: "l10n directory path cannot be empty" };
110
+ if (trimmedI18n.startsWith("/") || /^[A-Za-z]:/.test(trimmedI18n)) {
111
+ return { valid: false, error: "i18n path must be relative" };
112
+ }
113
+ if (trimmedL10n.startsWith("/") || /^[A-Za-z]:/.test(trimmedL10n)) {
114
+ return { valid: false, error: "l10n path must be relative" };
115
+ }
116
+ return { valid: true };
117
+ }
118
+ var GITKEEP = ".gitkeep";
119
+ function ensureDirectoriesWithGitkeep(rootDir, i18nDir, l10nDir, force) {
120
+ const leaves = [
121
+ (0, import_path.join)(rootDir, i18nDir, "projects"),
122
+ (0, import_path.join)(rootDir, i18nDir, "resources"),
123
+ (0, import_path.join)(rootDir, l10nDir, "translations"),
124
+ (0, import_path.join)(rootDir, l10nDir, "xliff")
125
+ ];
126
+ for (const leaf of leaves) {
127
+ const parent = (0, import_path.dirname)(leaf);
128
+ if (!(0, import_fs.existsSync)(parent)) {
129
+ (0, import_fs.mkdirSync)(parent, { recursive: true });
130
+ }
131
+ if (!(0, import_fs.existsSync)(leaf)) {
132
+ (0, import_fs.mkdirSync)(leaf, { recursive: true });
133
+ }
134
+ const gitkeepPath = (0, import_path.join)(leaf, GITKEEP);
135
+ if (force || !(0, import_fs.existsSync)(gitkeepPath)) {
136
+ (0, import_fs.writeFileSync)(gitkeepPath, "", "utf-8");
137
+ }
138
+ }
139
+ }
140
+ function isAlreadyInitialized(pkg, rootDir, i18nDir, l10nDir) {
141
+ const dirs = pkg.directories;
142
+ if (!dirs || typeof dirs !== "object") return false;
143
+ if (dirs.i18n !== i18nDir || dirs.l10n !== l10nDir) return false;
144
+ const i18nFull = (0, import_path.join)(rootDir, i18nDir);
145
+ const l10nFull = (0, import_path.join)(rootDir, l10nDir);
146
+ return (0, import_fs.existsSync)(i18nFull) && (0, import_fs.existsSync)(l10nFull);
147
+ }
148
+ function addDirectoriesToPackageJson(pkg, i18nDir, l10nDir) {
149
+ const directories = { ...pkg.directories, i18n: i18nDir, l10n: l10nDir, root: "." };
150
+ return { ...pkg, directories };
151
+ }
152
+ function addImportAliasesToPackageJson(pkg, i18nDir, l10nDir) {
153
+ const imports = {
154
+ ...pkg.imports,
155
+ "#i18n/*": `${i18nDir}/*`,
156
+ "#l10n/*": `${l10nDir}/*`,
157
+ "#root/*": "./*"
158
+ };
159
+ return { ...pkg, imports };
160
+ }
161
+ function addScriptsToPackageJson(pkg) {
162
+ const scripts = {
163
+ ...pkg.scripts,
164
+ "i18n-export": "msg export:resources",
165
+ "l10n-import": "msg import:translations"
166
+ };
167
+ return { ...pkg, scripts };
168
+ }
169
+ function addTsconfigPaths(tsconfigPath, i18nDir, l10nDir) {
170
+ const raw = (0, import_fs.readFileSync)(tsconfigPath, "utf-8");
171
+ let config;
172
+ try {
173
+ config = JSON.parse(raw);
174
+ } catch {
175
+ throw new Error("Invalid tsconfig.json");
176
+ }
177
+ if (!config.compilerOptions) config.compilerOptions = {};
178
+ const co = config.compilerOptions;
179
+ co.baseUrl = co.baseUrl ?? ".";
180
+ co.paths = {
181
+ ...co.paths,
182
+ "#i18n/*": [`${i18nDir}/*`],
183
+ "#l10n/*": [`${l10nDir}/*`],
184
+ "#root/*": ["./*"]
185
+ };
186
+ (0, import_fs.writeFileSync)(tsconfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
187
+ }
188
+ // Annotate the CommonJS export names for ESM import in node:
189
+ 0 && (module.exports = {
190
+ DEFAULT_I18N_DIR,
191
+ DEFAULT_L10N_DIR,
192
+ addDirectoriesToPackageJson,
193
+ addImportAliasesToPackageJson,
194
+ addScriptsToPackageJson,
195
+ addTsconfigPaths,
196
+ ensureDirectoriesWithGitkeep,
197
+ findPackageJsonPath,
198
+ isAlreadyInitialized,
199
+ loadPackageJsonForMsg,
200
+ readPackageJson,
201
+ validatePaths,
202
+ writePackageJson
203
+ });