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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jostraca",
3
- "version": "0.18.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.17",
39
- "esbuild": "^0.25.4",
40
- "oxc-parser": "^0.68.1",
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": "^7.0.0",
48
+ "diff": "^8.0.2",
49
49
  "gubu": "^9.0.0",
50
50
  "node-diff3": "^3.1.2"
51
51
  }
@@ -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
@@ -44,7 +44,7 @@ type JostracaResult = {
44
44
  conflicted: string[],
45
45
  unchanged: string[],
46
46
  }
47
- vol?: any
47
+ vol?: () => any
48
48
  }
49
49
 
50
50
 
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
+ }