@mearie/codegen 0.0.1-next.3 → 0.0.1-next.4
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/chunk-CoQ2GtNH.js +39 -0
- package/dist/chunk-DUogzOV2.cjs +60 -0
- package/dist/compiler-DysSfBLv.js +46035 -0
- package/dist/compiler-wSZSa-gf.cjs +46041 -0
- package/dist/index.cjs +334 -50
- package/dist/index.d.cts +14 -24
- package/dist/index.d.ts +14 -24
- package/dist/index.js +323 -16
- package/dist/typescript-ChH5VlJx.cjs +149563 -0
- package/dist/typescript-dgELwr0O.js +149560 -0
- package/package.json +21 -18
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as __toDynamicImportESM } from "./chunk-CoQ2GtNH.js";
|
|
2
2
|
import { glob } from "tinyglobby";
|
|
3
3
|
import picomatch from "picomatch";
|
|
4
|
-
import { generateCode } from "@mearie/native";
|
|
5
|
-
import { MearieAggregateError, MearieError } from "@mearie/core";
|
|
6
4
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
7
|
-
import { extractGraphQLSources } from "@mearie/
|
|
5
|
+
import { extractGraphQLSources, generateCode } from "@mearie/native";
|
|
8
6
|
import path from "node:path";
|
|
7
|
+
import { configureSync, getAnsiColorFormatter, getConsoleSink, getLogger } from "@logtape/logtape";
|
|
8
|
+
import pc from "picocolors";
|
|
9
9
|
|
|
10
10
|
//#region src/glob.ts
|
|
11
11
|
/**
|
|
@@ -38,6 +38,265 @@ const createMatcher = (patterns) => {
|
|
|
38
38
|
};
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/errors.ts
|
|
43
|
+
/**
|
|
44
|
+
* Custom error class for Mearie-specific errors.
|
|
45
|
+
*/
|
|
46
|
+
var MearieError = class MearieError extends Error {
|
|
47
|
+
filePath;
|
|
48
|
+
line;
|
|
49
|
+
column;
|
|
50
|
+
constructor(message, filePath, line, column) {
|
|
51
|
+
super(message);
|
|
52
|
+
this.name = "MearieError";
|
|
53
|
+
this.filePath = filePath;
|
|
54
|
+
this.line = line;
|
|
55
|
+
this.column = column;
|
|
56
|
+
}
|
|
57
|
+
static fromNative(data) {
|
|
58
|
+
if (!data || typeof data !== "object") throw new TypeError("Invalid native error data");
|
|
59
|
+
const error = data;
|
|
60
|
+
const filePath = error.location?.file_path;
|
|
61
|
+
const line = error.location?.line;
|
|
62
|
+
const column = error.location?.column;
|
|
63
|
+
return new MearieError(error.message, filePath, line, column);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Aggregate error for multiple Mearie errors.
|
|
68
|
+
*/
|
|
69
|
+
var MearieAggregateError = class extends Error {
|
|
70
|
+
errors;
|
|
71
|
+
constructor(errors, message) {
|
|
72
|
+
super(message ?? `${errors.length} error${errors.length > 1 ? "s" : ""} occurred`);
|
|
73
|
+
this.name = "MearieAggregateError";
|
|
74
|
+
this.errors = errors;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Error thrown when `@vue/compiler-sfc` is not installed.
|
|
79
|
+
*/
|
|
80
|
+
var MissingVueCompilerError = class extends Error {
|
|
81
|
+
constructor() {
|
|
82
|
+
super(`
|
|
83
|
+
GraphQL operations cannot be extracted from Vue files without @vue/compiler-sfc.
|
|
84
|
+
|
|
85
|
+
Install it with:
|
|
86
|
+
npm install @vue/compiler-sfc
|
|
87
|
+
# or
|
|
88
|
+
pnpm add @vue/compiler-sfc
|
|
89
|
+
# or
|
|
90
|
+
yarn add @vue/compiler-sfc
|
|
91
|
+
`);
|
|
92
|
+
this.name = "MissingVueCompilerError";
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Error thrown when svelte compiler is not installed.
|
|
97
|
+
*/
|
|
98
|
+
var MissingSvelteCompilerError = class extends Error {
|
|
99
|
+
constructor() {
|
|
100
|
+
super(`
|
|
101
|
+
GraphQL operations cannot be extracted from Svelte files without svelte.
|
|
102
|
+
|
|
103
|
+
Install it with:
|
|
104
|
+
npm install svelte
|
|
105
|
+
# or
|
|
106
|
+
pnpm add svelte
|
|
107
|
+
# or
|
|
108
|
+
yarn add svelte
|
|
109
|
+
`);
|
|
110
|
+
this.name = "MissingSvelteCompilerError";
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Error thrown when TypeScript is not installed.
|
|
115
|
+
*/
|
|
116
|
+
var MissingTypeScriptError = class extends Error {
|
|
117
|
+
constructor() {
|
|
118
|
+
super(`
|
|
119
|
+
GraphQL operations cannot be extracted from Vue files without typescript.
|
|
120
|
+
|
|
121
|
+
Install it with:
|
|
122
|
+
npm install typescript
|
|
123
|
+
# or
|
|
124
|
+
pnpm add typescript
|
|
125
|
+
# or
|
|
126
|
+
yarn add typescript
|
|
127
|
+
`);
|
|
128
|
+
this.name = "MissingTypeScriptError";
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/loaders.ts
|
|
134
|
+
/**
|
|
135
|
+
* Loads the Vue compiler dynamically.
|
|
136
|
+
* @returns The Vue compiler module.
|
|
137
|
+
* @throws {MissingVueCompilerError} If `@vue/compiler-sfc` is not installed.
|
|
138
|
+
*/
|
|
139
|
+
const loadVueCompiler = async () => {
|
|
140
|
+
try {
|
|
141
|
+
return await import("@vue/compiler-sfc");
|
|
142
|
+
} catch {
|
|
143
|
+
throw new MissingVueCompilerError();
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Loads TypeScript dynamically.
|
|
148
|
+
* @returns The TypeScript module.
|
|
149
|
+
* @throws {MissingTypeScriptError} If typescript is not installed.
|
|
150
|
+
*/
|
|
151
|
+
const loadTypeScript = async () => {
|
|
152
|
+
try {
|
|
153
|
+
return await import("./typescript-dgELwr0O.js").then(__toDynamicImportESM(1));
|
|
154
|
+
} catch {
|
|
155
|
+
throw new MissingTypeScriptError();
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* Loads the Svelte compiler dynamically.
|
|
160
|
+
* @returns The Svelte compiler module.
|
|
161
|
+
* @throws {MissingSvelteCompilerError} If svelte is not installed.
|
|
162
|
+
*/
|
|
163
|
+
const loadSvelteCompiler = async () => {
|
|
164
|
+
try {
|
|
165
|
+
return await import("./compiler-DysSfBLv.js");
|
|
166
|
+
} catch {
|
|
167
|
+
throw new MissingSvelteCompilerError();
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
//#endregion
|
|
172
|
+
//#region src/parsers.ts
|
|
173
|
+
const extractVueScript = async (source) => {
|
|
174
|
+
const [vueCompiler, typescript] = await Promise.all([loadVueCompiler(), loadTypeScript()]);
|
|
175
|
+
vueCompiler.registerTS(() => typescript);
|
|
176
|
+
const { descriptor } = vueCompiler.parse(source.code, { filename: source.filePath });
|
|
177
|
+
const blocks = [];
|
|
178
|
+
if (descriptor.script) blocks.push({
|
|
179
|
+
code: descriptor.script.content,
|
|
180
|
+
filePath: source.filePath,
|
|
181
|
+
startLine: source.startLine + descriptor.script.loc.start.line - 1
|
|
182
|
+
});
|
|
183
|
+
if (descriptor.scriptSetup) blocks.push({
|
|
184
|
+
code: descriptor.scriptSetup.content,
|
|
185
|
+
filePath: source.filePath,
|
|
186
|
+
startLine: source.startLine + descriptor.scriptSetup.loc.start.line - 1
|
|
187
|
+
});
|
|
188
|
+
return blocks;
|
|
189
|
+
};
|
|
190
|
+
const extractSvelteScript = async (source) => {
|
|
191
|
+
const ast = (await loadSvelteCompiler()).parse(source.code);
|
|
192
|
+
const blocks = [];
|
|
193
|
+
if (ast.instance?.content) {
|
|
194
|
+
const code = source.code.slice(ast.instance.content.start, ast.instance.content.end);
|
|
195
|
+
const lineOffset = source.code.slice(0, ast.instance.content.start).split("\n").length - 1;
|
|
196
|
+
blocks.push({
|
|
197
|
+
code,
|
|
198
|
+
filePath: `${source.filePath}.instance.ts`,
|
|
199
|
+
startLine: source.startLine + lineOffset
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
if (ast.module?.content) {
|
|
203
|
+
const code = source.code.slice(ast.module.content.start, ast.module.content.end);
|
|
204
|
+
const lineOffset = source.code.slice(0, ast.module.content.start).split("\n").length - 1;
|
|
205
|
+
blocks.push({
|
|
206
|
+
code,
|
|
207
|
+
filePath: `${source.filePath}.module.ts`,
|
|
208
|
+
startLine: source.startLine + lineOffset
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
return blocks;
|
|
212
|
+
};
|
|
213
|
+
const extractAstroScripts = (source) => {
|
|
214
|
+
const blocks = [];
|
|
215
|
+
const frontmatterMatch = /^---\s*\n([\s\S]*?)\n---/.exec(source.code);
|
|
216
|
+
if (frontmatterMatch) {
|
|
217
|
+
const lineOffset = source.code.slice(0, frontmatterMatch.index).split("\n").length;
|
|
218
|
+
blocks.push({
|
|
219
|
+
code: frontmatterMatch[1],
|
|
220
|
+
filePath: `${source.filePath}.frontmatter.ts`,
|
|
221
|
+
startLine: source.startLine + lineOffset
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
const scriptMatches = source.code.matchAll(/<script\b[^>]*>([\s\S]*?)<\/script>/gi);
|
|
225
|
+
let index = 0;
|
|
226
|
+
for (const match of scriptMatches) {
|
|
227
|
+
const lineOffset = source.code.slice(0, match.index).split("\n").length;
|
|
228
|
+
blocks.push({
|
|
229
|
+
code: match[1],
|
|
230
|
+
filePath: `${source.filePath}.${index}.ts`,
|
|
231
|
+
startLine: source.startLine + lineOffset
|
|
232
|
+
});
|
|
233
|
+
index++;
|
|
234
|
+
}
|
|
235
|
+
return blocks;
|
|
236
|
+
};
|
|
237
|
+
const extractMarkdownCodeBlocks = (source) => {
|
|
238
|
+
const codeBlocks = [];
|
|
239
|
+
const codeBlockRegex = /```(tsx|ts)[^\n]*mearie[^\n]*\n([\s\S]*?)```/g;
|
|
240
|
+
let match;
|
|
241
|
+
let index = 0;
|
|
242
|
+
while ((match = codeBlockRegex.exec(source.code)) !== null) {
|
|
243
|
+
const lineOffset = source.code.slice(0, match.index).split("\n").length;
|
|
244
|
+
codeBlocks.push({
|
|
245
|
+
code: match[2],
|
|
246
|
+
filePath: `${source.filePath}.${index}.${match[1]}`,
|
|
247
|
+
startLine: source.startLine + lineOffset
|
|
248
|
+
});
|
|
249
|
+
index++;
|
|
250
|
+
}
|
|
251
|
+
return codeBlocks;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
//#endregion
|
|
255
|
+
//#region src/extractor.ts
|
|
256
|
+
const extractGraphQLSources$1 = async (source) => {
|
|
257
|
+
const ext = source.filePath.split(".").pop()?.toLowerCase();
|
|
258
|
+
const sources = [];
|
|
259
|
+
const errors = [];
|
|
260
|
+
const blocks = [];
|
|
261
|
+
try {
|
|
262
|
+
switch (ext) {
|
|
263
|
+
case "vue":
|
|
264
|
+
blocks.push(...await extractVueScript(source));
|
|
265
|
+
break;
|
|
266
|
+
case "svelte":
|
|
267
|
+
blocks.push(...await extractSvelteScript(source));
|
|
268
|
+
break;
|
|
269
|
+
case "astro":
|
|
270
|
+
blocks.push(...extractAstroScripts(source));
|
|
271
|
+
break;
|
|
272
|
+
case "md":
|
|
273
|
+
blocks.push(...extractMarkdownCodeBlocks(source));
|
|
274
|
+
break;
|
|
275
|
+
case "js":
|
|
276
|
+
case "jsx":
|
|
277
|
+
case "ts":
|
|
278
|
+
case "tsx":
|
|
279
|
+
blocks.push(source);
|
|
280
|
+
break;
|
|
281
|
+
default: return {
|
|
282
|
+
sources,
|
|
283
|
+
errors
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
} catch (error) {
|
|
287
|
+
throw new MearieError(error instanceof Error ? error.message : String(error), source.filePath);
|
|
288
|
+
}
|
|
289
|
+
for (const block of blocks) {
|
|
290
|
+
const result = extractGraphQLSources(block);
|
|
291
|
+
sources.push(...result.sources);
|
|
292
|
+
errors.push(...result.errors.map((error) => MearieError.fromNative(error)));
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
sources,
|
|
296
|
+
errors
|
|
297
|
+
};
|
|
298
|
+
};
|
|
299
|
+
|
|
41
300
|
//#endregion
|
|
42
301
|
//#region src/generator.ts
|
|
43
302
|
/**
|
|
@@ -47,8 +306,8 @@ const createMatcher = (patterns) => {
|
|
|
47
306
|
* @throws {Error} If code generation fails.
|
|
48
307
|
*/
|
|
49
308
|
const generate = (options) => {
|
|
50
|
-
const { schemas, documents } = options;
|
|
51
|
-
const { sources, errors } = generateCode(schemas, documents);
|
|
309
|
+
const { schemas, documents, config } = options;
|
|
310
|
+
const { sources, errors } = generateCode(schemas, documents, config);
|
|
52
311
|
return {
|
|
53
312
|
sources,
|
|
54
313
|
errors: errors.map((error) => MearieError.fromNative(error))
|
|
@@ -57,12 +316,10 @@ const generate = (options) => {
|
|
|
57
316
|
|
|
58
317
|
//#endregion
|
|
59
318
|
//#region src/writer.ts
|
|
60
|
-
const writeFiles = async (sources) => {
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
await mkdir(clientDir, { recursive: true });
|
|
65
|
-
await Promise.all(sources.map((source) => writeFile(path.join(clientDir, source.filePath), source.code, "utf8")));
|
|
319
|
+
const writeFiles = async (cwd, sources) => {
|
|
320
|
+
const mearieDir = path.resolve(cwd, ".mearie");
|
|
321
|
+
await mkdir(mearieDir, { recursive: true });
|
|
322
|
+
await Promise.all(sources.map((source) => writeFile(path.join(mearieDir, source.filePath), source.code, "utf8")));
|
|
66
323
|
};
|
|
67
324
|
|
|
68
325
|
//#endregion
|
|
@@ -74,6 +331,14 @@ const writeFiles = async (sources) => {
|
|
|
74
331
|
var CodegenContext = class {
|
|
75
332
|
schemas = /* @__PURE__ */ new Map();
|
|
76
333
|
documents = /* @__PURE__ */ new Map();
|
|
334
|
+
cwd;
|
|
335
|
+
config;
|
|
336
|
+
constructor(cwd = process.cwd()) {
|
|
337
|
+
this.cwd = cwd;
|
|
338
|
+
}
|
|
339
|
+
setConfig(config) {
|
|
340
|
+
this.config = config;
|
|
341
|
+
}
|
|
77
342
|
/**
|
|
78
343
|
* Adds a schema file by reading it.
|
|
79
344
|
* @param filePath - Schema file path.
|
|
@@ -98,7 +363,7 @@ var CodegenContext = class {
|
|
|
98
363
|
* @param filePath - Document file path.
|
|
99
364
|
*/
|
|
100
365
|
async addDocument(filePath) {
|
|
101
|
-
const { sources, errors } = await extractGraphQLSources({
|
|
366
|
+
const { sources, errors } = await extractGraphQLSources$1({
|
|
102
367
|
code: await readFile(filePath, "utf8"),
|
|
103
368
|
filePath,
|
|
104
369
|
startLine: 1
|
|
@@ -121,12 +386,54 @@ var CodegenContext = class {
|
|
|
121
386
|
async generate() {
|
|
122
387
|
const { sources, errors } = generate({
|
|
123
388
|
schemas: [...this.schemas.values()],
|
|
124
|
-
documents: [...this.documents.values()].flat()
|
|
389
|
+
documents: [...this.documents.values()].flat(),
|
|
390
|
+
config: this.config
|
|
125
391
|
});
|
|
126
|
-
await writeFiles(sources);
|
|
392
|
+
await writeFiles(this.cwd, sources);
|
|
127
393
|
if (errors.length > 0) throw new MearieAggregateError(errors);
|
|
128
394
|
}
|
|
129
395
|
};
|
|
130
396
|
|
|
131
397
|
//#endregion
|
|
132
|
-
|
|
398
|
+
//#region src/logger.ts
|
|
399
|
+
configureSync({
|
|
400
|
+
reset: true,
|
|
401
|
+
sinks: { console: getConsoleSink({ formatter: getAnsiColorFormatter({
|
|
402
|
+
level: "FULL",
|
|
403
|
+
timestamp: "time",
|
|
404
|
+
category: (category) => `💬 ${category.join("·")}`
|
|
405
|
+
}) }) },
|
|
406
|
+
loggers: [{
|
|
407
|
+
category: "mearie",
|
|
408
|
+
lowestLevel: "info",
|
|
409
|
+
sinks: ["console"]
|
|
410
|
+
}, {
|
|
411
|
+
category: ["logtape", "meta"],
|
|
412
|
+
lowestLevel: "warning",
|
|
413
|
+
sinks: ["console"]
|
|
414
|
+
}]
|
|
415
|
+
});
|
|
416
|
+
const logger = getLogger(["mearie"]);
|
|
417
|
+
const formatMearieError = (error) => {
|
|
418
|
+
const parts = [
|
|
419
|
+
error.filePath,
|
|
420
|
+
error.line,
|
|
421
|
+
error.column
|
|
422
|
+
].filter((part) => part !== void 0 && part !== null).map(String);
|
|
423
|
+
const location = parts.length > 0 ? parts.join(":") : "";
|
|
424
|
+
if (location) return `${pc.bold(error.message)} ${pc.cyan(pc.underline(location))}`;
|
|
425
|
+
return pc.bold(error.message);
|
|
426
|
+
};
|
|
427
|
+
/**
|
|
428
|
+
* Reports an error using the provided logger.
|
|
429
|
+
* @param logger - The logger to use.
|
|
430
|
+
* @param error - The error to report.
|
|
431
|
+
*/
|
|
432
|
+
const report = (logger$1, error) => {
|
|
433
|
+
if (error instanceof MearieAggregateError) for (const err of error.errors) logger$1.error(formatMearieError(err));
|
|
434
|
+
else if (error instanceof MearieError) logger$1.error(formatMearieError(error));
|
|
435
|
+
else logger$1.error("{error}", { error });
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
//#endregion
|
|
439
|
+
export { CodegenContext, createMatcher, findFiles, logger, report };
|