whet 0.1.1 → 0.4.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 (48) hide show
  1. package/bin/genes/util/EsMap.d.ts +1 -0
  2. package/bin/genes/util/EsMap.js +3 -0
  3. package/bin/haxe/Constraints.d.ts +1 -0
  4. package/bin/haxe/ds/IntMap.d.ts +6 -0
  5. package/bin/haxe/ds/IntMap.js +25 -0
  6. package/bin/haxe/ds/Vector.d.ts +2 -0
  7. package/bin/minimatch/MinimatchOptions.d.ts +28 -0
  8. package/bin/whet/Log.js +3 -0
  9. package/bin/whet/Project.d.ts +13 -0
  10. package/bin/whet/Project.js +26 -0
  11. package/bin/whet/Stone.d.ts +23 -0
  12. package/bin/whet/Stone.js +162 -7
  13. package/bin/whet/Whet.d.ts +1 -1
  14. package/bin/whet/Whet.js +68 -1
  15. package/bin/whet/cache/BaseCache.d.ts +7 -0
  16. package/bin/whet/cache/BaseCache.js +103 -7
  17. package/bin/whet/cache/CacheManager.d.ts +5 -0
  18. package/bin/whet/cache/CacheManager.js +97 -7
  19. package/bin/whet/cache/FileCache.d.ts +1 -0
  20. package/bin/whet/cache/FileCache.js +4 -0
  21. package/bin/whet/cache/MemoContext.d.ts +17 -0
  22. package/bin/whet/cache/MemoContext.js +35 -0
  23. package/bin/whet/magic/RoutePathType.js +5 -5
  24. package/bin/whet/profiler/Profiler.d.ts +65 -0
  25. package/bin/whet/profiler/Profiler.js +351 -0
  26. package/bin/whet/profiler/Span.d.ts +90 -0
  27. package/bin/whet/profiler/Span.js +56 -0
  28. package/bin/whet/profiler/SpanRecorder.d.ts +20 -0
  29. package/bin/whet/profiler/SpanRecorder.js +63 -0
  30. package/bin/whet/profiler/SpanStats.d.ts +15 -0
  31. package/bin/whet/profiler/SpanStats.js +49 -0
  32. package/bin/whet/route/Router.d.ts +5 -0
  33. package/bin/whet/route/Router.js +47 -33
  34. package/bin/whet/stones/Files.d.ts +5 -0
  35. package/bin/whet/stones/Files.js +20 -0
  36. package/bin/whet/stones/StoneFactory.d.ts +55 -0
  37. package/bin/whet/stones/StoneFactory.js +116 -0
  38. package/bin/whet.d.ts +2 -0
  39. package/bin/whet.js +1 -0
  40. package/package.json +2 -2
  41. package/bin/haxe/Log.d.ts +0 -33
  42. package/bin/haxe/Log.js +0 -61
  43. package/bin/pino_pretty/PrettyOptions.d.ts +0 -98
  44. package/bin/pino_pretty/default_/MessageFormatFunc.d.ts +0 -2
  45. package/bin/pino_pretty/default_/Prettifier.d.ts +0 -2
  46. package/bin/whet/extern/Minimatch.d.ts +0 -77
  47. package/bin/whet/stones/Server.d.ts +0 -59
  48. package/bin/whet/stones/Server.js +0 -261
@@ -6,6 +6,7 @@ export declare class EsMap<K, V> {
6
6
  protected inst: Map<K, V>
7
7
  set(key: K, value: V): void
8
8
  get(key: K): null | V
9
+ remove(key: K): boolean
9
10
  exists(key: K): boolean
10
11
  keys(): Iterator<K>
11
12
  protected static adaptIterator<T>(from: Iterator__1<T>): Iterator<T>
@@ -13,6 +13,9 @@ class EsMap extends Register.inherits() {
13
13
  get(key) {
14
14
  return this.inst.get(key);
15
15
  }
16
+ remove(key) {
17
+ return this.inst["delete"](key);
18
+ }
16
19
  exists(key) {
17
20
  return this.inst.has(key);
18
21
  }
@@ -4,5 +4,6 @@ export declare interface IMap<K, V> {
4
4
  get(k: K): null | V
5
5
  set(k: K, v: V): void
6
6
  exists(k: K): boolean
7
+ remove(k: K): boolean
7
8
  keys(): Iterator<K>
8
9
  }
@@ -0,0 +1,6 @@
1
+ import {IMap} from "../Constraints"
2
+ import {EsMap} from "../../genes/util/EsMap"
3
+
4
+ export declare class IntMap<T> extends EsMap<number, T> implements IMap<number, T> {
5
+ constructor()
6
+ }
@@ -0,0 +1,25 @@
1
+ import {IMap} from "../Constraints.js"
2
+ import {EsMap} from "../../genes/util/EsMap.js"
3
+ import {Register} from "../../genes/Register.js"
4
+
5
+ const $global = Register.$global
6
+
7
+ export const IntMap = Register.global("$hxClasses")["haxe.ds.IntMap"] =
8
+ class IntMap extends Register.inherits(EsMap) {
9
+ [Register.new]() {
10
+ super[Register.new]();
11
+ }
12
+ static get __name__() {
13
+ return "haxe.ds.IntMap"
14
+ }
15
+ static get __interfaces__() {
16
+ return [IMap]
17
+ }
18
+ static get __super__() {
19
+ return EsMap
20
+ }
21
+ get __class__() {
22
+ return IntMap
23
+ }
24
+ }
25
+
@@ -0,0 +1,2 @@
1
+
2
+ export type VectorData<T> = T[]
@@ -32,6 +32,34 @@ export type MinimatchOptions = {
32
32
  */
33
33
  matchBase?: null | boolean,
34
34
  /**
35
+ Max depth to traverse for nested extglobs like `*(a|b|c)`
36
+
37
+ Default is 2, which is quite low, but any higher value
38
+ swiftly results in punishing performance impacts. Note
39
+ that this is *not* relevant when the globstar types can
40
+ be safely coalesced into a single set.
41
+
42
+ For example, `*(a|@(b|c)|d)` would be flattened into
43
+ `*(a|b|c|d)`. Thus, many common extglobs will retain good
44
+ performance and never hit this limit, even if they are
45
+ excessively deep and complicated.
46
+
47
+ If the limit is hit, then the extglob characters are simply
48
+ not parsed, and the pattern effectively switches into
49
+ `noextglob: true` mode for the contents of that nested
50
+ sub-pattern. This will typically _not_ result in a match,
51
+ but is considered a valid trade-off for security and
52
+ performance.
53
+ */
54
+ maxExtglobRecursion?: null | number,
55
+ /**
56
+ Max number of non-adjacent `**` patterns to recursively walk down.
57
+
58
+ The default of 200 is almost certainly high enough for most purposes,
59
+ and can handle absurdly excessive patterns.
60
+ */
61
+ maxGlobstarRecursion?: null | number,
62
+ /**
35
63
  do not expand `{x,y}` style braces
36
64
  */
37
65
  nobrace?: null | boolean,
package/bin/whet/Log.js CHANGED
@@ -89,6 +89,9 @@ class LogLevel {
89
89
  case "info":
90
90
  return 30;
91
91
  break
92
+ case "silent":
93
+ return 100;
94
+ break
92
95
  case "trace":
93
96
  return 10;
94
97
  break
@@ -1,3 +1,4 @@
1
+ import {Profiler, ProfilerConfig} from "./profiler/Profiler"
1
2
  import {CacheManager} from "./cache/CacheManager"
2
3
  import {CacheStrategy} from "./cache/Cache"
3
4
  import {AnyStone, OutputFilter} from "./Stone"
@@ -13,6 +14,7 @@ export declare class Project {
13
14
  rootDir: string
14
15
  cache: CacheManager
15
16
  configStore: ConfigStore
17
+ profiler: null | Profiler
16
18
  stones: AnyStone[]
17
19
  onInit: (config: any) => Promise<any>
18
20
 
@@ -22,6 +24,11 @@ export declare class Project {
22
24
  config: any
23
25
  protected options: Option[]
24
26
  getStone(id: string): null | AnyStone
27
+
28
+ /**
29
+ Remove a stone from the project. Does not clear cache — use cache.clearStone() separately if needed.
30
+ */
31
+ removeStone(stone: AnyStone): boolean
25
32
  describeStones(): StoneDescription[]
26
33
  listStoneOutputs(id: string): Promise<null | string[]>
27
34
  getStoneSource(id: string, sourceId?: null | string): Promise<null | Source>
@@ -29,6 +36,8 @@ export declare class Project {
29
36
  getStoneConfig(id: string): Promise<null | StoneConfigView>
30
37
  setStoneConfig(id: string, patch: any, mode: string): Promise<boolean>
31
38
  clearStoneConfigPreview(id: string): Promise<boolean>
39
+ enableProfiling(config?: null | ProfilerConfig): void
40
+ disableProfiling(): void
32
41
  addCommand(name: string, stone?: null | AnyStone): Command
33
42
  protected isCommandNameTaken(name: string): boolean
34
43
  toString(): string
@@ -49,6 +58,10 @@ export type ProjectConfig = {
49
58
  */
50
59
  onInit?: null | ((config: any) => Promise<any>),
51
60
  options?: null | Option[],
61
+ /**
62
+ Enable profiling with optional config.
63
+ */
64
+ profiler?: null | ProfilerConfig,
52
65
  rootDir?: null | string
53
66
  }
54
67
 
@@ -1,4 +1,5 @@
1
1
  import {Router} from "./route/Router.js"
2
+ import {Profiler} from "./profiler/Profiler.js"
2
3
  import {StoneId_Fields_} from "./magic/StoneId.js"
3
4
  import {MaybeArray_Fields_} from "./magic/MaybeArray.js"
4
5
  import {CacheManager} from "./cache/CacheManager.js"
@@ -18,6 +19,7 @@ export const Project = Register.global("$hxClasses")["whet.Project"] =
18
19
  class Project extends Register.inherits() {
19
20
  [Register.new](config) {
20
21
  this.stones = [];
22
+ this.profiler = null;
21
23
  this.configStore = null;
22
24
  this.cache = null;
23
25
  Log.log(20, ...["Instantiating new Project."]);
@@ -55,6 +57,9 @@ class Project extends Register.inherits() {
55
57
  };
56
58
  this.configStore = config.configStore;
57
59
  this.cache = (config.cache == null) ? new CacheManager(this) : config.cache;
60
+ if (config.profiler != null) {
61
+ this.profiler = new Profiler(config.profiler);
62
+ };
58
63
  Project.projects.push(this);
59
64
  Log.log(30, ...["New project created.", {"project": this, "projectCount": Project.projects.length}]);
60
65
  }
@@ -70,6 +75,18 @@ class Project extends Register.inherits() {
70
75
  };
71
76
  return null;
72
77
  }
78
+
79
+ /**
80
+ Remove a stone from the project. Does not clear cache — use cache.clearStone() separately if needed.
81
+ */
82
+ removeStone(stone) {
83
+ let idx = this.stones.indexOf(stone);
84
+ if (idx == -1) {
85
+ return false;
86
+ };
87
+ this.stones.splice(idx, 1);
88
+ return true;
89
+ }
73
90
  describeStones() {
74
91
  let _g = [];
75
92
  let _g1 = 0;
@@ -201,6 +218,14 @@ class Project extends Register.inherits() {
201
218
  store.clearEntry(stone.id);
202
219
  return Promise.resolve(true);
203
220
  }
221
+ enableProfiling(config) {
222
+ if (this.profiler == null) {
223
+ this.profiler = new Profiler(config);
224
+ };
225
+ }
226
+ disableProfiling() {
227
+ this.profiler = null;
228
+ }
204
229
  addCommand(name, stone) {
205
230
  let cmdName = name;
206
231
  let cmdAlias = null;
@@ -252,6 +277,7 @@ Project.prototype.description = null;
252
277
  Project.prototype.rootDir = null;
253
278
  Project.prototype.cache = null;
254
279
  Project.prototype.configStore = null;
280
+ Project.prototype.profiler = null;
255
281
  Project.prototype.stones = null;
256
282
  Project.prototype.onInit = null;
257
283
  Project.prototype.config = null;
@@ -1,3 +1,4 @@
1
+ import {AnySpan} from "./profiler/Span"
1
2
  import {StoneIdType} from "./magic/StoneId"
2
3
  import {MaybeArray} from "./magic/MaybeArray"
3
4
  import {CacheManager} from "./cache/CacheManager"
@@ -54,6 +55,7 @@ export declare class Stone<T extends StoneConfig> {
54
55
  * Hashes of dependency stones (see `config.dependencies`) will be added to the hash.
55
56
  */
56
57
  getHash(): Promise<SourceHash>
58
+ protected _computeHash(): Promise<SourceHash>
57
59
 
58
60
  /**
59
61
  * **Do not override.**
@@ -126,6 +128,7 @@ export declare class Stone<T extends StoneConfig> {
126
128
  * Uses the same cache as getSource() — partial and full share the pool.
127
129
  */
128
130
  getPartialSource(sourceId: string): Promise<null | Source>
131
+ protected _computePartialSource(sourceId: string): Promise<null | Source>
129
132
 
130
133
  /**
131
134
  * Called by cache infrastructure. Generates partial source directly,
@@ -184,6 +187,26 @@ export declare class Stone<T extends StoneConfig> {
184
187
  * Useful for pure JS stones.
185
188
  */
186
189
  cwdPath(path: string): string
190
+
191
+ /**
192
+ Wraps an async operation in a profiler span. No-op when profiler is null.
193
+ */
194
+ protected profilerWithSpan<T, R>(op: string, fn: (() => Promise<R>), meta?: null | T): Promise<R>
195
+
196
+ /**
197
+ Starts a manual profiler span. Returns null when profiler is null.
198
+ */
199
+ protected profilerStartSpan<T>(op: string, meta?: null | T): null | AnySpan
200
+
201
+ /**
202
+ Ends a manual profiler span. No-op when span is null.
203
+ */
204
+ protected profilerEndSpan(span: null | AnySpan): void
205
+
206
+ /**
207
+ Returns the current span from ALS context, or null when profiler is disabled.
208
+ */
209
+ protected profilerGetCurrentSpan(): null | AnySpan
187
210
  protected get_cache(): CacheManager
188
211
  toString(): string
189
212
  }
package/bin/whet/Stone.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import {StoneId_Fields_} from "./magic/StoneId.js"
2
2
  import {MaybeArray_Fields_} from "./magic/MaybeArray.js"
3
+ import {MemoContext} from "./cache/MemoContext.js"
3
4
  import {CacheStrategy, CacheDurability} from "./cache/Cache.js"
4
5
  import {Utils} from "./Utils.js"
5
6
  import {RootDir} from "./SourceId.js"
@@ -75,13 +76,23 @@ class Stone extends Register.inherits() {
75
76
  let _gthis = this;
76
77
  if (this.locked) {
77
78
  Log.log(20, ...["Stone is locked, waiting.", {"stone": this}]);
79
+ let waitSpan = (this.project.profiler != null) ? this.project.profiler.startSpan(this, "LockWait", {"queuePosition": this.lockQueue.length, "queueLength": this.lockQueue.length + 1}) : null;
78
80
  let deferredRes;
79
81
  let deferredRej;
80
82
  let deferred = new Promise(function (res, rej) {
81
83
  deferredRes = res;
82
84
  deferredRej = rej;
83
85
  });
84
- this.lockQueue.push({"run": run, "res": deferredRes, "rej": deferredRej});
86
+ this.lockQueue.push({"run": function () {
87
+ if (waitSpan != null) {
88
+ _gthis.project.profiler.endSpan(waitSpan);
89
+ };
90
+ if (_gthis.project.profiler != null) {
91
+ return _gthis.project.profiler.withSpan(_gthis, "LockHeld", run, null);
92
+ } else {
93
+ return run();
94
+ };
95
+ }, "res": deferredRes, "rej": deferredRej});
85
96
  return deferred;
86
97
  } else {
87
98
  this.locked = true;
@@ -96,7 +107,7 @@ class Stone extends Register.inherits() {
96
107
  Log.log(10, ...["No function in lock queue. Stone is now unlocked.", {"stone": _gthis}]);
97
108
  };
98
109
  };
99
- return run()["finally"](runNext);
110
+ return ((this.project.profiler != null) ? this.project.profiler.withSpan(this, "LockHeld", run, null) : run())["finally"](runNext);
100
111
  };
101
112
  }
102
113
 
@@ -106,7 +117,24 @@ class Stone extends Register.inherits() {
106
117
  */
107
118
  getSource() {
108
119
  Log.log(20, ...["Getting source.", {"stone": this}]);
109
- return this.project.cache.getSource(this);
120
+ let ctx = MemoContext.als.getStore();
121
+ if (ctx != null) {
122
+ let cached = ctx.sources.get(this);
123
+ if (cached != null) {
124
+ Log.log(10, ...["Source memo hit.", {"stone": this}]);
125
+ return cached;
126
+ };
127
+ let p = this.project.cache.getSource(this);
128
+ ctx.sources.set(this, p);
129
+ return p;
130
+ };
131
+ let _gthis = this;
132
+ return MemoContext.ensure(function () {
133
+ let newCtx = MemoContext.als.getStore();
134
+ let p = _gthis.project.cache.getSource(_gthis);
135
+ newCtx.sources.set(_gthis, p);
136
+ return p;
137
+ });
110
138
  }
111
139
 
112
140
  /**
@@ -116,6 +144,44 @@ class Stone extends Register.inherits() {
116
144
  */
117
145
  getHash() {
118
146
  Log.log(20, ...["Generating hash.", {"stone": this}]);
147
+ let ctx = MemoContext.als.getStore();
148
+ if (ctx != null) {
149
+ let cached = ctx.hashes.get(this);
150
+ if (cached != null) {
151
+ Log.log(10, ...["Hash memo hit.", {"stone": this}]);
152
+ return cached;
153
+ };
154
+ let _gthis = this;
155
+ let p = this.finalMaybeHash().then(function (hash) {
156
+ if (hash != null) {
157
+ return hash;
158
+ } else {
159
+ return _gthis.getSource().then(function (s) {
160
+ return s.hash;
161
+ });
162
+ };
163
+ });
164
+ ctx.hashes.set(this, p);
165
+ return p;
166
+ };
167
+ let _gthis = this;
168
+ return MemoContext.ensure(function () {
169
+ let newCtx = MemoContext.als.getStore();
170
+ let _gthis1 = _gthis;
171
+ let p = _gthis.finalMaybeHash().then(function (hash) {
172
+ if (hash != null) {
173
+ return hash;
174
+ } else {
175
+ return _gthis1.getSource().then(function (s) {
176
+ return s.hash;
177
+ });
178
+ };
179
+ });
180
+ newCtx.hashes.set(_gthis, p);
181
+ return p;
182
+ });
183
+ }
184
+ _computeHash() {
119
185
  let _gthis = this;
120
186
  return this.finalMaybeHash().then(function (hash) {
121
187
  if (hash != null) {
@@ -158,13 +224,25 @@ class Stone extends Register.inherits() {
158
224
  throw new Error("Acquire a lock before generating.");
159
225
  };
160
226
  Log.log(20, ...["Generating source.", {"stone": this, "hash": hash}]);
227
+ let deps = (this.config.dependencies != null) ? MaybeArray_Fields_.makeArray(this.config.dependencies) : null;
161
228
  let init;
162
- if (this.config.dependencies != null) {
229
+ if (deps != null) {
163
230
  let _g = [];
164
231
  let _g1 = 0;
165
- let _g2 = MaybeArray_Fields_.makeArray(this.config.dependencies);
166
- while (_g1 < _g2.length) _g.push(_g2[_g1++].getSource());
167
- init = Promise.all(_g);
232
+ while (_g1 < deps.length) _g.push(deps[_g1++].id);
233
+ if (this.project.profiler != null) {
234
+ init = this.project.profiler.withSpan(this, "DependencyResolve", function () {
235
+ let _g = [];
236
+ let _g1 = 0;
237
+ while (_g1 < deps.length) _g.push(deps[_g1++].getSource());
238
+ return Promise.all(_g);
239
+ }, {"dependencyIds": _g});
240
+ } else {
241
+ let _g = [];
242
+ let _g1 = 0;
243
+ while (_g1 < deps.length) _g.push(deps[_g1++].getSource());
244
+ init = Promise.all(_g);
245
+ };
168
246
  } else {
169
247
  init = Promise.resolve(null);
170
248
  };
@@ -325,6 +403,41 @@ class Stone extends Register.inherits() {
325
403
  * Uses the same cache as getSource() — partial and full share the pool.
326
404
  */
327
405
  getPartialSource(sourceId) {
406
+ let ctx = MemoContext.als.getStore();
407
+ if (ctx != null) {
408
+ let partialMap = ctx.partials.get(this);
409
+ if (partialMap != null) {
410
+ let cached = partialMap.get(sourceId);
411
+ if (cached != null) {
412
+ Log.log(10, ...["Partial source memo hit.", {"stone": this, "sourceId": sourceId}]);
413
+ return cached;
414
+ };
415
+ };
416
+ let fullCached = ctx.sources.get(this);
417
+ if (fullCached != null) {
418
+ return fullCached.then(function (s) {
419
+ return s.filterTo(sourceId);
420
+ });
421
+ };
422
+ let p = this._computePartialSource(sourceId);
423
+ if (partialMap == null) {
424
+ partialMap = new Map();
425
+ ctx.partials.set(this, partialMap);
426
+ };
427
+ partialMap.set(sourceId, p);
428
+ return p;
429
+ };
430
+ let _gthis = this;
431
+ return MemoContext.ensure(function () {
432
+ let newCtx = MemoContext.als.getStore();
433
+ let p = _gthis._computePartialSource(sourceId);
434
+ let partialMap = new Map();
435
+ newCtx.partials.set(_gthis, partialMap);
436
+ partialMap.set(sourceId, p);
437
+ return p;
438
+ });
439
+ }
440
+ _computePartialSource(sourceId) {
328
441
  let _gthis = this;
329
442
  return this.finalMaybeHash().then(function (hash) {
330
443
  if (hash == null) {
@@ -471,6 +584,48 @@ class Stone extends Register.inherits() {
471
584
  cwdPath(path) {
472
585
  return Path.posix.join(".", RootDir.fromProject(this.project), ".", path);
473
586
  }
587
+
588
+ /**
589
+ Wraps an async operation in a profiler span. No-op when profiler is null.
590
+ */
591
+ profilerWithSpan(op, fn, meta) {
592
+ if (this.project.profiler != null) {
593
+ return this.project.profiler.withSpan(this, op, fn, meta);
594
+ } else {
595
+ return fn();
596
+ };
597
+ }
598
+
599
+ /**
600
+ Starts a manual profiler span. Returns null when profiler is null.
601
+ */
602
+ profilerStartSpan(op, meta) {
603
+ if (this.project.profiler != null) {
604
+ return this.project.profiler.startSpan(this, op, meta);
605
+ } else {
606
+ return null;
607
+ };
608
+ }
609
+
610
+ /**
611
+ Ends a manual profiler span. No-op when span is null.
612
+ */
613
+ profilerEndSpan(span) {
614
+ if (span != null) {
615
+ this.project.profiler.endSpan(span);
616
+ };
617
+ }
618
+
619
+ /**
620
+ Returns the current span from ALS context, or null when profiler is disabled.
621
+ */
622
+ profilerGetCurrentSpan() {
623
+ if (this.project.profiler != null) {
624
+ return this.project.profiler.getCurrentSpan();
625
+ } else {
626
+ return null;
627
+ };
628
+ }
474
629
  get_cache() {
475
630
  return this.project.cache;
476
631
  }
@@ -1,4 +1,4 @@
1
- import {Command} from "commander"
1
+ import {Command, Option} from "commander"
2
2
 
3
3
  export const program: Command
4
4
  export const main: () => void
package/bin/whet/Whet.js CHANGED
@@ -26,7 +26,7 @@ class Whet_Fields_ {
26
26
  if (entryUrl != thisUrl) {
27
27
  return;
28
28
  };
29
- Whet_Fields_.program.enablePositionalOptions().passThroughOptions().description("Project tooling.").usage("[options] [command] [+ [command]...]").version("0.1.1", "-v, --version").allowUnknownOption(true).allowExcessArguments(true).showSuggestionAfterError(true).option("-p, --project <file>", "project to run", "Project.mjs").option("-l, --log-level <level>", "log level, a string/number", "info").option("--no-pretty", "disable pretty logging").exitOverride();
29
+ Whet_Fields_.program.enablePositionalOptions().passThroughOptions().description("Project tooling.").usage("[options] [command] [+ [command]...]").version("0.4.0", "-v, --version").allowUnknownOption(true).allowExcessArguments(true).showSuggestionAfterError(true).option("-p, --project <file>", "project to run", "Project.mjs").option("-l, --log-level <level>", "log level, a string/number", "info").option("--no-pretty", "disable pretty logging").option("--profile <format>", "enable profiling, export to whet-profile.json on exit (format: json or trace, default: json)").exitOverride();
30
30
  try {
31
31
  Whet_Fields_.program.parse();
32
32
  }catch (_g) {
@@ -87,11 +87,34 @@ class Whet_Fields_ {
87
87
  while (_g2 < _g3.length) Whet_Fields_.program.addOption(_g3[_g2++]);
88
88
  };
89
89
  Whet_Fields_.program.allowUnknownOption(false);
90
+ let schemaCmd = new Command("schema");
91
+ schemaCmd.description("Export project schema as JSON.");
92
+ schemaCmd.action(Whet_Fields_.outputSchema);
93
+ Whet_Fields_.program.addCommand(schemaCmd);
90
94
  let commands = Whet_Fields_.getCommands(Whet_Fields_.program.args);
91
95
  let initProm;
92
96
  if (commands.length > 0) {
93
97
  let res = Whet_Fields_.program.parseOptions(commands[0]);
94
98
  commands[0] = res.operands.concat(res.unknown);
99
+ let profileFormat = Whet_Fields_.program.opts().profile;
100
+ if (profileFormat != null) {
101
+ let format = (profileFormat == true) ? "json" : profileFormat;
102
+ let _g = 0;
103
+ let _g1 = Project.projects;
104
+ while (_g < _g1.length) _g1[_g++].enableProfiling();
105
+ let onExit = function () {
106
+ let _g = 0;
107
+ let _g1 = Project.projects;
108
+ while (_g < _g1.length) {
109
+ let p = _g1[_g];
110
+ ++_g;
111
+ if (p.profiler != null) {
112
+ Fs.writeFileSync("whet-profile.json", JSON.stringify(p.profiler["export"](format), null, " "));
113
+ };
114
+ };
115
+ };
116
+ process.on("exit", onExit);
117
+ };
95
118
  let promises = [];
96
119
  let _g = 0;
97
120
  let _g1 = Project.projects;
@@ -131,6 +154,50 @@ class Whet_Fields_ {
131
154
  nextCommand();
132
155
  });
133
156
  }
157
+ static outputSchema() {
158
+ Log.logLevel = 100;
159
+ let excludeCommands = ["help", "schema"];
160
+ let _g = [];
161
+ let _g1 = 0;
162
+ let _g2 = Project.projects;
163
+ while (_g1 < _g2.length) {
164
+ let p = _g2[_g1];
165
+ ++_g1;
166
+ let p1 = p.name;
167
+ let p2 = p.id;
168
+ let p3 = p.description;
169
+ let _g3 = [];
170
+ let _g4 = 0;
171
+ let _g5 = p.options;
172
+ while (_g4 < _g5.length) _g3.push(Whet_Fields_.serializeOption(_g5[_g4++]));
173
+ _g.push({"name": p1, "id": p2, "description": p3, "options": _g3});
174
+ };
175
+ let _g3 = [];
176
+ let _g4 = 0;
177
+ let _g5 = Whet_Fields_.program.commands;
178
+ while (_g4 < _g5.length) {
179
+ let cmd = _g5[_g4];
180
+ ++_g4;
181
+ let x = cmd.name();
182
+ if (!excludeCommands.includes(x)) {
183
+ _g3.push(Whet_Fields_.serializeCommand(cmd));
184
+ };
185
+ };
186
+ process.stdout.write(JSON.stringify({"projects": _g, "commands": _g3}, null, " ") + "\n");
187
+ }
188
+ static serializeOption(opt) {
189
+ return {"name": opt.name(), "attributeName": opt.attributeName(), "flags": opt.flags, "description": opt.description, "choices": opt.argChoices, "defaultValue": opt.defaultValue, "required": opt.required, "mandatory": opt.mandatory, "boolean": opt.isBoolean(), "hidden": opt.hidden};
190
+ }
191
+ static serializeCommand(cmd) {
192
+ let tmp = cmd.name();
193
+ let tmp1 = cmd.description();
194
+ let tmp2 = cmd.aliases();
195
+ let _g = [];
196
+ let _g1 = 0;
197
+ let _g2 = cmd.options;
198
+ while (_g1 < _g2.length) _g.push(Whet_Fields_.serializeOption(_g2[_g1++]));
199
+ return {"name": tmp, "description": tmp1, "aliases": tmp2, "options": _g};
200
+ }
134
201
  static getCommands(args) {
135
202
  let commands = [];
136
203
  let from = 0;
@@ -1,3 +1,4 @@
1
+ import {AnySpan} from "../profiler/Span"
1
2
  import {Cache, CacheDurability, DurabilityCheck} from "./Cache"
2
3
  import {AnyStone} from "../Stone"
3
4
  import {SourceHash} from "../SourceHash"
@@ -26,6 +27,11 @@ export declare class BaseCache<Key, Value extends {
26
27
  protected shouldKeep(stone: AnyStone, val: Value, durability: CacheDurability, useIndex: ((arg0: Value) => number), ageIndex: ((arg0: Value) => number)): boolean
27
28
  protected setRecentUseOrder(values: Value[], value: Value): boolean
28
29
  protected remove(stone: AnyStone, value: Value): Promise<any>
30
+
31
+ /**
32
+ Remove all cached entries for a stone.
33
+ */
34
+ clearStone(stone: AnyStone): void
29
35
  protected key(stone: AnyStone): Key
30
36
  protected value(source: Source): Promise<Value>
31
37
  protected source(stone: AnyStone, value: Value): Promise<Source>
@@ -47,4 +53,5 @@ export declare class BaseCache<Key, Value extends {
47
53
  */
48
54
  protected replaceEntry(stone: AnyStone, existing: Value, replacement: Source): Promise<Value>
49
55
  toString(): string
56
+ protected static setGenerateMeta(span: null | AnySpan, src: Source): void
50
57
  }