skir-typescript-gen 0.0.1
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/README.md +370 -0
- package/dist/class_speller.d.ts +48 -0
- package/dist/class_speller.d.ts.map +1 -0
- package/dist/class_speller.js +84 -0
- package/dist/class_speller.js.map +1 -0
- package/dist/expression_maker.d.ts +14 -0
- package/dist/expression_maker.d.ts.map +1 -0
- package/dist/expression_maker.js +120 -0
- package/dist/expression_maker.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +685 -0
- package/dist/index.js.map +1 -0
- package/dist/record_info.d.ts +112 -0
- package/dist/record_info.d.ts.map +1 -0
- package/dist/record_info.js +359 -0
- package/dist/record_info.js.map +1 -0
- package/dist/ts_type.d.ts +43 -0
- package/dist/ts_type.d.ts.map +1 -0
- package/dist/ts_type.js +99 -0
- package/dist/ts_type.js.map +1 -0
- package/dist/type_speller.d.ts +31 -0
- package/dist/type_speller.d.ts.map +1 -0
- package/dist/type_speller.js +127 -0
- package/dist/type_speller.js.map +1 -0
- package/package.json +52 -0
- package/src/class_speller.ts +142 -0
- package/src/expression_maker.ts +129 -0
- package/src/index.ts +818 -0
- package/src/record_info.ts +540 -0
- package/src/ts_type.ts +105 -0
- package/src/type_speller.ts +151 -0
package/README.md
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
[](https://www.npmjs.com/package/skir-typescript-gen)
|
|
2
|
+
[](https://github.com/gepheum/skir-typescript-gen/actions)
|
|
3
|
+
|
|
4
|
+
# Skir's TypeScript code generator
|
|
5
|
+
|
|
6
|
+
Official plugin for generating TypeScript/JavaScript code from [.skir](https://github.com/gepheum/skir) files.
|
|
7
|
+
|
|
8
|
+
Generated code can run Node, Deno or in the browser.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
From your project's root directory, run `npm i --save-dev skir-typescript-gen`.
|
|
13
|
+
|
|
14
|
+
In your `skir.yml` file, add the following snippet under `generators`:
|
|
15
|
+
```yaml
|
|
16
|
+
- mod: skir-typescript-gen
|
|
17
|
+
config:
|
|
18
|
+
# Possible values: "" (CommonJS), ".js" (ES Modules), ".ts" (Deno)
|
|
19
|
+
importPathExtension: ""
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The `npm run skirc` command will now generate .js and .t.ts files within the `skirout` directory.
|
|
23
|
+
|
|
24
|
+
For more information, see this TypeScript project [example](https://github.com/gepheum/skir-typescript-example).
|
|
25
|
+
|
|
26
|
+
## TypeScript generated code guide
|
|
27
|
+
|
|
28
|
+
The examples below are for the code generated from [this](https://github.com/gepheum/skir-typescript-example/blob/main/skir_src/user.skir) .skir file.
|
|
29
|
+
|
|
30
|
+
### Referring to generated symbols
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { TARZAN, User, UserHistory, UserRegistry } from "../skirout/user";
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Struct classes
|
|
37
|
+
|
|
38
|
+
For every struct `S` in the .skir file, skir generates a frozen (deeply immutable) class `S` and a mutable class `S.Mutable`.
|
|
39
|
+
|
|
40
|
+
#### Frozen struct classes
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
// Construct a frozen User with User.create({...})
|
|
44
|
+
const john = User.create({
|
|
45
|
+
userId: 42,
|
|
46
|
+
name: "John Doe",
|
|
47
|
+
quote: "Coffee is just a socially acceptable form of rage.",
|
|
48
|
+
pets: [
|
|
49
|
+
{
|
|
50
|
+
name: "Dumbo",
|
|
51
|
+
heightInMeters: 1.0,
|
|
52
|
+
picture: "🐘",
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
subscriptionStatus: "FREE",
|
|
56
|
+
// foo: "bar",
|
|
57
|
+
// ^ Does not compile: 'foo' is not a field of User
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
assert(john.name === "John Doe");
|
|
61
|
+
|
|
62
|
+
// john.name = "John Smith";
|
|
63
|
+
// ^ Does not compile: all the properties are read-only
|
|
64
|
+
|
|
65
|
+
// With create<"partial">({...}), you don't need to specify all the fields of
|
|
66
|
+
// the struct.
|
|
67
|
+
const jane = User.create<"partial">({
|
|
68
|
+
userId: 43,
|
|
69
|
+
name: "Jane Doe",
|
|
70
|
+
pets: [{ name: "Fluffy" }, { name: "Fido" }],
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Missing fields are initialized to their default values.
|
|
74
|
+
assert(jane.quote === "");
|
|
75
|
+
|
|
76
|
+
const janeHistory = UserHistory.create({
|
|
77
|
+
user: jane,
|
|
78
|
+
// ^ the object you pass to create({...}) can contain struct values
|
|
79
|
+
sessions: [
|
|
80
|
+
{
|
|
81
|
+
login: Timestamp.fromUnixMillis(1234),
|
|
82
|
+
logout: Timestamp.fromUnixMillis(2345),
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const defaultUser = User.DEFAULT;
|
|
88
|
+
assert(defaultUser.name === "");
|
|
89
|
+
// User.DEFAULT is same as User.create<"partial">({});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### Mutable struct classes
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// User.Mutable is a mutable version of User.
|
|
96
|
+
const lylaMut = new User.Mutable();
|
|
97
|
+
lylaMut.userId = 44;
|
|
98
|
+
lylaMut.name = "Lyla Doe";
|
|
99
|
+
|
|
100
|
+
// The User.Mutable() constructor also accepts an initializer object.
|
|
101
|
+
const jolyMut = new User.Mutable({ userId: 45 });
|
|
102
|
+
jolyMut.name = "Joly Doe";
|
|
103
|
+
|
|
104
|
+
// jolyHistoryMut.user.quote = "I am Joly.";
|
|
105
|
+
// ^ Does not compile: quote is readonly because jolyHistoryMut.user might be
|
|
106
|
+
// a frozen struct
|
|
107
|
+
|
|
108
|
+
const jolyHistoryMut = new UserHistory.Mutable();
|
|
109
|
+
jolyHistoryMut.user = jolyMut;
|
|
110
|
+
// ^ The right-hand side of the assignment can be either frozen or mutable.
|
|
111
|
+
|
|
112
|
+
// The mutableUser() getter first checks if 'user' is already a mutable struct,
|
|
113
|
+
// and if so, returns it. Otherwise, it assigns to 'user' a mutable shallow copy
|
|
114
|
+
// of itself and returns it.
|
|
115
|
+
jolyHistoryMut.mutableUser.quote = "I am Joly.";
|
|
116
|
+
|
|
117
|
+
// Similarly, mutablePets() first checks if 'pets' is already a mutable array,
|
|
118
|
+
// and if so, returns it. Otherwise, it assigns to 'pets' a mutable shallow copy
|
|
119
|
+
// of itself and returns it.
|
|
120
|
+
lylaMut.mutablePets.push(User.Pet.create<"partial">({ name: "Cupcake" }));
|
|
121
|
+
lylaMut.mutablePets.push(new User.Pet.Mutable({ name: "Simba" }));
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### Converting between frozen and mutable
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
// toMutable() does a shallow copy of the frozen struct, so it's cheap. All the
|
|
128
|
+
// properties of the copy hold a frozen value.
|
|
129
|
+
const evilJaneMut = jane.toMutable();
|
|
130
|
+
evilJaneMut.name = "Evil Jane";
|
|
131
|
+
|
|
132
|
+
// toFrozen() recursively copies the mutable values held by properties of the
|
|
133
|
+
// object. It's cheap if all the values are frozen, like in this example.
|
|
134
|
+
const evilJane: User = evilJaneMut.toFrozen();
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
#### Writing logic agnostic of mutability
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// 'User.OrMutable' is a type alias for 'User | User.Mutable'.
|
|
141
|
+
function greet(user: User.OrMutable) {
|
|
142
|
+
console.log(`Hello, ${user.name}`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
greet(jane);
|
|
146
|
+
// Hello, Jane Doe
|
|
147
|
+
greet(lylaMut);
|
|
148
|
+
// Hello, Lyla Doe
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Enum classes
|
|
152
|
+
|
|
153
|
+
The definition of the `SubscriptionStatus` enum in the .skir file is:
|
|
154
|
+
```rust
|
|
155
|
+
enum SubscriptionStatus {
|
|
156
|
+
FREE;
|
|
157
|
+
trial: Trial;
|
|
158
|
+
PREMIUM;
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### Making enum values
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const johnStatus = User.SubscriptionStatus.FREE;
|
|
166
|
+
const janeStatus = User.SubscriptionStatus.PREMIUM;
|
|
167
|
+
const lylaStatus = User.SubscriptionStatus.create("PREMIUM");
|
|
168
|
+
// ^ same as User.SubscriptionStatus.PREMIUM
|
|
169
|
+
const jolyStatus = User.SubscriptionStatus.UNKNOWN;
|
|
170
|
+
|
|
171
|
+
// Use create({kind: ..., value: ...}) for data variants.
|
|
172
|
+
const roniStatus = User.SubscriptionStatus.create({
|
|
173
|
+
kind: "trial",
|
|
174
|
+
value: {
|
|
175
|
+
startTime: Timestamp.fromUnixMillis(1234),
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### Conditions on enums
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
// Use e.kind === "CONSTANT_NAME" to check if the enum value is a constant.
|
|
184
|
+
assert(johnStatus.kind === "FREE");
|
|
185
|
+
assert(johnStatus.value === undefined);
|
|
186
|
+
|
|
187
|
+
// Use "?" for UNKNOWN.
|
|
188
|
+
assert(jolyStatus.kind === "?");
|
|
189
|
+
|
|
190
|
+
assert(roniStatus.kind === "trial");
|
|
191
|
+
assert(roniStatus.value!.startTime.unixMillis === 1234);
|
|
192
|
+
|
|
193
|
+
function getSubscriptionInfoText(status: User.SubscriptionStatus): string {
|
|
194
|
+
// Use the 'union' getter for typesafe switches on enums.
|
|
195
|
+
switch (status.union.kind) {
|
|
196
|
+
case "?":
|
|
197
|
+
return "Unknown subscription status";
|
|
198
|
+
case "FREE":
|
|
199
|
+
return "Free user";
|
|
200
|
+
case "PREMIUM":
|
|
201
|
+
return "Premium user";
|
|
202
|
+
case "trial":
|
|
203
|
+
// Here the compiler knows that the type of union.value is 'User.Trial'.
|
|
204
|
+
return "On trial since " + status.union.value.startTime;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Serialization
|
|
210
|
+
|
|
211
|
+
Every frozen struct class and enum class has a static readonly `serializer` property which can be used for serializing and deserializing instances of the class.
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
|
|
215
|
+
const serializer = User.serializer;
|
|
216
|
+
|
|
217
|
+
// Serialize 'john' to dense JSON.
|
|
218
|
+
console.log(serializer.toJsonCode(john));
|
|
219
|
+
// [42,"John Doe"]
|
|
220
|
+
|
|
221
|
+
// Serialize 'john' to readable JSON.
|
|
222
|
+
console.log(serializer.toJsonCode(john, "readable"));
|
|
223
|
+
// {
|
|
224
|
+
// "user_id": 42,
|
|
225
|
+
// "name": "John Doe"
|
|
226
|
+
// }
|
|
227
|
+
|
|
228
|
+
// The dense JSON flavor is the flavor you should pick if you intend to
|
|
229
|
+
// deserialize the value in the future. Skir allows fields to be renamed, and
|
|
230
|
+
// because fields names are not part of the dense JSON, renaming a field does
|
|
231
|
+
// not prevent you from deserializing the value.
|
|
232
|
+
// You should pick the readable flavor mostly for debugging purposes.
|
|
233
|
+
|
|
234
|
+
// Serialize 'john' to binary format.
|
|
235
|
+
console.log(serializer.toBytes(john));
|
|
236
|
+
|
|
237
|
+
// The binary format is not human readable, but it is slightly more compact than
|
|
238
|
+
// JSON, and serialization/deserialization can be a bit faster in languages like
|
|
239
|
+
// C++. Only use it when this small performance gain is likely to matter, which
|
|
240
|
+
// should be rare.
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Deserialization
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
// Use fromJson(), fromJsonCode() and fromBytes() to deserialize.
|
|
247
|
+
|
|
248
|
+
const reserializedJohn = serializer.fromJsonCode(serializer.toJsonCode(john));
|
|
249
|
+
assert(reserializedJohn.name === "John Doe");
|
|
250
|
+
|
|
251
|
+
const reserializedJane = serializer.fromJsonCode(
|
|
252
|
+
serializer.toJsonCode(jane, "readable"),
|
|
253
|
+
);
|
|
254
|
+
assert(reserializedJane.name === "Jane Doe");
|
|
255
|
+
|
|
256
|
+
const reserializedLyla = serializer.fromBytes(
|
|
257
|
+
serializer.toBytes(lylaMut).toBuffer(),
|
|
258
|
+
);
|
|
259
|
+
assert(reserializedLyla.name === "Lyla Doe");
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Frozen arrays and copies
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
const pets = [
|
|
266
|
+
User.Pet.create<"partial">({ name: "Fluffy" }),
|
|
267
|
+
User.Pet.create<"partial">({ name: "Fido" }),
|
|
268
|
+
];
|
|
269
|
+
|
|
270
|
+
const jade = User.create<"partial">({
|
|
271
|
+
pets: pets,
|
|
272
|
+
// ^ makes a copy of 'pets' because 'pets' is mutable
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// jade.pets.push(...)
|
|
276
|
+
// ^ Compile-time error: pets is readonly
|
|
277
|
+
|
|
278
|
+
assert(jade.pets !== pets);
|
|
279
|
+
|
|
280
|
+
const jack = User.create<"partial">({
|
|
281
|
+
pets: jade.pets,
|
|
282
|
+
// ^ doesn't make a copy because 'jade.pets' is frozen
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
assert(jack.pets === jade.pets);
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Keyed arrays
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
const userRegistry = UserRegistry.create({
|
|
292
|
+
users: [john, jane, lylaMut],
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
// searchUsers() returns the user with the given key (specified in the .skir
|
|
296
|
+
// file). In this example, the key is the user id.
|
|
297
|
+
// The first lookup runs in O(N) time, and the following lookups run in O(1)
|
|
298
|
+
// time.
|
|
299
|
+
assert(userRegistry.searchUsers(42) === john);
|
|
300
|
+
assert(userRegistry.searchUsers(100) === undefined);
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Constants
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
console.log(TARZAN);
|
|
307
|
+
// User {
|
|
308
|
+
// userId: 123,
|
|
309
|
+
// name: 'Tarzan',
|
|
310
|
+
// quote: 'AAAAaAaAaAyAAAAaAaAaAyAAAAaAaAaA',
|
|
311
|
+
// pets: [ User_Pet { name: 'Cheeta', heightInMeters: 1.67, picture: '🐒' } ],
|
|
312
|
+
// subscriptionStatus: User_SubscriptionStatus {
|
|
313
|
+
// kind: 'trial',
|
|
314
|
+
// value: User_Trial { startTime: [Timestamp] }
|
|
315
|
+
// }
|
|
316
|
+
// }
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Skir services
|
|
320
|
+
|
|
321
|
+
#### Starting a skir service on an HTTP server
|
|
322
|
+
|
|
323
|
+
Full example [here](https://github.com/gepheum/skir-typescript-example/blob/main/src/server.ts).
|
|
324
|
+
|
|
325
|
+
#### Sending RPCs to a skir service
|
|
326
|
+
|
|
327
|
+
Full example [here](https://github.com/gepheum/skir-typescript-example/blob/main/src/client.ts).
|
|
328
|
+
|
|
329
|
+
### Reflection
|
|
330
|
+
|
|
331
|
+
Reflection allows you to inspect a skir type at runtime.
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
const fieldNames: string[] = [];
|
|
335
|
+
for (const field of User.serializer.typeDescriptor.fields) {
|
|
336
|
+
const { name, number, property, type } = field;
|
|
337
|
+
fieldNames.push(name);
|
|
338
|
+
}
|
|
339
|
+
console.log(fieldNames);
|
|
340
|
+
// [ 'user_id', 'name', 'quote', 'pets', 'subscription_status' ]
|
|
341
|
+
|
|
342
|
+
// A type descriptor can be serialized to JSON and deserialized later.
|
|
343
|
+
const typeDescriptor = parseTypeDescriptorFromJson(
|
|
344
|
+
User.serializer.typeDescriptor.asJson(),
|
|
345
|
+
);
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Writing unit tests
|
|
349
|
+
|
|
350
|
+
With mocha and [buckwheat](https://github.com/gepheum/buckwheat).
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
expect(tarzan).toMatch({
|
|
354
|
+
name: "Tarzan",
|
|
355
|
+
quote: /^A/, // must start with the letter A
|
|
356
|
+
pets: [
|
|
357
|
+
{
|
|
358
|
+
name: "Cheeta",
|
|
359
|
+
heightInMeters: near(1.6, 0.1),
|
|
360
|
+
},
|
|
361
|
+
],
|
|
362
|
+
subscriptionStatus: {
|
|
363
|
+
kind: "trial",
|
|
364
|
+
value: {
|
|
365
|
+
startTime: Timestamp.fromUnixMillis(1234),
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
// `userId` is not specified so it can be anything
|
|
369
|
+
});
|
|
370
|
+
```
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Module, RecordLocation } from "skir-internal";
|
|
2
|
+
export interface ClassName {
|
|
3
|
+
/**
|
|
4
|
+
* Name of the TypeScript class, e.g. "Bar". It is obtained by taking the
|
|
5
|
+
* record name, as specified in the '.skir' file, and appending one or
|
|
6
|
+
* multiple underscores if there is a conflict with another name.
|
|
7
|
+
* If the class is nested, the `name` does not include the name of the parent
|
|
8
|
+
* classes.
|
|
9
|
+
*/
|
|
10
|
+
readonly name: string;
|
|
11
|
+
/**
|
|
12
|
+
* Qualified type name, e.g. "Foo.Bar".
|
|
13
|
+
* This is what you want to use in type declarations.
|
|
14
|
+
*/
|
|
15
|
+
readonly type: string;
|
|
16
|
+
/**
|
|
17
|
+
* Class expression, e.g. "Foo_Bar" if the class is defined in the same
|
|
18
|
+
* module, or "x_other_module.Foo.Bar" if it is defined in a different module.
|
|
19
|
+
* This is what you want to use in the TypeScript code that gets transpiled to
|
|
20
|
+
* Javascript.
|
|
21
|
+
*/
|
|
22
|
+
readonly value: string;
|
|
23
|
+
/**
|
|
24
|
+
* Expression referring to the parent class if this class is nested, undefined
|
|
25
|
+
* otherwise.
|
|
26
|
+
*/
|
|
27
|
+
parentClassValue: string | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Name of the record, as specified in the '.skir' file. This can be different
|
|
30
|
+
* from `name` if for example the record name conflicts with a built-in class.
|
|
31
|
+
* If the record is nested, the `recordName` does not include the name of the
|
|
32
|
+
* parent records.
|
|
33
|
+
*/
|
|
34
|
+
readonly recordName: string;
|
|
35
|
+
/**
|
|
36
|
+
* Dot-separated record names, where the first record is a record defined at
|
|
37
|
+
* the top-level, the last record is this record, and every record in the
|
|
38
|
+
* chain is nested within the previous record.
|
|
39
|
+
*/
|
|
40
|
+
readonly recordQualifiedName: string;
|
|
41
|
+
readonly recordType: "struct" | "enum";
|
|
42
|
+
/** True if the class is nested within another class. */
|
|
43
|
+
readonly isNested: boolean;
|
|
44
|
+
}
|
|
45
|
+
/** Returns the name of the frozen TypeScript class for the given record. */
|
|
46
|
+
export declare function getClassName(record: RecordLocation, origin: Module): ClassName;
|
|
47
|
+
export declare function maybeEscapeTopLevelUpperCaseName(name: string): string;
|
|
48
|
+
//# sourceMappingURL=class_speller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"class_speller.d.ts","sourceRoot":"","sources":["../src/class_speller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE5D,MAAM,WAAW,SAAS;IACxB;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IAErC,QAAQ,CAAC,UAAU,EAAE,QAAQ,GAAG,MAAM,CAAC;IACvC,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAC1B,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,MAAM,GACb,SAAS,CA6DX;AAED,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErE"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/** Returns the name of the frozen TypeScript class for the given record. */
|
|
2
|
+
export function getClassName(record, origin) {
|
|
3
|
+
const recordType = record.record.recordType;
|
|
4
|
+
const { recordAncestors } = record;
|
|
5
|
+
const isNested = recordAncestors.length >= 2;
|
|
6
|
+
const seenNames = new Set();
|
|
7
|
+
const parts = [];
|
|
8
|
+
for (let i = 0; i < recordAncestors.length; ++i) {
|
|
9
|
+
const reservedNames = i === 0
|
|
10
|
+
? BUILTIN_TYPE_NAMES
|
|
11
|
+
: recordAncestors[i - 1].recordType === "struct"
|
|
12
|
+
? STRUCT_NESTED_TYPE_NAMES
|
|
13
|
+
: ENUM_NESTED_TYPE_NAMES;
|
|
14
|
+
const record = recordAncestors[i];
|
|
15
|
+
let name = record.name.text;
|
|
16
|
+
while (seenNames.has(name) || reservedNames.has(name)) {
|
|
17
|
+
name += "_";
|
|
18
|
+
}
|
|
19
|
+
parts.push(name);
|
|
20
|
+
seenNames.add(name);
|
|
21
|
+
}
|
|
22
|
+
const name = parts.at(-1);
|
|
23
|
+
const recordName = record.record.name.text;
|
|
24
|
+
const recordQualifiedName = recordAncestors.map((r) => r.name.text).join(".");
|
|
25
|
+
let type;
|
|
26
|
+
let value;
|
|
27
|
+
let parentClassValue;
|
|
28
|
+
if (record.modulePath !== origin.path) {
|
|
29
|
+
// The record is located in an imported module.
|
|
30
|
+
const path = record.modulePath;
|
|
31
|
+
const importedNames = origin.pathToImportedNames[path];
|
|
32
|
+
if (importedNames.kind === "all") {
|
|
33
|
+
const alias = importedNames.alias;
|
|
34
|
+
type = [`x_${alias}`].concat(parts).join(".");
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
type = `${parts.join(".")}`;
|
|
38
|
+
}
|
|
39
|
+
value = type;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
type = parts.join(".");
|
|
43
|
+
value = parts.join("_");
|
|
44
|
+
if (isNested) {
|
|
45
|
+
parentClassValue = parts.slice(0, -1).join("_");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
name: name,
|
|
50
|
+
type: type,
|
|
51
|
+
value: value,
|
|
52
|
+
parentClassValue: parentClassValue,
|
|
53
|
+
recordName: recordName,
|
|
54
|
+
recordQualifiedName: recordQualifiedName,
|
|
55
|
+
recordType: recordType,
|
|
56
|
+
isNested: isNested,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export function maybeEscapeTopLevelUpperCaseName(name) {
|
|
60
|
+
return BUILTIN_TYPE_NAMES.has(name) ? `${name}_` : name;
|
|
61
|
+
}
|
|
62
|
+
const BUILTIN_TYPE_NAMES = new Set([
|
|
63
|
+
// Subset of the standard built-in Typescript types and Javascript class names
|
|
64
|
+
// used in the generated code, either in the ".d.ts" file or the ".js" file.
|
|
65
|
+
// We can't use those as names for generated declarations at the top-level.
|
|
66
|
+
"Array",
|
|
67
|
+
"BigInt",
|
|
68
|
+
"Partial",
|
|
69
|
+
"ReadonlyArray",
|
|
70
|
+
]);
|
|
71
|
+
/** Generated types nested within a struct namespace. */
|
|
72
|
+
const STRUCT_NESTED_TYPE_NAMES = new Set([
|
|
73
|
+
"Initializer",
|
|
74
|
+
"Mutable",
|
|
75
|
+
"OrMutable",
|
|
76
|
+
]);
|
|
77
|
+
/** Generated types nested within an enum namespace. */
|
|
78
|
+
const ENUM_NESTED_TYPE_NAMES = new Set([
|
|
79
|
+
"Initializer",
|
|
80
|
+
"Kind",
|
|
81
|
+
"Value",
|
|
82
|
+
"UnionView",
|
|
83
|
+
]);
|
|
84
|
+
//# sourceMappingURL=class_speller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"class_speller.js","sourceRoot":"","sources":["../src/class_speller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Returns a TypeScript expression transforming a value from a
|
|
3
|
+
* `initializer` type into a `frozen` type.
|
|
4
|
+
*/
|
|
5
|
+
import type { ResolvedType } from "skir-internal";
|
|
6
|
+
import { TypeSpeller } from "./type_speller.js";
|
|
7
|
+
export interface ToFrozenExpressionArg {
|
|
8
|
+
type: ResolvedType;
|
|
9
|
+
inExpr: string;
|
|
10
|
+
maybeUndefined: boolean;
|
|
11
|
+
typeSpeller: TypeSpeller;
|
|
12
|
+
}
|
|
13
|
+
export declare function toFrozenExpression(arg: ToFrozenExpressionArg): string;
|
|
14
|
+
//# sourceMappingURL=expression_maker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression_maker.d.ts","sourceRoot":"","sources":["../src/expression_maker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,YAAY,CAAC;IAEnB,MAAM,EAAE,MAAM,CAAC;IAEf,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,qBAAqB,GAAG,MAAM,CA2FrE"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
export function toFrozenExpression(arg) {
|
|
2
|
+
const { type, inExpr, maybeUndefined, typeSpeller } = arg;
|
|
3
|
+
if (type.kind === "record") {
|
|
4
|
+
const frozenClass = typeSpeller.getClassName(type.key);
|
|
5
|
+
const defaultExpr = type.recordType === "struct"
|
|
6
|
+
? `${frozenClass.value}.DEFAULT`
|
|
7
|
+
: `${frozenClass.value}.UNKNOWN`;
|
|
8
|
+
const inExprOrDefault = maybeUndefined
|
|
9
|
+
? `${inExpr} ?? ${defaultExpr}`
|
|
10
|
+
: inExpr;
|
|
11
|
+
return `${frozenClass.value}.create(${inExprOrDefault})`;
|
|
12
|
+
}
|
|
13
|
+
else if (type.kind === "array") {
|
|
14
|
+
const transformItemExpr = toFrozenExpression({
|
|
15
|
+
type: type.item,
|
|
16
|
+
inExpr: "e",
|
|
17
|
+
maybeUndefined: false,
|
|
18
|
+
typeSpeller: typeSpeller,
|
|
19
|
+
});
|
|
20
|
+
const inExprOrEmpty = maybeUndefined ? `${inExpr} || []` : inExpr;
|
|
21
|
+
if (transformItemExpr === "e") {
|
|
22
|
+
return `$._toFrozenArray(\n${inExprOrEmpty})`;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
let mapFnExpr;
|
|
26
|
+
if (type.item.kind === "record") {
|
|
27
|
+
// Instead of creating a lambda, we can just get the `create` static
|
|
28
|
+
// function.
|
|
29
|
+
const frozenClass = typeSpeller.getClassName(type.item.key);
|
|
30
|
+
mapFnExpr = `${frozenClass.value}.create`;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
mapFnExpr = `(e) => ${transformItemExpr}`;
|
|
34
|
+
}
|
|
35
|
+
const funName = "$._toFrozenArray";
|
|
36
|
+
return `${funName}(\n${inExprOrEmpty},\n${mapFnExpr},\n)`;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else if (type.kind === "optional") {
|
|
40
|
+
const otherType = type.other;
|
|
41
|
+
const otherExpr = toFrozenExpression({
|
|
42
|
+
type: otherType,
|
|
43
|
+
inExpr: inExpr,
|
|
44
|
+
maybeUndefined: false,
|
|
45
|
+
typeSpeller: typeSpeller,
|
|
46
|
+
});
|
|
47
|
+
if (otherExpr === inExpr) {
|
|
48
|
+
return maybeUndefined ? `${inExpr} ?? null` : inExpr;
|
|
49
|
+
}
|
|
50
|
+
// The condition for returning otherExpr.
|
|
51
|
+
let condition;
|
|
52
|
+
if (canBeFalsy(otherType)) {
|
|
53
|
+
if (maybeUndefined) {
|
|
54
|
+
// This is one way to test that inExpr is not null or undefined.
|
|
55
|
+
// Works because if inExpr was === 0, then we would have already
|
|
56
|
+
// returned.
|
|
57
|
+
condition = `((${inExpr} ?? 0) !== 0)`;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
condition = `${inExpr} !== null`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// Just rely on implicit boolean conversion.
|
|
65
|
+
// Also works if maybeUndefined is true.
|
|
66
|
+
condition = inExpr;
|
|
67
|
+
}
|
|
68
|
+
return `${condition} ? ${otherExpr} : null`;
|
|
69
|
+
}
|
|
70
|
+
// A primitive type.
|
|
71
|
+
if (!maybeUndefined) {
|
|
72
|
+
return inExpr;
|
|
73
|
+
}
|
|
74
|
+
const { primitive } = type;
|
|
75
|
+
let defaultValue;
|
|
76
|
+
if (primitive === "bool") {
|
|
77
|
+
defaultValue = "false";
|
|
78
|
+
}
|
|
79
|
+
else if (primitive === "int32" ||
|
|
80
|
+
primitive === "float32" ||
|
|
81
|
+
primitive === "float64") {
|
|
82
|
+
defaultValue = "0";
|
|
83
|
+
}
|
|
84
|
+
else if (primitive === "int64" || primitive === "uint64") {
|
|
85
|
+
defaultValue = "BigInt(0)";
|
|
86
|
+
}
|
|
87
|
+
else if (primitive === "timestamp") {
|
|
88
|
+
defaultValue = "$.Timestamp.UNIX_EPOCH";
|
|
89
|
+
}
|
|
90
|
+
else if (primitive === "string") {
|
|
91
|
+
defaultValue = '""';
|
|
92
|
+
}
|
|
93
|
+
else if (primitive === "bytes") {
|
|
94
|
+
defaultValue = "$.ByteString.EMPTY";
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const _ = primitive;
|
|
98
|
+
throw TypeError();
|
|
99
|
+
}
|
|
100
|
+
return `${inExpr} ?? ${defaultValue}`;
|
|
101
|
+
}
|
|
102
|
+
// Returns true if values of the given type can ever be falsy.
|
|
103
|
+
// See https://developer.mozilla.org/en-US/docs/Glossary/Falsy
|
|
104
|
+
function canBeFalsy(type) {
|
|
105
|
+
if (type.kind === "optional") {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
if (type.kind !== "primitive") {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
const { primitive } = type;
|
|
112
|
+
return (primitive === "bool" ||
|
|
113
|
+
primitive === "int32" ||
|
|
114
|
+
primitive === "int64" ||
|
|
115
|
+
primitive === "uint64" ||
|
|
116
|
+
primitive === "float32" ||
|
|
117
|
+
primitive === "float64" ||
|
|
118
|
+
primitive === "string");
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=expression_maker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression_maker.js","sourceRoot":"","sources":["../src/expression_maker.ts"],"names":[],"mappings":"AAgBA,MAAM,UAAU,kBAAkB,CAAC,GAA0B;IAC3D,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC;IAC1D,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvD,MAAM,WAAW,GACf,IAAI,CAAC,UAAU,KAAK,QAAQ;YAC1B,CAAC,CAAC,GAAG,WAAW,CAAC,KAAK,UAAU;YAChC,CAAC,CAAC,GAAG,WAAW,CAAC,KAAK,UAAU,CAAC;QACrC,MAAM,eAAe,GAAG,cAAc;YACpC,CAAC,CAAC,GAAG,MAAM,OAAO,WAAW,EAAE;YAC/B,CAAC,CAAC,MAAM,CAAC;QACX,OAAO,GAAG,WAAW,CAAC,KAAK,WAAW,eAAe,GAAG,CAAC;IAC3D,CAAC;SAAM,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;YAC3C,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,GAAG;YACX,cAAc,EAAE,KAAK;YACrB,WAAW,EAAE,WAAW;SACzB,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,MAAM,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;QAClE,IAAI,iBAAiB,KAAK,GAAG,EAAE,CAAC;YAC9B,OAAO,sBAAsB,aAAa,GAAG,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,IAAI,SAAiB,CAAC;YACtB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAChC,oEAAoE;gBACpE,YAAY;gBACZ,MAAM,WAAW,GAAG,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC5D,SAAS,GAAG,GAAG,WAAW,CAAC,KAAK,SAAS,CAAC;YAC5C,CAAC;iBAAM,CAAC;gBACN,SAAS,GAAG,UAAU,iBAAiB,EAAE,CAAC;YAC5C,CAAC;YACD,MAAM,OAAO,GAAG,kBAAkB,CAAC;YACnC,OAAO,GAAG,OAAO,MAAM,aAAa,MAAM,SAAS,MAAM,CAAC;QAC5D,CAAC;IACH,CAAC;SAAM,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QACpC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC;QAC7B,MAAM,SAAS,GAAG,kBAAkB,CAAC;YACnC,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,MAAM;YACd,cAAc,EAAE,KAAK;YACrB,WAAW,EAAE,WAAW;SACzB,CAAC,CAAC;QACH,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;YACzB,OAAO,cAAc,CAAC,CAAC,CAAC,GAAG,MAAM,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC;QACvD,CAAC;QACD,yCAAyC;QACzC,IAAI,SAAiB,CAAC;QACtB,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1B,IAAI,cAAc,EAAE,CAAC;gBACnB,gEAAgE;gBAChE,gEAAgE;gBAChE,YAAY;gBACZ,SAAS,GAAG,KAAK,MAAM,eAAe,CAAC;YACzC,CAAC;iBAAM,CAAC;gBACN,SAAS,GAAG,GAAG,MAAM,WAAW,CAAC;YACnC,CAAC;QACH,CAAC;aAAM,CAAC;YACN,4CAA4C;YAC5C,wCAAwC;YACxC,SAAS,GAAG,MAAM,CAAC;QACrB,CAAC;QACD,OAAO,GAAG,SAAS,MAAM,SAAS,SAAS,CAAC;IAC9C,CAAC;IACD,oBAAoB;IACpB,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAC3B,IAAI,YAAoB,CAAC;IACzB,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACzB,YAAY,GAAG,OAAO,CAAC;IACzB,CAAC;SAAM,IACL,SAAS,KAAK,OAAO;QACrB,SAAS,KAAK,SAAS;QACvB,SAAS,KAAK,SAAS,EACvB,CAAC;QACD,YAAY,GAAG,GAAG,CAAC;IACrB,CAAC;SAAM,IAAI,SAAS,KAAK,OAAO,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QAC3D,YAAY,GAAG,WAAW,CAAC;IAC7B,CAAC;SAAM,IAAI,SAAS,KAAK,WAAW,EAAE,CAAC;QACrC,YAAY,GAAG,wBAAwB,CAAC;IAC1C,CAAC;SAAM,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QAClC,YAAY,GAAG,IAAI,CAAC;IACtB,CAAC;SAAM,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;QACjC,YAAY,GAAG,oBAAoB,CAAC;IACtC,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,GAAU,SAAS,CAAC;QAC3B,MAAM,SAAS,EAAE,CAAC;IACpB,CAAC;IACD,OAAO,GAAG,MAAM,OAAO,YAAY,EAAE,CAAC;AACxC,CAAC;AAED,8DAA8D;AAC9D,8DAA8D;AAC9D,SAAS,UAAU,CAAC,IAAkB;IACpC,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAC3B,OAAO,CACL,SAAS,KAAK,MAAM;QACpB,SAAS,KAAK,OAAO;QACrB,SAAS,KAAK,OAAO;QACrB,SAAS,KAAK,QAAQ;QACtB,SAAS,KAAK,SAAS;QACvB,SAAS,KAAK,SAAS;QACvB,SAAS,KAAK,QAAQ,CACvB,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CodeGenerator } from "skir-internal";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
declare const Config: z.ZodObject<{
|
|
4
|
+
importPathExtension: z.ZodUnion<readonly [z.ZodLiteral<"">, z.ZodLiteral<".js">, z.ZodLiteral<".ts">]>;
|
|
5
|
+
clientModulePath: z.ZodOptional<z.ZodString>;
|
|
6
|
+
}, z.core.$strip>;
|
|
7
|
+
type Config = z.infer<typeof Config>;
|
|
8
|
+
declare class TypescriptCodeGenerator implements CodeGenerator<Config> {
|
|
9
|
+
readonly id = "typescript";
|
|
10
|
+
readonly configType: z.ZodObject<{
|
|
11
|
+
importPathExtension: z.ZodUnion<readonly [z.ZodLiteral<"">, z.ZodLiteral<".js">, z.ZodLiteral<".ts">]>;
|
|
12
|
+
clientModulePath: z.ZodOptional<z.ZodString>;
|
|
13
|
+
}, z.core.$strip>;
|
|
14
|
+
readonly version = "1.0.0";
|
|
15
|
+
generateCode(input: CodeGenerator.Input<Config>): CodeGenerator.Output;
|
|
16
|
+
}
|
|
17
|
+
export declare const GENERATOR: TypescriptCodeGenerator;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EAOd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAYxB,QAAA,MAAM,MAAM;;;iBAOV,CAAC;AAEH,KAAK,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAErC,cAAM,uBAAwB,YAAW,aAAa,CAAC,MAAM,CAAC;IAC5D,QAAQ,CAAC,EAAE,gBAAgB;IAC3B,QAAQ,CAAC,UAAU;;;sBAAU;IAC7B,QAAQ,CAAC,OAAO,WAAW;IAE3B,YAAY,CAAC,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,aAAa,CAAC,MAAM;CAyBvE;AAkvBD,eAAO,MAAM,SAAS,yBAAgC,CAAC"}
|