@workos/oagen 0.9.0 → 0.9.2

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.
@@ -6313,12 +6313,351 @@ async function extractCommand(opts) {
6313
6313
  console.log(`Extracted ${symbolCount} symbols → ${opts.output}`);
6314
6314
  }
6315
6315
  //#endregion
6316
+ //#region src/compat/policy.ts
6317
+ /** Built-in language defaults. */
6318
+ const LANGUAGE_DEFAULTS = {
6319
+ php: {
6320
+ callerUsesParamNames: true,
6321
+ constructorOrderMatters: true,
6322
+ methodParameterNamesArePublicApi: true,
6323
+ constructorParameterNamesArePublicApi: true,
6324
+ overloadsArePublicApi: false,
6325
+ arityIsPublicApi: false
6326
+ },
6327
+ python: {
6328
+ callerUsesParamNames: true,
6329
+ constructorOrderMatters: true,
6330
+ methodParameterNamesArePublicApi: true,
6331
+ constructorParameterNamesArePublicApi: true,
6332
+ overloadsArePublicApi: false,
6333
+ arityIsPublicApi: false
6334
+ },
6335
+ ruby: {
6336
+ callerUsesParamNames: true,
6337
+ constructorOrderMatters: true,
6338
+ methodParameterNamesArePublicApi: true,
6339
+ constructorParameterNamesArePublicApi: true,
6340
+ overloadsArePublicApi: false,
6341
+ arityIsPublicApi: false
6342
+ },
6343
+ go: {
6344
+ callerUsesParamNames: false,
6345
+ constructorOrderMatters: true,
6346
+ methodParameterNamesArePublicApi: false,
6347
+ constructorParameterNamesArePublicApi: false,
6348
+ overloadsArePublicApi: false,
6349
+ arityIsPublicApi: true
6350
+ },
6351
+ kotlin: {
6352
+ callerUsesParamNames: true,
6353
+ constructorOrderMatters: false,
6354
+ methodParameterNamesArePublicApi: true,
6355
+ constructorParameterNamesArePublicApi: true,
6356
+ overloadsArePublicApi: true,
6357
+ arityIsPublicApi: false
6358
+ },
6359
+ dotnet: {
6360
+ callerUsesParamNames: true,
6361
+ constructorOrderMatters: false,
6362
+ methodParameterNamesArePublicApi: true,
6363
+ constructorParameterNamesArePublicApi: true,
6364
+ overloadsArePublicApi: true,
6365
+ arityIsPublicApi: false
6366
+ },
6367
+ elixir: {
6368
+ callerUsesParamNames: true,
6369
+ constructorOrderMatters: false,
6370
+ methodParameterNamesArePublicApi: true,
6371
+ constructorParameterNamesArePublicApi: false,
6372
+ overloadsArePublicApi: false,
6373
+ arityIsPublicApi: true
6374
+ },
6375
+ rust: {
6376
+ callerUsesParamNames: false,
6377
+ constructorOrderMatters: true,
6378
+ methodParameterNamesArePublicApi: false,
6379
+ constructorParameterNamesArePublicApi: false,
6380
+ overloadsArePublicApi: false,
6381
+ arityIsPublicApi: true
6382
+ },
6383
+ node: {
6384
+ callerUsesParamNames: false,
6385
+ constructorOrderMatters: false,
6386
+ methodParameterNamesArePublicApi: false,
6387
+ constructorParameterNamesArePublicApi: false,
6388
+ overloadsArePublicApi: false,
6389
+ arityIsPublicApi: false
6390
+ }
6391
+ };
6392
+ /** Get the built-in default policy for a language. */
6393
+ function getDefaultPolicy(language) {
6394
+ return { ...LANGUAGE_DEFAULTS[language] };
6395
+ }
6396
+ /** Merge user overrides onto language defaults. Only provided keys are overridden. */
6397
+ function mergePolicy(defaults, overrides) {
6398
+ return {
6399
+ ...defaults,
6400
+ ...overrides
6401
+ };
6402
+ }
6403
+ //#endregion
6404
+ //#region src/compat/schema.ts
6405
+ /** Validate the basic structure of a parsed compat snapshot. */
6406
+ function validateSnapshot(data) {
6407
+ if (typeof data !== "object" || data === null) return false;
6408
+ const obj = data;
6409
+ return typeof obj.schemaVersion === "string" && typeof obj.source === "object" && obj.source !== null && typeof obj.policies === "object" && obj.policies !== null && Array.isArray(obj.symbols);
6410
+ }
6411
+ //#endregion
6412
+ //#region src/compat/ir.ts
6413
+ /**
6414
+ * Convert a legacy ApiSurface to a CompatSnapshot.
6415
+ *
6416
+ * This bridge allows existing extractors (which produce ApiSurface) to feed
6417
+ * into the new classified diff engine without requiring immediate migration.
6418
+ */
6419
+ function apiSurfaceToSnapshot(surface) {
6420
+ const language = surface.language || "node";
6421
+ const symbols = [];
6422
+ for (const [className, cls] of Object.entries(surface.classes)) {
6423
+ symbols.push({
6424
+ id: `class:${className}`,
6425
+ kind: "service_accessor",
6426
+ fqName: className,
6427
+ displayName: className,
6428
+ visibility: "public",
6429
+ stability: cls.deprecationMessage ? "deprecated" : "stable",
6430
+ sourceKind: "generated_service_wrapper"
6431
+ });
6432
+ if (cls.constructorParams.length > 0) symbols.push({
6433
+ id: `ctor:${className}`,
6434
+ kind: "constructor",
6435
+ fqName: `${className}.constructor`,
6436
+ ownerFqName: className,
6437
+ displayName: `new ${className}`,
6438
+ visibility: "public",
6439
+ stability: "stable",
6440
+ sourceKind: "generated_resource_constructor",
6441
+ parameters: cls.constructorParams.map((p, i) => apiParamToCompatParam(p, i, language))
6442
+ });
6443
+ for (const [methodName, overloads] of Object.entries(cls.methods)) for (let oi = 0; oi < overloads.length; oi++) {
6444
+ const method = overloads[oi];
6445
+ const suffix = overloads.length > 1 ? `#${oi}` : "";
6446
+ symbols.push({
6447
+ id: `method:${className}.${methodName}${suffix}`,
6448
+ kind: "callable",
6449
+ fqName: `${className}.${methodName}`,
6450
+ ownerFqName: className,
6451
+ displayName: `${className}.${methodName}`,
6452
+ visibility: "public",
6453
+ stability: "stable",
6454
+ sourceKind: "generated_service_wrapper",
6455
+ parameters: method.params.map((p, i) => apiParamToCompatParam(p, i, language)),
6456
+ returns: { name: method.returnType }
6457
+ });
6458
+ }
6459
+ for (const [propName, prop] of Object.entries(cls.properties)) symbols.push({
6460
+ id: `prop:${className}.${propName}`,
6461
+ kind: "property",
6462
+ fqName: `${className}.${propName}`,
6463
+ ownerFqName: className,
6464
+ displayName: `${className}.${propName}`,
6465
+ visibility: "public",
6466
+ stability: "stable",
6467
+ sourceKind: "generated_service_wrapper",
6468
+ typeRef: { name: prop.type }
6469
+ });
6470
+ }
6471
+ for (const [ifaceName, iface] of Object.entries(surface.interfaces)) {
6472
+ symbols.push({
6473
+ id: `iface:${ifaceName}`,
6474
+ kind: "alias",
6475
+ fqName: ifaceName,
6476
+ displayName: ifaceName,
6477
+ visibility: "public",
6478
+ stability: "stable",
6479
+ sourceKind: "generated_resource_constructor"
6480
+ });
6481
+ for (const [fieldName, field] of Object.entries(iface.fields)) symbols.push({
6482
+ id: `field:${ifaceName}.${fieldName}`,
6483
+ kind: "field",
6484
+ fqName: `${ifaceName}.${fieldName}`,
6485
+ ownerFqName: ifaceName,
6486
+ displayName: `${ifaceName}.${fieldName}`,
6487
+ visibility: "public",
6488
+ stability: "stable",
6489
+ sourceKind: "generated_resource_constructor",
6490
+ typeRef: { name: field.type }
6491
+ });
6492
+ if (iface.hasCustomConstructor) symbols.push({
6493
+ id: `ctor:${ifaceName}`,
6494
+ kind: "constructor",
6495
+ fqName: `${ifaceName}.constructor`,
6496
+ ownerFqName: ifaceName,
6497
+ displayName: `new ${ifaceName}`,
6498
+ visibility: "public",
6499
+ stability: "stable",
6500
+ sourceKind: "generated_resource_constructor"
6501
+ });
6502
+ }
6503
+ for (const [aliasName] of Object.entries(surface.typeAliases)) symbols.push({
6504
+ id: `alias:${aliasName}`,
6505
+ kind: "alias",
6506
+ fqName: aliasName,
6507
+ displayName: aliasName,
6508
+ visibility: "public",
6509
+ stability: "stable",
6510
+ sourceKind: "generated_resource_constructor"
6511
+ });
6512
+ for (const [enumName, enumDef] of Object.entries(surface.enums)) {
6513
+ symbols.push({
6514
+ id: `enum:${enumName}`,
6515
+ kind: "enum",
6516
+ fqName: enumName,
6517
+ displayName: enumName,
6518
+ visibility: "public",
6519
+ stability: "stable",
6520
+ sourceKind: "generated_enum"
6521
+ });
6522
+ for (const [memberName, memberValue] of Object.entries(enumDef.members)) symbols.push({
6523
+ id: `enum_member:${enumName}.${memberName}`,
6524
+ kind: "enum_member",
6525
+ fqName: `${enumName}.${memberName}`,
6526
+ ownerFqName: enumName,
6527
+ displayName: `${enumName}.${memberName}`,
6528
+ visibility: "public",
6529
+ stability: "stable",
6530
+ sourceKind: "generated_enum",
6531
+ value: memberValue
6532
+ });
6533
+ }
6534
+ return {
6535
+ schemaVersion: "1",
6536
+ source: { extractedAt: surface.extractedAt },
6537
+ policies: getDefaultPolicy(language),
6538
+ symbols
6539
+ };
6540
+ }
6541
+ /** Convert a legacy ApiParam to a CompatParameter. */
6542
+ function apiParamToCompatParam(param, position, language) {
6543
+ const policy = getDefaultPolicy(language);
6544
+ return {
6545
+ publicName: param.name,
6546
+ position,
6547
+ required: !param.optional,
6548
+ nullable: false,
6549
+ hasDefault: param.optional,
6550
+ passing: param.passingStyle ?? inferPassingStyle(language),
6551
+ type: { name: param.type },
6552
+ sensitivity: {
6553
+ order: policy.constructorOrderMatters,
6554
+ publicName: policy.methodParameterNamesArePublicApi,
6555
+ requiredness: true,
6556
+ type: true
6557
+ }
6558
+ };
6559
+ }
6560
+ /** Infer the default parameter passing style for a language. */
6561
+ function inferPassingStyle(language) {
6562
+ switch (language) {
6563
+ case "python":
6564
+ case "ruby":
6565
+ case "elixir": return "keyword";
6566
+ case "php":
6567
+ case "kotlin":
6568
+ case "dotnet": return "named";
6569
+ case "node": return "options_object";
6570
+ default: return "positional";
6571
+ }
6572
+ }
6573
+ //#endregion
6316
6574
  //#region src/cli/compat-extract.ts
6317
6575
  const SNAPSHOT_FILENAME = ".oagen-compat-snapshot.json";
6576
+ /** Normalize a name for case-insensitive matching: strip underscores and lowercase. */
6577
+ function normalize(name) {
6578
+ return name.replace(/_/g, "").toLowerCase();
6579
+ }
6580
+ /**
6581
+ * Build a map of normalized service name → Set of generated method names
6582
+ * from the manifest's operations record.
6583
+ */
6584
+ function buildServiceMethodMap(operations) {
6585
+ const result = /* @__PURE__ */ new Map();
6586
+ for (const value of Object.values(operations)) {
6587
+ if (typeof value !== "object" || value === null) continue;
6588
+ const { sdkMethod, service } = value;
6589
+ if (typeof sdkMethod !== "string" || typeof service !== "string") continue;
6590
+ const key = normalize(service);
6591
+ if (!result.has(key)) result.set(key, /* @__PURE__ */ new Set());
6592
+ result.get(key).add(sdkMethod);
6593
+ }
6594
+ return result;
6595
+ }
6596
+ /**
6597
+ * Filter an ApiSurface to only include generated symbols based on the manifest.
6598
+ *
6599
+ * Two levels of filtering:
6600
+ * 1. File-level: classes/interfaces/enums from files not in the manifest are
6601
+ * dropped entirely (they are wholly hand-written).
6602
+ * 2. Method-level: for service classes (those whose name matches a manifest
6603
+ * service), only methods listed in the manifest operations are kept.
6604
+ * Constructors and properties are always preserved since they are structural.
6605
+ * Non-service classes (models, enums, etc.) keep all their symbols.
6606
+ */
6607
+ function filterSurfaceByManifest(surface, manifest) {
6608
+ const manifestFiles = new Set(manifest.files);
6609
+ const serviceMethodMap = manifest.operations ? buildServiceMethodMap(manifest.operations) : /* @__PURE__ */ new Map();
6610
+ let filesExcluded = 0;
6611
+ let methodsExcluded = 0;
6612
+ const filterByFile = (record) => {
6613
+ const result = {};
6614
+ for (const [name, entry] of Object.entries(record)) if (entry.sourceFile && manifestFiles.has(entry.sourceFile)) result[name] = entry;
6615
+ else filesExcluded++;
6616
+ return result;
6617
+ };
6618
+ const filteredClasses = {};
6619
+ for (const [name, cls] of Object.entries(surface.classes)) {
6620
+ if (cls.sourceFile && !manifestFiles.has(cls.sourceFile)) {
6621
+ filesExcluded++;
6622
+ continue;
6623
+ }
6624
+ const generatedMethods = serviceMethodMap.get(normalize(name));
6625
+ if (generatedMethods) {
6626
+ const methods = {};
6627
+ for (const [methodName, overloads] of Object.entries(cls.methods)) if (generatedMethods.has(methodName)) methods[methodName] = overloads;
6628
+ else methodsExcluded++;
6629
+ filteredClasses[name] = {
6630
+ ...cls,
6631
+ methods
6632
+ };
6633
+ } else filteredClasses[name] = cls;
6634
+ }
6635
+ const filteredExports = {};
6636
+ for (const [filePath, symbols] of Object.entries(surface.exports)) if (manifestFiles.has(filePath)) filteredExports[filePath] = symbols;
6637
+ return {
6638
+ filtered: {
6639
+ ...surface,
6640
+ classes: filteredClasses,
6641
+ interfaces: filterByFile(surface.interfaces),
6642
+ typeAliases: filterByFile(surface.typeAliases),
6643
+ enums: filterByFile(surface.enums),
6644
+ exports: filteredExports
6645
+ },
6646
+ filesExcluded,
6647
+ methodsExcluded
6648
+ };
6649
+ }
6318
6650
  async function compatExtractCommand(opts) {
6319
6651
  const extractor = getExtractor(opts.lang);
6320
6652
  console.log(`Extracting ${opts.lang} compat snapshot from ${opts.sdkPath}...`);
6321
- const snapshot = await extractor.extractSnapshot(opts.sdkPath);
6653
+ let surface = await extractor.extract(opts.sdkPath);
6654
+ const manifest = await readManifest(opts.sdkPath);
6655
+ if (manifest) {
6656
+ const { filtered, filesExcluded, methodsExcluded } = filterSurfaceByManifest(surface, manifest);
6657
+ surface = filtered;
6658
+ if (filesExcluded > 0 || methodsExcluded > 0) console.log(`Manifest filter: excluded ${filesExcluded} hand-written file(s), ${methodsExcluded} hand-written method(s)`);
6659
+ }
6660
+ const snapshot = apiSurfaceToSnapshot(surface);
6322
6661
  if (opts.spec) {
6323
6662
  const specContent = readFileSync(opts.spec, "utf-8");
6324
6663
  snapshot.source.specSha = createHash("sha256").update(specContent).digest("hex");
@@ -6349,20 +6688,12 @@ function enrichWithSpecContext(snapshot, spec) {
6349
6688
  const match = opLookup.get(sym.fqName);
6350
6689
  if (match) {
6351
6690
  sym.operationId = match.operationId;
6352
- sym.route = {
6353
- method: match.method,
6354
- path: match.path
6355
- };
6356
- }
6357
- }
6358
- }
6359
- //#endregion
6360
- //#region src/compat/schema.ts
6361
- /** Validate the basic structure of a parsed compat snapshot. */
6362
- function validateSnapshot(data) {
6363
- if (typeof data !== "object" || data === null) return false;
6364
- const obj = data;
6365
- return typeof obj.schemaVersion === "string" && typeof obj.source === "object" && obj.source !== null && typeof obj.policies === "object" && obj.policies !== null && Array.isArray(obj.symbols);
6691
+ sym.route = {
6692
+ method: match.method,
6693
+ path: match.path
6694
+ };
6695
+ }
6696
+ }
6366
6697
  }
6367
6698
  //#endregion
6368
6699
  //#region src/compat/config.ts
@@ -7150,256 +7481,6 @@ function narrowingMatches(match, change) {
7150
7481
  return true;
7151
7482
  }
7152
7483
  //#endregion
7153
- //#region src/compat/policy.ts
7154
- /** Built-in language defaults. */
7155
- const LANGUAGE_DEFAULTS = {
7156
- php: {
7157
- callerUsesParamNames: true,
7158
- constructorOrderMatters: true,
7159
- methodParameterNamesArePublicApi: true,
7160
- constructorParameterNamesArePublicApi: true,
7161
- overloadsArePublicApi: false,
7162
- arityIsPublicApi: false
7163
- },
7164
- python: {
7165
- callerUsesParamNames: true,
7166
- constructorOrderMatters: true,
7167
- methodParameterNamesArePublicApi: true,
7168
- constructorParameterNamesArePublicApi: true,
7169
- overloadsArePublicApi: false,
7170
- arityIsPublicApi: false
7171
- },
7172
- ruby: {
7173
- callerUsesParamNames: true,
7174
- constructorOrderMatters: true,
7175
- methodParameterNamesArePublicApi: true,
7176
- constructorParameterNamesArePublicApi: true,
7177
- overloadsArePublicApi: false,
7178
- arityIsPublicApi: false
7179
- },
7180
- go: {
7181
- callerUsesParamNames: false,
7182
- constructorOrderMatters: true,
7183
- methodParameterNamesArePublicApi: false,
7184
- constructorParameterNamesArePublicApi: false,
7185
- overloadsArePublicApi: false,
7186
- arityIsPublicApi: true
7187
- },
7188
- kotlin: {
7189
- callerUsesParamNames: true,
7190
- constructorOrderMatters: false,
7191
- methodParameterNamesArePublicApi: true,
7192
- constructorParameterNamesArePublicApi: true,
7193
- overloadsArePublicApi: true,
7194
- arityIsPublicApi: false
7195
- },
7196
- dotnet: {
7197
- callerUsesParamNames: true,
7198
- constructorOrderMatters: false,
7199
- methodParameterNamesArePublicApi: true,
7200
- constructorParameterNamesArePublicApi: true,
7201
- overloadsArePublicApi: true,
7202
- arityIsPublicApi: false
7203
- },
7204
- elixir: {
7205
- callerUsesParamNames: true,
7206
- constructorOrderMatters: false,
7207
- methodParameterNamesArePublicApi: true,
7208
- constructorParameterNamesArePublicApi: false,
7209
- overloadsArePublicApi: false,
7210
- arityIsPublicApi: true
7211
- },
7212
- rust: {
7213
- callerUsesParamNames: false,
7214
- constructorOrderMatters: true,
7215
- methodParameterNamesArePublicApi: false,
7216
- constructorParameterNamesArePublicApi: false,
7217
- overloadsArePublicApi: false,
7218
- arityIsPublicApi: true
7219
- },
7220
- node: {
7221
- callerUsesParamNames: false,
7222
- constructorOrderMatters: false,
7223
- methodParameterNamesArePublicApi: false,
7224
- constructorParameterNamesArePublicApi: false,
7225
- overloadsArePublicApi: false,
7226
- arityIsPublicApi: false
7227
- }
7228
- };
7229
- /** Get the built-in default policy for a language. */
7230
- function getDefaultPolicy(language) {
7231
- return { ...LANGUAGE_DEFAULTS[language] };
7232
- }
7233
- /** Merge user overrides onto language defaults. Only provided keys are overridden. */
7234
- function mergePolicy(defaults, overrides) {
7235
- return {
7236
- ...defaults,
7237
- ...overrides
7238
- };
7239
- }
7240
- //#endregion
7241
- //#region src/compat/ir.ts
7242
- /**
7243
- * Convert a legacy ApiSurface to a CompatSnapshot.
7244
- *
7245
- * This bridge allows existing extractors (which produce ApiSurface) to feed
7246
- * into the new classified diff engine without requiring immediate migration.
7247
- */
7248
- function apiSurfaceToSnapshot(surface) {
7249
- const language = surface.language || "node";
7250
- const symbols = [];
7251
- for (const [className, cls] of Object.entries(surface.classes)) {
7252
- symbols.push({
7253
- id: `class:${className}`,
7254
- kind: "service_accessor",
7255
- fqName: className,
7256
- displayName: className,
7257
- visibility: "public",
7258
- stability: cls.deprecationMessage ? "deprecated" : "stable",
7259
- sourceKind: "generated_service_wrapper"
7260
- });
7261
- if (cls.constructorParams.length > 0) symbols.push({
7262
- id: `ctor:${className}`,
7263
- kind: "constructor",
7264
- fqName: `${className}.constructor`,
7265
- ownerFqName: className,
7266
- displayName: `new ${className}`,
7267
- visibility: "public",
7268
- stability: "stable",
7269
- sourceKind: "generated_resource_constructor",
7270
- parameters: cls.constructorParams.map((p, i) => apiParamToCompatParam(p, i, language))
7271
- });
7272
- for (const [methodName, overloads] of Object.entries(cls.methods)) for (let oi = 0; oi < overloads.length; oi++) {
7273
- const method = overloads[oi];
7274
- const suffix = overloads.length > 1 ? `#${oi}` : "";
7275
- symbols.push({
7276
- id: `method:${className}.${methodName}${suffix}`,
7277
- kind: "callable",
7278
- fqName: `${className}.${methodName}`,
7279
- ownerFqName: className,
7280
- displayName: `${className}.${methodName}`,
7281
- visibility: "public",
7282
- stability: "stable",
7283
- sourceKind: "generated_service_wrapper",
7284
- parameters: method.params.map((p, i) => apiParamToCompatParam(p, i, language)),
7285
- returns: { name: method.returnType }
7286
- });
7287
- }
7288
- for (const [propName, prop] of Object.entries(cls.properties)) symbols.push({
7289
- id: `prop:${className}.${propName}`,
7290
- kind: "property",
7291
- fqName: `${className}.${propName}`,
7292
- ownerFqName: className,
7293
- displayName: `${className}.${propName}`,
7294
- visibility: "public",
7295
- stability: "stable",
7296
- sourceKind: "generated_service_wrapper",
7297
- typeRef: { name: prop.type }
7298
- });
7299
- }
7300
- for (const [ifaceName, iface] of Object.entries(surface.interfaces)) {
7301
- symbols.push({
7302
- id: `iface:${ifaceName}`,
7303
- kind: "alias",
7304
- fqName: ifaceName,
7305
- displayName: ifaceName,
7306
- visibility: "public",
7307
- stability: "stable",
7308
- sourceKind: "generated_resource_constructor"
7309
- });
7310
- for (const [fieldName, field] of Object.entries(iface.fields)) symbols.push({
7311
- id: `field:${ifaceName}.${fieldName}`,
7312
- kind: "field",
7313
- fqName: `${ifaceName}.${fieldName}`,
7314
- ownerFqName: ifaceName,
7315
- displayName: `${ifaceName}.${fieldName}`,
7316
- visibility: "public",
7317
- stability: "stable",
7318
- sourceKind: "generated_resource_constructor",
7319
- typeRef: { name: field.type }
7320
- });
7321
- if (iface.hasCustomConstructor) symbols.push({
7322
- id: `ctor:${ifaceName}`,
7323
- kind: "constructor",
7324
- fqName: `${ifaceName}.constructor`,
7325
- ownerFqName: ifaceName,
7326
- displayName: `new ${ifaceName}`,
7327
- visibility: "public",
7328
- stability: "stable",
7329
- sourceKind: "generated_resource_constructor"
7330
- });
7331
- }
7332
- for (const [aliasName] of Object.entries(surface.typeAliases)) symbols.push({
7333
- id: `alias:${aliasName}`,
7334
- kind: "alias",
7335
- fqName: aliasName,
7336
- displayName: aliasName,
7337
- visibility: "public",
7338
- stability: "stable",
7339
- sourceKind: "generated_resource_constructor"
7340
- });
7341
- for (const [enumName, enumDef] of Object.entries(surface.enums)) {
7342
- symbols.push({
7343
- id: `enum:${enumName}`,
7344
- kind: "enum",
7345
- fqName: enumName,
7346
- displayName: enumName,
7347
- visibility: "public",
7348
- stability: "stable",
7349
- sourceKind: "generated_enum"
7350
- });
7351
- for (const [memberName, memberValue] of Object.entries(enumDef.members)) symbols.push({
7352
- id: `enum_member:${enumName}.${memberName}`,
7353
- kind: "enum_member",
7354
- fqName: `${enumName}.${memberName}`,
7355
- ownerFqName: enumName,
7356
- displayName: `${enumName}.${memberName}`,
7357
- visibility: "public",
7358
- stability: "stable",
7359
- sourceKind: "generated_enum",
7360
- value: memberValue
7361
- });
7362
- }
7363
- return {
7364
- schemaVersion: "1",
7365
- source: { extractedAt: surface.extractedAt },
7366
- policies: getDefaultPolicy(language),
7367
- symbols
7368
- };
7369
- }
7370
- /** Convert a legacy ApiParam to a CompatParameter. */
7371
- function apiParamToCompatParam(param, position, language) {
7372
- const policy = getDefaultPolicy(language);
7373
- return {
7374
- publicName: param.name,
7375
- position,
7376
- required: !param.optional,
7377
- nullable: false,
7378
- hasDefault: param.optional,
7379
- passing: param.passingStyle ?? inferPassingStyle(language),
7380
- type: { name: param.type },
7381
- sensitivity: {
7382
- order: policy.constructorOrderMatters,
7383
- publicName: policy.methodParameterNamesArePublicApi,
7384
- requiredness: true,
7385
- type: true
7386
- }
7387
- };
7388
- }
7389
- /** Infer the default parameter passing style for a language. */
7390
- function inferPassingStyle(language) {
7391
- switch (language) {
7392
- case "python":
7393
- case "ruby":
7394
- case "elixir": return "keyword";
7395
- case "php":
7396
- case "kotlin":
7397
- case "dotnet": return "named";
7398
- case "node": return "options_object";
7399
- default: return "positional";
7400
- }
7401
- }
7402
- //#endregion
7403
7484
  //#region src/verify/run-compat-check.ts
7404
7485
  async function runCompatCheck(baseline, outputDir, lang, spec, policyOverrides) {
7405
7486
  const extractor = getExtractor(lang);