@nexus-rpc/gen-core 0.1.0-alpha0
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/definition-schema.d.ts +29 -0
- package/dist/definition-schema.js +3 -0
- package/dist/generator.d.ts +53 -0
- package/dist/generator.js +128 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/language-csharp.d.ts +4 -0
- package/dist/language-csharp.js +107 -0
- package/dist/language-go.d.ts +15 -0
- package/dist/language-go.js +213 -0
- package/dist/language-java.d.ts +5 -0
- package/dist/language-java.js +111 -0
- package/dist/language-python.d.ts +4 -0
- package/dist/language-python.js +181 -0
- package/dist/language-typescript.d.ts +5 -0
- package/dist/language-typescript.js +179 -0
- package/dist/parser.d.ts +2 -0
- package/dist/parser.js +34 -0
- package/dist/render-adapter.d.ts +44 -0
- package/dist/render-adapter.js +88 -0
- package/dist/utility.d.ts +10 -0
- package/dist/utility.js +30 -0
- package/package.json +31 -0
- package/src/definition-schema.ts +22 -0
- package/src/generator.ts +222 -0
- package/src/index.ts +8 -0
- package/src/language-csharp.ts +190 -0
- package/src/language-go.ts +310 -0
- package/src/language-java.ts +191 -0
- package/src/language-python.ts +260 -0
- package/src/language-typescript.ts +288 -0
- package/src/parser.ts +47 -0
- package/src/render-adapter.ts +205 -0
- package/src/utility.ts +52 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConvenienceRenderer,
|
|
3
|
+
Name,
|
|
4
|
+
Namer,
|
|
5
|
+
type RendererOptions,
|
|
6
|
+
type Sourcelike,
|
|
7
|
+
} from "quicktype-core";
|
|
8
|
+
import {
|
|
9
|
+
getNexusRendererOptions,
|
|
10
|
+
type NexusRendererOptions,
|
|
11
|
+
type PreparedSchema,
|
|
12
|
+
} from "./generator.js";
|
|
13
|
+
import { proxyWithOverrides } from "./utility.js";
|
|
14
|
+
import type {
|
|
15
|
+
BlankLineConfig,
|
|
16
|
+
ForEachPosition,
|
|
17
|
+
Renderer,
|
|
18
|
+
} from "quicktype-core/dist/Renderer.js";
|
|
19
|
+
import type {
|
|
20
|
+
ClassProperty,
|
|
21
|
+
ClassType,
|
|
22
|
+
EnumType,
|
|
23
|
+
ObjectType,
|
|
24
|
+
Type,
|
|
25
|
+
TypeGraph,
|
|
26
|
+
UnionType,
|
|
27
|
+
} from "quicktype-core/dist/Type/index.js";
|
|
28
|
+
import type { ForbiddenWordsInfo } from "quicktype-core/dist/ConvenienceRenderer.js";
|
|
29
|
+
import { FixedName } from "quicktype-core/dist/Naming.js";
|
|
30
|
+
|
|
31
|
+
type AnyFunction = (...arguments_: any[]) => any;
|
|
32
|
+
|
|
33
|
+
export abstract class RenderAdapter<AccessibleRenderer> {
|
|
34
|
+
public readonly render: AccessibleRenderer &
|
|
35
|
+
RenderAccessible &
|
|
36
|
+
ConvenienceRenderer;
|
|
37
|
+
protected readonly nexusRendererOptions: NexusRendererOptions;
|
|
38
|
+
private readonly serviceTypeNamesInUse: Record<string, boolean> = {};
|
|
39
|
+
|
|
40
|
+
constructor(render: ConvenienceRenderer, rendererOptions: RendererOptions) {
|
|
41
|
+
this.render = render as any;
|
|
42
|
+
this.nexusRendererOptions = getNexusRendererOptions(rendererOptions);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public get schema(): PreparedSchema {
|
|
46
|
+
return this.nexusRendererOptions.nexusSchema;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
makeRenderer<T extends ConvenienceRenderer>(overrides: {
|
|
50
|
+
[K in keyof AccessibleRenderer]?: AccessibleRenderer[K] extends AnyFunction
|
|
51
|
+
? (
|
|
52
|
+
this: AccessibleRenderer,
|
|
53
|
+
original: AccessibleRenderer[K],
|
|
54
|
+
...arguments_: Parameters<AccessibleRenderer[K]>
|
|
55
|
+
) => ReturnType<AccessibleRenderer[K]>
|
|
56
|
+
: never;
|
|
57
|
+
}): T {
|
|
58
|
+
return proxyWithOverrides(
|
|
59
|
+
this.render as ConvenienceRenderer,
|
|
60
|
+
overrides,
|
|
61
|
+
) as T;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
makeServiceTypeName(idealName: string) {
|
|
65
|
+
// If name in use but not with services, suffix "Service"
|
|
66
|
+
if (this.topLevelNameInUse(idealName, false)) {
|
|
67
|
+
idealName += "Service";
|
|
68
|
+
}
|
|
69
|
+
// If name in use, append number, starting with 2
|
|
70
|
+
if (this.topLevelNameInUse(idealName, true)) {
|
|
71
|
+
for (let index = 2; ; index++) {
|
|
72
|
+
if (!this.topLevelNameInUse(`${idealName}${index}`, true)) {
|
|
73
|
+
idealName += `${index}`;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
this.serviceTypeNamesInUse[idealName] = true;
|
|
79
|
+
return idealName;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
makeOperationFunctionName(idealName: string, inUse: Record<string, boolean>) {
|
|
83
|
+
// If forbidden, suffix with "Operation"
|
|
84
|
+
if (this.opNameForbidden(idealName)) {
|
|
85
|
+
idealName += "Operation";
|
|
86
|
+
}
|
|
87
|
+
// Append numbers starting with 2 if already in use
|
|
88
|
+
if (Object.hasOwn(inUse, idealName)) {
|
|
89
|
+
for (let index = 2; ; index++) {
|
|
90
|
+
if (!Object.hasOwn(inUse, `${idealName}${index}`)) {
|
|
91
|
+
idealName += `${index}`;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
inUse[idealName] = true;
|
|
97
|
+
return idealName;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
topLevelNameInUse(name: string, includeServices: boolean) {
|
|
101
|
+
// Considered in use if forbidden
|
|
102
|
+
if (this.render.forbiddenNamesForGlobalNamespace().includes(name)) {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Check services
|
|
107
|
+
if (includeServices && Object.hasOwn(this.serviceTypeNamesInUse, name)) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
let inNames = false;
|
|
111
|
+
this.render.names.forEach((value) => {
|
|
112
|
+
if (value == name) {
|
|
113
|
+
inNames = true;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return inNames;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
opNameForbidden(name: string) {
|
|
120
|
+
// TODO(cretz): hacking undefined in for object type ok?
|
|
121
|
+
const info = this.render.forbiddenForObjectProperties(
|
|
122
|
+
undefined as any,
|
|
123
|
+
new FixedName(name),
|
|
124
|
+
);
|
|
125
|
+
if (info.includeGlobalForbidden && this.topLevelNameInUse(name, true)) {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
for (const badName of info.names) {
|
|
129
|
+
if (badName instanceof Name) {
|
|
130
|
+
if (name == this.render.names.get(badName)) {
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
} else if (name == badName) {
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface RenderAccessible {
|
|
142
|
+
readonly typeGraph: TypeGraph;
|
|
143
|
+
descriptionForClassProperty(
|
|
144
|
+
o: ObjectType,
|
|
145
|
+
name: string,
|
|
146
|
+
): string[] | undefined;
|
|
147
|
+
descriptionForType(t: Type): string[] | undefined;
|
|
148
|
+
emitDescription(description: Sourcelike[] | undefined): void;
|
|
149
|
+
emitGatheredSource(items: Sourcelike[]): void;
|
|
150
|
+
emitLineOnce(...lineParts: Sourcelike[]): void;
|
|
151
|
+
emitSourceStructure(givenOutputFilename: string): void;
|
|
152
|
+
emitTable(tableArray: Sourcelike[][]): void;
|
|
153
|
+
finishFile(filename: string): void;
|
|
154
|
+
forbiddenForObjectProperties(
|
|
155
|
+
_o: ObjectType,
|
|
156
|
+
_className: Name,
|
|
157
|
+
): ForbiddenWordsInfo;
|
|
158
|
+
forbiddenNamesForGlobalNamespace(): readonly string[];
|
|
159
|
+
forEachClassProperty(
|
|
160
|
+
o: ObjectType,
|
|
161
|
+
blankLocations: BlankLineConfig,
|
|
162
|
+
f: (
|
|
163
|
+
name: Name,
|
|
164
|
+
jsonName: string,
|
|
165
|
+
p: ClassProperty,
|
|
166
|
+
position: ForEachPosition,
|
|
167
|
+
) => void,
|
|
168
|
+
): void;
|
|
169
|
+
forEachNamedType(
|
|
170
|
+
blankLocations: BlankLineConfig,
|
|
171
|
+
objectFunction:
|
|
172
|
+
| ((c: ClassType, className: Name, position: ForEachPosition) => void)
|
|
173
|
+
| ((o: ObjectType, objectName: Name, position: ForEachPosition) => void),
|
|
174
|
+
enumFunction: (
|
|
175
|
+
enm: EnumType,
|
|
176
|
+
enumName: Name,
|
|
177
|
+
position: ForEachPosition,
|
|
178
|
+
) => void,
|
|
179
|
+
unionFunction: (
|
|
180
|
+
u: UnionType,
|
|
181
|
+
unionName: Name,
|
|
182
|
+
position: ForEachPosition,
|
|
183
|
+
) => void,
|
|
184
|
+
): void;
|
|
185
|
+
forEachTopLevel(
|
|
186
|
+
blankLocations: BlankLineConfig,
|
|
187
|
+
f: (t: Type, name: Name, position: ForEachPosition) => void,
|
|
188
|
+
predicate?: (t: Type) => boolean,
|
|
189
|
+
): boolean;
|
|
190
|
+
forEachWithBlankLines<K, V>(
|
|
191
|
+
iterable: Iterable<[K, V]>,
|
|
192
|
+
blankLineConfig: BlankLineConfig,
|
|
193
|
+
emitter: (v: V, k: K, position: ForEachPosition) => void,
|
|
194
|
+
): boolean;
|
|
195
|
+
gatherSource(emitter: () => void): Sourcelike[];
|
|
196
|
+
makeNamedTypeNamer(): Namer;
|
|
197
|
+
makeNameForTopLevel(
|
|
198
|
+
_t: Type,
|
|
199
|
+
givenName: string,
|
|
200
|
+
_maybeNamedType: Type | undefined,
|
|
201
|
+
): Name;
|
|
202
|
+
nameForNamedType(t: Type): Name;
|
|
203
|
+
namerForObjectProperty(o: ObjectType, p: ClassProperty): Namer | null;
|
|
204
|
+
sourcelikeToString(source: Sourcelike): string;
|
|
205
|
+
}
|
package/src/utility.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import wordwrap from "wordwrap";
|
|
2
|
+
|
|
3
|
+
type AnyFunction = (...arguments_: any[]) => any;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A helper that proxies an instance and overrides selected methods.
|
|
7
|
+
* The overrides receive both the original method and its typed parameters.
|
|
8
|
+
*/
|
|
9
|
+
export function proxyWithOverrides<T extends object>(
|
|
10
|
+
instance: T,
|
|
11
|
+
overrides: {
|
|
12
|
+
[K in keyof T]?: T[K] extends AnyFunction
|
|
13
|
+
? (
|
|
14
|
+
this: T,
|
|
15
|
+
original: T[K],
|
|
16
|
+
...arguments_: Parameters<T[K]>
|
|
17
|
+
) => ReturnType<T[K]>
|
|
18
|
+
: never;
|
|
19
|
+
},
|
|
20
|
+
): T {
|
|
21
|
+
return new Proxy(instance, {
|
|
22
|
+
get(target, property, receiver) {
|
|
23
|
+
// @ts-expect-error index signature is fine for Proxy
|
|
24
|
+
const override = overrides[property];
|
|
25
|
+
if (typeof override === "function") {
|
|
26
|
+
const original = Reflect.get(target, property, receiver);
|
|
27
|
+
return function (this: T, ...arguments_: any[]) {
|
|
28
|
+
// Call the override, passing original and args
|
|
29
|
+
return override.call(
|
|
30
|
+
this,
|
|
31
|
+
(original as any).bind(this),
|
|
32
|
+
...arguments_,
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return Reflect.get(target, property, receiver);
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const wordWrap = wordwrap(90);
|
|
42
|
+
|
|
43
|
+
export function splitDescription(
|
|
44
|
+
string_: string | undefined,
|
|
45
|
+
): string[] | undefined {
|
|
46
|
+
if (!string_) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
return wordWrap(string_)
|
|
50
|
+
.split("\n")
|
|
51
|
+
.map((l) => l.trim());
|
|
52
|
+
}
|