@voxgig/apidef 1.9.0 → 2.0.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.
Files changed (74) hide show
  1. package/dist/apidef.d.ts +3 -29
  2. package/dist/apidef.js +84 -186
  3. package/dist/apidef.js.map +1 -1
  4. package/dist/builder/entity/apiEntity.d.ts +3 -0
  5. package/dist/builder/entity/apiEntity.js +51 -0
  6. package/dist/builder/entity/apiEntity.js.map +1 -0
  7. package/dist/builder/entity/def.d.ts +3 -0
  8. package/dist/builder/entity/def.js +19 -0
  9. package/dist/builder/entity/def.js.map +1 -0
  10. package/dist/builder/entity.d.ts +2 -0
  11. package/dist/builder/entity.js +30 -0
  12. package/dist/builder/entity.js.map +1 -0
  13. package/dist/builder/flow/flowHeuristic01.d.ts +2 -0
  14. package/dist/builder/flow/flowHeuristic01.js +125 -0
  15. package/dist/builder/flow/flowHeuristic01.js.map +1 -0
  16. package/dist/builder/flow.d.ts +2 -0
  17. package/dist/builder/flow.js +41 -0
  18. package/dist/builder/flow.js.map +1 -0
  19. package/dist/guide/heuristic01.d.ts +2 -0
  20. package/dist/guide/heuristic01.js +178 -0
  21. package/dist/guide/heuristic01.js.map +1 -0
  22. package/dist/guide.d.ts +2 -0
  23. package/dist/guide.js +62 -0
  24. package/dist/guide.js.map +1 -0
  25. package/dist/parse.d.ts +1 -1
  26. package/dist/parse.js +5 -4
  27. package/dist/parse.js.map +1 -1
  28. package/dist/resolver.d.ts +2 -0
  29. package/dist/resolver.js +62 -0
  30. package/dist/resolver.js.map +1 -0
  31. package/dist/transform/entity.js +4 -2
  32. package/dist/transform/entity.js.map +1 -1
  33. package/dist/transform/field.js +4 -84
  34. package/dist/transform/field.js.map +1 -1
  35. package/dist/transform/operation.d.ts +2 -2
  36. package/dist/transform/operation.js +22 -11
  37. package/dist/transform/operation.js.map +1 -1
  38. package/dist/transform/top.d.ts +2 -2
  39. package/dist/transform/top.js +5 -4
  40. package/dist/transform/top.js.map +1 -1
  41. package/dist/transform.d.ts +1 -1
  42. package/dist/transform.js +21 -10
  43. package/dist/transform.js.map +1 -1
  44. package/dist/tsconfig.tsbuildinfo +1 -1
  45. package/dist/types.d.ts +682 -0
  46. package/dist/types.js +38 -0
  47. package/dist/types.js.map +1 -0
  48. package/dist/utility.d.ts +4 -0
  49. package/dist/utility.js +59 -0
  50. package/dist/utility.js.map +1 -0
  51. package/model/apidef.jsonic +28 -24
  52. package/package.json +8 -6
  53. package/src/apidef.ts +117 -263
  54. package/src/builder/entity/apiEntity.ts +88 -0
  55. package/src/builder/entity/def.ts +44 -0
  56. package/src/builder/entity.ts +54 -0
  57. package/src/builder/flow/flowHeuristic01.ts +165 -0
  58. package/src/builder/flow/flowHeuristic01.ts~ +45 -0
  59. package/src/builder/flow.ts +60 -0
  60. package/src/guide/heuristic01.ts +225 -0
  61. package/src/guide.ts +91 -0
  62. package/src/parse.ts +6 -4
  63. package/src/resolver.ts +91 -0
  64. package/src/transform/entity.ts +10 -7
  65. package/src/transform/field.ts +9 -92
  66. package/src/transform/operation.ts +39 -25
  67. package/src/transform/top.ts +11 -9
  68. package/src/transform.ts +23 -11
  69. package/src/types.ts +88 -0
  70. package/src/utility.ts +83 -0
  71. package/dist/transform/manual.d.ts +0 -3
  72. package/dist/transform/manual.js +0 -12
  73. package/dist/transform/manual.js.map +0 -1
  74. package/src/transform/manual.ts +0 -29
package/src/guide.ts ADDED
@@ -0,0 +1,91 @@
1
+
2
+ import Path from 'node:path'
3
+
4
+ import { File, Content, each } from 'jostraca'
5
+
6
+
7
+ import { heuristic01 } from './guide/heuristic01'
8
+
9
+
10
+ async function resolveGuide(ctx: any) {
11
+ // console.log('GUIDE CTX', ctx)
12
+
13
+ let guide: Record<string, any> = ctx.model.main.api.guide
14
+
15
+ if ('heuristic01' === ctx.opts.strategy) {
16
+ guide = await heuristic01(ctx)
17
+ }
18
+ else {
19
+ throw new Error('Unknown guide strategy: ' + ctx.opts.strategy)
20
+ }
21
+
22
+ guide = cleanGuide(guide)
23
+
24
+ ctx.model.main.api.guide = guide
25
+
26
+ const guideFile =
27
+ Path.join(ctx.opts.folder,
28
+ (null == ctx.opts.outprefix ? '' : ctx.opts.outprefix) + 'guide.jsonic')
29
+
30
+ const guideBlocks = [
31
+ '# Guide',
32
+ '',
33
+ 'main: api: guide: { ',
34
+ '',
35
+ ]
36
+
37
+
38
+ guideBlocks.push(...each(guide.entity, (entity, entityname) => {
39
+ guideBlocks.push(`\nentity: ${entityname}: path: {`)
40
+
41
+ each(entity.path, (path, pathname) => {
42
+ guideBlocks.push(` '${pathname}': op: {`)
43
+
44
+ each(path.op, (op, opname) => {
45
+ guideBlocks.push(` '${opname}': method: ${op.method}`)
46
+ if (op.transform?.reqform) {
47
+ guideBlocks.push(
48
+ ` '${opname}': transform: reqform: ${JSON.stringify(op.transform.reqform)}`)
49
+ }
50
+ })
51
+
52
+ guideBlocks.push(` }`)
53
+ })
54
+
55
+ guideBlocks.push(`}`)
56
+ }))
57
+
58
+ guideBlocks.push('}')
59
+
60
+ const guideSrc = guideBlocks.join('\n')
61
+
62
+ // console.log(guideSrc)
63
+
64
+ return () => {
65
+ File({ name: Path.basename(guideFile) }, () => Content(guideSrc))
66
+
67
+ }
68
+ }
69
+
70
+
71
+ function cleanGuide(guide: Record<string, any>): Record<string, any> {
72
+ const clean: Record<string, any> = {
73
+ control: guide.control,
74
+ entity: {}
75
+ }
76
+
77
+ each(guide.entity, (entity: any, name: string) => {
78
+ let ent: any = clean.entity[name] = clean.entity[name] = { name, path: {} }
79
+
80
+ each(entity.path, (path: any, pathname: string) => {
81
+ ent.path[pathname] = path
82
+ })
83
+ })
84
+
85
+ return clean
86
+ }
87
+
88
+
89
+ export {
90
+ resolveGuide
91
+ }
package/src/parse.ts CHANGED
@@ -3,9 +3,11 @@
3
3
  import { bundleFromString, createConfig } from '@redocly/openapi-core'
4
4
 
5
5
 
6
- async function parse(kind: string, source: any) {
6
+
7
+ // Parse an API definition source into a JSON sructure.
8
+ async function parse(kind: string, source: any, meta?: any) {
7
9
  if ('OpenAPI' === kind) {
8
- return parseOpenAPI(source)
10
+ return parseOpenAPI(source, meta)
9
11
  }
10
12
  else {
11
13
  throw new Error('@voxgig/apidef-parse: unknown kind: ' + kind)
@@ -13,8 +15,8 @@ async function parse(kind: string, source: any) {
13
15
  }
14
16
 
15
17
 
16
- async function parseOpenAPI(source: any) {
17
- const config = await createConfig({})
18
+ async function parseOpenAPI(source: any, meta?: any) {
19
+ const config = await createConfig(meta?.config || {})
18
20
  let bundle
19
21
 
20
22
  bundle = await bundleFromString({
@@ -0,0 +1,91 @@
1
+ /* Copyright (c) 2024-2025 Voxgig, MIT License */
2
+
3
+
4
+ import Path from 'node:path'
5
+
6
+
7
+ async function resolveElements(
8
+ ctx: any,
9
+ kind: string,
10
+ subkind: string,
11
+ standard: Record<string, any>
12
+ ) {
13
+
14
+ const { log, model } = ctx
15
+
16
+ // TODO: model access should be via a utility that generates
17
+ // useful errors when the target is missing
18
+ const control = model.main.api.guide.control[kind][subkind]
19
+
20
+ const target = kind + '.' + subkind
21
+
22
+ const elementNames = control.order
23
+ .split(/\s*,\s*/)
24
+ .map((t: string) => t.trim())
25
+ .filter((elem: string) => '' != elem)
26
+
27
+ log.info({
28
+ point: 'element', note: target + ': order: ' + elementNames.join(';'),
29
+ order: elementNames
30
+ })
31
+
32
+ const elementResults: any = []
33
+
34
+ for (const en of elementNames) {
35
+ log.debug({ point: 'element', note: target + ': ' + en })
36
+ const element = await resolveElement(en, control, target, standard, ctx)
37
+ const result = await element(ctx)
38
+ elementResults.push(result)
39
+ }
40
+
41
+ return elementResults
42
+ }
43
+
44
+
45
+ async function resolveElement(
46
+ en: string,
47
+ control: any,
48
+ target: string,
49
+ standard: Record<string, any>,
50
+ ctx: any
51
+ ) {
52
+ const { log } = ctx
53
+
54
+ let element = standard[en]
55
+ if (element) {
56
+ return element
57
+ }
58
+
59
+ const elemdef = control.element[en]
60
+ if (null == elemdef) {
61
+ const err = new Error('Unknown element: ' + en)
62
+ log.error({ what: 'element', element: target + ': ' + en, fail: 'unknown', err })
63
+ throw err
64
+ }
65
+
66
+ if (!en.startsWith('custom')) {
67
+ const err =
68
+ new Error('Custom element name must start with "custom": ' + en)
69
+ log.error({ what: 'element', element: target + ': ' + en, fail: 'prefix', err })
70
+ throw err
71
+ }
72
+
73
+ const customtpath = Path.join(ctx.defpath, elemdef.load)
74
+ try {
75
+ const elementModule = require(customtpath)
76
+ element = elementModule[en]
77
+ }
78
+ catch (e: any) {
79
+ const err = new Error('Custom element not found: ' +
80
+ customtpath + ': ' + e.message)
81
+ log.error({ what: 'element', element: target + ': ' + en, fail: 'require', err })
82
+ throw err
83
+ }
84
+
85
+ return element
86
+ }
87
+
88
+
89
+ export {
90
+ resolveElements,
91
+ }
@@ -2,25 +2,28 @@
2
2
 
3
3
  import { each } from 'jostraca'
4
4
 
5
- import type { TransformCtx, TransformSpec, TransformResult, Transform, Guide } from '../transform'
5
+ import type { TransformResult, Transform } from '../transform'
6
6
 
7
7
  import { fixName } from '../transform'
8
8
 
9
9
 
10
10
  const entityTransform: Transform = async function(
11
- ctx: TransformCtx,
12
- guide: Guide,
13
- tspec: TransformSpec,
14
- model: any,
15
- def: any
11
+ ctx: any,
12
+ // guide: Guide,
13
+ // // tspec: TransformSpec,
14
+ // model: any,
15
+ // def: any
16
16
  ): Promise<TransformResult> {
17
+ const { apimodel, model, def } = ctx
18
+ const guide = model.main.api.guide
19
+
17
20
  let msg = ''
18
21
 
19
22
  each(guide.entity, (guideEntity: any) => {
20
23
  const entityName = guideEntity.key$
21
24
  ctx.log.debug({ point: 'guide-entity', note: entityName })
22
25
 
23
- const entityModel: any = model.main.api.entity[entityName] = {
26
+ const entityModel: any = apimodel.main.api.entity[entityName] = {
24
27
  op: {},
25
28
  field: {},
26
29
  cmd: {},
@@ -2,25 +2,27 @@
2
2
 
3
3
  import { each, getx } from 'jostraca'
4
4
 
5
- import type { TransformCtx, TransformSpec, TransformResult, Transform, Guide } from '../transform'
5
+ import type { TransformResult, Transform } from '../transform'
6
6
 
7
7
  import { fixName } from '../transform'
8
8
 
9
9
 
10
10
 
11
11
  const fieldTransform: Transform = async function(
12
- ctx: TransformCtx,
13
- guide: Guide,
14
- tspec: TransformSpec,
15
- model: any,
16
- def: any
12
+ ctx: any,
13
+ // guide: Guide,
14
+ // // tspec: TransformSpec,
15
+ // model: any,
16
+ // def: any
17
17
  ): Promise<TransformResult> {
18
+ const { apimodel, model, def } = ctx
19
+ const guide = model.main.api.guide
18
20
 
19
21
  let msg = 'fields: '
20
22
 
21
23
  each(guide.entity, (guideEntity: any) => {
22
24
  const entityName = guideEntity.key$
23
- const entityModel = model.main.api.entity[entityName]
25
+ const entityModel = apimodel.main.api.entity[entityName]
24
26
 
25
27
  let fieldCount = 0
26
28
  each(guideEntity.path, (guidePath: any) => {
@@ -96,88 +98,3 @@ export {
96
98
  fieldTransform
97
99
  }
98
100
 
99
-
100
-
101
-
102
- /*
103
-
104
- # API Specification Transform Guide
105
-
106
-
107
- @"@voxgig/apidef/model/guide.jsonic"
108
-
109
-
110
- guide: control: transform: openapi: order: `
111
-
112
- top,
113
- entity,
114
- operation,
115
- field,
116
- customField,
117
-
118
- `
119
-
120
- guide: transform: customField: {
121
- load: 'customField.js'
122
- }
123
-
124
-
125
- guide: entity: {
126
- pet: path: {
127
- '/pet/{petId}': {
128
- op:{ load: 'get', create: 'post', update: 'put' }
129
- }
130
- }
131
- pet: test: {
132
- quick: {
133
- active: true,
134
- create: { id: 1, name:'Rex' },
135
- load: { id: 1 },
136
- }
137
- }
138
-
139
- # direct custom definition
140
- pet: def: {}
141
- }
142
-
143
-
144
-
145
-
146
- const { each, getx } = require('jostraca')
147
-
148
-
149
- async function customField(ctx, tspec, model, def) {
150
- const { spec, util: {fixName} } = ctx
151
-
152
- const nameField = {
153
- name: 'name',
154
- type: 'string',
155
- short: 'Name of pet'
156
- }
157
- fixName(nameField, nameField.name)
158
- fixName(nameField, nameField.type, 'type')
159
-
160
- const ageField = {
161
- name: 'age',
162
- type: 'number',
163
- short: 'Age of pet'
164
- }
165
- fixName(ageField, ageField.name)
166
- fixName(ageField, ageField.type, 'type')
167
-
168
-
169
- Object.assign(model.main.api.entity.pet.field, {
170
- name: nameField,
171
- age: ageField,
172
- })
173
-
174
- return { ok: true }
175
- }
176
-
177
-
178
- module.exports = {
179
- customField
180
- }
181
-
182
-
183
- */
@@ -2,19 +2,21 @@
2
2
 
3
3
  import { each, getx } from 'jostraca'
4
4
 
5
- import type { TransformCtx, TransformSpec, TransformResult, Transform, Guide } from '../transform'
5
+ import type { TransformResult } from '../transform'
6
6
 
7
7
  import { fixName, OPKIND } from '../transform'
8
8
 
9
9
 
10
10
 
11
11
  const operationTransform = async function(
12
- ctx: TransformCtx,
13
- guide: Guide,
14
- tspec: TransformSpec,
15
- model: any,
16
- def: any
12
+ ctx: any,
13
+ // guide: Guide,
14
+ // // tspec: TransformSpec,
15
+ // model: any,
16
+ // def: any
17
17
  ): Promise<TransformResult> {
18
+ const { apimodel, model, def } = ctx
19
+ const guide = model.main.api.guide
18
20
 
19
21
  let msg = 'operations: '
20
22
 
@@ -48,6 +50,7 @@ const operationTransform = async function(
48
50
  // Resolve the JSON structure of the request or response.
49
51
  // NOTE: uses heuristics.
50
52
  const resolveTransform = (
53
+ entityModel: any,
51
54
  op: any,
52
55
  kind: 'res' | 'req',
53
56
  direction: 'resform' | 'reqform',
@@ -69,28 +72,39 @@ const operationTransform = async function(
69
72
  getx(mdef, 'responses.201.content')) :
70
73
  getx(mdef, 'requestBody.content')
71
74
 
75
+ // console.log(entityModel)
76
+ // console.log(mdef)
77
+ // console.log(getx(mdef, 'responses.200.content'))
78
+ // console.log(kind, method, pathdef, content)
72
79
 
73
- const schema = content['application/json']?.schema
80
+ if (content) {
74
81
 
75
- const propkeys = null == schema?.properties ? [] : Object.keys(schema.properties)
82
+ const schema = content['application/json']?.schema
76
83
 
77
- const resolveDirectionTransform =
78
- 'resform' === direction ? resolveResponseTransform : resolveRequestTransform
84
+ const propkeys = null == schema?.properties ? [] : Object.keys(schema.properties)
79
85
 
80
- const transform = resolveDirectionTransform(
81
- op,
82
- kind,
83
- method,
84
- mdef,
85
- content,
86
- schema,
87
- propkeys
88
- )
89
-
90
- // out = JSON.stringify(transform)
91
- out = transform
86
+ const resolveDirectionTransform =
87
+ 'resform' === direction ? resolveResponseTransform : resolveRequestTransform
88
+
89
+ const transform = resolveDirectionTransform(
90
+ op,
91
+ kind,
92
+ method,
93
+ mdef,
94
+ content,
95
+ schema,
96
+ propkeys
97
+ )
98
+
99
+ // out = JSON.stringify(transform)
100
+ out = transform
101
+ }
102
+ else {
103
+ out = 'res' === kind ? '`body`' : '`reqdata`'
104
+ }
92
105
  }
93
106
 
107
+
94
108
  return out
95
109
  }
96
110
 
@@ -218,8 +232,8 @@ const operationTransform = async function(
218
232
  param: {},
219
233
  query: {},
220
234
  // transform: {
221
- resform: resolveTransform(op, kind, 'resform', pathdef),
222
- reqform: resolveTransform(op, kind, 'reqform', pathdef),
235
+ resform: resolveTransform(entityModel, op, kind, 'resform', pathdef),
236
+ reqform: resolveTransform(entityModel, op, kind, 'reqform', pathdef),
223
237
  // }
224
238
  }
225
239
 
@@ -270,7 +284,7 @@ const operationTransform = async function(
270
284
 
271
285
  each(guide.entity, (guideEntity: any) => {
272
286
  let opcount = 0
273
- const entityModel = model.main.api.entity[guideEntity.key$]
287
+ const entityModel = apimodel.main.api.entity[guideEntity.key$]
274
288
  each(guideEntity.path, (guidePath: any) => {
275
289
  const pathdef = def.paths[guidePath.key$]
276
290
 
@@ -1,22 +1,24 @@
1
1
 
2
2
  import { each, getx } from 'jostraca'
3
3
 
4
- import type { TransformCtx, TransformSpec, TransformResult, Transform, Guide } from '../transform'
4
+ import type { TransformResult } from '../transform'
5
5
 
6
6
  import { fixName } from '../transform'
7
7
 
8
8
 
9
9
  const topTransform = async function(
10
- ctx: TransformCtx,
11
- guide: Guide,
12
- tspec: TransformSpec,
13
- model: any,
14
- def: any
10
+ ctx: any,
11
+ // guide: Guide,
12
+ // // tspec: TransformSpec,
13
+ // model: any,
14
+ // def: any
15
15
  ): Promise<TransformResult> {
16
- const { spec } = ctx
16
+ const { apimodel, def } = ctx
17
17
 
18
- model.main.def.info = def.info
19
- model.main.def.servers = def.servers
18
+ // const { spec } = ctx
19
+
20
+ apimodel.main.def.info = def.info
21
+ apimodel.main.def.servers = def.servers
20
22
 
21
23
  return { ok: true, msg: 'top' }
22
24
  }
package/src/transform.ts CHANGED
@@ -11,7 +11,7 @@ import { topTransform } from './transform/top'
11
11
  import { entityTransform } from './transform/entity'
12
12
  import { operationTransform } from './transform/operation'
13
13
  import { fieldTransform } from './transform/field'
14
- import { manualTransform } from './transform/manual'
14
+ // import { manualTransform } from './transform/manual'
15
15
 
16
16
 
17
17
 
@@ -55,7 +55,7 @@ const TRANSFORM: Record<string, Transform> = {
55
55
  entity: entityTransform,
56
56
  operation: operationTransform,
57
57
  field: fieldTransform,
58
- manual: manualTransform,
58
+ // manual: manualTransform,
59
59
  }
60
60
 
61
61
 
@@ -98,10 +98,16 @@ async function resolveTransforms(ctx: TransformCtx): Promise<TransformSpec> {
98
98
  order: transformNames
99
99
  })
100
100
 
101
- for (const tn of transformNames) {
102
- log.debug({ what: 'transform', transform: tn, note: tn })
103
- const transform = await resolveTransform(tn, ctx)
104
- tspec.transform.push(transform)
101
+ try {
102
+ for (const tn of transformNames) {
103
+ log.debug({ what: 'transform', transform: tn, note: tn })
104
+ const transform = await resolveTransform(tn, ctx)
105
+ tspec.transform.push(transform)
106
+ }
107
+ }
108
+ catch (err: any) {
109
+ console.log(err)
110
+ throw err
105
111
  }
106
112
 
107
113
  return tspec
@@ -146,10 +152,10 @@ async function resolveTransform(tn: string, ctx: TransformCtx) {
146
152
  }
147
153
 
148
154
 
149
-
150
155
  async function processTransforms(
151
156
  ctx: TransformCtx,
152
- spec: TransformSpec,
157
+ // spec: TransformSpec,
158
+ transforms: any[],
153
159
  apimodel: any,
154
160
  def: any
155
161
  ): Promise<ProcessResult> {
@@ -162,15 +168,21 @@ async function processTransforms(
162
168
  const guide: Guide = GuideShape(ctx.model.main.api.guide)
163
169
 
164
170
 
165
- for (let tI = 0; tI < spec.transform.length; tI++) {
166
- const transform = spec.transform[tI]
171
+ // for (let tI = 0; tI < spec.transform.length; tI++) {
172
+ // const transform = spec.transform[tI]
173
+
174
+ for (let tI = 0; tI < transforms.length; tI++) {
175
+ const transform = transforms[tI]
167
176
 
168
177
  try {
169
- const tres = await transform(ctx, guide, spec, apimodel, def)
178
+ const tres = await transform(ctx, guide, apimodel, def)
170
179
  pres.ok = pres.ok && tres.ok
171
180
  pres.results.push(tres)
172
181
  }
173
182
  catch (err: any) {
183
+ // TODO: fix: this error does not get printed
184
+ console.log(err)
185
+
174
186
  pres.ok = false
175
187
  pres.msg += transform.name + ': ' + err.message + '\n'
176
188
  pres.results.push({
package/src/types.ts ADDED
@@ -0,0 +1,88 @@
1
+ /* Copyright (c) 2025 Voxgig, MIT License */
2
+
3
+ import * as Fs from 'node:fs'
4
+
5
+ import { Pino, prettyPino } from '@voxgig/util'
6
+ import { Gubu, Open, Any } from 'gubu'
7
+
8
+
9
+ type FsUtil = typeof Fs
10
+ type Log = ReturnType<typeof prettyPino>
11
+
12
+
13
+ type ApiDefOptions = {
14
+ def?: string
15
+ fs?: any
16
+ pino?: ReturnType<typeof Pino>
17
+ debug?: boolean | string
18
+ folder?: string
19
+ meta?: Record<string, any>
20
+ outprefix?: string
21
+ strategy?: string
22
+ }
23
+
24
+
25
+ const ModelShape = Gubu({
26
+ name: String,
27
+ def: String,
28
+ main: {
29
+ sdk: {},
30
+ def: {},
31
+ api: {
32
+ guide: {}
33
+ },
34
+ }
35
+ })
36
+ const OpenModelShape = Gubu(Open(ModelShape))
37
+
38
+ type Model = ReturnType<typeof ModelShape>
39
+
40
+
41
+ const BuildShape = Gubu({
42
+ spec: {
43
+ base: '',
44
+ path: '',
45
+ debug: '',
46
+ use: {},
47
+ res: [],
48
+ require: '',
49
+ log: {},
50
+ fs: Any(),
51
+ watch: {
52
+ mod: true,
53
+ add: true,
54
+ rem: true,
55
+ }
56
+ }
57
+ })
58
+ const OpenBuildShape = Gubu(Open(BuildShape))
59
+
60
+ type Build = ReturnType<typeof BuildShape>
61
+
62
+
63
+
64
+ type ApiModel = {
65
+ main: {
66
+ api: {
67
+ entity: Record<string, any>
68
+ }
69
+ def: Record<string, any>
70
+ }
71
+ }
72
+
73
+
74
+ export {
75
+ OpenModelShape,
76
+ OpenBuildShape,
77
+ }
78
+
79
+
80
+ export type {
81
+ Log,
82
+ FsUtil,
83
+ ApiDefOptions,
84
+ Model,
85
+ Build,
86
+ ApiModel,
87
+ }
88
+