jostraca 0.18.0 → 0.19.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/dist/cmp/Fragment.js +2 -0
- package/dist/cmp/Fragment.js.map +1 -1
- package/dist/jostraca.d.ts +2 -1
- package/dist/jostraca.js +4 -2
- package/dist/jostraca.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/util/basic.d.ts +1 -0
- package/dist/util/basic.js +22 -0
- package/dist/util/basic.js.map +1 -1
- package/dist/util/point.d.ts +130 -0
- package/dist/util/point.js +205 -0
- package/dist/util/point.js.map +1 -0
- package/package.json +5 -5
- package/src/cmp/Fragment.ts +2 -0
- package/src/jostraca.ts +6 -1
- package/src/types.ts +1 -1
- package/src/util/basic.ts +29 -0
- package/src/util/point.ts +296 -0
- package/src/util/basic.ts~ +0 -572
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jostraca",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"main": "dist/jostraca.js",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"types": "dist/jostraca.d.ts",
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
],
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@hapi/code": "^9.0.3",
|
|
38
|
-
"@types/node": "22.15.
|
|
39
|
-
"esbuild": "^0.25.
|
|
40
|
-
"oxc-parser": "^0.
|
|
38
|
+
"@types/node": "22.15.29",
|
|
39
|
+
"esbuild": "^0.25.5",
|
|
40
|
+
"oxc-parser": "^0.72.2",
|
|
41
41
|
"typescript": "^5.8.3"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"memfs": ">=4"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"diff": "^
|
|
48
|
+
"diff": "^8.0.2",
|
|
49
49
|
"gubu": "^9.0.0",
|
|
50
50
|
"node-diff3": "^3.1.2"
|
|
51
51
|
}
|
package/src/cmp/Fragment.ts
CHANGED
|
@@ -16,6 +16,7 @@ const FragmentShape = Gubu({
|
|
|
16
16
|
exclude: Optional(One(Boolean, [String])) as unknown as boolean | string[],
|
|
17
17
|
indent: Optional(One(Empty(String), Number)),
|
|
18
18
|
replace: {} as any,
|
|
19
|
+
eject: Optional([One(String, RegExp)]) as unknown as any[]
|
|
19
20
|
}, { name: 'Fragment' })
|
|
20
21
|
|
|
21
22
|
|
|
@@ -74,6 +75,7 @@ const Fragment = cmp(function Fragment(props: FragmentProps, children: any) {
|
|
|
74
75
|
|
|
75
76
|
template(src, model, {
|
|
76
77
|
replace,
|
|
78
|
+
eject: props?.eject,
|
|
77
79
|
handle: (s?: string) => null == s ? null : Content(s)
|
|
78
80
|
})
|
|
79
81
|
})
|
package/src/jostraca.ts
CHANGED
|
@@ -49,6 +49,8 @@ import {
|
|
|
49
49
|
} from './util/basic'
|
|
50
50
|
|
|
51
51
|
|
|
52
|
+
import * as PointUtil from './util/point'
|
|
53
|
+
|
|
52
54
|
// TODO: the actual signatures
|
|
53
55
|
const deep: (...args: any[]) => any = JsonicUtil.deep
|
|
54
56
|
const omap: (...args: any[]) => any = JsonicUtil.omap
|
|
@@ -242,7 +244,7 @@ function Jostraca(gopts_in?: JostracaOptions | {}) {
|
|
|
242
244
|
}
|
|
243
245
|
|
|
244
246
|
if (memfs) {
|
|
245
|
-
res.vol = memfs.vol
|
|
247
|
+
res.vol = () => memfs.vol
|
|
246
248
|
}
|
|
247
249
|
|
|
248
250
|
return res
|
|
@@ -385,6 +387,7 @@ function cmp(component: Function): Component {
|
|
|
385
387
|
// }
|
|
386
388
|
|
|
387
389
|
|
|
390
|
+
|
|
388
391
|
export type {
|
|
389
392
|
JostracaOptions,
|
|
390
393
|
Component,
|
|
@@ -429,6 +432,8 @@ export {
|
|
|
429
432
|
Line,
|
|
430
433
|
Slot,
|
|
431
434
|
List,
|
|
435
|
+
|
|
436
|
+
PointUtil,
|
|
432
437
|
}
|
|
433
438
|
|
|
434
439
|
|
package/src/types.ts
CHANGED
package/src/util/basic.ts
CHANGED
|
@@ -350,12 +350,41 @@ function template(
|
|
|
350
350
|
ref?: string,
|
|
351
351
|
insert?: RegExp,
|
|
352
352
|
replace?: Record<string, any>,
|
|
353
|
+
eject?: any[]
|
|
353
354
|
handle?: (s?: string) => void
|
|
354
355
|
},
|
|
355
356
|
) {
|
|
356
357
|
|
|
357
358
|
src = null == src ? '' : '' + src
|
|
358
359
|
model = null == model ? {} : model
|
|
360
|
+
|
|
361
|
+
let eject = spec?.eject
|
|
362
|
+
if (null != eject) {
|
|
363
|
+
const ejectStart: RegExp | null = null == eject[0] ? null :
|
|
364
|
+
eject[0] instanceof RegExp ? eject[0] :
|
|
365
|
+
new RegExp('[ \t]*' + escre('' + eject[0]) + '[ \t]*\\n?')
|
|
366
|
+
const ejectEnd: RegExp | null = null == eject[1] ? null :
|
|
367
|
+
eject[1] instanceof RegExp ? eject[1] :
|
|
368
|
+
new RegExp('[ \t]*' + escre('' + eject[1]) + '[ \t]*\\n?')
|
|
369
|
+
|
|
370
|
+
if (null != ejectStart && null != ejectEnd) {
|
|
371
|
+
let startIndex = 0
|
|
372
|
+
let endIndex = src.length
|
|
373
|
+
|
|
374
|
+
const startMatch = src.match(ejectStart)
|
|
375
|
+
if (startMatch) {
|
|
376
|
+
startIndex = (startMatch as any).index + startMatch[0].length
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const endMatch = src.match(ejectEnd)
|
|
380
|
+
if (endMatch) {
|
|
381
|
+
endIndex = (endMatch as any).index
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
src = src.substring(startIndex, endIndex)
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
359
388
|
let open = null == spec?.open ? '\\$\\$' : spec.open
|
|
360
389
|
let close = null == spec?.close ? '\\$\\$' : spec.close
|
|
361
390
|
let ref = null == spec?.ref ? '[^$]+' : spec.ref
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
|
|
2
|
+
import { Gubu, Skip, Any } from 'gubu'
|
|
3
|
+
|
|
4
|
+
import { getx } from './basic'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
type PointCtx = {
|
|
8
|
+
async: boolean
|
|
9
|
+
log: LogEntry[]
|
|
10
|
+
data: Record<string, any>
|
|
11
|
+
depth: number,
|
|
12
|
+
sys: (() => {
|
|
13
|
+
now: () => number,
|
|
14
|
+
print: (...s: any) => void
|
|
15
|
+
}) & { plog?: string[] }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
type LogEntry = {
|
|
20
|
+
note: string
|
|
21
|
+
when: number
|
|
22
|
+
depth: number
|
|
23
|
+
args: any
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
abstract class Point implements Point {
|
|
28
|
+
id: string
|
|
29
|
+
name?: string
|
|
30
|
+
args?: any
|
|
31
|
+
|
|
32
|
+
constructor(id: string, name?: string) {
|
|
33
|
+
this.id = id
|
|
34
|
+
this.name = name
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async runner(pctx: PointCtx): Promise<void> {
|
|
38
|
+
const suffix = (null == this.name || '' === this.name) ? '' : ':' + this.name
|
|
39
|
+
this.logger(pctx, {
|
|
40
|
+
note: this.constructor.name + ':before:' + this.id + suffix, args: this.args
|
|
41
|
+
})
|
|
42
|
+
if (pctx.async) {
|
|
43
|
+
await this.run(pctx)
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.run(pctx)
|
|
47
|
+
}
|
|
48
|
+
this.logger(pctx, {
|
|
49
|
+
note: this.constructor.name + ':after:' + this.id + suffix, args: this.args
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
logger(pctx: PointCtx, entry: Partial<LogEntry>) {
|
|
55
|
+
entry.note = null == entry.note ? 'none' : entry.note
|
|
56
|
+
entry.when = pctx.sys().now()
|
|
57
|
+
entry.depth = pctx.depth
|
|
58
|
+
if (undefined === entry.args) {
|
|
59
|
+
delete entry.args
|
|
60
|
+
}
|
|
61
|
+
pctx.log.push(entry as LogEntry)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
abstract run(pctx: PointCtx): Promise<void>
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class SerialPoint extends Point {
|
|
69
|
+
points: Point[]
|
|
70
|
+
|
|
71
|
+
constructor(id: string) {
|
|
72
|
+
super(id)
|
|
73
|
+
this.points = []
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
add(p: Point) {
|
|
77
|
+
this.points.push(p)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async run(pctx: PointCtx): Promise<void> {
|
|
81
|
+
let childctx: PointCtx = { ...pctx }
|
|
82
|
+
childctx.depth++
|
|
83
|
+
for (let p of this.points) {
|
|
84
|
+
if (pctx.async) {
|
|
85
|
+
await p.runner(childctx)
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
p.runner(childctx)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class RootPoint extends SerialPoint {
|
|
96
|
+
points: Point[]
|
|
97
|
+
|
|
98
|
+
constructor(id: string) {
|
|
99
|
+
super(id)
|
|
100
|
+
this.points = []
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
direct(data?: Record<string, any>, sys?: any): PointCtx {
|
|
104
|
+
const pctx = this.makePointCtx(false, data, sys)
|
|
105
|
+
this.runner(pctx)
|
|
106
|
+
return pctx
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async start(data?: Record<string, any>, sys?: any): Promise<PointCtx> {
|
|
110
|
+
const pctx = this.makePointCtx(true, data, sys)
|
|
111
|
+
await this.runner(pctx)
|
|
112
|
+
return pctx
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
makePointCtx(async: boolean, data?: Record<string, any>, sys?: any): PointCtx {
|
|
117
|
+
const pctx: PointCtx = {
|
|
118
|
+
async,
|
|
119
|
+
log: [],
|
|
120
|
+
data: data || {},
|
|
121
|
+
depth: 0,
|
|
122
|
+
sys: sys || (() => ({
|
|
123
|
+
now: () => Date.now(),
|
|
124
|
+
print: (...s: any) => {
|
|
125
|
+
if (null != s[0] && 'string' === typeof s[0]) {
|
|
126
|
+
console.dir(s[0], s[1] || { depth: null })
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
console.log(...s)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}))
|
|
133
|
+
}
|
|
134
|
+
return pctx
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class ParallelPoint extends Point {
|
|
141
|
+
points: Point[]
|
|
142
|
+
|
|
143
|
+
constructor(id: string) {
|
|
144
|
+
super(id)
|
|
145
|
+
this.points = []
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
add(p: Point) {
|
|
149
|
+
this.points.push(p)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async run(pctx: PointCtx): Promise<void> {
|
|
153
|
+
let childctx: PointCtx = { ...pctx }
|
|
154
|
+
childctx.depth++
|
|
155
|
+
await Promise.all(this.points.map(p => p.runner(childctx)))
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class FuncPoint extends Point {
|
|
163
|
+
func: (pctx: PointCtx) => any
|
|
164
|
+
|
|
165
|
+
constructor(id: string, func: (pctx: PointCtx) => any) {
|
|
166
|
+
super(id, func.name)
|
|
167
|
+
this.func = func
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async run(pctx: PointCtx): Promise<void> {
|
|
171
|
+
if (pctx.async) {
|
|
172
|
+
await this.func(pctx)
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
this.func(pctx)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class PrintPoint extends Point {
|
|
182
|
+
path?: string
|
|
183
|
+
|
|
184
|
+
constructor(id: string, path?: string) {
|
|
185
|
+
super(id)
|
|
186
|
+
this.path = path
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async run(pctx: PointCtx): Promise<void> {
|
|
190
|
+
let print = pctx.sys().print
|
|
191
|
+
let d = pctx.data
|
|
192
|
+
if (null != this.path) {
|
|
193
|
+
d = getx(d, this.path)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (null != d && 'object' === typeof d) {
|
|
197
|
+
print('POINTCTX:')
|
|
198
|
+
print(d)
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
print('POINTCTX: ' + d)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
const PointDefShape = Gubu({
|
|
208
|
+
k: Skip(String),
|
|
209
|
+
n: Skip(String),
|
|
210
|
+
p: Skip([]),
|
|
211
|
+
a: Any(),
|
|
212
|
+
m: {}
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
type PointDef = Partial<ReturnType<typeof PointDefShape>>
|
|
216
|
+
|
|
217
|
+
type MakePoint = (id: () => string, pdef: PointDef) => Point
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
function buildPoints(pdef: PointDef, pm: Record<string, MakePoint>, id?: () => string): Point {
|
|
221
|
+
let idi = 0
|
|
222
|
+
id = id || (() => (++idi) + '')
|
|
223
|
+
let p: Point | undefined = undefined
|
|
224
|
+
|
|
225
|
+
// TODO: fix point kind resolution to be more extensible
|
|
226
|
+
|
|
227
|
+
pdef = PointDefShape(pdef)
|
|
228
|
+
let isSerial = 'Serial' === pdef.k || Array.isArray(pdef.p)
|
|
229
|
+
|
|
230
|
+
const mp = pm[pdef.k]
|
|
231
|
+
if (null != mp) {
|
|
232
|
+
p = mp(id, pdef)
|
|
233
|
+
}
|
|
234
|
+
else if (null == pdef.k || 'Root' === pdef.k) {
|
|
235
|
+
const rp = new RootPoint(id())
|
|
236
|
+
let cp = pdef.p
|
|
237
|
+
for (let c of cp) {
|
|
238
|
+
rp.add(buildPoints(c, pm, id))
|
|
239
|
+
}
|
|
240
|
+
p = rp
|
|
241
|
+
isSerial = false
|
|
242
|
+
}
|
|
243
|
+
else if ('Parallel' === pdef.k) {
|
|
244
|
+
const sp = new ParallelPoint(id())
|
|
245
|
+
let cp = pdef.p
|
|
246
|
+
for (let c of cp) {
|
|
247
|
+
sp.add(buildPoints(c, pm, id))
|
|
248
|
+
}
|
|
249
|
+
p = sp
|
|
250
|
+
isSerial = false
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (isSerial) {
|
|
254
|
+
const sp = (p || new SerialPoint(id())) as SerialPoint
|
|
255
|
+
let cp = pdef.p
|
|
256
|
+
for (let c of cp) {
|
|
257
|
+
sp.add(buildPoints(c, pm, id))
|
|
258
|
+
}
|
|
259
|
+
p = sp
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (null == p) {
|
|
263
|
+
throw new Error('Unknown point kind: ' + JSON.stringify(pdef))
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return p
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
function makeFuncDef(fd: (pdef: PointDef) => (pctx: PointCtx) => any) {
|
|
271
|
+
return (id: () => string, pdef: PointDef) => {
|
|
272
|
+
const fp = new FuncPoint(id(), fd(pdef))
|
|
273
|
+
fp.args = pdef.a
|
|
274
|
+
return fp
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
export type {
|
|
281
|
+
PointCtx,
|
|
282
|
+
MakePoint,
|
|
283
|
+
PointDef,
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
export {
|
|
288
|
+
Point,
|
|
289
|
+
RootPoint,
|
|
290
|
+
SerialPoint,
|
|
291
|
+
ParallelPoint,
|
|
292
|
+
FuncPoint,
|
|
293
|
+
PrintPoint,
|
|
294
|
+
buildPoints,
|
|
295
|
+
makeFuncDef,
|
|
296
|
+
}
|