@workos/oagen 0.21.0 → 0.21.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 +229 -34
- package/dist/cli/index.mjs.map +1 -1
- package/dist/{diff-CBFCoTCw.mjs → diff-Dobf9PHC.mjs} +205 -33
- package/dist/diff-Dobf9PHC.mjs.map +1 -0
- package/dist/index.mjs +26 -3
- package/dist/index.mjs.map +1 -1
- package/dist/scripts/smoke/baseline.mjs +25 -2
- package/dist/scripts/smoke/baseline.mjs.map +1 -1
- package/dist/smoke.mjs +25 -2
- package/dist/smoke.mjs.map +1 -1
- package/dist/verify/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/diff-CBFCoTCw.mjs.map +0 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -433,7 +433,7 @@ function qualifyInlineModelName(baseName, parentName) {
|
|
|
433
433
|
function extractInlineModelsFromSchemas(schemas) {
|
|
434
434
|
if (!schemas) return [];
|
|
435
435
|
const inlineModels = [];
|
|
436
|
-
for (const [schemaName, schema] of Object.entries(schemas)) extractInlineModelsFromProperties(schema, inlineModels,
|
|
436
|
+
for (const [schemaName, schema] of Object.entries(schemas)) extractInlineModelsFromProperties(schema, inlineModels, resolveSchemaName(schemaName));
|
|
437
437
|
return inlineModels;
|
|
438
438
|
}
|
|
439
439
|
function extractInlineModelsFromProperties(schema, results, parentName) {
|
|
@@ -2617,6 +2617,27 @@ function collapseJsonSuffixModels(models, services) {
|
|
|
2617
2617
|
rewriteModelRefs(normalizedModels, services, jsonModel.name, baseModel.name);
|
|
2618
2618
|
console.warn(`[oagen] Merged "${jsonModel.name}" into "${baseModel.name}" (${jsonModel.fields.length} fields, superset)`);
|
|
2619
2619
|
}
|
|
2620
|
+
for (const { jsonModel, baseModel } of mergeCandidates) {
|
|
2621
|
+
const jsonPrefix = jsonModel.name;
|
|
2622
|
+
const basePrefix = baseModel.name;
|
|
2623
|
+
for (const model of normalizedModels) {
|
|
2624
|
+
if (toRemove.has(model.name)) continue;
|
|
2625
|
+
if (model.name.length <= jsonPrefix.length) continue;
|
|
2626
|
+
if (!model.name.startsWith(jsonPrefix)) continue;
|
|
2627
|
+
const newName = basePrefix + model.name.slice(jsonPrefix.length);
|
|
2628
|
+
const existing = byName.get(newName);
|
|
2629
|
+
if (existing && !toRemove.has(existing.name)) {
|
|
2630
|
+
toRemove.add(model.name);
|
|
2631
|
+
rewriteModelRefs(normalizedModels, services, model.name, newName);
|
|
2632
|
+
console.warn(`[oagen] Collapsed child "${model.name}" into existing "${newName}"`);
|
|
2633
|
+
} else {
|
|
2634
|
+
rewriteModelRefs(normalizedModels, services, model.name, newName);
|
|
2635
|
+
model.name = newName;
|
|
2636
|
+
byName.set(newName, model);
|
|
2637
|
+
console.warn(`[oagen] Renamed child "${jsonPrefix}…" → "${newName}"`);
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2620
2641
|
return normalizedModels.filter((m) => !toRemove.has(m.name));
|
|
2621
2642
|
}
|
|
2622
2643
|
//#endregion
|
|
@@ -2669,8 +2690,10 @@ async function parseSpec(specPath, options) {
|
|
|
2669
2690
|
if (!version.startsWith("3.")) throw new SpecParseError(`Unsupported OpenAPI version: ${version}. oagen requires OpenAPI 3.x`, `Update the spec to OpenAPI 3.0 or 3.1. If you are using Swagger 2.x, convert it first with \`npx swagger2openapi ${specPath}\`.`);
|
|
2670
2691
|
const { models, enums } = extractSchemas(spec.components?.schemas, { schemaNameTransform: options?.schemaNameTransform });
|
|
2671
2692
|
const { services, inlineModels } = extractOperations(spec.paths, options?.operationIdTransform, spec.components?.schemas);
|
|
2693
|
+
const responseNormalizedModels = mergeInlineResponseModels(models, inlineModels);
|
|
2694
|
+
const fieldInlineModels = extractInlineModelsFromSchemas(spec.components?.schemas);
|
|
2672
2695
|
clearSchemaNameTransform();
|
|
2673
|
-
const finalModels = collapseJsonSuffixModels(mergeFieldInlineModels(
|
|
2696
|
+
const finalModels = collapseJsonSuffixModels(mergeFieldInlineModels(responseNormalizedModels, fieldInlineModels), services);
|
|
2674
2697
|
collectInlineEnumsFromModels(finalModels, enums);
|
|
2675
2698
|
collectInlineEnumsFromOperations(services, enums);
|
|
2676
2699
|
const auth = extractAuthSchemes(spec.components?.securitySchemes);
|
|
@@ -4279,10 +4302,10 @@ async function extractClassEndLines(source, language) {
|
|
|
4279
4302
|
const tree = safeParse(await getParser(language), source);
|
|
4280
4303
|
const map = /* @__PURE__ */ new Map();
|
|
4281
4304
|
function processClassNode(node) {
|
|
4282
|
-
const nameNode = node.childForFieldName("name");
|
|
4305
|
+
const nameNode = node.childForFieldName("name") ?? node.children.find((c) => c.type === "type_identifier" || c.type === "identifier");
|
|
4283
4306
|
if (!nameNode) return;
|
|
4284
4307
|
const name = nameNode.text;
|
|
4285
|
-
const body = node.childForFieldName("body");
|
|
4308
|
+
const body = node.childForFieldName("body") ?? node.children.find((c) => c.type === "class_body" || c.type === "body");
|
|
4286
4309
|
const endRow = body ? body.endPosition.row : node.endPosition.row;
|
|
4287
4310
|
if (source[body ? body.endIndex - 1 : node.endIndex - 1] === "}") map.set(name, { bodyEndLine: endRow });
|
|
4288
4311
|
else map.set(name, { bodyEndLine: endRow + 1 });
|
|
@@ -4831,9 +4854,16 @@ async function overwriteWithPreservedRegions(existingContent, generatedContent,
|
|
|
4831
4854
|
if (!existingLines[i].includes("@oagen-ignore-start")) continue;
|
|
4832
4855
|
const startIdx = i;
|
|
4833
4856
|
while (i < existingLines.length && !existingLines[i].includes("@oagen-ignore-end")) i++;
|
|
4857
|
+
let anchor = "";
|
|
4858
|
+
for (let a = i + 1; a < existingLines.length; a++) if (existingLines[a].trim()) {
|
|
4859
|
+
anchor = existingLines[a].trimStart();
|
|
4860
|
+
break;
|
|
4861
|
+
}
|
|
4834
4862
|
blocks.push({
|
|
4835
4863
|
containingClass: findContainingClass(existingLines, startIdx),
|
|
4836
|
-
|
|
4864
|
+
containingScope: findContainingDescribeScope(existingLines, startIdx),
|
|
4865
|
+
lines: existingLines.slice(startIdx, i + 1),
|
|
4866
|
+
anchor
|
|
4837
4867
|
});
|
|
4838
4868
|
}
|
|
4839
4869
|
if (blocks.length === 0) return generatedContent;
|
|
@@ -4843,15 +4873,19 @@ async function overwriteWithPreservedRegions(existingContent, generatedContent,
|
|
|
4843
4873
|
const blocksByClass = /* @__PURE__ */ new Map();
|
|
4844
4874
|
for (const b of blocks) {
|
|
4845
4875
|
if (!blocksByClass.has(b.containingClass)) blocksByClass.set(b.containingClass, []);
|
|
4846
|
-
blocksByClass.get(b.containingClass).push(
|
|
4876
|
+
blocksByClass.get(b.containingClass).push({
|
|
4877
|
+
containingScope: b.containingScope,
|
|
4878
|
+
lines: b.lines,
|
|
4879
|
+
anchor: b.anchor
|
|
4880
|
+
});
|
|
4847
4881
|
}
|
|
4848
4882
|
const replacedClasses = /* @__PURE__ */ new Set();
|
|
4849
4883
|
const handledBlockKeys = /* @__PURE__ */ new Set();
|
|
4850
4884
|
const replacements = [];
|
|
4851
4885
|
for (const [className, classBlocks] of blocksByClass) {
|
|
4852
4886
|
let targetClass = className;
|
|
4853
|
-
if (!targetClass) for (const
|
|
4854
|
-
for (const l of
|
|
4887
|
+
if (!targetClass) for (const entry of classBlocks) {
|
|
4888
|
+
for (const l of entry.lines) {
|
|
4855
4889
|
const m = l.match(/^(?:export\s+)?class\s+(\w+)/);
|
|
4856
4890
|
if (m && classEndLines.has(m[1])) {
|
|
4857
4891
|
targetClass = m[1];
|
|
@@ -4861,7 +4895,7 @@ async function overwriteWithPreservedRegions(existingContent, generatedContent,
|
|
|
4861
4895
|
if (targetClass) break;
|
|
4862
4896
|
}
|
|
4863
4897
|
if (!targetClass) continue;
|
|
4864
|
-
if (!classBlocks.some((
|
|
4898
|
+
if (!classBlocks.some((entry) => entry.lines.some((l) => {
|
|
4865
4899
|
return l.match(/^(?:export\s+)?class\s+(\w+)/)?.[1] === targetClass;
|
|
4866
4900
|
}))) continue;
|
|
4867
4901
|
const info = classEndLines.get(targetClass);
|
|
@@ -4869,9 +4903,9 @@ async function overwriteWithPreservedRegions(existingContent, generatedContent,
|
|
|
4869
4903
|
const startLine = findClassDeclarationStart(result, targetClass, info.bodyEndLine);
|
|
4870
4904
|
if (startLine < 0) continue;
|
|
4871
4905
|
const content = [];
|
|
4872
|
-
for (const
|
|
4906
|
+
for (const entry of classBlocks) {
|
|
4873
4907
|
content.push("");
|
|
4874
|
-
content.push(...
|
|
4908
|
+
content.push(...entry.lines);
|
|
4875
4909
|
}
|
|
4876
4910
|
replacements.push({
|
|
4877
4911
|
startLine,
|
|
@@ -4886,22 +4920,46 @@ async function overwriteWithPreservedRegions(existingContent, generatedContent,
|
|
|
4886
4920
|
let effectiveClassEndLines = classEndLines;
|
|
4887
4921
|
if (replacedClasses.size > 0) effectiveClassEndLines = await extractClassEndLines(result.join("\n"), language);
|
|
4888
4922
|
const insertions = [];
|
|
4923
|
+
let insertionOrder = 0;
|
|
4889
4924
|
for (const [className, classBlocks] of blocksByClass) {
|
|
4890
4925
|
if (handledBlockKeys.has(className) || replacedClasses.has(className)) continue;
|
|
4891
4926
|
const info = className ? effectiveClassEndLines.get(className) : void 0;
|
|
4892
|
-
const
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4927
|
+
for (const entry of classBlocks) {
|
|
4928
|
+
let insertLine;
|
|
4929
|
+
if (entry.anchor && !entry.anchor.includes("@oagen-ignore") && /[a-zA-Z]|^\/\*|^\/\//.test(entry.anchor)) {
|
|
4930
|
+
for (let li = 0; li < result.length; li++) if (result[li].trimStart() === entry.anchor) {
|
|
4931
|
+
insertLine = li;
|
|
4932
|
+
break;
|
|
4933
|
+
}
|
|
4934
|
+
}
|
|
4935
|
+
if (insertLine === void 0) if (info) insertLine = info.bodyEndLine;
|
|
4936
|
+
else {
|
|
4937
|
+
const scopeEndLine = entry.containingScope ? findDescribeScopeEndLine(result, entry.containingScope) : void 0;
|
|
4938
|
+
const blockHasImportsFallback = entry.lines.some((l) => /^\s*(import|from)\s/.test(l));
|
|
4939
|
+
if (scopeEndLine !== void 0) insertLine = scopeEndLine;
|
|
4940
|
+
else if (blockHasImportsFallback || hasTopLevelDeclaration(entry.lines)) {
|
|
4941
|
+
let lastImportLine = 0;
|
|
4942
|
+
for (let li = 0; li < result.length; li++) {
|
|
4943
|
+
const trimmed = result[li].trimStart();
|
|
4944
|
+
if (/^(import|from)\s/.test(trimmed)) lastImportLine = li + 1;
|
|
4945
|
+
}
|
|
4946
|
+
insertLine = lastImportLine;
|
|
4947
|
+
} else insertLine = result.length;
|
|
4948
|
+
}
|
|
4949
|
+
if (entry.lines.some((l) => /^\s*import\s/.test(l))) while (insertLine >= 2 && result[insertLine - 1]?.trim() === "" && /^\s*(import|using|from)\s/.test(result[insertLine - 2] ?? "")) insertLine--;
|
|
4950
|
+
const prevLine = insertLine > 0 ? result[insertLine - 1]?.trimStart() ?? "" : "";
|
|
4951
|
+
const blockContent = /^import\s/.test(prevLine) || /^using\s/.test(prevLine) || /^from\s/.test(prevLine) || insertLine > 0 && prevLine === "" ? [...entry.lines] : ["", ...entry.lines];
|
|
4952
|
+
if ((result[insertLine]?.trimStart() ?? "").startsWith("///")) blockContent.push("");
|
|
4953
|
+
insertions.push({
|
|
4954
|
+
line: insertLine,
|
|
4955
|
+
order: insertionOrder++,
|
|
4956
|
+
content: blockContent
|
|
4957
|
+
});
|
|
4897
4958
|
}
|
|
4898
|
-
insertions.push({
|
|
4899
|
-
line: insertLine,
|
|
4900
|
-
content
|
|
4901
|
-
});
|
|
4902
4959
|
}
|
|
4903
|
-
insertions.sort((a, b) => b.line - a.line);
|
|
4960
|
+
insertions.sort((a, b) => b.line - a.line || b.order - a.order);
|
|
4904
4961
|
for (const ins of insertions) result.splice(ins.line, 0, ...ins.content);
|
|
4962
|
+
removeDuplicateImportsCoveredByIgnoreBlocks(result);
|
|
4905
4963
|
return result.join("\n");
|
|
4906
4964
|
}
|
|
4907
4965
|
/**
|
|
@@ -4929,12 +4987,47 @@ function stripIgnoreRegions(lines) {
|
|
|
4929
4987
|
}
|
|
4930
4988
|
/** Scan backwards from `lineIdx` to find the nearest class declaration name. */
|
|
4931
4989
|
function findContainingClass(lines, lineIdx) {
|
|
4990
|
+
if (/^\S/.test(lines[lineIdx] ?? "")) return "";
|
|
4932
4991
|
for (let j = lineIdx - 1; j >= 0; j--) {
|
|
4933
|
-
const m = lines[j].match(/^\s*(?:export\s+)
|
|
4992
|
+
const m = lines[j].match(/^\s*(?:(?:export|public|private|protected|internal|abstract|sealed|static|partial)\s+)*class\s+(\w+)/);
|
|
4934
4993
|
if (m) return m[1];
|
|
4935
4994
|
}
|
|
4936
4995
|
return "";
|
|
4937
4996
|
}
|
|
4997
|
+
function findContainingDescribeScope(lines, lineIdx) {
|
|
4998
|
+
const markerLine = lines[lineIdx] ?? "";
|
|
4999
|
+
if (/^\S/.test(markerLine)) return "";
|
|
5000
|
+
const markerIndent = leadingSpaces(markerLine);
|
|
5001
|
+
for (let j = lineIdx - 1; j >= 0; j--) {
|
|
5002
|
+
const line = lines[j];
|
|
5003
|
+
if (leadingSpaces(line) >= markerIndent) continue;
|
|
5004
|
+
const match = line.match(/^\s*describe\((['"`])(.+?)\1\s*,/);
|
|
5005
|
+
if (match) return match[2];
|
|
5006
|
+
if (/^\s*(?:export\s+)?class\s+\w+/.test(line)) return "";
|
|
5007
|
+
}
|
|
5008
|
+
return "";
|
|
5009
|
+
}
|
|
5010
|
+
function findDescribeScopeEndLine(lines, scopeName) {
|
|
5011
|
+
for (let i = 0; i < lines.length; i++) {
|
|
5012
|
+
const match = lines[i].match(/^\s*describe\((['"`])(.+?)\1\s*,/);
|
|
5013
|
+
if (!match || match[2] !== scopeName) continue;
|
|
5014
|
+
let depth = 0;
|
|
5015
|
+
for (let j = i; j < lines.length; j++) {
|
|
5016
|
+
depth += countChar(lines[j], "{");
|
|
5017
|
+
depth -= countChar(lines[j], "}");
|
|
5018
|
+
if (j > i && depth <= 0) return j;
|
|
5019
|
+
}
|
|
5020
|
+
}
|
|
5021
|
+
}
|
|
5022
|
+
function leadingSpaces(line) {
|
|
5023
|
+
return line.match(/^\s*/)?.[0].length ?? 0;
|
|
5024
|
+
}
|
|
5025
|
+
function countChar(line, char) {
|
|
5026
|
+
return [...line].filter((c) => c === char).length;
|
|
5027
|
+
}
|
|
5028
|
+
function hasTopLevelDeclaration(lines) {
|
|
5029
|
+
return lines.some((line) => /^(?:export\s+)?(?:interface|type|class|function|const|let|var|enum)\s+\w+/.test(line.trim()));
|
|
5030
|
+
}
|
|
4938
5031
|
/**
|
|
4939
5032
|
* Find the start line of a class declaration (including decorators above it)
|
|
4940
5033
|
* by scanning backwards from `beforeLine`.
|
|
@@ -5012,9 +5105,13 @@ function collectTsImports(lines) {
|
|
|
5012
5105
|
const mod = m[4];
|
|
5013
5106
|
if (defaultName) out.defaults.set(mod, defaultName);
|
|
5014
5107
|
const names = namesRaw.split(",").map((s) => s.trim().replace(/\s+as\s+\w+$/, "")).filter(Boolean);
|
|
5015
|
-
const
|
|
5016
|
-
|
|
5017
|
-
|
|
5108
|
+
for (const rawName of names) {
|
|
5109
|
+
const isInlineTypeOnly = rawName.startsWith("type ");
|
|
5110
|
+
const name = rawName.replace(/^type\s+/, "");
|
|
5111
|
+
const target = isTypeOnly || isInlineTypeOnly ? out.typeOnly : out.named;
|
|
5112
|
+
if (!target.has(mod)) target.set(mod, /* @__PURE__ */ new Set());
|
|
5113
|
+
target.get(mod).add(name);
|
|
5114
|
+
}
|
|
5018
5115
|
continue;
|
|
5019
5116
|
}
|
|
5020
5117
|
m = normalized.match(/^import\s+(?:type\s+)?(\w+)\s+from\s+['"]([^'"]+)['"]$/);
|
|
@@ -5037,12 +5134,99 @@ function collectTsImports(lines) {
|
|
|
5037
5134
|
*
|
|
5038
5135
|
* Mutates `resultLines` in place.
|
|
5039
5136
|
*/
|
|
5137
|
+
function filterOutIgnoreRegions(lines) {
|
|
5138
|
+
const out = [];
|
|
5139
|
+
let skipping = false;
|
|
5140
|
+
for (const line of lines) {
|
|
5141
|
+
if (!skipping && line.includes("@oagen-ignore-start")) {
|
|
5142
|
+
skipping = true;
|
|
5143
|
+
continue;
|
|
5144
|
+
}
|
|
5145
|
+
if (skipping) {
|
|
5146
|
+
if (line.includes("@oagen-ignore-end")) skipping = false;
|
|
5147
|
+
continue;
|
|
5148
|
+
}
|
|
5149
|
+
out.push(line);
|
|
5150
|
+
}
|
|
5151
|
+
return out;
|
|
5152
|
+
}
|
|
5153
|
+
function collectIgnoreRegionUsageText(lines) {
|
|
5154
|
+
const out = [];
|
|
5155
|
+
let skipping = false;
|
|
5156
|
+
for (const line of lines) {
|
|
5157
|
+
if (!skipping && line.includes("@oagen-ignore-start")) {
|
|
5158
|
+
skipping = true;
|
|
5159
|
+
continue;
|
|
5160
|
+
}
|
|
5161
|
+
if (!skipping) continue;
|
|
5162
|
+
if (/^\s*(import|from)\s/.test(line)) continue;
|
|
5163
|
+
out.push(line);
|
|
5164
|
+
if (line.includes("@oagen-ignore-end")) skipping = false;
|
|
5165
|
+
}
|
|
5166
|
+
return out.join("\n");
|
|
5167
|
+
}
|
|
5168
|
+
function removeDuplicateImportsCoveredByIgnoreBlocks(lines) {
|
|
5169
|
+
const ignoredImports = /* @__PURE__ */ new Set();
|
|
5170
|
+
const importStatements = collectImportStatements(lines);
|
|
5171
|
+
for (const stmt of importStatements) if (stmt.inIgnore) ignoredImports.add(normalizeImportStatement(stmt.lines));
|
|
5172
|
+
if (ignoredImports.size === 0) return;
|
|
5173
|
+
for (const stmt of [...importStatements].reverse()) {
|
|
5174
|
+
if (stmt.inIgnore) continue;
|
|
5175
|
+
if (ignoredImports.has(normalizeImportStatement(stmt.lines))) lines.splice(stmt.start, stmt.end - stmt.start + 1);
|
|
5176
|
+
}
|
|
5177
|
+
}
|
|
5178
|
+
function collectImportStatements(lines) {
|
|
5179
|
+
const statements = [];
|
|
5180
|
+
let inIgnore = false;
|
|
5181
|
+
for (let i = 0; i < lines.length; i++) {
|
|
5182
|
+
const line = lines[i];
|
|
5183
|
+
if (!inIgnore && line.includes("@oagen-ignore-start")) {
|
|
5184
|
+
inIgnore = true;
|
|
5185
|
+
continue;
|
|
5186
|
+
}
|
|
5187
|
+
if (inIgnore && line.includes("@oagen-ignore-end")) {
|
|
5188
|
+
inIgnore = false;
|
|
5189
|
+
continue;
|
|
5190
|
+
}
|
|
5191
|
+
if (!isImportLine(line)) continue;
|
|
5192
|
+
const start = i;
|
|
5193
|
+
let end = i;
|
|
5194
|
+
const statementLines = [line];
|
|
5195
|
+
if ((line.match(/[({]/g) ?? []).length > (line.match(/[)}]/g) ?? []).length) {
|
|
5196
|
+
while (end + 1 < lines.length) {
|
|
5197
|
+
end++;
|
|
5198
|
+
statementLines.push(lines[end]);
|
|
5199
|
+
if ((lines[end].match(/[)}]/g) ?? []).length > 0 && /\bfrom\b/.test(lines[end])) break;
|
|
5200
|
+
}
|
|
5201
|
+
i = end;
|
|
5202
|
+
}
|
|
5203
|
+
statements.push({
|
|
5204
|
+
start,
|
|
5205
|
+
end,
|
|
5206
|
+
lines: statementLines,
|
|
5207
|
+
inIgnore
|
|
5208
|
+
});
|
|
5209
|
+
}
|
|
5210
|
+
return statements;
|
|
5211
|
+
}
|
|
5212
|
+
function normalizeImportStatement(lines) {
|
|
5213
|
+
return lines.join("\n").replace(/,\s*}/g, " }").replace(/\s+/g, " ").trim();
|
|
5214
|
+
}
|
|
5215
|
+
function isImportLine(line) {
|
|
5216
|
+
const trimmed = line.trim();
|
|
5217
|
+
return /^import(\s|$)/.test(trimmed) || /^from\s+/.test(trimmed) || /^use\s+[\w\\]/.test(trimmed) || /^require(_relative)?\s+['"]/.test(trimmed);
|
|
5218
|
+
}
|
|
5219
|
+
function identifierUsed(source, identifier) {
|
|
5220
|
+
return new RegExp(`\\b${identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`).test(source);
|
|
5221
|
+
}
|
|
5040
5222
|
function spliceExtraImports(existingLines, resultLines) {
|
|
5223
|
+
const existingOutsideIgnore = filterOutIgnoreRegions(existingLines);
|
|
5224
|
+
const ignoreRegionText = collectIgnoreRegionUsageText(existingLines);
|
|
5041
5225
|
const isPythonSimpleImport = (l) => /^import\s+\w/.test(l) && !/\sfrom\s/.test(l) && !/[{}]/.test(l);
|
|
5042
|
-
const existingSimple = new Set(
|
|
5226
|
+
const existingSimple = new Set(existingOutsideIgnore.filter(isPythonSimpleImport).map((l) => l.trim()));
|
|
5043
5227
|
const generatedSimple = new Set(resultLines.filter(isPythonSimpleImport).map((l) => l.trim()));
|
|
5044
5228
|
const extraSimple = [...existingSimple].filter((l) => !generatedSimple.has(l));
|
|
5045
|
-
const existingFrom = collectFromImports(
|
|
5229
|
+
const existingFrom = collectFromImports(existingOutsideIgnore);
|
|
5046
5230
|
const generatedFrom = collectFromImports(resultLines);
|
|
5047
5231
|
const allGeneratedIds = /* @__PURE__ */ new Set();
|
|
5048
5232
|
for (const ids of generatedFrom.values()) for (const id of ids) allGeneratedIds.add(id);
|
|
@@ -5057,29 +5241,33 @@ function spliceExtraImports(existingLines, resultLines) {
|
|
|
5057
5241
|
if (extra.length > 0) extraFromLines.push(`from ${mod} import ${extra.join(", ")}`);
|
|
5058
5242
|
}
|
|
5059
5243
|
}
|
|
5060
|
-
const existingTs = collectTsImports(
|
|
5244
|
+
const existingTs = collectTsImports(existingOutsideIgnore);
|
|
5061
5245
|
const generatedTs = collectTsImports(resultLines);
|
|
5062
5246
|
const extraTsLines = [];
|
|
5063
5247
|
for (const mod of existingTs.sideEffects) if (!generatedTs.sideEffects.has(mod)) extraTsLines.push(`import '${mod}';`);
|
|
5064
5248
|
for (const [mod, name] of existingTs.defaults) {
|
|
5065
5249
|
if (generatedTs.defaults.has(mod)) continue;
|
|
5250
|
+
if (!identifierUsed(ignoreRegionText, name)) continue;
|
|
5066
5251
|
extraTsLines.push(`import ${name} from '${mod}';`);
|
|
5067
5252
|
}
|
|
5068
|
-
for (const [mod, name] of existingTs.namespaces)
|
|
5253
|
+
for (const [mod, name] of existingTs.namespaces) {
|
|
5254
|
+
if (!identifierUsed(ignoreRegionText, name)) continue;
|
|
5255
|
+
if (!generatedTs.namespaces.has(mod)) extraTsLines.push(`import * as ${name} from '${mod}';`);
|
|
5256
|
+
}
|
|
5069
5257
|
for (const [mod, existIds] of existingTs.named) {
|
|
5070
5258
|
const genIds = generatedTs.named.get(mod) ?? /* @__PURE__ */ new Set();
|
|
5071
5259
|
const genTypeIds = generatedTs.typeOnly.get(mod) ?? /* @__PURE__ */ new Set();
|
|
5072
|
-
const extra = [...existIds].filter((id) => !genIds.has(id) && !genTypeIds.has(id));
|
|
5260
|
+
const extra = [...existIds].filter((id) => !genIds.has(id) && !genTypeIds.has(id) && identifierUsed(ignoreRegionText, id));
|
|
5073
5261
|
if (extra.length > 0) extraTsLines.push(`import { ${extra.join(", ")} } from '${mod}';`);
|
|
5074
5262
|
}
|
|
5075
5263
|
for (const [mod, existIds] of existingTs.typeOnly) {
|
|
5076
5264
|
const genIds = generatedTs.typeOnly.get(mod) ?? /* @__PURE__ */ new Set();
|
|
5077
5265
|
const genNamedIds = generatedTs.named.get(mod) ?? /* @__PURE__ */ new Set();
|
|
5078
|
-
const extra = [...existIds].filter((id) => !genIds.has(id) && !genNamedIds.has(id));
|
|
5266
|
+
const extra = [...existIds].filter((id) => !genIds.has(id) && !genNamedIds.has(id) && identifierUsed(ignoreRegionText, id));
|
|
5079
5267
|
if (extra.length > 0) extraTsLines.push(`import type { ${extra.join(", ")} } from '${mod}';`);
|
|
5080
5268
|
}
|
|
5081
5269
|
const isPhpUseImport = (l) => /^use\s+[\w\\]+\\[\w\\]*(\s+as\s+\w+)?\s*;?$/.test(l);
|
|
5082
|
-
const existingPhpUse = new Set(
|
|
5270
|
+
const existingPhpUse = new Set(existingOutsideIgnore.filter(isPhpUseImport).map((l) => l.trim()));
|
|
5083
5271
|
const generatedPhpUse = new Set(resultLines.filter(isPhpUseImport).map((l) => l.trim()));
|
|
5084
5272
|
const extraPhpUse = [...existingPhpUse].filter((l) => !generatedPhpUse.has(l));
|
|
5085
5273
|
const rubyRequireRe = /^(require(?:_relative)?)\s+['"]([^'"]+)['"]\s*$/;
|
|
@@ -5094,7 +5282,7 @@ function spliceExtraImports(existingLines, resultLines) {
|
|
|
5094
5282
|
}
|
|
5095
5283
|
const seenExistingKeys = /* @__PURE__ */ new Set();
|
|
5096
5284
|
const extraRubyRequire = [];
|
|
5097
|
-
for (const l of
|
|
5285
|
+
for (const l of existingOutsideIgnore) {
|
|
5098
5286
|
const key = rubyRequireKey(l);
|
|
5099
5287
|
if (!key) continue;
|
|
5100
5288
|
if (generatedRubyRequireKeys.has(key)) continue;
|
|
@@ -5626,6 +5814,7 @@ async function readManifest(dir) {
|
|
|
5626
5814
|
}
|
|
5627
5815
|
/** Write `.oagen-manifest.json` to a directory with sorted paths. */
|
|
5628
5816
|
async function writeManifest(dir, opts) {
|
|
5817
|
+
const manifestPath = path$1.join(dir, MANIFEST_FILENAME);
|
|
5629
5818
|
const manifest = {
|
|
5630
5819
|
version: MANIFEST_VERSION,
|
|
5631
5820
|
language: opts.language,
|
|
@@ -5640,10 +5829,16 @@ async function writeManifest(dir, opts) {
|
|
|
5640
5829
|
files: [...new Set(opts.files)].sort(),
|
|
5641
5830
|
...opts.operations !== void 0 ? { operations: opts.operations } : {}
|
|
5642
5831
|
};
|
|
5643
|
-
const
|
|
5832
|
+
const previous = await readManifest(dir);
|
|
5833
|
+
if (previous && sameManifestExceptGeneratedAt(previous, manifest)) manifest.generatedAt = previous.generatedAt;
|
|
5644
5834
|
await fs.mkdir(dir, { recursive: true });
|
|
5645
5835
|
await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
|
|
5646
5836
|
}
|
|
5837
|
+
function sameManifestExceptGeneratedAt(a, b) {
|
|
5838
|
+
const { generatedAt: _aGeneratedAt, ...aComparable } = a;
|
|
5839
|
+
const { generatedAt: _bGeneratedAt, ...bComparable } = b;
|
|
5840
|
+
return JSON.stringify(aComparable) === JSON.stringify(bComparable);
|
|
5841
|
+
}
|
|
5647
5842
|
/** Return the set of previous paths no longer present in the current emission. */
|
|
5648
5843
|
function computeStalePaths(prev, currentPaths) {
|
|
5649
5844
|
const current = new Set(currentPaths);
|