@workos/oagen 0.22.4 → 0.22.6
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/README.md +1 -1
- package/dist/cli/index.mjs +149 -1
- package/dist/cli/index.mjs.map +1 -1
- package/dist/{diff-B8Yi0oQa.mjs → diff-CQzcGuFJ.mjs} +150 -2
- package/dist/diff-CQzcGuFJ.mjs.map +1 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +4 -1
- package/dist/index.mjs.map +1 -1
- package/dist/verify/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/diff-B8Yi0oQa.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# oagen
|
|
2
2
|
|
|
3
|
-
oagen ([
|
|
3
|
+
oagen ([oʊweɪdd͡ʒɛn](https://ipa-reader.com/?text=o%CA%8Awe%C9%AAdd%CD%A1%CA%92%C9%9Bn)) is a framework for building custom SDK generators from OpenAPI 3.x specifications.
|
|
4
4
|
|
|
5
5
|
Its core job is narrow:
|
|
6
6
|
|
package/dist/cli/index.mjs
CHANGED
|
@@ -4917,8 +4917,23 @@ async function overwriteWithPreservedRegions(existingContent, generatedContent,
|
|
|
4917
4917
|
}
|
|
4918
4918
|
replacements.sort((a, b) => b.startLine - a.startLine);
|
|
4919
4919
|
for (const rep of replacements) result.splice(rep.startLine, rep.endLine - rep.startLine, ...rep.content);
|
|
4920
|
+
let regionDeclarationEdits = 0;
|
|
4921
|
+
{
|
|
4922
|
+
const topLevelEntries = blocksByClass.get("");
|
|
4923
|
+
if (topLevelEntries) {
|
|
4924
|
+
const alreadyPlaced = handledBlockKeys.has("");
|
|
4925
|
+
const remaining = [];
|
|
4926
|
+
for (const entry of topLevelEntries) {
|
|
4927
|
+
const outcome = await applyRegionDeclarationOverride(result, entry.lines, language, !alreadyPlaced);
|
|
4928
|
+
if (outcome.edited) regionDeclarationEdits++;
|
|
4929
|
+
if (!alreadyPlaced && !outcome.placed) remaining.push(entry);
|
|
4930
|
+
}
|
|
4931
|
+
if (!alreadyPlaced) if (remaining.length === 0) blocksByClass.delete("");
|
|
4932
|
+
else blocksByClass.set("", remaining);
|
|
4933
|
+
}
|
|
4934
|
+
}
|
|
4920
4935
|
let effectiveClassEndLines = classEndLines;
|
|
4921
|
-
if (replacedClasses.size > 0) effectiveClassEndLines = await extractClassEndLines(result.join("\n"), language);
|
|
4936
|
+
if (replacedClasses.size > 0 || regionDeclarationEdits > 0) effectiveClassEndLines = await extractClassEndLines(result.join("\n"), language);
|
|
4922
4937
|
const insertions = [];
|
|
4923
4938
|
let insertionOrder = 0;
|
|
4924
4939
|
for (const [className, classBlocks] of blocksByClass) {
|
|
@@ -5044,6 +5059,139 @@ function findClassDeclarationStart(lines, className, beforeLine) {
|
|
|
5044
5059
|
return -1;
|
|
5045
5060
|
}
|
|
5046
5061
|
/**
|
|
5062
|
+
* Conservative top-level declaration matcher for ignore-block content.
|
|
5063
|
+
* Matches column-0 declarations like `export interface X`, `type X = …`,
|
|
5064
|
+
* `const X = …`, `function X(…)`, `class X` (export optional). Names found
|
|
5065
|
+
* here are only acted on when the language's merge adapter also reports a
|
|
5066
|
+
* generated top-level statement with the same key, so false positives are
|
|
5067
|
+
* filtered by the real parser.
|
|
5068
|
+
*/
|
|
5069
|
+
const REGION_DECLARATION_PATTERN = /^(?:export\s+)?(?:declare\s+)?(?:interface|type|enum|class|const|let|var|async\s+function|function)\s+([A-Za-z_$][\w$]*)/;
|
|
5070
|
+
/** Extract top-level symbol names declared inside an ignore block's lines. */
|
|
5071
|
+
function collectRegionDeclaredNames(blockLines) {
|
|
5072
|
+
const names = /* @__PURE__ */ new Set();
|
|
5073
|
+
for (const line of blockLines) {
|
|
5074
|
+
if (line.includes("@oagen-ignore")) continue;
|
|
5075
|
+
const m = line.match(REGION_DECLARATION_PATTERN);
|
|
5076
|
+
if (m) names.add(m[1]);
|
|
5077
|
+
}
|
|
5078
|
+
return names;
|
|
5079
|
+
}
|
|
5080
|
+
/** Inclusive line ranges of `@oagen-ignore-start`..`@oagen-ignore-end` regions. */
|
|
5081
|
+
function collectIgnoreRegionLineRanges(lines) {
|
|
5082
|
+
const ranges = [];
|
|
5083
|
+
let start = -1;
|
|
5084
|
+
for (let i = 0; i < lines.length; i++) {
|
|
5085
|
+
if (start === -1 && lines[i].includes("@oagen-ignore-start")) {
|
|
5086
|
+
start = i;
|
|
5087
|
+
continue;
|
|
5088
|
+
}
|
|
5089
|
+
if (start !== -1 && lines[i].includes("@oagen-ignore-end")) {
|
|
5090
|
+
ranges.push({
|
|
5091
|
+
start,
|
|
5092
|
+
end: i
|
|
5093
|
+
});
|
|
5094
|
+
start = -1;
|
|
5095
|
+
}
|
|
5096
|
+
}
|
|
5097
|
+
return ranges;
|
|
5098
|
+
}
|
|
5099
|
+
/**
|
|
5100
|
+
* Walk upward from a declaration's first line over its contiguous comment
|
|
5101
|
+
* block (doc comment), so the comment is dropped together with the
|
|
5102
|
+
* declaration. Stops at blank lines, region markers, and line 0 (a comment
|
|
5103
|
+
* on line 0 is the file header, not a docstring).
|
|
5104
|
+
*/
|
|
5105
|
+
function extendOverPrecedingComments(lines, startLine) {
|
|
5106
|
+
let s = startLine;
|
|
5107
|
+
while (s > 1) {
|
|
5108
|
+
const prev = lines[s - 1].trim();
|
|
5109
|
+
if (prev === "" || prev.includes("@oagen-ignore")) break;
|
|
5110
|
+
if (!(prev.startsWith("//") || prev.startsWith("/*") || prev.startsWith("*") || prev.startsWith("#"))) break;
|
|
5111
|
+
s--;
|
|
5112
|
+
}
|
|
5113
|
+
return s;
|
|
5114
|
+
}
|
|
5115
|
+
/**
|
|
5116
|
+
* Drop generated top-level declarations that are redeclared inside an ignore
|
|
5117
|
+
* block ("region wins"). When `placeBlock` is set and at least one generated
|
|
5118
|
+
* declaration matches, the block's lines replace the first match in place
|
|
5119
|
+
* (mirroring the class-replacement behavior above); any further matches are
|
|
5120
|
+
* deleted. Mutates `result` in place.
|
|
5121
|
+
*
|
|
5122
|
+
* Returns `placed` (the block content now lives in `result` and must not be
|
|
5123
|
+
* inserted again) and `edited` (line numbers shifted).
|
|
5124
|
+
*/
|
|
5125
|
+
async function applyRegionDeclarationOverride(result, blockLines, language, placeBlock) {
|
|
5126
|
+
const names = collectRegionDeclaredNames(blockLines);
|
|
5127
|
+
if (names.size === 0) return {
|
|
5128
|
+
placed: false,
|
|
5129
|
+
edited: false
|
|
5130
|
+
};
|
|
5131
|
+
const source = result.join("\n");
|
|
5132
|
+
let parsed;
|
|
5133
|
+
try {
|
|
5134
|
+
parsed = await extractStatements(source, language);
|
|
5135
|
+
} catch {
|
|
5136
|
+
return {
|
|
5137
|
+
placed: false,
|
|
5138
|
+
edited: false
|
|
5139
|
+
};
|
|
5140
|
+
}
|
|
5141
|
+
const regionRanges = collectIgnoreRegionLineRanges(result);
|
|
5142
|
+
const inRegion = (line) => regionRanges.some((r) => line >= r.start && line <= r.end);
|
|
5143
|
+
const spans = [];
|
|
5144
|
+
for (const stmt of parsed.statements) {
|
|
5145
|
+
if (stmt.kind !== "declaration" || !stmt.key || !names.has(stmt.key)) continue;
|
|
5146
|
+
let idx = source.indexOf(stmt.text);
|
|
5147
|
+
let startLine = -1;
|
|
5148
|
+
while (idx !== -1) {
|
|
5149
|
+
const line = source.slice(0, idx).split("\n").length - 1;
|
|
5150
|
+
if (!inRegion(line)) {
|
|
5151
|
+
startLine = line;
|
|
5152
|
+
break;
|
|
5153
|
+
}
|
|
5154
|
+
idx = source.indexOf(stmt.text, idx + 1);
|
|
5155
|
+
}
|
|
5156
|
+
if (startLine === -1) continue;
|
|
5157
|
+
const endLine = startLine + stmt.text.split("\n").length - 1;
|
|
5158
|
+
spans.push({
|
|
5159
|
+
start: extendOverPrecedingComments(result, startLine),
|
|
5160
|
+
end: endLine
|
|
5161
|
+
});
|
|
5162
|
+
}
|
|
5163
|
+
if (spans.length === 0) return {
|
|
5164
|
+
placed: false,
|
|
5165
|
+
edited: false
|
|
5166
|
+
};
|
|
5167
|
+
spans.sort((a, b) => a.start - b.start);
|
|
5168
|
+
for (let i = spans.length - 1; i >= 1; i--) {
|
|
5169
|
+
const span = spans[i];
|
|
5170
|
+
let deleteCount = span.end - span.start + 1;
|
|
5171
|
+
const prevBlank = span.start === 0 || (result[span.start - 1] ?? "").trim() === "";
|
|
5172
|
+
const nextBlank = (result[span.end + 1] ?? "").trim() === "";
|
|
5173
|
+
if (prevBlank && nextBlank && span.end + 1 < result.length) deleteCount++;
|
|
5174
|
+
result.splice(span.start, deleteCount);
|
|
5175
|
+
}
|
|
5176
|
+
const first = spans[0];
|
|
5177
|
+
if (placeBlock) {
|
|
5178
|
+
result.splice(first.start, first.end - first.start + 1, ...blockLines);
|
|
5179
|
+
return {
|
|
5180
|
+
placed: true,
|
|
5181
|
+
edited: true
|
|
5182
|
+
};
|
|
5183
|
+
}
|
|
5184
|
+
let deleteCount = first.end - first.start + 1;
|
|
5185
|
+
const prevBlank = first.start === 0 || (result[first.start - 1] ?? "").trim() === "";
|
|
5186
|
+
const nextBlank = (result[first.end + 1] ?? "").trim() === "";
|
|
5187
|
+
if (prevBlank && nextBlank && first.end + 1 < result.length) deleteCount++;
|
|
5188
|
+
result.splice(first.start, deleteCount);
|
|
5189
|
+
return {
|
|
5190
|
+
placed: false,
|
|
5191
|
+
edited: true
|
|
5192
|
+
};
|
|
5193
|
+
}
|
|
5194
|
+
/**
|
|
5047
5195
|
* Collect `from X import Y, Z` identifiers grouped by module, handling
|
|
5048
5196
|
* both single-line and multiline (parenthesized) forms.
|
|
5049
5197
|
*/
|