Skip to content

Commit 2eec0e7

Browse files
committed
perf(graph): avoid repeatedly looping graphs node
1 parent 1968330 commit 2eec0e7

1 file changed

Lines changed: 35 additions & 35 deletions

File tree

  • packages/shared/src/openApi/shared/utils

packages/shared/src/openApi/shared/utils/graph.ts

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -211,34 +211,6 @@ const propagateScopesToNode = (fromNodeInfo: NodeInfo, toNodeInfo: NodeInfo): bo
211211
return changed;
212212
};
213213

214-
/**
215-
* Seeds each node in the graph with its local access scope(s) based on its own properties.
216-
* - 'read' if readOnly: true
217-
* - 'write' if writeOnly: true
218-
* - 'normal' if node is an object property
219-
*
220-
* Only non-array objects are considered for scope seeding.
221-
*
222-
* @param nodes - Map of JSON Pointer to NodeInfo.
223-
*/
224-
export const seedLocalScopes = (nodes: Graph['nodes']): void => {
225-
for (const [pointer, nodeInfo] of nodes) {
226-
const { node } = nodeInfo;
227-
228-
if (typeof node !== 'object' || node === null || node instanceof Array) {
229-
continue;
230-
}
231-
232-
if ('readOnly' in node && node.readOnly === true) {
233-
nodeInfo.scopes = new Set(['read']);
234-
} else if ('writeOnly' in node && node.writeOnly === true) {
235-
nodeInfo.scopes = new Set(['write']);
236-
} else if (pointer.match(/\/properties\/[^/]+$/)) {
237-
nodeInfo.scopes = new Set(['normal']);
238-
}
239-
}
240-
};
241-
242214
/**
243215
* Builds a graph of all nodes in an OpenAPI spec, indexed by normalized JSON Pointer,
244216
* and tracks all $ref dependencies and reverse dependencies between nodes.
@@ -299,14 +271,14 @@ export function buildGraph(
299271
graph.nodeDependencies.get(pointer)!.add(refPointer);
300272
}
301273
// Check for tags property (should be an array of strings)
302-
if ('tags' in node && node.tags instanceof Array) {
274+
if ('tags' in node && Array.isArray(node.tags)) {
303275
tags = new Set(node.tags.filter((tag) => typeof tag === 'string'));
304276
}
305277
}
306278

307279
graph.nodes.set(pointer, { deprecated, key, node, parentPointer, tags });
308280

309-
if (node instanceof Array) {
281+
if (Array.isArray(node)) {
310282
node.forEach((item, index) =>
311283
walk({
312284
key: index,
@@ -340,16 +312,44 @@ export function buildGraph(
340312
transitiveDependencies: new Map(),
341313
};
342314

315+
// Merge parentToChildren cache build + scope seeding into one pass over graph.nodes.
343316
for (const [pointer, nodeInfo] of graph.nodes) {
344317
const parent = nodeInfo.parentPointer;
345-
if (!parent) continue;
346-
if (!cache.parentToChildren.has(parent)) {
347-
cache.parentToChildren.set(parent, []);
318+
if (parent) {
319+
let arr = cache.parentToChildren.get(parent);
320+
if (!arr) {
321+
arr = [];
322+
cache.parentToChildren.set(parent, arr);
323+
}
324+
arr.push(pointer);
325+
}
326+
327+
// Seeds each node in the graph with its local access scope(s) based on its own properties.
328+
// - 'read' if readOnly: true
329+
// - 'write' if writeOnly: true
330+
// - 'normal' if node is an object property
331+
//
332+
// Only non-array objects are considered for scope seeding.
333+
const { node } = nodeInfo;
334+
if (typeof node === 'object' && node !== null && !Array.isArray(node)) {
335+
if ('readOnly' in node && node.readOnly === true) {
336+
nodeInfo.scopes = new Set(['read']);
337+
} else if ('writeOnly' in node && node.writeOnly === true) {
338+
nodeInfo.scopes = new Set(['write']);
339+
} else {
340+
// Check /properties/{key} without a regex: compare the segment before the
341+
// last slash to the string 'properties'.
342+
const lastSlash = pointer.lastIndexOf('/');
343+
if (lastSlash > 0) {
344+
const prevSlash = pointer.lastIndexOf('/', lastSlash - 1);
345+
if (prevSlash >= 0 && pointer.slice(prevSlash + 1, lastSlash) === 'properties') {
346+
nodeInfo.scopes = new Set(['normal']);
347+
}
348+
}
349+
}
348350
}
349-
cache.parentToChildren.get(parent)!.push(pointer);
350351
}
351352

352-
seedLocalScopes(graph.nodes);
353353
propagateScopes(graph);
354354
annotateChildScopes(graph.nodes);
355355

0 commit comments

Comments
 (0)