@voxgig/model 3.5.0 → 5.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.
- package/bin/voxgig-model +150 -31
- package/dist/{lib/build.d.ts → build.d.ts} +6 -5
- package/dist/{lib/build.js → build.js} +4 -3
- package/dist/build.js.map +1 -0
- package/dist/{lib/builder → builder}/local.js +13 -34
- package/dist/builder/local.js.map +1 -0
- package/dist/{lib/builder → builder}/model.js +5 -0
- package/dist/builder/model.js.map +1 -0
- package/dist/config.d.ts +12 -0
- package/dist/{lib/config.js → config.js} +6 -4
- package/dist/config.js.map +1 -0
- package/dist/model.d.ts +8 -7
- package/dist/model.js +35 -20
- package/dist/model.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/{lib/types.d.ts → types.d.ts} +25 -3
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/{lib/watch.d.ts → watch.d.ts} +15 -18
- package/dist/watch.js +227 -0
- package/dist/watch.js.map +1 -0
- package/package.json +19 -20
- package/dist/lib/build.js.map +0 -1
- package/dist/lib/builder/local.js.map +0 -1
- package/dist/lib/builder/model.js.map +0 -1
- package/dist/lib/config.d.ts +0 -11
- package/dist/lib/config.js.map +0 -1
- package/dist/lib/model-builder.d.ts +0 -0
- package/dist/lib/model-builder.js +0 -2
- package/dist/lib/model-builder.js.map +0 -1
- package/dist/lib/types.js +0 -3
- package/dist/lib/types.js.map +0 -1
- package/dist/lib/util.d.ts +0 -7
- package/dist/lib/util.js +0 -94
- package/dist/lib/util.js.map +0 -1
- package/dist/lib/watch.js +0 -172
- package/dist/lib/watch.js.map +0 -1
- package/dist/model.min.js +0 -94
- package/lib/build.ts +0 -138
- package/lib/builder/local.ts +0 -130
- package/lib/builder/model.ts +0 -37
- package/lib/config.ts +0 -50
- package/lib/types.ts +0 -67
- package/lib/watch.ts +0 -250
- package/model.ts +0 -145
- /package/dist/{lib/builder → builder}/local.d.ts +0 -0
- /package/dist/{lib/builder → builder}/model.d.ts +0 -0
package/lib/watch.ts
DELETED
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
/* Copyright © 2021-2024 Voxgig Ltd, MIT License. */
|
|
2
|
-
|
|
3
|
-
import Path from 'node:path'
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import type { Build, BuildResult } from './types'
|
|
7
|
-
|
|
8
|
-
import { makeBuild } from './build'
|
|
9
|
-
import { FSWatcher } from 'chokidar'
|
|
10
|
-
|
|
11
|
-
import { readFile, stat } from 'fs/promises'
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const print = console.log
|
|
15
|
-
const warn = console.warn
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
type Run = {
|
|
19
|
-
canon: string
|
|
20
|
-
path: string
|
|
21
|
-
start: number
|
|
22
|
-
end: number
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
type Canon = {
|
|
26
|
-
path: string
|
|
27
|
-
isFolder: boolean
|
|
28
|
-
when: number
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
class Watch {
|
|
32
|
-
fsw: FSWatcher
|
|
33
|
-
spec: any
|
|
34
|
-
last?: BuildResult
|
|
35
|
-
last_change_time: number
|
|
36
|
-
build: Build | undefined
|
|
37
|
-
runq: Run[]
|
|
38
|
-
doneq: Run[]
|
|
39
|
-
canons: Canon[]
|
|
40
|
-
running: boolean
|
|
41
|
-
|
|
42
|
-
constructor(spec: any) {
|
|
43
|
-
this.spec = spec
|
|
44
|
-
this.fsw = new FSWatcher()
|
|
45
|
-
this.last_change_time = 0
|
|
46
|
-
this.runq = []
|
|
47
|
-
this.doneq = []
|
|
48
|
-
this.canons = []
|
|
49
|
-
this.running = false
|
|
50
|
-
|
|
51
|
-
// const run = this.run.bind(this)
|
|
52
|
-
const drain = this.drain.bind(this)
|
|
53
|
-
|
|
54
|
-
this.fsw.on('change', async (path: string) => {
|
|
55
|
-
// TODO: needs a much more robust queue that checks for dups,
|
|
56
|
-
// otherwise BuildContext state will have concurrency corruptions
|
|
57
|
-
// Avoid rebuilding when, for example, TS rewrites all files in dist
|
|
58
|
-
// const dorun = 1111 < Date.now() - this.last_change_time
|
|
59
|
-
// console.log('CHANGE', dorun, this.last_change_time, args)
|
|
60
|
-
|
|
61
|
-
const canon = this.canon(path)
|
|
62
|
-
|
|
63
|
-
const running = this.runq.find((run: Run) => run.canon === canon)
|
|
64
|
-
if (running) {
|
|
65
|
-
// console.log('RUNNING', canon, path)
|
|
66
|
-
return
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
this.runq.push({
|
|
70
|
-
canon,
|
|
71
|
-
path,
|
|
72
|
-
start: Date.now(),
|
|
73
|
-
end: -1,
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
// console.log('RUNQ-ADD', this.runq)
|
|
77
|
-
setImmediate(drain)
|
|
78
|
-
})
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
async drain() {
|
|
83
|
-
if (this.running) {
|
|
84
|
-
return
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
this.running = true
|
|
88
|
-
let r
|
|
89
|
-
while (r = this.runq[0]) {
|
|
90
|
-
// console.log('DRAIN')
|
|
91
|
-
let br = await this.run(false, r.canon)
|
|
92
|
-
// console.log('BR', br)
|
|
93
|
-
this.runq.shift()
|
|
94
|
-
r.end = Date.now()
|
|
95
|
-
|
|
96
|
-
this.doneq.push(r)
|
|
97
|
-
|
|
98
|
-
// console.log('DONEQ', this.doneq)
|
|
99
|
-
}
|
|
100
|
-
this.running = false
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
async add(path: string) {
|
|
105
|
-
if (!Path.isAbsolute(path)) {
|
|
106
|
-
path = Path.join(this.spec.require, path)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Ignore if aleady added
|
|
110
|
-
if (this.canons.find((c: Canon) => c.path === path)) {
|
|
111
|
-
return
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const fileStat = await stat(path)
|
|
115
|
-
const canon: Canon = {
|
|
116
|
-
path: path,
|
|
117
|
-
isFolder: fileStat.isDirectory(),
|
|
118
|
-
when: Date.now()
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
this.canons.push(canon)
|
|
122
|
-
|
|
123
|
-
this.fsw.add(path)
|
|
124
|
-
|
|
125
|
-
// console.log('ADD', canon)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// If path is inside a watched folder, return folder as canonical reference.
|
|
130
|
-
canon(path: string) {
|
|
131
|
-
for (const canon of this.canons) {
|
|
132
|
-
if (canon.isFolder && path.startsWith(canon.path)) {
|
|
133
|
-
return canon.path
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return path
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
async update(br: BuildResult) {
|
|
141
|
-
let build = (br.build as Build)
|
|
142
|
-
|
|
143
|
-
let files: string[] =
|
|
144
|
-
Object.keys(build.root.deps).reduce((files: string[], target: any) => {
|
|
145
|
-
files = files.concat(Object.keys(build.root.deps[target]))
|
|
146
|
-
return files
|
|
147
|
-
}, [build.path])
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
// TODO: remove deleted files
|
|
151
|
-
files.forEach(async (file: string) => {
|
|
152
|
-
if ('string' === typeof (file) &&
|
|
153
|
-
'' !== file &&
|
|
154
|
-
build.opts.base !== file
|
|
155
|
-
) {
|
|
156
|
-
await this.add(file)
|
|
157
|
-
}
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
// Returns first BuildResult
|
|
164
|
-
async start(): Promise<BuildResult> {
|
|
165
|
-
return await this.run(false, '<start>')
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
async run(once?: boolean, trigger?: string): Promise<BuildResult> {
|
|
170
|
-
// console.trace()
|
|
171
|
-
|
|
172
|
-
this.last_change_time = Date.now()
|
|
173
|
-
print('\n@voxgig/model', this.last_change_time, new Date(this.last_change_time))
|
|
174
|
-
print('TRIGGER:', trigger, '\n')
|
|
175
|
-
|
|
176
|
-
// TODO: build spec should not have src!
|
|
177
|
-
let src = (await readFile(this.spec.path)).toString()
|
|
178
|
-
this.spec.src = src
|
|
179
|
-
|
|
180
|
-
this.build = this.build || makeBuild(this.spec)
|
|
181
|
-
|
|
182
|
-
// TODO: better way to do this?
|
|
183
|
-
this.build.src = src
|
|
184
|
-
|
|
185
|
-
let br: BuildResult = await this.build.run()
|
|
186
|
-
|
|
187
|
-
print('\nFILES:\n' + this.descDeps((br as any).build.root.deps) + '\n')
|
|
188
|
-
|
|
189
|
-
if (br.ok) {
|
|
190
|
-
print('TOP:', Object.keys(br?.build?.model).join(', '), '\n')
|
|
191
|
-
|
|
192
|
-
if (!once) {
|
|
193
|
-
// There may be new files.
|
|
194
|
-
await this.update(br)
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
198
|
-
warn('MODEL ERRORS: ' + br.err?.length)
|
|
199
|
-
this.handleErrors(br)
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
this.last = br
|
|
203
|
-
|
|
204
|
-
return br
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
async stop() {
|
|
209
|
-
await this.fsw.close()
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
handleErrors(br: BuildResult) {
|
|
214
|
-
if (br.err) {
|
|
215
|
-
for (let be of br.err) {
|
|
216
|
-
// TODO: print stack if not a model error
|
|
217
|
-
|
|
218
|
-
if (be.isVal && be.msg) {
|
|
219
|
-
warn(be.msg)
|
|
220
|
-
}
|
|
221
|
-
// else if (be.message) {
|
|
222
|
-
// warn(be.message)
|
|
223
|
-
// }
|
|
224
|
-
else {
|
|
225
|
-
warn(be)
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
descDeps(deps: Record<string, Record<string, { tar: string }>>) {
|
|
232
|
-
if (null == deps) {
|
|
233
|
-
return ''
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
let desc = []
|
|
237
|
-
for (let entryPath of Object.keys(deps)) {
|
|
238
|
-
desc.push(' ' + entryPath)
|
|
239
|
-
for (let depPath of Object.keys(deps[entryPath])) {
|
|
240
|
-
desc.push(' ' + depPath)
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
return desc.join('\n')
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
export {
|
|
249
|
-
Watch
|
|
250
|
-
}
|
package/model.ts
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/* Copyright © 2021-2023 Voxgig Ltd, MIT License. */
|
|
2
|
-
|
|
3
|
-
// TODO: remove need for this
|
|
4
|
-
import Fs from 'fs'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import type { Build, BuildResult, BuildAction, BuildContext, Spec } from './lib/types'
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import { Config } from './lib/config'
|
|
11
|
-
import { Watch } from './lib/watch'
|
|
12
|
-
|
|
13
|
-
import { model_builder } from './lib/builder/model'
|
|
14
|
-
import { local_builder } from './lib/builder/local'
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class Model {
|
|
18
|
-
config: Config
|
|
19
|
-
build: any
|
|
20
|
-
watch: Watch
|
|
21
|
-
|
|
22
|
-
trigger_model = false
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
constructor(spec: Spec) {
|
|
26
|
-
const self = this
|
|
27
|
-
|
|
28
|
-
// Config is a special Watch to handle model config.
|
|
29
|
-
this.config = makeConfig(spec, {
|
|
30
|
-
path: '/',
|
|
31
|
-
build: async function trigger_model(build: Build, ctx: BuildContext) {
|
|
32
|
-
if ('post' !== ctx.step) {
|
|
33
|
-
return { ok: true }
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
let res
|
|
37
|
-
|
|
38
|
-
// console.log('TRIGGER', build.id, self.trigger_model, ctx)
|
|
39
|
-
// console.log(new Error().stack)
|
|
40
|
-
|
|
41
|
-
if (self.trigger_model) {
|
|
42
|
-
|
|
43
|
-
// TODO: fix!!!
|
|
44
|
-
self.build.use.config.watch.last.build = build
|
|
45
|
-
|
|
46
|
-
res = self.watch.run(true)
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
self.trigger_model = true
|
|
50
|
-
res = { ok: true }
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const watchmap = build.model?.sys?.model?.watch
|
|
54
|
-
|
|
55
|
-
if (watchmap) {
|
|
56
|
-
Object.keys(watchmap).map((file: string) => {
|
|
57
|
-
self.watch.add(file)
|
|
58
|
-
})
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return res
|
|
62
|
-
}
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// The actual model.
|
|
67
|
-
this.build = {
|
|
68
|
-
src: spec.src,
|
|
69
|
-
path: spec.path,
|
|
70
|
-
base: spec.base,
|
|
71
|
-
use: { config: self.config },
|
|
72
|
-
res: [
|
|
73
|
-
{
|
|
74
|
-
path: '/',
|
|
75
|
-
build: model_builder
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
path: '/',
|
|
79
|
-
build: local_builder
|
|
80
|
-
}
|
|
81
|
-
],
|
|
82
|
-
require: spec.require
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
this.watch = new Watch(self.build)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
async run(): Promise<BuildResult> {
|
|
91
|
-
this.trigger_model = false
|
|
92
|
-
const br = await this.config.run()
|
|
93
|
-
return br.ok ? this.watch.run(true) : br
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
async start(): Promise<BuildResult> {
|
|
98
|
-
this.trigger_model = false
|
|
99
|
-
const br = await this.config.start()
|
|
100
|
-
return br.ok ? this.watch.start() : br
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
async stop() {
|
|
105
|
-
return this.watch.stop()
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
function makeConfig(spec: Spec, trigger_model_build: BuildAction) {
|
|
111
|
-
let cbase = spec.base + '/.model-config'
|
|
112
|
-
let cpath = cbase + '/model-config.jsonic'
|
|
113
|
-
|
|
114
|
-
// Build should load file
|
|
115
|
-
let src = Fs.readFileSync(cpath).toString()
|
|
116
|
-
|
|
117
|
-
let cspec: Spec = {
|
|
118
|
-
src: src,
|
|
119
|
-
path: cpath,
|
|
120
|
-
base: cbase,
|
|
121
|
-
res: [
|
|
122
|
-
|
|
123
|
-
// Generate full config model and save as a file.
|
|
124
|
-
{
|
|
125
|
-
path: '/',
|
|
126
|
-
build: model_builder
|
|
127
|
-
},
|
|
128
|
-
|
|
129
|
-
// Trigger main model build.
|
|
130
|
-
trigger_model_build
|
|
131
|
-
],
|
|
132
|
-
require: spec.require
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return new Config(cspec)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
export {
|
|
141
|
-
Model,
|
|
142
|
-
Spec,
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
|
|
File without changes
|
|
File without changes
|