@voxgig/apidef 5.1.1 → 5.3.0

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.
@@ -98,11 +98,14 @@ function buildRelations(guideEntity: any, paths$: PathDesc[]) {
98
98
  .filter(n => 0 < n.length)
99
99
  .sort((a, b) => a.length - b.length)
100
100
 
101
- // remove suffixes
101
+ // remove suffixes: keep only ancestors that are not a suffix of any later ancestor
102
102
  ancestors = ancestors
103
- .reduce((a, n, j) =>
104
- ((0 < (ancestors.slice(j + 1).filter(p => suffix(p, n))).length
105
- ? null : a.push(n)), a), [])
103
+ .filter((n, j) => {
104
+ for (let k = j + 1; k < ancestors.length; k++) {
105
+ if (suffix(ancestors[k], n)) return false
106
+ }
107
+ return true
108
+ })
106
109
 
107
110
  const relations = {
108
111
  ancestors
@@ -114,9 +117,13 @@ function buildRelations(guideEntity: any, paths$: PathDesc[]) {
114
117
  }
115
118
 
116
119
 
117
- // True if array c is a suffix of array p,
120
+ // True if array c is a suffix of array p.
118
121
  function suffix(p: string[], c: string[]): boolean {
119
- return c.reduce((b, _, i) => (b && c[c.length - 1 - i] === p[p.length - 1 - i]), true)
122
+ if (c.length > p.length) return false
123
+ for (let i = 0; i < c.length; i++) {
124
+ if (c[c.length - 1 - i] !== p[p.length - 1 - i]) return false
125
+ }
126
+ return true
120
127
  }
121
128
 
122
129
 
@@ -122,9 +122,9 @@ const createStep: MakeFlowStep = (
122
122
  ent: ModelEntity,
123
123
  args: Record<string, any>
124
124
  ) => {
125
- if (null != opmap.update) {
125
+ if (null != opmap.create) {
126
126
  // Use last point as most generic
127
- const point = getelem(opmap.update.points, -1)
127
+ const point = getelem(opmap.create.points, -1)
128
128
  const step = newFlowStep('create', args)
129
129
 
130
130
  each(point.args.params, (param: any) => {
@@ -93,6 +93,12 @@ function sortPoints(
93
93
  _ment: ModelEntity,
94
94
  mop: ModelOp,
95
95
  ) {
96
+ // Cache joined exist strings to avoid recomputing on every comparison.
97
+ const existCache = new Map<ModelTarget, string>()
98
+ for (const pt of mop.points) {
99
+ existCache.set(pt, pt.select.exist.join('\t'))
100
+ }
101
+
96
102
  mop.points.sort((a: ModelTarget, b: ModelTarget) => {
97
103
  // longest exist len first
98
104
  let order = b.select.exist.length - a.select.exist.length
@@ -103,8 +109,8 @@ function sortPoints(
103
109
  }
104
110
 
105
111
  if (0 === order) {
106
- const a_exist_str = a.select.exist.join('\t')
107
- const b_exist_str = b.select.exist.join('\t')
112
+ const a_exist_str = existCache.get(a)!
113
+ const b_exist_str = existCache.get(b)!
108
114
  order = a_exist_str < b_exist_str ? -1 :
109
115
  a_exist_str > b_exist_str ? 1 : 0
110
116
  }
package/src/utility.ts CHANGED
@@ -29,6 +29,10 @@ const RE_JSON_KEY = /"([a-zA-Z_][a-zA-Z_0-9]*)": /g
29
29
  const RE_JSON_TRAILING_BRACE = /},/g
30
30
  const RE_JSON_COMMENT = /\n(\s*)([a-zA-Z_][a-zA-Z_0-9]*)_COMMENT:\s*"(.*)",/g
31
31
 
32
+ const RE_BARE_KEY = /^[A-Za-z_][_A-Za-z0-9]*$/
33
+ const isBareKey = (k: string) => RE_BARE_KEY.test(k)
34
+ const quoteKey = (k: string) => (isBareKey(k) ? k : JSON.stringify(k))
35
+
32
36
 
33
37
  function makeWarner(spec: { point: string, log: Log }): Warner {
34
38
  const { point, log } = spec
@@ -101,59 +105,59 @@ function formatJsonSrc(jsonsrc: string) {
101
105
  }
102
106
 
103
107
 
108
+ // Common irregular plurals - hoisted to module scope to avoid re-allocation per call.
109
+ const IRREGULARS: Record<string, string> = {
110
+ 'analytics': 'analytics',
111
+ 'analyses': 'analysis',
112
+ 'appendices': 'appendix',
113
+ 'axes': 'axis',
114
+ 'children': 'child',
115
+ 'courses': 'course',
116
+ 'crises': 'crisis',
117
+ 'criteria': 'criterion',
118
+ // 'data': 'datum',
119
+ 'diagnoses': 'diagnosis',
120
+ 'feet': 'foot',
121
+ 'furnace': 'furnaces',
122
+ 'geese': 'goose',
123
+ 'horses': 'horse',
124
+ 'house': 'houses',
125
+ 'indices': 'index',
126
+ 'lens': 'lens',
127
+ 'license': 'licenses',
128
+ 'matrices': 'matrix',
129
+ 'men': 'man',
130
+ 'mice': 'mouse',
131
+ 'movies': 'movie',
132
+ 'notice': 'notices',
133
+ 'oases': 'oasis',
134
+ 'phrase': 'phrase',
135
+ 'releases': 'release',
136
+ 'people': 'person',
137
+ 'phenomena': 'phenomenon',
138
+ 'practice': 'practices',
139
+ 'promise': 'promises',
140
+ 'series': 'series',
141
+ 'species': 'species',
142
+ 'teeth': 'tooth',
143
+ 'theses': 'thesis',
144
+ 'vertices': 'vertex',
145
+ 'women': 'woman',
146
+ 'yes': 'yes',
147
+ }
148
+
104
149
  function depluralize(word: string): string {
105
150
  if (!word || word.length === 0) {
106
151
  return word
107
152
  }
108
153
 
109
- // Common irregular plurals
110
- const irregulars: Record<string, string> = {
111
- 'analytics': 'analytics',
112
- 'analyses': 'analysis',
113
- 'appendices': 'appendix',
114
- 'axes': 'axis',
115
- 'children': 'child',
116
- 'courses': 'course',
117
- 'crises': 'crisis',
118
- 'criteria': 'criterion',
119
- // 'data': 'datum',
120
- 'diagnoses': 'diagnosis',
121
- 'feet': 'foot',
122
- 'furnace': 'furnaces',
123
- 'geese': 'goose',
124
- 'horses': 'horse',
125
- 'house': 'houses',
126
- 'indices': 'index',
127
- 'lens': 'lens',
128
- 'license': 'licenses',
129
- 'matrices': 'matrix',
130
- 'men': 'man',
131
- 'mice': 'mouse',
132
- 'movies': 'movie',
133
- 'notice': 'notices',
134
- 'oases': 'oasis',
135
- 'phrase': 'phrase',
136
- 'releases': 'release',
137
- 'people': 'person',
138
- 'phenomena': 'phenomenon',
139
- 'practice': 'practices',
140
- 'promise': 'promises',
141
- 'series': 'series',
142
- 'species': 'species',
143
- 'teeth': 'tooth',
144
- 'theses': 'thesis',
145
- 'vertices': 'vertex',
146
- 'women': 'woman',
147
- 'yes': 'yes',
148
- }
149
-
150
- if (irregulars[word]) {
151
- return irregulars[word]
154
+ if (IRREGULARS[word]) {
155
+ return IRREGULARS[word]
152
156
  }
153
157
 
154
- for (let ending in irregulars) {
158
+ for (let ending in IRREGULARS) {
155
159
  if (word.endsWith(ending)) {
156
- return word.replace(ending, irregulars[ending])
160
+ return word.replace(ending, IRREGULARS[ending])
157
161
  }
158
162
  }
159
163
 
@@ -527,18 +531,12 @@ function formatJSONIC(
527
531
 
528
532
  if (undefined === val) return ''
529
533
 
530
- val = decircular(val)
531
-
532
534
  const hsepd = opts?.hsepd ?? 1
533
535
  const showd = !!opts?.$
534
536
  const useColor = opts?.color ?? false
535
537
  const maxlines = opts?.maxlines ?? Number.MAX_VALUE
536
538
  const exclude = opts?.exclude ?? []
537
539
 
538
- const space = ' '
539
- const isBareKey = (k: string) => /^[A-Za-z_][_A-Za-z0-9]*$/.test(k)
540
- const quoteKey = (k: string) => (isBareKey(k) ? k : JSON.stringify(k))
541
-
542
540
  // ANSI color codes
543
541
  const colors = {
544
542
  reset: '\x1b[0m',
@@ -583,6 +581,25 @@ function formatJSONIC(
583
581
  try { return JSON.stringify(c) } catch { return String(c) }
584
582
  }
585
583
 
584
+ return renderJSONIC(val, hsepd, showd, useColor, maxlines, exclude, c,
585
+ renderPrimitive, renderComment)
586
+ }
587
+
588
+
589
+ function renderJSONIC(
590
+ val: any,
591
+ hsepd: number,
592
+ showd: boolean,
593
+ useColor: boolean,
594
+ maxlines: number,
595
+ exclude: string[],
596
+ c: (color: any, text: string) => string,
597
+ renderPrimitive: (v: any) => string,
598
+ renderComment: (c: any) => string | null,
599
+ ): string {
600
+
601
+ const space = ' '
602
+
586
603
  type ValueFrame = {
587
604
  kind: 'value'
588
605
  value: any
@@ -597,6 +614,8 @@ function formatJSONIC(
597
614
  indentLevel: number
598
615
  }
599
616
 
617
+ const seen = new WeakSet()
618
+
600
619
  let stack = new Array<ValueFrame | CloseFrame | undefined>(32)
601
620
  let top = -1
602
621
 
@@ -637,6 +656,13 @@ function formatJSONIC(
637
656
  continue
638
657
  }
639
658
 
659
+ // Circular reference detected — fall back to decircular
660
+ if (seen.has(v)) {
661
+ return renderJSONIC(decircular(val), hsepd, showd, useColor, maxlines, exclude, c,
662
+ renderPrimitive, renderComment)
663
+ }
664
+ seen.add(v)
665
+
640
666
  if (Array.isArray(v)) {
641
667
  const arr = v as any[]
642
668
  if (arr.length === 0) {