Skip to content

Commit fdc096d

Browse files
committed
ts: add openResourceTypeSet options. Refactoring.
1 parent cdde040 commit fdc096d

3 files changed

Lines changed: 33 additions & 13 deletions

File tree

examples/typescript-r4/generate.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ if (require.main === module) {
1010
.verbose()
1111
.throwException()
1212
.fromPackage("hl7.fhir.r4.core", "4.0.1")
13-
.typescript({ withDebugComment: false, generateProfile: true })
13+
.typescript({
14+
withDebugComment: false,
15+
generateProfile: true,
16+
openResourceTypeSet: false,
17+
})
1418
// .typescript({ withDebugComment: false, generateProfile: false })
1519
// .fromPackageRef("https://build.fhir.org/ig/FHIR/sql-on-fhir-v2//package.tgz")
1620
// .writeTypeSchemas("examples/r4-type-schema")

src/api/builder.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import * as afs from "node:fs/promises";
1010
import * as Path from "node:path";
1111
import { CanonicalManager } from "@atomic-ehr/fhir-canonical-manager";
1212
import type { GeneratedFile } from "@root/api/generators/base/types";
13-
import { CSharp } from "@root/api/writer-generator/csharp/csharp.ts";
13+
import { CSharp } from "@root/api/writer-generator/csharp/csharp";
1414
import { registerFromManager } from "@root/typeschema/register";
1515
import { mkTypeSchemaIndex, type TreeShake, treeShake } from "@root/typeschema/utils";
1616
import { generateTypeSchemas, TypeSchemaCache, TypeSchemaGenerator, TypeSchemaParser } from "@typeschema/index";
@@ -19,7 +19,7 @@ import type { Config, TypeSchemaConfig } from "../config";
1919
import { CodegenLogger, createLogger } from "../utils/codegen-logger";
2020
import type { GeneratorInput } from "./generators/base/BaseGenerator";
2121
import { TypeScriptGenerator as TypeScriptGeneratorDepricated } from "./generators/typescript";
22-
import * as TS2 from "./writer-generator/typescript";
22+
import { TypeScript, type TypeScriptOptions } from "./writer-generator/typescript";
2323
import type { Writer, WriterOptions } from "./writer-generator/writer";
2424

2525
/**
@@ -309,19 +309,26 @@ export class APIBuilder {
309309
return this;
310310
}
311311

312-
typescript(opts: Partial<WriterOptions>) {
313-
const writerOpts = {
312+
typescript(userOpts: Partial<TypeScriptOptions>) {
313+
const defaultWriterOpts: WriterOptions = {
314+
logger: this.logger,
314315
outputDir: Path.join(this.options.outputDir, "/types"),
315316
tabSize: 4,
316317
withDebugComment: false,
317318
commentLinePrefix: "//",
318319
generateProfile: true,
319-
exportTypeTree: this.options.exportTypeTree,
320320
};
321-
const effectiveOpts = { logger: this.logger, ...writerOpts, ...opts };
322-
const generator = writerToGenerator(new TS2.TypeScript(effectiveOpts));
321+
const defaultTsOpts: TypeScriptOptions = {
322+
...defaultWriterOpts,
323+
openResourceTypeSet: false,
324+
};
325+
const opts: TypeScriptOptions = {
326+
...defaultTsOpts,
327+
...Object.fromEntries(Object.entries(userOpts).filter(([_, v]) => v !== undefined)),
328+
};
329+
const generator = writerToGenerator(new TypeScript(opts));
323330
this.generators.set("typescript", generator);
324-
this.logger.debug(`Configured TypeScript generator (${JSON.stringify(effectiveOpts, undefined, 2)})`);
331+
this.logger.debug(`Configured TypeScript generator (${JSON.stringify(opts, undefined, 2)})`);
325332
return this;
326333
}
327334

src/api/writer-generator/typescript.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,16 @@ const tsEnumType = (enumValues: string[]) => {
112112
return `(${enumValues.map((e) => `"${e}"`).join(" | ")})`;
113113
};
114114

115-
export type TypeScriptOptions = {} & WriterOptions;
116-
117-
export class TypeScript extends Writer {
115+
export type TypeScriptOptions = {
116+
/** openResourceTypeSet -- for resource families (Resource, DomainResource) use open set for resourceType field.
117+
*
118+
* - when openResourceTypeSet is false: `type Resource = { resourceType: "Resource" | "DomainResource" | "Patient" }`
119+
* - when openResourceTypeSet is true: `type Resource = { resourceType: "Resource" | "DomainResource" | "Patient" | string }`
120+
*/
121+
openResourceTypeSet: boolean;
122+
} & WriterOptions;
123+
124+
export class TypeScript extends Writer<TypeScriptOptions> {
118125
tsImportType(tsPackageName: string, ...entities: string[]) {
119126
this.lineSM(`import type { ${entities.join(", ")} } from "${tsPackageName}"`);
120127
}
@@ -239,11 +246,13 @@ export class TypeScript extends Writer {
239246
if (isResourceTypeSchema(schema)) {
240247
const possibleResourceTypes = [schema.identifier];
241248
possibleResourceTypes.push(...tsIndex.resourceChildren(schema.identifier));
249+
const openSetSuffix =
250+
this.opts.openResourceTypeSet && possibleResourceTypes.length > 1 ? " | string" : "";
242251
this.lineSM(
243252
`resourceType: ${possibleResourceTypes
244253
.sort((a, b) => a.name.localeCompare(b.name))
245254
.map((e) => `"${e.name}"`)
246-
.join(" | ")}`,
255+
.join(" | ")}${openSetSuffix}`,
247256
);
248257
this.line();
249258
}

0 commit comments

Comments
 (0)