@workos/oagen 0.9.2 → 0.10.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/dist/cli/index.mjs +81 -31
- package/dist/cli/index.mjs.map +1 -1
- package/dist/compat/index.mjs +1 -1
- package/dist/differ-CTl98yoS.d.mts.map +1 -1
- package/dist/{overlay-Bt6oz0dg.mjs → overlay-DWU6W29l.mjs} +39 -19
- package/dist/overlay-DWU6W29l.mjs.map +1 -0
- package/dist/verify/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/overlay-Bt6oz0dg.mjs.map +0 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -6661,17 +6661,21 @@ async function compatExtractCommand(opts) {
|
|
|
6661
6661
|
if (opts.spec) {
|
|
6662
6662
|
const specContent = readFileSync(opts.spec, "utf-8");
|
|
6663
6663
|
snapshot.source.specSha = createHash("sha256").update(specContent).digest("hex");
|
|
6664
|
-
enrichWithSpecContext(snapshot, await parseSpec(opts.spec));
|
|
6664
|
+
enrichWithSpecContext(snapshot, await parseSpec(opts.spec, { schemaNameTransform: opts.schemaNameTransform }));
|
|
6665
6665
|
}
|
|
6666
6666
|
const outputPath = resolve(opts.output, SNAPSHOT_FILENAME);
|
|
6667
6667
|
writeFileSync(outputPath, JSON.stringify(snapshot, null, 2));
|
|
6668
6668
|
console.log(`Extracted ${snapshot.symbols.length} symbols → ${outputPath}`);
|
|
6669
6669
|
}
|
|
6670
6670
|
/**
|
|
6671
|
-
* Enrich snapshot symbols with
|
|
6671
|
+
* Enrich snapshot symbols with spec-level identity.
|
|
6672
6672
|
*
|
|
6673
|
-
*
|
|
6674
|
-
*
|
|
6673
|
+
* - Callable symbols get `operationId` and `route` from spec operations.
|
|
6674
|
+
* - Property/field/constructor/service_accessor symbols get `schemaName`
|
|
6675
|
+
* from spec models, enabling cross-language grouping in reports.
|
|
6676
|
+
*
|
|
6677
|
+
* The `schemaName` uses the spec-level identity (e.g. "GenerateLinkBody.admin_emails")
|
|
6678
|
+
* which is the same regardless of the language's naming conventions.
|
|
6675
6679
|
*/
|
|
6676
6680
|
function enrichWithSpecContext(snapshot, spec) {
|
|
6677
6681
|
const opLookup = /* @__PURE__ */ new Map();
|
|
@@ -6683,15 +6687,38 @@ function enrichWithSpecContext(snapshot, spec) {
|
|
|
6683
6687
|
path: op.path
|
|
6684
6688
|
});
|
|
6685
6689
|
}
|
|
6690
|
+
const norm = (s) => s.replace(/_/g, "").toLowerCase();
|
|
6691
|
+
const modelLookup = /* @__PURE__ */ new Map();
|
|
6692
|
+
for (const model of spec.models) {
|
|
6693
|
+
const fieldMap = /* @__PURE__ */ new Map();
|
|
6694
|
+
for (const field of model.fields) fieldMap.set(norm(field.name), field.name);
|
|
6695
|
+
modelLookup.set(norm(model.name), {
|
|
6696
|
+
specName: model.name,
|
|
6697
|
+
fields: fieldMap
|
|
6698
|
+
});
|
|
6699
|
+
}
|
|
6686
6700
|
for (const sym of snapshot.symbols) {
|
|
6687
|
-
if (sym.kind
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6701
|
+
if (sym.kind === "callable") {
|
|
6702
|
+
const match = opLookup.get(sym.fqName);
|
|
6703
|
+
if (match) {
|
|
6704
|
+
sym.operationId = match.operationId;
|
|
6705
|
+
sym.route = {
|
|
6706
|
+
method: match.method,
|
|
6707
|
+
path: match.path
|
|
6708
|
+
};
|
|
6709
|
+
}
|
|
6710
|
+
}
|
|
6711
|
+
if (sym.ownerFqName) {
|
|
6712
|
+
const modelMatch = modelLookup.get(norm(sym.ownerFqName));
|
|
6713
|
+
if (modelMatch) {
|
|
6714
|
+
const localName = sym.fqName.includes(".") ? sym.fqName.split(".").pop() : sym.fqName;
|
|
6715
|
+
const fieldMatch = modelMatch.fields.get(norm(localName));
|
|
6716
|
+
if (fieldMatch) sym.schemaName = `${modelMatch.specName}.${fieldMatch}`;
|
|
6717
|
+
else sym.schemaName = modelMatch.specName;
|
|
6718
|
+
}
|
|
6719
|
+
} else {
|
|
6720
|
+
const modelMatch = modelLookup.get(norm(sym.fqName));
|
|
6721
|
+
if (modelMatch) sym.schemaName = modelMatch.specName;
|
|
6695
6722
|
}
|
|
6696
6723
|
}
|
|
6697
6724
|
}
|
|
@@ -6741,6 +6768,7 @@ function severityMeetsThreshold(severity, threshold) {
|
|
|
6741
6768
|
*/
|
|
6742
6769
|
function classifySymbolChanges(baseline, candidate, policy) {
|
|
6743
6770
|
const changes = [];
|
|
6771
|
+
const specRef = baseline.schemaName ?? candidate?.schemaName;
|
|
6744
6772
|
if (!candidate) {
|
|
6745
6773
|
changes.push(makeChange({
|
|
6746
6774
|
category: "symbol_removed",
|
|
@@ -6748,7 +6776,8 @@ function classifySymbolChanges(baseline, candidate, policy) {
|
|
|
6748
6776
|
old: { symbol: baseline.fqName },
|
|
6749
6777
|
new: { symbol: "(removed)" },
|
|
6750
6778
|
message: `Symbol "${baseline.displayName}" was removed`,
|
|
6751
|
-
policy
|
|
6779
|
+
policy,
|
|
6780
|
+
specRef
|
|
6752
6781
|
}));
|
|
6753
6782
|
return changes;
|
|
6754
6783
|
}
|
|
@@ -6758,16 +6787,18 @@ function classifySymbolChanges(baseline, candidate, policy) {
|
|
|
6758
6787
|
old: { name: baseline.fqName },
|
|
6759
6788
|
new: { name: candidate.fqName },
|
|
6760
6789
|
message: `Symbol renamed from "${baseline.displayName}" to "${candidate.displayName}"`,
|
|
6761
|
-
policy
|
|
6790
|
+
policy,
|
|
6791
|
+
specRef
|
|
6762
6792
|
}));
|
|
6763
|
-
if (baseline.parameters && candidate.parameters) changes.push(...classifyParameterChanges(baseline, candidate, policy));
|
|
6793
|
+
if (baseline.parameters && candidate.parameters) changes.push(...classifyParameterChanges(baseline, candidate, policy, specRef));
|
|
6764
6794
|
if (baseline.returns && candidate.returns && baseline.returns.name !== candidate.returns.name) changes.push(makeChange({
|
|
6765
6795
|
category: "return_type_changed",
|
|
6766
6796
|
symbol: baseline.fqName,
|
|
6767
6797
|
old: { returnType: baseline.returns.name },
|
|
6768
6798
|
new: { returnType: candidate.returns.name },
|
|
6769
6799
|
message: `Return type changed for "${baseline.displayName}" from "${baseline.returns.name}" to "${candidate.returns.name}"`,
|
|
6770
|
-
policy
|
|
6800
|
+
policy,
|
|
6801
|
+
specRef
|
|
6771
6802
|
}));
|
|
6772
6803
|
if (baseline.typeRef && candidate.typeRef && baseline.typeRef.name !== candidate.typeRef.name) changes.push(makeChange({
|
|
6773
6804
|
category: "field_type_changed",
|
|
@@ -6775,7 +6806,8 @@ function classifySymbolChanges(baseline, candidate, policy) {
|
|
|
6775
6806
|
old: { type: baseline.typeRef.name },
|
|
6776
6807
|
new: { type: candidate.typeRef.name },
|
|
6777
6808
|
message: `Type changed for "${baseline.displayName}" from "${baseline.typeRef.name}" to "${candidate.typeRef.name}"`,
|
|
6778
|
-
policy
|
|
6809
|
+
policy,
|
|
6810
|
+
specRef
|
|
6779
6811
|
}));
|
|
6780
6812
|
if (baseline.kind === "enum_member" && candidate.kind === "enum_member" && baseline.value !== void 0 && candidate.value !== void 0 && baseline.value !== candidate.value) changes.push(makeChange({
|
|
6781
6813
|
category: "enum_member_value_changed",
|
|
@@ -6790,7 +6822,7 @@ function classifySymbolChanges(baseline, candidate, policy) {
|
|
|
6790
6822
|
/**
|
|
6791
6823
|
* Classify parameter-level changes between two symbol versions.
|
|
6792
6824
|
*/
|
|
6793
|
-
function classifyParameterChanges(baseline, candidate, policy) {
|
|
6825
|
+
function classifyParameterChanges(baseline, candidate, policy, specRef) {
|
|
6794
6826
|
const changes = [];
|
|
6795
6827
|
const baseParams = baseline.parameters ?? [];
|
|
6796
6828
|
const candParams = candidate.parameters ?? [];
|
|
@@ -6810,6 +6842,7 @@ function classifyParameterChanges(baseline, candidate, policy) {
|
|
|
6810
6842
|
new: { parameter: positionalMatch.publicName },
|
|
6811
6843
|
message: `Parameter "${baseParam.publicName}" renamed to "${positionalMatch.publicName}" on "${baseline.displayName}"`,
|
|
6812
6844
|
policy,
|
|
6845
|
+
specRef,
|
|
6813
6846
|
severityOverride: isBreakingRename ? void 0 : "soft-risk"
|
|
6814
6847
|
}));
|
|
6815
6848
|
} else changes.push(makeChange({
|
|
@@ -6818,7 +6851,8 @@ function classifyParameterChanges(baseline, candidate, policy) {
|
|
|
6818
6851
|
old: { parameter: baseParam.publicName },
|
|
6819
6852
|
new: { parameter: "(removed)" },
|
|
6820
6853
|
message: `Parameter "${baseParam.publicName}" removed from "${baseline.displayName}"`,
|
|
6821
|
-
policy
|
|
6854
|
+
policy,
|
|
6855
|
+
specRef
|
|
6822
6856
|
}));
|
|
6823
6857
|
continue;
|
|
6824
6858
|
}
|
|
@@ -6834,7 +6868,8 @@ function classifyParameterChanges(baseline, candidate, policy) {
|
|
|
6834
6868
|
required: "true"
|
|
6835
6869
|
},
|
|
6836
6870
|
message: `Parameter "${baseParam.publicName}" became required on "${baseline.displayName}"`,
|
|
6837
|
-
policy
|
|
6871
|
+
policy,
|
|
6872
|
+
specRef
|
|
6838
6873
|
}));
|
|
6839
6874
|
if (baseParam.type.name !== candParam.type.name) changes.push(makeChange({
|
|
6840
6875
|
category: "parameter_type_narrowed",
|
|
@@ -6848,7 +6883,8 @@ function classifyParameterChanges(baseline, candidate, policy) {
|
|
|
6848
6883
|
type: candParam.type.name
|
|
6849
6884
|
},
|
|
6850
6885
|
message: `Parameter type changed for "${baseParam.publicName}" on "${baseline.displayName}"`,
|
|
6851
|
-
policy
|
|
6886
|
+
policy,
|
|
6887
|
+
specRef
|
|
6852
6888
|
}));
|
|
6853
6889
|
if (baseParam.position !== candParam.position) if (isConstructor ? policy.constructorOrderMatters : baseParam.sensitivity.order) {
|
|
6854
6890
|
const category = isConstructor ? "constructor_position_changed_order_sensitive" : "parameter_position_changed_order_sensitive";
|
|
@@ -6864,7 +6900,8 @@ function classifyParameterChanges(baseline, candidate, policy) {
|
|
|
6864
6900
|
position: String(candParam.position)
|
|
6865
6901
|
},
|
|
6866
6902
|
message: `Parameter "${baseParam.publicName}" moved from position ${baseParam.position} to ${candParam.position} on "${baseline.displayName}"`,
|
|
6867
|
-
policy
|
|
6903
|
+
policy,
|
|
6904
|
+
specRef
|
|
6868
6905
|
}));
|
|
6869
6906
|
} else changes.push(makeChange({
|
|
6870
6907
|
category: "constructor_reordered_named_friendly",
|
|
@@ -6878,7 +6915,8 @@ function classifyParameterChanges(baseline, candidate, policy) {
|
|
|
6878
6915
|
position: String(candParam.position)
|
|
6879
6916
|
},
|
|
6880
6917
|
message: `Parameter "${baseParam.publicName}" reordered on "${baseline.displayName}" (named-friendly language)`,
|
|
6881
|
-
policy
|
|
6918
|
+
policy,
|
|
6919
|
+
specRef
|
|
6882
6920
|
}));
|
|
6883
6921
|
}
|
|
6884
6922
|
for (const candParam of candParams) if (!baseByName.has(candParam.publicName)) {
|
|
@@ -6894,7 +6932,8 @@ function classifyParameterChanges(baseline, candidate, policy) {
|
|
|
6894
6932
|
required: "true"
|
|
6895
6933
|
},
|
|
6896
6934
|
message: `Required parameter "${candParam.publicName}" added to "${baseline.displayName}"`,
|
|
6897
|
-
policy
|
|
6935
|
+
policy,
|
|
6936
|
+
specRef
|
|
6898
6937
|
}));
|
|
6899
6938
|
else changes.push(makeChange({
|
|
6900
6939
|
category,
|
|
@@ -6902,7 +6941,8 @@ function classifyParameterChanges(baseline, candidate, policy) {
|
|
|
6902
6941
|
old: { parameter: "(absent)" },
|
|
6903
6942
|
new: { parameter: candParam.publicName },
|
|
6904
6943
|
message: `Optional parameter "${candParam.publicName}" added to "${baseline.displayName}"`,
|
|
6905
|
-
policy
|
|
6944
|
+
policy,
|
|
6945
|
+
specRef
|
|
6906
6946
|
}));
|
|
6907
6947
|
}
|
|
6908
6948
|
return changes;
|
|
@@ -6912,12 +6952,19 @@ function parameterNameIsPublicApi(param, policy, isConstructor) {
|
|
|
6912
6952
|
if (isConstructor) return policy.constructorParameterNamesArePublicApi;
|
|
6913
6953
|
return policy.methodParameterNamesArePublicApi;
|
|
6914
6954
|
}
|
|
6915
|
-
/**
|
|
6916
|
-
|
|
6955
|
+
/**
|
|
6956
|
+
* Build a deterministic conceptual change ID.
|
|
6957
|
+
*
|
|
6958
|
+
* When `specRef` is provided (e.g. "GenerateLinkBody.admin_emails"), it is
|
|
6959
|
+
* used instead of the language-specific symbol name. This ensures the same
|
|
6960
|
+
* spec entity produces the same ID across all languages, enabling cross-
|
|
6961
|
+
* language rollup in reports.
|
|
6962
|
+
*/
|
|
6963
|
+
function buildConceptualChangeId(category, symbol, match, specRef) {
|
|
6917
6964
|
const parts = [
|
|
6918
6965
|
"chg",
|
|
6919
6966
|
category,
|
|
6920
|
-
symbol.replace(/[^a-zA-Z0-9_.]/g, "_")
|
|
6967
|
+
(specRef ?? symbol).replace(/[^a-zA-Z0-9_.]/g, "_")
|
|
6921
6968
|
];
|
|
6922
6969
|
if (match.parameter) parts.push(match.parameter);
|
|
6923
6970
|
if (match.member) parts.push(match.member);
|
|
@@ -6928,7 +6975,7 @@ function makeChange(opts) {
|
|
|
6928
6975
|
category: opts.category,
|
|
6929
6976
|
severity: opts.severityOverride ?? defaultSeverityForCategory(opts.category),
|
|
6930
6977
|
symbol: opts.symbol,
|
|
6931
|
-
conceptualChangeId: buildConceptualChangeId(opts.category, opts.symbol, opts.old),
|
|
6978
|
+
conceptualChangeId: buildConceptualChangeId(opts.category, opts.symbol, opts.old, opts.specRef),
|
|
6932
6979
|
provenance: opts.provenance ?? "unknown",
|
|
6933
6980
|
old: opts.old,
|
|
6934
6981
|
new: opts.new,
|
|
@@ -6943,7 +6990,7 @@ function classifyAddedSymbol(symbol) {
|
|
|
6943
6990
|
category: "symbol_added",
|
|
6944
6991
|
severity: "additive",
|
|
6945
6992
|
symbol: symbol.fqName,
|
|
6946
|
-
conceptualChangeId: buildConceptualChangeId("symbol_added", symbol.fqName, {}),
|
|
6993
|
+
conceptualChangeId: buildConceptualChangeId("symbol_added", symbol.fqName, {}, symbol.schemaName),
|
|
6947
6994
|
provenance: "unknown",
|
|
6948
6995
|
old: { symbol: "(absent)" },
|
|
6949
6996
|
new: { symbol: symbol.fqName },
|
|
@@ -8355,7 +8402,10 @@ program.command("extract").description("Extract public API surface from a live S
|
|
|
8355
8402
|
});
|
|
8356
8403
|
program.command("compat-extract").description("Extract a compat snapshot from a live SDK and write .oagen-compat-snapshot.json").requiredOption("--sdk-path <path>", "Path to the live SDK").requiredOption("--lang <language>", "Target language").requiredOption("--output <dir>", "Directory to write .oagen-compat-snapshot.json into").option("--spec <path>", "Path to OpenAPI spec — enriches symbols with operationId, route, and specSha").action((opts) => {
|
|
8357
8404
|
opts.spec ??= process.env.OPENAPI_SPEC_PATH;
|
|
8358
|
-
compatExtractCommand(
|
|
8405
|
+
compatExtractCommand({
|
|
8406
|
+
...opts,
|
|
8407
|
+
schemaNameTransform: configSchemaNameTransform
|
|
8408
|
+
}).catch(handleError);
|
|
8359
8409
|
});
|
|
8360
8410
|
program.command("compat-diff").description("Diff two compat snapshot files and produce a classified change report").requiredOption("--baseline <path>", "Path to the baseline compat snapshot JSON").requiredOption("--candidate <path>", "Path to the candidate compat snapshot JSON").option("--output <path>", "Write machine-readable report to this path").option("--fail-on <level>", "Fail threshold: none, breaking, or soft-risk", "breaking").option("--explain", "Include provenance explanations in output").action((opts) => {
|
|
8361
8411
|
compatDiffCommand(opts).catch(handleError);
|