@atscript/typescript 0.1.29 → 0.1.30

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/cli.cjs CHANGED
@@ -344,12 +344,62 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
344
344
  const exported = node.token("export")?.text === "export";
345
345
  this.renderJsDoc(node);
346
346
  this.write(exported ? "export declare " : "declare ");
347
- this.write(`class ${node.id} `);
348
- const struct = node.getDefinition();
349
- if (struct?.entity === "structure") this.renderStructure(struct, node.id);
347
+ if (node.hasExtends) {
348
+ const firstParent = node.extendsTokens[0].text;
349
+ this.write(`class ${node.id} extends ${firstParent} `);
350
+ const resolved = this.doc.resolveInterfaceExtends(node);
351
+ if (resolved?.entity === "structure") {
352
+ const firstParentUnwound = this.doc.unwindType(firstParent);
353
+ let firstParentProps;
354
+ if (firstParentUnwound?.def) {
355
+ let fpDef = firstParentUnwound.def;
356
+ if ((0, __atscript_core.isInterface)(fpDef)) {
357
+ if (fpDef.hasExtends) {
358
+ const fpResolved = firstParentUnwound.doc.resolveInterfaceExtends(fpDef);
359
+ if (fpResolved && (0, __atscript_core.isStructure)(fpResolved)) firstParentProps = fpResolved.props;
360
+ }
361
+ if (!firstParentProps) fpDef = fpDef.getDefinition() || fpDef;
362
+ }
363
+ if (!firstParentProps && (0, __atscript_core.isStructure)(fpDef)) firstParentProps = fpDef.props;
364
+ }
365
+ this.renderStructureFiltered(resolved, node.id, firstParentProps);
366
+ } else this.writeln("{}");
367
+ } else {
368
+ this.write(`class ${node.id} `);
369
+ const struct = node.getDefinition();
370
+ if (struct?.entity === "structure") this.renderStructure(struct, node.id);
350
371
  else this.writeln("{}");
372
+ }
351
373
  this.writeln();
352
374
  }
375
+ /**
376
+ * Renders a structure block, optionally filtering out props that exist in a parent.
377
+ */ renderStructureFiltered(struct, asClass, filterProps) {
378
+ if (!filterProps) return this.renderStructure(struct, asClass);
379
+ this.blockln("{}");
380
+ for (const prop of Array.from(struct.props.values())) {
381
+ if (filterProps.has(prop.id)) continue;
382
+ if (prop.token("identifier")?.pattern) continue;
383
+ const phantomType = this.phantomPropType(prop.getDefinition());
384
+ if (phantomType) {
385
+ this.writeln(`// ${prop.id}: ${phantomType}`);
386
+ continue;
387
+ }
388
+ const optional = !!prop.token("optional");
389
+ this.write(wrapProp(prop.id), optional ? "?" : "", ": ");
390
+ const renderedDef = this.renderTypeDefString(prop.getDefinition());
391
+ renderedDef.split("\n").forEach((l) => this.writeln(l));
392
+ }
393
+ this.writeln("static __is_atscript_annotated_type: true");
394
+ this.writeln(`static type: TAtscriptTypeObject<keyof ${asClass}, ${asClass}>`);
395
+ this.writeln(`static metadata: TMetadataMap<AtscriptMetadata>`);
396
+ this.writeln(`static validator: (opts?: Partial<TValidatorOptions>) => Validator<typeof ${asClass}>`);
397
+ if (resolveJsonSchemaMode(this.opts) === false) this.writeln("/** @deprecated JSON Schema support is disabled. Calling this method will throw a runtime error. To enable, set `jsonSchema: 'lazy'` or `jsonSchema: 'bundle'` in tsPlugin options, or add `@emit.jsonSchema` annotation to individual interfaces. */");
398
+ this.writeln("static toJsonSchema: () => any");
399
+ if (!this.opts?.exampleData) this.writeln("/** @deprecated Example Data support is disabled. To enable, set `exampleData: true` in tsPlugin options. */");
400
+ this.writeln("static toExampleData?: () => any");
401
+ this.pop();
402
+ }
353
403
  renderType(node) {
354
404
  this.writeln();
355
405
  const exported = node.token("export")?.text === "export";
@@ -1214,7 +1264,11 @@ else {
1214
1264
  const unwound = this.doc.unwindType(annotateNode.targetName);
1215
1265
  if (unwound?.def) {
1216
1266
  let def = this.doc.mergeIntersection(unwound.def);
1217
- if ((0, __atscript_core.isInterface)(def)) def = def.getDefinition() || def;
1267
+ if ((0, __atscript_core.isInterface)(def)) if (def.hasExtends) {
1268
+ const resolved = unwound.doc.resolveInterfaceExtends(def);
1269
+ if (resolved) def = resolved;
1270
+ else def = def.getDefinition() || def;
1271
+ } else def = def.getDefinition() || def;
1218
1272
  this._adHocAnnotations = this.buildAdHocMap([annotateNode]);
1219
1273
  this.annotateType(def, node.id);
1220
1274
  this._adHocAnnotations = null;
@@ -1225,7 +1279,12 @@ else {
1225
1279
  }
1226
1280
  }
1227
1281
  } else {
1228
- this.annotateType(node.getDefinition(), node.id);
1282
+ let def = node.getDefinition();
1283
+ if ((0, __atscript_core.isInterface)(node) && node.hasExtends) {
1284
+ const resolved = this.doc.resolveInterfaceExtends(node);
1285
+ if (resolved) def = resolved;
1286
+ }
1287
+ this.annotateType(def, node.id);
1229
1288
  this.indent().defineMetadata(node).unindent();
1230
1289
  this.writeln();
1231
1290
  }
@@ -1314,7 +1373,11 @@ else {
1314
1373
  switch (node.entity) {
1315
1374
  case "interface":
1316
1375
  case "type": {
1317
- const def = node.getDefinition();
1376
+ let def = node.getDefinition();
1377
+ if ((0, __atscript_core.isInterface)(node) && node.hasExtends) {
1378
+ const resolved = this.doc.resolveInterfaceExtends(node);
1379
+ if (resolved) def = resolved;
1380
+ }
1318
1381
  const handle = this.toAnnotatedHandle(def, true);
1319
1382
  const typeId = this.typeIds.get(node) ?? (node.__typeId !== null && node.__typeId !== undefined ? node.id : undefined);
1320
1383
  if (typeId) handle.id(typeId);
package/dist/index.cjs CHANGED
@@ -342,12 +342,62 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
342
342
  const exported = node.token("export")?.text === "export";
343
343
  this.renderJsDoc(node);
344
344
  this.write(exported ? "export declare " : "declare ");
345
- this.write(`class ${node.id} `);
346
- const struct = node.getDefinition();
347
- if (struct?.entity === "structure") this.renderStructure(struct, node.id);
345
+ if (node.hasExtends) {
346
+ const firstParent = node.extendsTokens[0].text;
347
+ this.write(`class ${node.id} extends ${firstParent} `);
348
+ const resolved = this.doc.resolveInterfaceExtends(node);
349
+ if (resolved?.entity === "structure") {
350
+ const firstParentUnwound = this.doc.unwindType(firstParent);
351
+ let firstParentProps;
352
+ if (firstParentUnwound?.def) {
353
+ let fpDef = firstParentUnwound.def;
354
+ if ((0, __atscript_core.isInterface)(fpDef)) {
355
+ if (fpDef.hasExtends) {
356
+ const fpResolved = firstParentUnwound.doc.resolveInterfaceExtends(fpDef);
357
+ if (fpResolved && (0, __atscript_core.isStructure)(fpResolved)) firstParentProps = fpResolved.props;
358
+ }
359
+ if (!firstParentProps) fpDef = fpDef.getDefinition() || fpDef;
360
+ }
361
+ if (!firstParentProps && (0, __atscript_core.isStructure)(fpDef)) firstParentProps = fpDef.props;
362
+ }
363
+ this.renderStructureFiltered(resolved, node.id, firstParentProps);
364
+ } else this.writeln("{}");
365
+ } else {
366
+ this.write(`class ${node.id} `);
367
+ const struct = node.getDefinition();
368
+ if (struct?.entity === "structure") this.renderStructure(struct, node.id);
348
369
  else this.writeln("{}");
370
+ }
349
371
  this.writeln();
350
372
  }
373
+ /**
374
+ * Renders a structure block, optionally filtering out props that exist in a parent.
375
+ */ renderStructureFiltered(struct, asClass, filterProps) {
376
+ if (!filterProps) return this.renderStructure(struct, asClass);
377
+ this.blockln("{}");
378
+ for (const prop of Array.from(struct.props.values())) {
379
+ if (filterProps.has(prop.id)) continue;
380
+ if (prop.token("identifier")?.pattern) continue;
381
+ const phantomType = this.phantomPropType(prop.getDefinition());
382
+ if (phantomType) {
383
+ this.writeln(`// ${prop.id}: ${phantomType}`);
384
+ continue;
385
+ }
386
+ const optional = !!prop.token("optional");
387
+ this.write(wrapProp(prop.id), optional ? "?" : "", ": ");
388
+ const renderedDef = this.renderTypeDefString(prop.getDefinition());
389
+ renderedDef.split("\n").forEach((l) => this.writeln(l));
390
+ }
391
+ this.writeln("static __is_atscript_annotated_type: true");
392
+ this.writeln(`static type: TAtscriptTypeObject<keyof ${asClass}, ${asClass}>`);
393
+ this.writeln(`static metadata: TMetadataMap<AtscriptMetadata>`);
394
+ this.writeln(`static validator: (opts?: Partial<TValidatorOptions>) => Validator<typeof ${asClass}>`);
395
+ if (resolveJsonSchemaMode(this.opts) === false) this.writeln("/** @deprecated JSON Schema support is disabled. Calling this method will throw a runtime error. To enable, set `jsonSchema: 'lazy'` or `jsonSchema: 'bundle'` in tsPlugin options, or add `@emit.jsonSchema` annotation to individual interfaces. */");
396
+ this.writeln("static toJsonSchema: () => any");
397
+ if (!this.opts?.exampleData) this.writeln("/** @deprecated Example Data support is disabled. To enable, set `exampleData: true` in tsPlugin options. */");
398
+ this.writeln("static toExampleData?: () => any");
399
+ this.pop();
400
+ }
351
401
  renderType(node) {
352
402
  this.writeln();
353
403
  const exported = node.token("export")?.text === "export";
@@ -1212,7 +1262,11 @@ else {
1212
1262
  const unwound = this.doc.unwindType(annotateNode.targetName);
1213
1263
  if (unwound?.def) {
1214
1264
  let def = this.doc.mergeIntersection(unwound.def);
1215
- if ((0, __atscript_core.isInterface)(def)) def = def.getDefinition() || def;
1265
+ if ((0, __atscript_core.isInterface)(def)) if (def.hasExtends) {
1266
+ const resolved = unwound.doc.resolveInterfaceExtends(def);
1267
+ if (resolved) def = resolved;
1268
+ else def = def.getDefinition() || def;
1269
+ } else def = def.getDefinition() || def;
1216
1270
  this._adHocAnnotations = this.buildAdHocMap([annotateNode]);
1217
1271
  this.annotateType(def, node.id);
1218
1272
  this._adHocAnnotations = null;
@@ -1223,7 +1277,12 @@ else {
1223
1277
  }
1224
1278
  }
1225
1279
  } else {
1226
- this.annotateType(node.getDefinition(), node.id);
1280
+ let def = node.getDefinition();
1281
+ if ((0, __atscript_core.isInterface)(node) && node.hasExtends) {
1282
+ const resolved = this.doc.resolveInterfaceExtends(node);
1283
+ if (resolved) def = resolved;
1284
+ }
1285
+ this.annotateType(def, node.id);
1227
1286
  this.indent().defineMetadata(node).unindent();
1228
1287
  this.writeln();
1229
1288
  }
@@ -1312,7 +1371,11 @@ else {
1312
1371
  switch (node.entity) {
1313
1372
  case "interface":
1314
1373
  case "type": {
1315
- const def = node.getDefinition();
1374
+ let def = node.getDefinition();
1375
+ if ((0, __atscript_core.isInterface)(node) && node.hasExtends) {
1376
+ const resolved = this.doc.resolveInterfaceExtends(node);
1377
+ if (resolved) def = resolved;
1378
+ }
1316
1379
  const handle = this.toAnnotatedHandle(def, true);
1317
1380
  const typeId = this.typeIds.get(node) ?? (node.__typeId !== null && node.__typeId !== undefined ? node.id : undefined);
1318
1381
  if (typeId) handle.id(typeId);
package/dist/index.mjs CHANGED
@@ -317,12 +317,62 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
317
317
  const exported = node.token("export")?.text === "export";
318
318
  this.renderJsDoc(node);
319
319
  this.write(exported ? "export declare " : "declare ");
320
- this.write(`class ${node.id} `);
321
- const struct = node.getDefinition();
322
- if (struct?.entity === "structure") this.renderStructure(struct, node.id);
320
+ if (node.hasExtends) {
321
+ const firstParent = node.extendsTokens[0].text;
322
+ this.write(`class ${node.id} extends ${firstParent} `);
323
+ const resolved = this.doc.resolveInterfaceExtends(node);
324
+ if (resolved?.entity === "structure") {
325
+ const firstParentUnwound = this.doc.unwindType(firstParent);
326
+ let firstParentProps;
327
+ if (firstParentUnwound?.def) {
328
+ let fpDef = firstParentUnwound.def;
329
+ if (isInterface(fpDef)) {
330
+ if (fpDef.hasExtends) {
331
+ const fpResolved = firstParentUnwound.doc.resolveInterfaceExtends(fpDef);
332
+ if (fpResolved && isStructure(fpResolved)) firstParentProps = fpResolved.props;
333
+ }
334
+ if (!firstParentProps) fpDef = fpDef.getDefinition() || fpDef;
335
+ }
336
+ if (!firstParentProps && isStructure(fpDef)) firstParentProps = fpDef.props;
337
+ }
338
+ this.renderStructureFiltered(resolved, node.id, firstParentProps);
339
+ } else this.writeln("{}");
340
+ } else {
341
+ this.write(`class ${node.id} `);
342
+ const struct = node.getDefinition();
343
+ if (struct?.entity === "structure") this.renderStructure(struct, node.id);
323
344
  else this.writeln("{}");
345
+ }
324
346
  this.writeln();
325
347
  }
348
+ /**
349
+ * Renders a structure block, optionally filtering out props that exist in a parent.
350
+ */ renderStructureFiltered(struct, asClass, filterProps) {
351
+ if (!filterProps) return this.renderStructure(struct, asClass);
352
+ this.blockln("{}");
353
+ for (const prop of Array.from(struct.props.values())) {
354
+ if (filterProps.has(prop.id)) continue;
355
+ if (prop.token("identifier")?.pattern) continue;
356
+ const phantomType = this.phantomPropType(prop.getDefinition());
357
+ if (phantomType) {
358
+ this.writeln(`// ${prop.id}: ${phantomType}`);
359
+ continue;
360
+ }
361
+ const optional = !!prop.token("optional");
362
+ this.write(wrapProp(prop.id), optional ? "?" : "", ": ");
363
+ const renderedDef = this.renderTypeDefString(prop.getDefinition());
364
+ renderedDef.split("\n").forEach((l) => this.writeln(l));
365
+ }
366
+ this.writeln("static __is_atscript_annotated_type: true");
367
+ this.writeln(`static type: TAtscriptTypeObject<keyof ${asClass}, ${asClass}>`);
368
+ this.writeln(`static metadata: TMetadataMap<AtscriptMetadata>`);
369
+ this.writeln(`static validator: (opts?: Partial<TValidatorOptions>) => Validator<typeof ${asClass}>`);
370
+ if (resolveJsonSchemaMode(this.opts) === false) this.writeln("/** @deprecated JSON Schema support is disabled. Calling this method will throw a runtime error. To enable, set `jsonSchema: 'lazy'` or `jsonSchema: 'bundle'` in tsPlugin options, or add `@emit.jsonSchema` annotation to individual interfaces. */");
371
+ this.writeln("static toJsonSchema: () => any");
372
+ if (!this.opts?.exampleData) this.writeln("/** @deprecated Example Data support is disabled. To enable, set `exampleData: true` in tsPlugin options. */");
373
+ this.writeln("static toExampleData?: () => any");
374
+ this.pop();
375
+ }
326
376
  renderType(node) {
327
377
  this.writeln();
328
378
  const exported = node.token("export")?.text === "export";
@@ -1187,7 +1237,11 @@ else {
1187
1237
  const unwound = this.doc.unwindType(annotateNode.targetName);
1188
1238
  if (unwound?.def) {
1189
1239
  let def = this.doc.mergeIntersection(unwound.def);
1190
- if (isInterface(def)) def = def.getDefinition() || def;
1240
+ if (isInterface(def)) if (def.hasExtends) {
1241
+ const resolved = unwound.doc.resolveInterfaceExtends(def);
1242
+ if (resolved) def = resolved;
1243
+ else def = def.getDefinition() || def;
1244
+ } else def = def.getDefinition() || def;
1191
1245
  this._adHocAnnotations = this.buildAdHocMap([annotateNode]);
1192
1246
  this.annotateType(def, node.id);
1193
1247
  this._adHocAnnotations = null;
@@ -1198,7 +1252,12 @@ else {
1198
1252
  }
1199
1253
  }
1200
1254
  } else {
1201
- this.annotateType(node.getDefinition(), node.id);
1255
+ let def = node.getDefinition();
1256
+ if (isInterface(node) && node.hasExtends) {
1257
+ const resolved = this.doc.resolveInterfaceExtends(node);
1258
+ if (resolved) def = resolved;
1259
+ }
1260
+ this.annotateType(def, node.id);
1202
1261
  this.indent().defineMetadata(node).unindent();
1203
1262
  this.writeln();
1204
1263
  }
@@ -1287,7 +1346,11 @@ else {
1287
1346
  switch (node.entity) {
1288
1347
  case "interface":
1289
1348
  case "type": {
1290
- const def = node.getDefinition();
1349
+ let def = node.getDefinition();
1350
+ if (isInterface(node) && node.hasExtends) {
1351
+ const resolved = this.doc.resolveInterfaceExtends(node);
1352
+ if (resolved) def = resolved;
1353
+ }
1291
1354
  const handle = this.toAnnotatedHandle(def, true);
1292
1355
  const typeId = this.typeIds.get(node) ?? (node.__typeId !== null && node.__typeId !== undefined ? node.id : undefined);
1293
1356
  if (typeId) handle.id(typeId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atscript/typescript",
3
- "version": "0.1.29",
3
+ "version": "0.1.30",
4
4
  "description": "Atscript: typescript-gen support.",
5
5
  "keywords": [
6
6
  "annotations",
@@ -64,7 +64,7 @@
64
64
  "vitest": "3.2.4"
65
65
  },
66
66
  "peerDependencies": {
67
- "@atscript/core": "^0.1.29"
67
+ "@atscript/core": "^0.1.30"
68
68
  },
69
69
  "build": [
70
70
  {},