@polyprism/core 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.
- package/LICENSE +21 -0
- package/README.md +32 -0
- package/dist/annotations/enrich.d.ts +5 -0
- package/dist/annotations/enrich.js +40 -0
- package/dist/annotations/enrich.js.map +1 -0
- package/dist/annotations/index.d.ts +3 -0
- package/dist/annotations/index.js +3 -0
- package/dist/annotations/index.js.map +1 -0
- package/dist/annotations/parser.d.ts +9 -0
- package/dist/annotations/parser.js +207 -0
- package/dist/annotations/parser.js.map +1 -0
- package/dist/emitter/emit-enums.d.ts +9 -0
- package/dist/emitter/emit-enums.js +19 -0
- package/dist/emitter/emit-enums.js.map +1 -0
- package/dist/emitter/emit-json-types.d.ts +9 -0
- package/dist/emitter/emit-json-types.js +28 -0
- package/dist/emitter/emit-json-types.js.map +1 -0
- package/dist/emitter/file-writer.d.ts +12 -0
- package/dist/emitter/file-writer.js +25 -0
- package/dist/emitter/file-writer.js.map +1 -0
- package/dist/emitter/format-type.d.ts +3 -0
- package/dist/emitter/format-type.js +162 -0
- package/dist/emitter/format-type.js.map +1 -0
- package/dist/emitter/index.d.ts +10 -0
- package/dist/emitter/index.js +7 -0
- package/dist/emitter/index.js.map +1 -0
- package/dist/emitter/render-enum.d.ts +6 -0
- package/dist/emitter/render-enum.js +56 -0
- package/dist/emitter/render-enum.js.map +1 -0
- package/dist/emitter/render-json-type.d.ts +3 -0
- package/dist/emitter/render-json-type.js +10 -0
- package/dist/emitter/render-json-type.js.map +1 -0
- package/dist/generator/config.d.ts +10 -0
- package/dist/generator/config.js +45 -0
- package/dist/generator/config.js.map +1 -0
- package/dist/generator/context.d.ts +18 -0
- package/dist/generator/context.js +1 -0
- package/dist/generator/context.js.map +1 -0
- package/dist/generator/define.d.ts +24 -0
- package/dist/generator/define.js +23 -0
- package/dist/generator/define.js.map +1 -0
- package/dist/generator/index.d.ts +6 -0
- package/dist/generator/index.js +4 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/generator/json-rpc.d.ts +7 -0
- package/dist/generator/json-rpc.js +59 -0
- package/dist/generator/json-rpc.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/ir/index.d.ts +1 -0
- package/dist/ir/index.js +2 -0
- package/dist/ir/index.js.map +1 -0
- package/dist/ir/types.d.ts +133 -0
- package/dist/ir/types.js +17 -0
- package/dist/ir/types.js.map +1 -0
- package/dist/naming/casing.d.ts +7 -0
- package/dist/naming/casing.js +34 -0
- package/dist/naming/casing.js.map +1 -0
- package/dist/naming/index.d.ts +3 -0
- package/dist/naming/index.js +4 -0
- package/dist/naming/index.js.map +1 -0
- package/dist/naming/resolver.d.ts +26 -0
- package/dist/naming/resolver.js +59 -0
- package/dist/naming/resolver.js.map +1 -0
- package/dist/naming/types.d.ts +11 -0
- package/dist/naming/types.js +9 -0
- package/dist/naming/types.js.map +1 -0
- package/dist/reader/dmmf-reader.d.ts +12 -0
- package/dist/reader/dmmf-reader.js +135 -0
- package/dist/reader/dmmf-reader.js.map +1 -0
- package/dist/reader/index.d.ts +3 -0
- package/dist/reader/index.js +2 -0
- package/dist/reader/index.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
const INDENT_UNIT = " ";
|
|
2
|
+
function prettyFormatType(expr) {
|
|
3
|
+
const out = [];
|
|
4
|
+
formatInto(expr.trim(), 0, out);
|
|
5
|
+
return out.join("");
|
|
6
|
+
}
|
|
7
|
+
function formatInto(expr, depth, out) {
|
|
8
|
+
let i = 0;
|
|
9
|
+
let inString = null;
|
|
10
|
+
let isEscaped = false;
|
|
11
|
+
while (i < expr.length) {
|
|
12
|
+
const ch = expr[i];
|
|
13
|
+
if (isEscaped) {
|
|
14
|
+
out.push(ch);
|
|
15
|
+
isEscaped = false;
|
|
16
|
+
i++;
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (ch === "\\") {
|
|
20
|
+
out.push(ch);
|
|
21
|
+
isEscaped = true;
|
|
22
|
+
i++;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (inString) {
|
|
26
|
+
out.push(ch);
|
|
27
|
+
if (ch === inString) inString = null;
|
|
28
|
+
i++;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
32
|
+
out.push(ch);
|
|
33
|
+
inString = ch;
|
|
34
|
+
i++;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (ch === "{") {
|
|
38
|
+
const closeIdx = findMatching(expr, i, "{", "}");
|
|
39
|
+
const inner = expr.slice(i + 1, closeIdx).trim();
|
|
40
|
+
if (inner.length === 0) {
|
|
41
|
+
out.push("{}");
|
|
42
|
+
} else if (!hasTopLevelSeparator(inner)) {
|
|
43
|
+
out.push("{ ");
|
|
44
|
+
formatInto(inner, depth, out);
|
|
45
|
+
out.push(" }");
|
|
46
|
+
} else {
|
|
47
|
+
const innerIndent = INDENT_UNIT.repeat(depth + 1);
|
|
48
|
+
out.push("{\n");
|
|
49
|
+
const props = splitTopLevel(inner);
|
|
50
|
+
for (let p = 0; p < props.length; p++) {
|
|
51
|
+
out.push(innerIndent);
|
|
52
|
+
formatInto(props[p].content, depth + 1, out);
|
|
53
|
+
out.push(";");
|
|
54
|
+
out.push("\n");
|
|
55
|
+
}
|
|
56
|
+
out.push(`${INDENT_UNIT.repeat(depth)}}`);
|
|
57
|
+
}
|
|
58
|
+
i = closeIdx + 1;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
out.push(ch);
|
|
62
|
+
i++;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function findMatching(s, openIdx, open, close) {
|
|
66
|
+
let depth = 0;
|
|
67
|
+
let inString = null;
|
|
68
|
+
let isEscaped = false;
|
|
69
|
+
for (let i = openIdx; i < s.length; i++) {
|
|
70
|
+
const ch = s[i];
|
|
71
|
+
if (isEscaped) {
|
|
72
|
+
isEscaped = false;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (ch === "\\") {
|
|
76
|
+
isEscaped = true;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (inString) {
|
|
80
|
+
if (ch === inString) inString = null;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
84
|
+
inString = ch;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (ch === open) depth++;
|
|
88
|
+
else if (ch === close) {
|
|
89
|
+
depth--;
|
|
90
|
+
if (depth === 0) return i;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return s.length - 1;
|
|
94
|
+
}
|
|
95
|
+
function hasTopLevelSeparator(inner) {
|
|
96
|
+
let depth = 0;
|
|
97
|
+
let inString = null;
|
|
98
|
+
let isEscaped = false;
|
|
99
|
+
for (let i = 0; i < inner.length; i++) {
|
|
100
|
+
const ch = inner[i];
|
|
101
|
+
if (isEscaped) {
|
|
102
|
+
isEscaped = false;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (ch === "\\") {
|
|
106
|
+
isEscaped = true;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (inString) {
|
|
110
|
+
if (ch === inString) inString = null;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
114
|
+
inString = ch;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (ch === "{" || ch === "(" || ch === "[" || ch === "<") depth++;
|
|
118
|
+
else if (ch === "}" || ch === ")" || ch === "]" || ch === ">") depth--;
|
|
119
|
+
else if ((ch === "," || ch === ";") && depth === 0) return true;
|
|
120
|
+
}
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
function splitTopLevel(inner) {
|
|
124
|
+
const result = [];
|
|
125
|
+
let depth = 0;
|
|
126
|
+
let inString = null;
|
|
127
|
+
let isEscaped = false;
|
|
128
|
+
let start = 0;
|
|
129
|
+
for (let i = 0; i < inner.length; i++) {
|
|
130
|
+
const ch = inner[i];
|
|
131
|
+
if (isEscaped) {
|
|
132
|
+
isEscaped = false;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (ch === "\\") {
|
|
136
|
+
isEscaped = true;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (inString) {
|
|
140
|
+
if (ch === inString) inString = null;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
144
|
+
inString = ch;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (ch === "{" || ch === "(" || ch === "[" || ch === "<") depth++;
|
|
148
|
+
else if (ch === "}" || ch === ")" || ch === "]" || ch === ">") depth--;
|
|
149
|
+
else if ((ch === "," || ch === ";") && depth === 0) {
|
|
150
|
+
const content = inner.slice(start, i).trim();
|
|
151
|
+
if (content.length > 0) result.push({ content });
|
|
152
|
+
start = i + 1;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const lastContent = inner.slice(start).trim();
|
|
156
|
+
if (lastContent.length > 0) result.push({ content: lastContent });
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
export {
|
|
160
|
+
prettyFormatType
|
|
161
|
+
};
|
|
162
|
+
//# sourceMappingURL=format-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/emitter/format-type.ts"],"sourcesContent":["// Pretty-formats a TypeScript type expression for emission.\n//\n// Goals:\n// - Object literals (`{ ... }`) with multiple properties break onto lines\n// - Single-property and empty objects stay on one line\n// - Tuples (`[...]`), generics (`<...>`), unions (`a | b`), functions\n// (`(x) => y`) are left untouched (they're usually short enough)\n// - Strings, template literals, and isEscaped sequences are opaque\n// - Idempotent — re-formatting formatted output yields the same string\n//\n// Not a full TS-AST formatter; just a structural prettifier for the inline\n// `@json({...})` annotation outputs that would otherwise be unreadable\n// one-liners.\n\nconst INDENT_UNIT = \" \";\n\nexport function prettyFormatType(expr: string): string {\n const out: string[] = [];\n formatInto(expr.trim(), 0, out);\n return out.join(\"\");\n}\n\nfunction formatInto(expr: string, depth: number, out: string[]): void {\n let i = 0;\n let inString: '\"' | \"'\" | \"`\" | null = null;\n let isEscaped = false;\n\n while (i < expr.length) {\n const ch = expr[i]!;\n\n if (isEscaped) {\n out.push(ch);\n isEscaped = false;\n i++;\n continue;\n }\n if (ch === \"\\\\\") {\n out.push(ch);\n isEscaped = true;\n i++;\n continue;\n }\n if (inString) {\n out.push(ch);\n if (ch === inString) inString = null;\n i++;\n continue;\n }\n if (ch === '\"' || ch === \"'\" || ch === \"`\") {\n out.push(ch);\n inString = ch;\n i++;\n continue;\n }\n\n if (ch === \"{\") {\n const closeIdx = findMatching(expr, i, \"{\", \"}\");\n const inner = expr.slice(i + 1, closeIdx).trim();\n\n if (inner.length === 0) {\n out.push(\"{}\");\n } else if (!hasTopLevelSeparator(inner)) {\n // Single-property or single-expression object — keep on one line.\n out.push(\"{ \");\n formatInto(inner, depth, out);\n out.push(\" }\");\n } else {\n // Multi-property — break onto lines.\n const innerIndent = INDENT_UNIT.repeat(depth + 1);\n out.push(\"{\\n\");\n const props = splitTopLevel(inner);\n for (let p = 0; p < props.length; p++) {\n out.push(innerIndent);\n formatInto(props[p]!.content, depth + 1, out);\n out.push(\";\");\n out.push(\"\\n\");\n }\n out.push(`${INDENT_UNIT.repeat(depth)}}`);\n }\n i = closeIdx + 1;\n continue;\n }\n\n out.push(ch);\n i++;\n }\n}\n\nfunction findMatching(s: string, openIdx: number, open: string, close: string): number {\n let depth = 0;\n let inString: '\"' | \"'\" | \"`\" | null = null;\n let isEscaped = false;\n for (let i = openIdx; i < s.length; i++) {\n const ch = s[i]!;\n if (isEscaped) {\n isEscaped = false;\n continue;\n }\n if (ch === \"\\\\\") {\n isEscaped = true;\n continue;\n }\n if (inString) {\n if (ch === inString) inString = null;\n continue;\n }\n if (ch === '\"' || ch === \"'\" || ch === \"`\") {\n inString = ch;\n continue;\n }\n if (ch === open) depth++;\n else if (ch === close) {\n depth--;\n if (depth === 0) return i;\n }\n }\n return s.length - 1;\n}\n\nfunction hasTopLevelSeparator(inner: string): boolean {\n let depth = 0;\n let inString: '\"' | \"'\" | \"`\" | null = null;\n let isEscaped = false;\n for (let i = 0; i < inner.length; i++) {\n const ch = inner[i]!;\n if (isEscaped) {\n isEscaped = false;\n continue;\n }\n if (ch === \"\\\\\") {\n isEscaped = true;\n continue;\n }\n if (inString) {\n if (ch === inString) inString = null;\n continue;\n }\n if (ch === '\"' || ch === \"'\" || ch === \"`\") {\n inString = ch;\n continue;\n }\n if (ch === \"{\" || ch === \"(\" || ch === \"[\" || ch === \"<\") depth++;\n else if (ch === \"}\" || ch === \")\" || ch === \"]\" || ch === \">\") depth--;\n else if ((ch === \",\" || ch === \";\") && depth === 0) return true;\n }\n return false;\n}\n\nfunction splitTopLevel(inner: string): Array<{ content: string }> {\n const result: Array<{ content: string }> = [];\n let depth = 0;\n let inString: '\"' | \"'\" | \"`\" | null = null;\n let isEscaped = false;\n let start = 0;\n\n for (let i = 0; i < inner.length; i++) {\n const ch = inner[i]!;\n if (isEscaped) {\n isEscaped = false;\n continue;\n }\n if (ch === \"\\\\\") {\n isEscaped = true;\n continue;\n }\n if (inString) {\n if (ch === inString) inString = null;\n continue;\n }\n if (ch === '\"' || ch === \"'\" || ch === \"`\") {\n inString = ch;\n continue;\n }\n if (ch === \"{\" || ch === \"(\" || ch === \"[\" || ch === \"<\") depth++;\n else if (ch === \"}\" || ch === \")\" || ch === \"]\" || ch === \">\") depth--;\n else if ((ch === \",\" || ch === \";\") && depth === 0) {\n const content = inner.slice(start, i).trim();\n if (content.length > 0) result.push({ content });\n start = i + 1;\n }\n }\n\n const lastContent = inner.slice(start).trim();\n if (lastContent.length > 0) result.push({ content: lastContent });\n\n return result;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { emitEnums } from './emit-enums.js';
|
|
2
|
+
export { emitJsonTypes } from './emit-json-types.js';
|
|
3
|
+
export { FileWriter, InMemoryFileWriter, createFileWriter, createInMemoryFileWriter } from './file-writer.js';
|
|
4
|
+
export { prettyFormatType } from './format-type.js';
|
|
5
|
+
export { renderEnum } from './render-enum.js';
|
|
6
|
+
export { renderJsonType } from './render-json-type.js';
|
|
7
|
+
import '../generator/context.js';
|
|
8
|
+
import '../ir/types.js';
|
|
9
|
+
import '../generator/config.js';
|
|
10
|
+
import '../naming/types.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/emitter/index.ts"],"sourcesContent":["export * from \"./emit-enums.js\";\nexport * from \"./emit-json-types.js\";\nexport * from \"./file-writer.js\";\nexport * from \"./format-type.js\";\nexport * from \"./render-enum.js\";\nexport * from \"./render-json-type.js\";\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { resolveTypeIdent } from "../naming/resolver.js";
|
|
2
|
+
function renderEnum(enumDef, naming) {
|
|
3
|
+
const ident = resolveTypeIdent({
|
|
4
|
+
schemaName: enumDef.name,
|
|
5
|
+
override: enumDef.annotations.name,
|
|
6
|
+
convention: naming.typeNaming
|
|
7
|
+
});
|
|
8
|
+
const visibleValues = enumDef.values.filter((v) => !v.annotations.hide);
|
|
9
|
+
const valueLines = visibleValues.map(renderEnumValue).join("\n");
|
|
10
|
+
const header = renderHeader(enumDef);
|
|
11
|
+
return `${header}export enum ${ident} {
|
|
12
|
+
${valueLines}
|
|
13
|
+
}
|
|
14
|
+
`;
|
|
15
|
+
}
|
|
16
|
+
function renderEnumValue(value) {
|
|
17
|
+
const dbValue = value.dbName ?? value.name;
|
|
18
|
+
const docBlock = renderValueJsDoc(value);
|
|
19
|
+
return `${docBlock} ${value.name} = "${dbValue}",`;
|
|
20
|
+
}
|
|
21
|
+
function renderHeader(enumDef) {
|
|
22
|
+
const lines = [];
|
|
23
|
+
if (enumDef.annotations.documentation) {
|
|
24
|
+
for (const docLine of enumDef.annotations.documentation.split("\n")) {
|
|
25
|
+
lines.push(` * ${docLine}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (enumDef.annotations.deprecated) {
|
|
29
|
+
const reason = enumDef.annotations.deprecated.reason;
|
|
30
|
+
lines.push(reason ? ` * @deprecated ${reason}` : " * @deprecated");
|
|
31
|
+
}
|
|
32
|
+
return lines.length > 0 ? `/**
|
|
33
|
+
${lines.join("\n")}
|
|
34
|
+
*/
|
|
35
|
+
` : "";
|
|
36
|
+
}
|
|
37
|
+
function renderValueJsDoc(value) {
|
|
38
|
+
const lines = [];
|
|
39
|
+
if (value.annotations.documentation) {
|
|
40
|
+
for (const docLine of value.annotations.documentation.split("\n")) {
|
|
41
|
+
lines.push(` * ${docLine}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (value.annotations.deprecated) {
|
|
45
|
+
const reason = value.annotations.deprecated.reason;
|
|
46
|
+
lines.push(reason ? ` * @deprecated ${reason}` : " * @deprecated");
|
|
47
|
+
}
|
|
48
|
+
return lines.length > 0 ? ` /**
|
|
49
|
+
${lines.join("\n")}
|
|
50
|
+
*/
|
|
51
|
+
` : "";
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
renderEnum
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=render-enum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/emitter/render-enum.ts"],"sourcesContent":["// Renders a single enum file. All patterns share this output — enums are\n// pure data declarations, not affected by pattern choice.\n\nimport type { EnumDef, EnumValueDef } from \"../ir/types.js\";\nimport { resolveTypeIdent } from \"../naming/resolver.js\";\nimport type { NamingConfig } from \"../naming/types.js\";\n\nexport function renderEnum(enumDef: EnumDef, naming: NamingConfig): string {\n const ident = resolveTypeIdent({\n schemaName: enumDef.name,\n override: enumDef.annotations.name,\n convention: naming.typeNaming,\n });\n\n const visibleValues = enumDef.values.filter((v) => !v.annotations.hide);\n const valueLines = visibleValues.map(renderEnumValue).join(\"\\n\");\n const header = renderHeader(enumDef);\n\n return `${header}export enum ${ident} {\\n${valueLines}\\n}\\n`;\n}\n\nfunction renderEnumValue(value: EnumValueDef): string {\n const dbValue = value.dbName ?? value.name;\n const docBlock = renderValueJsDoc(value);\n return `${docBlock} ${value.name} = \"${dbValue}\",`;\n}\n\nfunction renderHeader(enumDef: EnumDef): string {\n const lines: string[] = [];\n if (enumDef.annotations.documentation) {\n for (const docLine of enumDef.annotations.documentation.split(\"\\n\")) {\n lines.push(` * ${docLine}`);\n }\n }\n if (enumDef.annotations.deprecated) {\n const reason = enumDef.annotations.deprecated.reason;\n lines.push(reason ? ` * @deprecated ${reason}` : \" * @deprecated\");\n }\n return lines.length > 0 ? `/**\\n${lines.join(\"\\n\")}\\n */\\n` : \"\";\n}\n\nfunction renderValueJsDoc(value: EnumValueDef): string {\n const lines: string[] = [];\n if (value.annotations.documentation) {\n for (const docLine of value.annotations.documentation.split(\"\\n\")) {\n lines.push(` * ${docLine}`);\n }\n }\n if (value.annotations.deprecated) {\n const reason = value.annotations.deprecated.reason;\n lines.push(reason ? ` * @deprecated ${reason}` : \" * @deprecated\");\n }\n return lines.length > 0 ? ` /**\\n${lines.join(\"\\n\")}\\n */\\n` : \"\";\n}\n"],"mappings":"AAIA,SAAS,wBAAwB;AAG1B,SAAS,WAAW,SAAkB,QAA8B;AACzE,QAAM,QAAQ,iBAAiB;AAAA,IAC7B,YAAY,QAAQ;AAAA,IACpB,UAAU,QAAQ,YAAY;AAAA,IAC9B,YAAY,OAAO;AAAA,EACrB,CAAC;AAED,QAAM,gBAAgB,QAAQ,OAAO,OAAO,CAAC,MAAM,CAAC,EAAE,YAAY,IAAI;AACtE,QAAM,aAAa,cAAc,IAAI,eAAe,EAAE,KAAK,IAAI;AAC/D,QAAM,SAAS,aAAa,OAAO;AAEnC,SAAO,GAAG,MAAM,eAAe,KAAK;AAAA,EAAO,UAAU;AAAA;AAAA;AACvD;AAEA,SAAS,gBAAgB,OAA6B;AACpD,QAAM,UAAU,MAAM,UAAU,MAAM;AACtC,QAAM,WAAW,iBAAiB,KAAK;AACvC,SAAO,GAAG,QAAQ,KAAK,MAAM,IAAI,OAAO,OAAO;AACjD;AAEA,SAAS,aAAa,SAA0B;AAC9C,QAAM,QAAkB,CAAC;AACzB,MAAI,QAAQ,YAAY,eAAe;AACrC,eAAW,WAAW,QAAQ,YAAY,cAAc,MAAM,IAAI,GAAG;AACnE,YAAM,KAAK,MAAM,OAAO,EAAE;AAAA,IAC5B;AAAA,EACF;AACA,MAAI,QAAQ,YAAY,YAAY;AAClC,UAAM,SAAS,QAAQ,YAAY,WAAW;AAC9C,UAAM,KAAK,SAAS,kBAAkB,MAAM,KAAK,gBAAgB;AAAA,EACnE;AACA,SAAO,MAAM,SAAS,IAAI;AAAA,EAAQ,MAAM,KAAK,IAAI,CAAC;AAAA;AAAA,IAAY;AAChE;AAEA,SAAS,iBAAiB,OAA6B;AACrD,QAAM,QAAkB,CAAC;AACzB,MAAI,MAAM,YAAY,eAAe;AACnC,eAAW,WAAW,MAAM,YAAY,cAAc,MAAM,IAAI,GAAG;AACjE,YAAM,KAAK,QAAQ,OAAO,EAAE;AAAA,IAC9B;AAAA,EACF;AACA,MAAI,MAAM,YAAY,YAAY;AAChC,UAAM,SAAS,MAAM,YAAY,WAAW;AAC5C,UAAM,KAAK,SAAS,oBAAoB,MAAM,KAAK,kBAAkB;AAAA,EACvE;AACA,SAAO,MAAM,SAAS,IAAI;AAAA,EAAU,MAAM,KAAK,IAAI,CAAC;AAAA;AAAA,IAAc;AACpE;","names":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { prettyFormatType } from "./format-type.js";
|
|
2
|
+
function renderJsonType(typeName, typeExpression) {
|
|
3
|
+
const formatted = prettyFormatType(typeExpression);
|
|
4
|
+
return `export type ${typeName} = ${formatted};
|
|
5
|
+
`;
|
|
6
|
+
}
|
|
7
|
+
export {
|
|
8
|
+
renderJsonType
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=render-json-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/emitter/render-json-type.ts"],"sourcesContent":["// Renders a JSON-type file from an inline `@json(...)` annotation.\n// All patterns share this output — JSON types are plain TypeScript type\n// aliases regardless of which pattern the model itself uses.\n//\n// The type expression is pretty-formatted so multi-property objects break\n// onto multiple lines instead of becoming one-line monstrosities.\n\nimport { prettyFormatType } from \"./format-type.js\";\n\nexport function renderJsonType(typeName: string, typeExpression: string): string {\n const formatted = prettyFormatType(typeExpression);\n return `export type ${typeName} = ${formatted};\\n`;\n}\n"],"mappings":"AAOA,SAAS,wBAAwB;AAE1B,SAAS,eAAe,UAAkB,gBAAgC;AAC/E,QAAM,YAAY,iBAAiB,cAAc;AACjD,SAAO,eAAe,QAAQ,MAAM,SAAS;AAAA;AAC/C;","names":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NamingConfig } from '../naming/types.js';
|
|
2
|
+
|
|
3
|
+
interface PolyPrismConfig {
|
|
4
|
+
readonly naming: NamingConfig;
|
|
5
|
+
readonly emitIndex: boolean;
|
|
6
|
+
}
|
|
7
|
+
type RawGeneratorConfig = Record<string, string | string[] | undefined>;
|
|
8
|
+
declare function parseGeneratorConfig(raw: RawGeneratorConfig): PolyPrismConfig;
|
|
9
|
+
|
|
10
|
+
export { type PolyPrismConfig, type RawGeneratorConfig, parseGeneratorConfig };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { DEFAULT_NAMING } from "../naming/types.js";
|
|
2
|
+
const FILE_NAMING_VALUES = /* @__PURE__ */ new Set([
|
|
3
|
+
"PascalCase",
|
|
4
|
+
"camelCase",
|
|
5
|
+
"kebab-case",
|
|
6
|
+
"snake_case",
|
|
7
|
+
"preserve"
|
|
8
|
+
]);
|
|
9
|
+
const TYPE_NAMING_VALUES = /* @__PURE__ */ new Set([
|
|
10
|
+
"PascalCase",
|
|
11
|
+
"camelCase",
|
|
12
|
+
"snake_case",
|
|
13
|
+
"preserve"
|
|
14
|
+
]);
|
|
15
|
+
const FIELD_NAMING_VALUES = /* @__PURE__ */ new Set([
|
|
16
|
+
"camelCase",
|
|
17
|
+
"snake_case",
|
|
18
|
+
"preserve"
|
|
19
|
+
]);
|
|
20
|
+
function parseGeneratorConfig(raw) {
|
|
21
|
+
return {
|
|
22
|
+
naming: {
|
|
23
|
+
fileNaming: pickEnum(raw, "fileNaming", FILE_NAMING_VALUES, DEFAULT_NAMING.fileNaming),
|
|
24
|
+
typeNaming: pickEnum(raw, "typeNaming", TYPE_NAMING_VALUES, DEFAULT_NAMING.typeNaming),
|
|
25
|
+
fieldNaming: pickEnum(raw, "fieldNaming", FIELD_NAMING_VALUES, DEFAULT_NAMING.fieldNaming)
|
|
26
|
+
},
|
|
27
|
+
emitIndex: pickBool(raw, "emitIndex", false)
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function pickEnum(raw, key, allowed, fallback) {
|
|
31
|
+
const value = raw[key];
|
|
32
|
+
if (typeof value !== "string") return fallback;
|
|
33
|
+
return allowed.has(value) ? value : fallback;
|
|
34
|
+
}
|
|
35
|
+
function pickBool(raw, key, fallback) {
|
|
36
|
+
const value = raw[key];
|
|
37
|
+
if (typeof value !== "string") return fallback;
|
|
38
|
+
if (value === "true") return true;
|
|
39
|
+
if (value === "false") return false;
|
|
40
|
+
return fallback;
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
parseGeneratorConfig
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/generator/config.ts"],"sourcesContent":["// Parse the generator-block `config` field (a Record<string, string | string[]>)\n// into a strongly-typed PolyPrismConfig. Unknown keys are ignored; invalid\n// values fall back to defaults silently in v0.1 (we can add warnings later).\n\nimport type {\n FieldNamingConvention,\n FileNamingConvention,\n NamingConfig,\n TypeNamingConvention,\n} from \"../naming/types.js\";\nimport { DEFAULT_NAMING } from \"../naming/types.js\";\n\nexport interface PolyPrismConfig {\n readonly naming: NamingConfig;\n readonly emitIndex: boolean;\n}\n\nconst FILE_NAMING_VALUES: ReadonlySet<FileNamingConvention> = new Set([\n \"PascalCase\",\n \"camelCase\",\n \"kebab-case\",\n \"snake_case\",\n \"preserve\",\n]);\n\nconst TYPE_NAMING_VALUES: ReadonlySet<TypeNamingConvention> = new Set([\n \"PascalCase\",\n \"camelCase\",\n \"snake_case\",\n \"preserve\",\n]);\n\nconst FIELD_NAMING_VALUES: ReadonlySet<FieldNamingConvention> = new Set([\n \"camelCase\",\n \"snake_case\",\n \"preserve\",\n]);\n\nexport type RawGeneratorConfig = Record<string, string | string[] | undefined>;\n\nexport function parseGeneratorConfig(raw: RawGeneratorConfig): PolyPrismConfig {\n return {\n naming: {\n fileNaming: pickEnum(raw, \"fileNaming\", FILE_NAMING_VALUES, DEFAULT_NAMING.fileNaming),\n typeNaming: pickEnum(raw, \"typeNaming\", TYPE_NAMING_VALUES, DEFAULT_NAMING.typeNaming),\n fieldNaming: pickEnum(raw, \"fieldNaming\", FIELD_NAMING_VALUES, DEFAULT_NAMING.fieldNaming),\n },\n emitIndex: pickBool(raw, \"emitIndex\", false),\n };\n}\n\nfunction pickEnum<T extends string>(\n raw: RawGeneratorConfig,\n key: string,\n allowed: ReadonlySet<T>,\n fallback: T,\n): T {\n const value = raw[key];\n if (typeof value !== \"string\") return fallback;\n return allowed.has(value as T) ? (value as T) : fallback;\n}\n\nfunction pickBool(raw: RawGeneratorConfig, key: string, fallback: boolean): boolean {\n const value = raw[key];\n if (typeof value !== \"string\") return fallback;\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n return fallback;\n}\n"],"mappings":"AAUA,SAAS,sBAAsB;AAO/B,MAAM,qBAAwD,oBAAI,IAAI;AAAA,EACpE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,MAAM,qBAAwD,oBAAI,IAAI;AAAA,EACpE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,MAAM,sBAA0D,oBAAI,IAAI;AAAA,EACtE;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAIM,SAAS,qBAAqB,KAA0C;AAC7E,SAAO;AAAA,IACL,QAAQ;AAAA,MACN,YAAY,SAAS,KAAK,cAAc,oBAAoB,eAAe,UAAU;AAAA,MACrF,YAAY,SAAS,KAAK,cAAc,oBAAoB,eAAe,UAAU;AAAA,MACrF,aAAa,SAAS,KAAK,eAAe,qBAAqB,eAAe,WAAW;AAAA,IAC3F;AAAA,IACA,WAAW,SAAS,KAAK,aAAa,KAAK;AAAA,EAC7C;AACF;AAEA,SAAS,SACP,KACA,KACA,SACA,UACG;AACH,QAAM,QAAQ,IAAI,GAAG;AACrB,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,SAAO,QAAQ,IAAI,KAAU,IAAK,QAAc;AAClD;AAEA,SAAS,SAAS,KAAyB,KAAa,UAA4B;AAClF,QAAM,QAAQ,IAAI,GAAG;AACrB,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,UAAU,OAAQ,QAAO;AAC7B,MAAI,UAAU,QAAS,QAAO;AAC9B,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FileWriter } from '../emitter/file-writer.js';
|
|
2
|
+
import { PolyPrismIR } from '../ir/types.js';
|
|
3
|
+
import { PolyPrismConfig } from './config.js';
|
|
4
|
+
import '../naming/types.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Passed to every pattern emitter's onGenerate callback. Contains the
|
|
8
|
+
* already-parsed IR (annotations enriched), resolved config, output dir,
|
|
9
|
+
* and a file writer.
|
|
10
|
+
*/
|
|
11
|
+
interface GeneratorContext {
|
|
12
|
+
readonly ir: PolyPrismIR;
|
|
13
|
+
readonly config: PolyPrismConfig;
|
|
14
|
+
readonly outputDir: string;
|
|
15
|
+
readonly writer: FileWriter;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type { GeneratorContext };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import './config.js';
|
|
2
|
+
import { GeneratorContext } from './context.js';
|
|
3
|
+
import '../naming/types.js';
|
|
4
|
+
import '../emitter/file-writer.js';
|
|
5
|
+
import '../ir/types.js';
|
|
6
|
+
|
|
7
|
+
interface GeneratorManifest {
|
|
8
|
+
readonly prettyName: string;
|
|
9
|
+
readonly defaultOutput?: string;
|
|
10
|
+
readonly version?: string;
|
|
11
|
+
readonly requiresGenerators?: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
interface GeneratorDefinition {
|
|
14
|
+
readonly manifest: GeneratorManifest;
|
|
15
|
+
readonly onGenerate: (ctx: GeneratorContext) => Promise<void> | void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Wire up a Prisma generator. Runs the JSON-RPC handler; when Prisma sends
|
|
19
|
+
* a `generate` request, the pattern's onGenerate callback fires with a
|
|
20
|
+
* GeneratorContext.
|
|
21
|
+
*/
|
|
22
|
+
declare function defineGenerator(def: GeneratorDefinition): void;
|
|
23
|
+
|
|
24
|
+
export { type GeneratorDefinition, type GeneratorManifest, defineGenerator };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { enrichAnnotations } from "../annotations/enrich.js";
|
|
2
|
+
import { createFileWriter } from "../emitter/file-writer.js";
|
|
3
|
+
import { readDmmf } from "../reader/dmmf-reader.js";
|
|
4
|
+
import { parseGeneratorConfig } from "./config.js";
|
|
5
|
+
import { runJsonRpc } from "./json-rpc.js";
|
|
6
|
+
function defineGenerator(def) {
|
|
7
|
+
runJsonRpc({
|
|
8
|
+
getManifest: () => ({ manifest: def.manifest }),
|
|
9
|
+
generate: async (params) => {
|
|
10
|
+
const opts = params;
|
|
11
|
+
const rawIr = readDmmf(opts.dmmf);
|
|
12
|
+
const ir = enrichAnnotations(rawIr);
|
|
13
|
+
const config = parseGeneratorConfig(opts.generator.config);
|
|
14
|
+
const outputDir = opts.generator.output?.value ?? def.manifest.defaultOutput ?? "./generated";
|
|
15
|
+
const writer = createFileWriter(outputDir);
|
|
16
|
+
await def.onGenerate({ ir, config, outputDir, writer });
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
defineGenerator
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=define.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/generator/define.ts"],"sourcesContent":["// Public generator API. Pattern packages (ts-interface, ts-class, ...) call\n// `defineGenerator({ manifest, onGenerate })` in their bin entry point.\n// We handle the JSON-RPC, DMMF reading, annotation parsing, and config\n// resolution; the pattern's onGenerate receives a clean GeneratorContext\n// with parsed IR and is never exposed to DMMF directly.\n\nimport type { DMMF } from \"@prisma/generator-helper\";\n\nimport { enrichAnnotations } from \"../annotations/enrich.js\";\nimport { createFileWriter } from \"../emitter/file-writer.js\";\nimport { readDmmf } from \"../reader/dmmf-reader.js\";\nimport { parseGeneratorConfig, type RawGeneratorConfig } from \"./config.js\";\nimport type { GeneratorContext } from \"./context.js\";\nimport { runJsonRpc } from \"./json-rpc.js\";\n\nexport interface GeneratorManifest {\n readonly prettyName: string;\n readonly defaultOutput?: string;\n readonly version?: string;\n readonly requiresGenerators?: readonly string[];\n}\n\nexport interface GeneratorDefinition {\n readonly manifest: GeneratorManifest;\n readonly onGenerate: (ctx: GeneratorContext) => Promise<void> | void;\n}\n\n/** Subset of Prisma's GeneratorOptions we actually consume. */\ninterface GeneratorOptions {\n readonly dmmf: DMMF.Document;\n readonly generator: {\n readonly output: { readonly value: string | null } | null;\n readonly config: RawGeneratorConfig;\n };\n}\n\n/**\n * Wire up a Prisma generator. Runs the JSON-RPC handler; when Prisma sends\n * a `generate` request, the pattern's onGenerate callback fires with a\n * GeneratorContext.\n */\nexport function defineGenerator(def: GeneratorDefinition): void {\n runJsonRpc({\n getManifest: () => ({ manifest: def.manifest }),\n generate: async (params) => {\n const opts = params as GeneratorOptions;\n\n const rawIr = readDmmf(opts.dmmf);\n const ir = enrichAnnotations(rawIr);\n const config = parseGeneratorConfig(opts.generator.config);\n\n const outputDir = opts.generator.output?.value ?? def.manifest.defaultOutput ?? \"./generated\";\n const writer = createFileWriter(outputDir);\n\n await def.onGenerate({ ir, config, outputDir, writer });\n },\n });\n}\n"],"mappings":"AAQA,SAAS,yBAAyB;AAClC,SAAS,wBAAwB;AACjC,SAAS,gBAAgB;AACzB,SAAS,4BAAqD;AAE9D,SAAS,kBAAkB;AA4BpB,SAAS,gBAAgB,KAAgC;AAC9D,aAAW;AAAA,IACT,aAAa,OAAO,EAAE,UAAU,IAAI,SAAS;AAAA,IAC7C,UAAU,OAAO,WAAW;AAC1B,YAAM,OAAO;AAEb,YAAM,QAAQ,SAAS,KAAK,IAAI;AAChC,YAAM,KAAK,kBAAkB,KAAK;AAClC,YAAM,SAAS,qBAAqB,KAAK,UAAU,MAAM;AAEzD,YAAM,YAAY,KAAK,UAAU,QAAQ,SAAS,IAAI,SAAS,iBAAiB;AAChF,YAAM,SAAS,iBAAiB,SAAS;AAEzC,YAAM,IAAI,WAAW,EAAE,IAAI,QAAQ,WAAW,OAAO,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AACH;","names":[]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { PolyPrismConfig, RawGeneratorConfig, parseGeneratorConfig } from './config.js';
|
|
2
|
+
export { GeneratorContext } from './context.js';
|
|
3
|
+
export { GeneratorDefinition, GeneratorManifest, defineGenerator } from './define.js';
|
|
4
|
+
import '../naming/types.js';
|
|
5
|
+
import '../emitter/file-writer.js';
|
|
6
|
+
import '../ir/types.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/generator/index.ts"],"sourcesContent":["export * from \"./config.js\";\nexport * from \"./context.js\";\nexport * from \"./define.js\";\n// json-rpc is internal — not exported. defineGenerator wraps it.\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { createInterface } from "node:readline";
|
|
2
|
+
function runJsonRpc(handlers) {
|
|
3
|
+
const rl = createInterface({
|
|
4
|
+
input: process.stdin,
|
|
5
|
+
terminal: false,
|
|
6
|
+
crlfDelay: Infinity
|
|
7
|
+
});
|
|
8
|
+
rl.on("line", (line) => {
|
|
9
|
+
void handleLine(line, handlers);
|
|
10
|
+
});
|
|
11
|
+
rl.on("close", () => {
|
|
12
|
+
process.exit(0);
|
|
13
|
+
});
|
|
14
|
+
process.stdin.resume();
|
|
15
|
+
}
|
|
16
|
+
async function handleLine(line, handlers) {
|
|
17
|
+
const trimmed = line.trim();
|
|
18
|
+
if (trimmed.length === 0) return;
|
|
19
|
+
let req;
|
|
20
|
+
try {
|
|
21
|
+
req = JSON.parse(trimmed);
|
|
22
|
+
} catch {
|
|
23
|
+
process.stderr.write(`PolyPrism: failed to parse JSON-RPC request: ${trimmed}
|
|
24
|
+
`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
if (req.method === "getManifest") {
|
|
29
|
+
const result = await handlers.getManifest();
|
|
30
|
+
respondResult(req.id, result);
|
|
31
|
+
} else if (req.method === "generate") {
|
|
32
|
+
await handlers.generate(req.params);
|
|
33
|
+
respondResult(req.id, null);
|
|
34
|
+
} else {
|
|
35
|
+
respondError(req.id, -32601, `Method not found: ${req.method}`);
|
|
36
|
+
}
|
|
37
|
+
} catch (e) {
|
|
38
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
39
|
+
respondError(req.id, -32603, message);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function respondResult(id, result) {
|
|
43
|
+
const response = { jsonrpc: "2.0", id, result };
|
|
44
|
+
process.stderr.write(`${JSON.stringify(response)}
|
|
45
|
+
`);
|
|
46
|
+
}
|
|
47
|
+
function respondError(id, code, message) {
|
|
48
|
+
const response = {
|
|
49
|
+
jsonrpc: "2.0",
|
|
50
|
+
id,
|
|
51
|
+
error: { code, message }
|
|
52
|
+
};
|
|
53
|
+
process.stderr.write(`${JSON.stringify(response)}
|
|
54
|
+
`);
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
runJsonRpc
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=json-rpc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/generator/json-rpc.ts"],"sourcesContent":["// Minimal JSON-RPC handler for the Prisma generator protocol.\n//\n// Prisma launches our binary, sends newline-delimited JSON-RPC requests over\n// stdin, expects newline-delimited responses on STDERR (yes, stderr — this is\n// a Prisma-specific quirk that's easy to miss: see @prisma/generator-helper's\n// implementation). Two methods only:\n// - `getManifest` — generator describes itself\n// - `generate` — generator does the codegen work\n//\n// Vendored intentionally (~80 lines) so @polyprism/* packages have zero\n// third-party runtime deps. If Prisma changes the protocol in the future,\n// this is the single file to update.\n\nimport { createInterface } from \"node:readline\";\n\ninterface JsonRpcRequest {\n readonly jsonrpc: \"2.0\";\n readonly method: string;\n readonly params?: unknown;\n readonly id: number | string;\n}\n\ninterface JsonRpcResponse {\n readonly jsonrpc: \"2.0\";\n readonly id: number | string;\n readonly result?: unknown;\n readonly error?: { readonly code: number; readonly message: string };\n}\n\nexport interface JsonRpcHandlers {\n readonly getManifest: () => unknown | Promise<unknown>;\n readonly generate: (params: unknown) => void | Promise<void>;\n}\n\nexport function runJsonRpc(handlers: JsonRpcHandlers): void {\n const rl = createInterface({\n input: process.stdin,\n terminal: false,\n crlfDelay: Infinity,\n });\n\n rl.on(\"line\", (line) => {\n void handleLine(line, handlers);\n });\n\n rl.on(\"close\", () => {\n process.exit(0);\n });\n\n // Prisma's reference implementation explicitly resumes stdin; mirror that\n // to avoid edge cases where readline doesn't auto-resume.\n process.stdin.resume();\n}\n\nasync function handleLine(line: string, handlers: JsonRpcHandlers): Promise<void> {\n const trimmed = line.trim();\n if (trimmed.length === 0) return;\n\n let req: JsonRpcRequest;\n try {\n req = JSON.parse(trimmed) as JsonRpcRequest;\n } catch {\n process.stderr.write(`PolyPrism: failed to parse JSON-RPC request: ${trimmed}\\n`);\n return;\n }\n\n try {\n if (req.method === \"getManifest\") {\n const result = await handlers.getManifest();\n respondResult(req.id, result);\n } else if (req.method === \"generate\") {\n await handlers.generate(req.params);\n respondResult(req.id, null);\n } else {\n respondError(req.id, -32601, `Method not found: ${req.method}`);\n }\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n respondError(req.id, -32603, message);\n }\n}\n\n// Prisma reads responses from STDERR. Writing to stdout would deadlock.\nfunction respondResult(id: number | string, result: unknown): void {\n const response: JsonRpcResponse = { jsonrpc: \"2.0\", id, result };\n process.stderr.write(`${JSON.stringify(response)}\\n`);\n}\n\nfunction respondError(id: number | string, code: number, message: string): void {\n const response: JsonRpcResponse = {\n jsonrpc: \"2.0\",\n id,\n error: { code, message },\n };\n process.stderr.write(`${JSON.stringify(response)}\\n`);\n}\n"],"mappings":"AAaA,SAAS,uBAAuB;AAqBzB,SAAS,WAAW,UAAiC;AAC1D,QAAM,KAAK,gBAAgB;AAAA,IACzB,OAAO,QAAQ;AAAA,IACf,UAAU;AAAA,IACV,WAAW;AAAA,EACb,CAAC;AAED,KAAG,GAAG,QAAQ,CAAC,SAAS;AACtB,SAAK,WAAW,MAAM,QAAQ;AAAA,EAChC,CAAC;AAED,KAAG,GAAG,SAAS,MAAM;AACnB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAID,UAAQ,MAAM,OAAO;AACvB;AAEA,eAAe,WAAW,MAAc,UAA0C;AAChF,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,QAAQ,WAAW,EAAG;AAE1B,MAAI;AACJ,MAAI;AACF,UAAM,KAAK,MAAM,OAAO;AAAA,EAC1B,QAAQ;AACN,YAAQ,OAAO,MAAM,gDAAgD,OAAO;AAAA,CAAI;AAChF;AAAA,EACF;AAEA,MAAI;AACF,QAAI,IAAI,WAAW,eAAe;AAChC,YAAM,SAAS,MAAM,SAAS,YAAY;AAC1C,oBAAc,IAAI,IAAI,MAAM;AAAA,IAC9B,WAAW,IAAI,WAAW,YAAY;AACpC,YAAM,SAAS,SAAS,IAAI,MAAM;AAClC,oBAAc,IAAI,IAAI,IAAI;AAAA,IAC5B,OAAO;AACL,mBAAa,IAAI,IAAI,QAAQ,qBAAqB,IAAI,MAAM,EAAE;AAAA,IAChE;AAAA,EACF,SAAS,GAAG;AACV,UAAM,UAAU,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AACzD,iBAAa,IAAI,IAAI,QAAQ,OAAO;AAAA,EACtC;AACF;AAGA,SAAS,cAAc,IAAqB,QAAuB;AACjE,QAAM,WAA4B,EAAE,SAAS,OAAO,IAAI,OAAO;AAC/D,UAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,QAAQ,CAAC;AAAA,CAAI;AACtD;AAEA,SAAS,aAAa,IAAqB,MAAc,SAAuB;AAC9E,QAAM,WAA4B;AAAA,IAChC,SAAS;AAAA,IACT;AAAA,IACA,OAAO,EAAE,MAAM,QAAQ;AAAA,EACzB;AACA,UAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,QAAQ,CAAC;AAAA,CAAI;AACtD;","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { enrichAnnotations } from './annotations/enrich.js';
|
|
2
|
+
export { parseAnnotations } from './annotations/parser.js';
|
|
3
|
+
export { emitEnums } from './emitter/emit-enums.js';
|
|
4
|
+
export { emitJsonTypes } from './emitter/emit-json-types.js';
|
|
5
|
+
export { FileWriter, InMemoryFileWriter, createFileWriter, createInMemoryFileWriter } from './emitter/file-writer.js';
|
|
6
|
+
export { prettyFormatType } from './emitter/format-type.js';
|
|
7
|
+
export { renderEnum } from './emitter/render-enum.js';
|
|
8
|
+
export { renderJsonType } from './emitter/render-json-type.js';
|
|
9
|
+
export { PolyPrismConfig, RawGeneratorConfig, parseGeneratorConfig } from './generator/config.js';
|
|
10
|
+
export { GeneratorContext } from './generator/context.js';
|
|
11
|
+
export { GeneratorDefinition, GeneratorManifest, defineGenerator } from './generator/define.js';
|
|
12
|
+
export { AnnotationSet, CoerceTo, DefaultValue, DeprecatedInfo, EnumDef, EnumValueDef, FieldDef, FieldType, IndexDef, JsonAnnotation, ModelDef, NativeType, NormaliseOp, PolyPrismIR, PrimaryKeyDef, ReferentialAction, ScalarType, TypeOverride, UniqueIndexDef, emptyAnnotationSet } from './ir/types.js';
|
|
13
|
+
export { splitWords, toCamelCase, toKebabCase, toPascalCase, toSnakeCase } from './naming/casing.js';
|
|
14
|
+
export { ResolveFieldIdent, ResolveTypeIdent, applyFieldConvention, applyFileConvention, applyTypeConvention, autoNameInlineJson, resolveFieldIdent, resolveTypeFilename, resolveTypeIdent } from './naming/resolver.js';
|
|
15
|
+
export { DEFAULT_NAMING, FieldNamingConvention, FileNamingConvention, NamingConfig, TypeNamingConvention } from './naming/types.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Public API: IR types + annotation parser. The DMMF reader is internal —\n// it would leak `@prisma/generator-helper` types into the public surface,\n// forcing consumers to install generator-helper just to typecheck. Instead,\n// `defineGenerator` (added in Task 5) consumes DMMF internally and hands\n// emitters parsed IR.\n\nexport * from \"./annotations/index.js\";\nexport * from \"./emitter/index.js\";\nexport * from \"./generator/index.js\";\nexport * from \"./ir/index.js\";\nexport * from \"./naming/index.js\";\n"],"mappings":"AAMA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AnnotationSet, CoerceTo, DefaultValue, DeprecatedInfo, EnumDef, EnumValueDef, FieldDef, FieldType, IndexDef, JsonAnnotation, ModelDef, NativeType, NormaliseOp, PolyPrismIR, PrimaryKeyDef, ReferentialAction, ScalarType, TypeOverride, UniqueIndexDef, emptyAnnotationSet } from './types.js';
|
package/dist/ir/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/ir/index.ts"],"sourcesContent":["export * from \"./types.js\";\n"],"mappings":"AAAA,cAAc;","names":[]}
|