whet 0.0.33 → 0.1.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 (81) hide show
  1. package/bin/Reflect.d.ts +31 -12
  2. package/bin/Reflect.js +46 -19
  3. package/bin/commander/LiteralUnion.d.ts +2 -0
  4. package/bin/commander/OptionValueSource.d.ts +2 -1
  5. package/bin/commander/OutputConfiguration.d.ts +3 -0
  6. package/bin/genes/Register.d.ts +2 -0
  7. package/bin/genes/Register.js +15 -11
  8. package/bin/genes/util/EsMap.js +2 -1
  9. package/bin/haxe/Exception.js +6 -1
  10. package/bin/haxe/ValueException.js +3 -2
  11. package/bin/haxe/ds/List.js +7 -2
  12. package/bin/haxe/ds/ObjectMap.js +2 -2
  13. package/bin/haxe/ds/StringMap.js +2 -2
  14. package/bin/haxe/exceptions/NotImplementedException.js +2 -2
  15. package/bin/haxe/exceptions/PosException.js +3 -2
  16. package/bin/haxe/io/Bytes.js +3 -1
  17. package/bin/haxe/io/BytesBuffer.js +6 -1
  18. package/bin/haxe/io/BytesOutput.js +2 -1
  19. package/bin/haxe/io/Output.js +1 -0
  20. package/bin/haxe/iterators/ArrayIterator.js +3 -1
  21. package/bin/haxe/zip/Writer.js +3 -1
  22. package/bin/js/lib/ConcatArray.d.ts +6 -0
  23. package/bin/js/lib/IRegExp.d.ts +53 -0
  24. package/bin/js/lib/IterableIterator.d.ts +8 -0
  25. package/bin/js/lib/IteratorResult.d.ts +2 -0
  26. package/bin/js/lib/IteratorReturnResult.d.ts +5 -0
  27. package/bin/js/lib/IteratorYieldResult.d.ts +5 -0
  28. package/bin/js/lib/RegExpExecArray.d.ts +137 -0
  29. package/bin/minimatch/MMRegExp.d.ts +55 -0
  30. package/bin/minimatch/MinimatchOptions.d.ts +102 -0
  31. package/bin/minimatch/ParseReturn.d.ts +2 -0
  32. package/bin/minimatch/ParseReturnFiltered.d.ts +2 -0
  33. package/bin/minimatch/Platform.d.ts +2 -0
  34. package/bin/pino_pretty/PrettyOptions.d.ts +2 -2
  35. package/bin/pino_pretty/default_/MessageFormatFunc.d.ts +1 -2
  36. package/bin/pino_pretty/default_/Prettifier.d.ts +2 -0
  37. package/bin/pino_pretty/pinopretty/PrettyOptions.d.ts +118 -0
  38. package/bin/sys/FileStat.d.ts +50 -0
  39. package/bin/whet/ConfigStore.d.ts +32 -0
  40. package/bin/whet/ConfigStore.js +342 -0
  41. package/bin/whet/Project.d.ts +39 -4
  42. package/bin/whet/Project.js +154 -3
  43. package/bin/whet/Source.d.ts +7 -1
  44. package/bin/whet/Source.js +40 -3
  45. package/bin/whet/SourceHash.js +18 -10
  46. package/bin/whet/Stone.d.ts +60 -9
  47. package/bin/whet/Stone.js +180 -18
  48. package/bin/whet/Whet.d.ts +0 -1
  49. package/bin/whet/Whet.js +23 -12
  50. package/bin/whet/cache/BaseCache.d.ts +23 -0
  51. package/bin/whet/cache/BaseCache.js +93 -1
  52. package/bin/whet/cache/CacheManager.d.ts +2 -0
  53. package/bin/whet/cache/CacheManager.js +38 -2
  54. package/bin/whet/cache/FileCache.d.ts +10 -2
  55. package/bin/whet/cache/FileCache.js +144 -42
  56. package/bin/whet/cache/HashCache.js +2 -1
  57. package/bin/whet/cache/MemoryCache.d.ts +3 -0
  58. package/bin/whet/cache/MemoryCache.js +53 -2
  59. package/bin/whet/magic/MinimatchType.d.ts +1 -1
  60. package/bin/whet/magic/MinimatchType.js +3 -3
  61. package/bin/whet/magic/RoutePathType.js +1 -1
  62. package/bin/whet/route/OutputFilterMatcher.js +2 -2
  63. package/bin/whet/route/RouteResult.d.ts +16 -0
  64. package/bin/whet/route/RouteResult.js +37 -4
  65. package/bin/whet/route/Router.d.ts +22 -1
  66. package/bin/whet/route/Router.js +121 -40
  67. package/bin/whet/stones/Files.d.ts +6 -1
  68. package/bin/whet/stones/Files.js +3 -2
  69. package/bin/whet/stones/JsonStone.d.ts +6 -1
  70. package/bin/whet/stones/JsonStone.js +3 -2
  71. package/bin/whet/stones/RemoteFile.d.ts +7 -2
  72. package/bin/whet/stones/RemoteFile.js +7 -4
  73. package/bin/whet/stones/Zip.d.ts +6 -1
  74. package/bin/whet/stones/Zip.js +2 -2
  75. package/bin/whet/stones/haxe/HaxeBuild.d.ts +7 -1
  76. package/bin/whet/stones/haxe/HaxeBuild.js +8 -6
  77. package/bin/whet/stones/haxe/Hxml.d.ts +7 -1
  78. package/bin/whet/stones/haxe/Hxml.js +7 -5
  79. package/bin/whet.d.ts +1 -2
  80. package/bin/whet.js +1 -1
  81. package/package.json +9 -10
@@ -13,7 +13,7 @@ const $global = Register.$global
13
13
 
14
14
  export const SourceHash = Register.global("$hxClasses")["whet.SourceHash"] =
15
15
  class SourceHash extends Register.inherits() {
16
- new(bytes) {
16
+ [Register.new](bytes) {
17
17
  this.bytes = bytes;
18
18
  }
19
19
  add(hash) {
@@ -128,30 +128,37 @@ class SourceHash extends Register.inherits() {
128
128
  * Only checks keys at root level, no deep inspection is done.
129
129
  */
130
130
  static fromConfig(obj, ignoreList) {
131
- let keys = [];
132
131
  let _g = [];
133
132
  let _g_keys = Reflect__1.fields(obj);
134
133
  let _g_index = 0;
135
134
  while (_g_index < _g_keys.length) {
136
135
  let key = _g_keys[_g_index++];
137
- let _g_value = obj[key];
138
- let tmp;
139
136
  switch (key) {
140
- case "cacheStrategy":case "dependencies":case "id":case "project":
137
+ case "cacheStrategy":case "configStore":case "dependencies":case "id":case "project":
141
138
  continue;
142
139
  break
143
140
  default:
144
141
  if (ignoreList != null && ignoreList.includes(key)) {
145
142
  continue;
146
- } else {
147
- keys.push(key);
148
- tmp = (((_g_value) instanceof Stone)) ? _g_value.getHash() : (((_g_value) instanceof Router)) ? _g_value.getHash() : SourceHash.fromStringify(_g_value);
149
143
  };
150
144
 
151
145
  };
152
- _g.push(tmp);
146
+ _g.push(key);
153
147
  };
154
- return Promise.all(_g).then(function (hashes) {
148
+ _g.sort(Reflect__1.compare);
149
+ let _g1 = [];
150
+ let _g2 = 0;
151
+ while (_g2 < _g.length) {
152
+ let val = obj[_g[_g2++]];
153
+ if (((val) instanceof Stone)) {
154
+ _g1.push(val.getHash());
155
+ } else if (((val) instanceof Router)) {
156
+ _g1.push(val.getHash());
157
+ } else {
158
+ _g1.push(SourceHash.fromStringify(val));
159
+ };
160
+ };
161
+ return Promise.all(_g1).then(function (hashes) {
155
162
  return SourceHash.merge(...hashes);
156
163
  });
157
164
  }
@@ -194,6 +201,7 @@ class SourceHash extends Register.inherits() {
194
201
  return SourceHash
195
202
  }
196
203
  }
204
+ SourceHash.prototype.bytes = null;
197
205
 
198
206
 
199
207
  Register.createStatic(SourceHash, "EMPTY", function () { return (function($this) {var $r0
@@ -5,6 +5,8 @@ import {CacheStrategy} from "./cache/Cache"
5
5
  import {SourceHash} from "./SourceHash"
6
6
  import {Source, SourceData} from "./Source"
7
7
  import {Project} from "./Project"
8
+ import {ConfigStore} from "./ConfigStore"
9
+ import {Buffer} from "buffer"
8
10
 
9
11
  export declare class Stone<T extends StoneConfig> {
10
12
  constructor(config: T)
@@ -89,20 +91,50 @@ export declare class Stone<T extends StoneConfig> {
89
91
  protected finalMaybeHash(): Promise<null | SourceHash>
90
92
 
91
93
  /**
92
- * Abstract method.
93
- * Function that actually generates the source. Passed hash is only non-null
94
- * if `generateHash()` is implemented. It can be used for `CacheManager.getDir` and
95
- * is passed mainly as optimization.
94
+ * Override to generate all source data at once. Passed hash is only non-null
95
+ * if `generateHash()` is implemented.
96
+ * Default implementation calls list() + generatePartial() for each ID.
97
+ * Stones must implement either this method or list() + generatePartial().
96
98
  */
97
99
  protected generate(hash: SourceHash): Promise<SourceData[]>
98
100
 
99
101
  /**
100
- * Returns a list of sources that this stone generates.
101
- * Used by Router for finding the correct asset.
102
- * Default implementation generates the sources to find their ids, but can be overriden
103
- * to provide optimized implementation that would avoid generating assets we might not need.
102
+ * Optional override: return the list of output sourceIds this stone produces,
103
+ * without triggering generation. Return null if unknown (default).
104
+ * Used by cache for partial entry completion and by listIds() as fast path.
104
105
  */
105
- list(): Promise<string[]>
106
+ protected list(): Promise<null | string[]>
107
+
108
+ /**
109
+ * Public API for getting output IDs. Calls list(), falls back to
110
+ * full generation if list() returns null.
111
+ */
112
+ listIds(): Promise<string[]>
113
+
114
+ /**
115
+ * Optional override for partial generation.
116
+ * Called when a single output is requested via getPartialSource().
117
+ * Return data for the requested sourceId, or null to signal
118
+ * "not supported" (triggers fallback to full generation + filter).
119
+ */
120
+ protected generatePartial(sourceId: string, hash: SourceHash): Promise<null | SourceData[]>
121
+
122
+ /**
123
+ * Get source for a single output by sourceId.
124
+ * If the stone implements generatePartial(), generates just the requested output.
125
+ * Otherwise falls back to full generation + filter.
126
+ * Uses the same cache as getSource() — partial and full share the pool.
127
+ */
128
+ getPartialSource(sourceId: string): Promise<null | Source>
129
+
130
+ /**
131
+ * Called by cache infrastructure. Generates partial source directly,
132
+ * never goes back through cache methods.
133
+ */
134
+ protected generatePartialSource(sourceId: string, hash: SourceHash): Promise<{
135
+ complete: boolean,
136
+ source: Source
137
+ }>
106
138
 
107
139
  /**
108
140
  * Optional filter describing what this Stone can produce.
@@ -132,6 +164,21 @@ export declare class Stone<T extends StoneConfig> {
132
164
  */
133
165
  exportTo(path: string): Promise<any>
134
166
 
167
+ /**
168
+ Get the raw Buffer of the first (or only) output.
169
+ */
170
+ getData(): Promise<Buffer>
171
+
172
+ /**
173
+ Get the first (or only) output as a UTF-8 string.
174
+ */
175
+ getString(): Promise<string>
176
+
177
+ /**
178
+ Get the first (or only) output parsed as JSON.
179
+ */
180
+ getJson(): Promise<any>
181
+
135
182
  /**
136
183
  * Convenient function to get CWD-relative path from project-relative one.
137
184
  * Useful for pure JS stones.
@@ -149,6 +196,10 @@ export type StoneConfig = {
149
196
  */
150
197
  cacheStrategy?: null | CacheStrategy,
151
198
  /**
199
+ Optional ConfigStore for persistent per-stone config patching. Overrides project-level configStore.
200
+ */
201
+ configStore?: null | ConfigStore,
202
+ /**
152
203
  * Registers another stone(s) as dependency of this one. Useful for external processes
153
204
  * that use a source of some stone, but don't go via Whet to get it.
154
205
  * Use with combination of `setAbsolutePath` on the dependency, so that the external process
package/bin/whet/Stone.js CHANGED
@@ -14,7 +14,7 @@ const $global = Register.$global
14
14
 
15
15
  export const Stone = Register.global("$hxClasses")["whet.Stone"] =
16
16
  class Stone extends Register.inherits() {
17
- new(config) {
17
+ [Register.new](config) {
18
18
  this.locked = false;
19
19
  this.lockQueue = [];
20
20
  this.ignoreFileHash = false;
@@ -27,9 +27,27 @@ class Stone extends Register.inherits() {
27
27
  if (this.project == null) {
28
28
  throw new Error("Did not find a project. Create one before creating stones.");
29
29
  };
30
- this.project.stones.push(this);
31
30
  this.initConfig();
32
- this.id = (config.id != null) ? StoneId_Fields_.makeStoneId(config.id) : StoneId_Fields_.makeStoneId(this);
31
+ let isExplicitId = config.id != null;
32
+ this.id = (isExplicitId) ? StoneId_Fields_.makeStoneId(config.id) : StoneId_Fields_.makeStoneId(this);
33
+ let duplicates = 0;
34
+ let _g = 0;
35
+ let _g1 = this.project.stones;
36
+ while (_g < _g1.length) {
37
+ let stone = _g1[_g];
38
+ ++_g;
39
+ if (stone.id == this.id || !isExplicitId && stone.id != null && stone.id.startsWith(this.id + ":")) {
40
+ ++duplicates;
41
+ };
42
+ };
43
+ if (duplicates > 0) {
44
+ if (isExplicitId) {
45
+ Log.log(40, ...["Duplicate explicit Stone ID.", {"id": this.id}]);
46
+ } else {
47
+ this.id = this.id + ":" + (duplicates + 1);
48
+ };
49
+ };
50
+ this.project.stones.push(this);
33
51
  this.cacheStrategy = (config.cacheStrategy == null) ? this.project.cache.defaultStrategy : config.cacheStrategy;
34
52
  this.addCommands();
35
53
  }
@@ -215,29 +233,139 @@ class Stone extends Register.inherits() {
215
233
  * dependencies.
216
234
  */
217
235
  finalMaybeHash() {
236
+ let tmp = this.config.configStore;
237
+ let store = (tmp != null) ? tmp : this.project.configStore;
238
+ let patchPromise = (store != null) ? store.ensureApplied(this) : Promise.resolve(null);
239
+ let _gthis = this;
240
+ return patchPromise.then(function (_) {
241
+ return _gthis.generateHash().then(function (hash) {
242
+ return _gthis.finalizeHash(hash);
243
+ });
244
+ });
245
+ }
246
+
247
+ /**
248
+ * Override to generate all source data at once. Passed hash is only non-null
249
+ * if `generateHash()` is implemented.
250
+ * Default implementation calls list() + generatePartial() for each ID.
251
+ * Stones must implement either this method or list() + generatePartial().
252
+ */
253
+ generate(hash) {
218
254
  let _gthis = this;
219
- return this.generateHash().then(function (hash) {
220
- return _gthis.finalizeHash(hash);
255
+ return this.list().then(function (ids) {
256
+ if (ids == null) {
257
+ throw new Error("Stone must implement either generate() or list() + generatePartial().");
258
+ };
259
+ let _g = [];
260
+ let _g1 = 0;
261
+ while (_g1 < ids.length) _g.push(_gthis.generatePartial(ids[_g1++], hash));
262
+ return Promise.all(_g).then(function (results) {
263
+ let all = [];
264
+ let _g = 0;
265
+ while (_g < results.length) {
266
+ let r = results[_g];
267
+ ++_g;
268
+ if (r != null) {
269
+ let _g = 0;
270
+ while (_g < r.length) all.push(r[_g++]);
271
+ };
272
+ };
273
+ return all;
274
+ });
221
275
  });
222
276
  }
223
277
 
224
278
  /**
225
- * Returns a list of sources that this stone generates.
226
- * Used by Router for finding the correct asset.
227
- * Default implementation generates the sources to find their ids, but can be overriden
228
- * to provide optimized implementation that would avoid generating assets we might not need.
279
+ * Optional override: return the list of output sourceIds this stone produces,
280
+ * without triggering generation. Return null if unknown (default).
281
+ * Used by cache for partial entry completion and by listIds() as fast path.
229
282
  */
230
283
  list() {
231
- return this.getSource().then(function (source) {
232
- let _this = source.data;
233
- let result = new Array(_this.length);
234
- let _g = 0;
235
- let _g1 = _this.length;
236
- while (_g < _g1) {
237
- let i = _g++;
238
- result[i] = _this[i].id;
284
+ return Promise.resolve(null);
285
+ }
286
+
287
+ /**
288
+ * Public API for getting output IDs. Calls list(), falls back to
289
+ * full generation if list() returns null.
290
+ */
291
+ listIds() {
292
+ let _gthis = this;
293
+ return this.list().then(function (ids) {
294
+ if (ids != null) {
295
+ return ids;
239
296
  };
240
- return result;
297
+ return _gthis.getSource().then(function (source) {
298
+ let _this = source.data;
299
+ let result = new Array(_this.length);
300
+ let _g = 0;
301
+ let _g1 = _this.length;
302
+ while (_g < _g1) {
303
+ let i = _g++;
304
+ result[i] = _this[i].id;
305
+ };
306
+ return result;
307
+ });
308
+ });
309
+ }
310
+
311
+ /**
312
+ * Optional override for partial generation.
313
+ * Called when a single output is requested via getPartialSource().
314
+ * Return data for the requested sourceId, or null to signal
315
+ * "not supported" (triggers fallback to full generation + filter).
316
+ */
317
+ generatePartial(sourceId, hash) {
318
+ return Promise.resolve(null);
319
+ }
320
+
321
+ /**
322
+ * Get source for a single output by sourceId.
323
+ * If the stone implements generatePartial(), generates just the requested output.
324
+ * Otherwise falls back to full generation + filter.
325
+ * Uses the same cache as getSource() — partial and full share the pool.
326
+ */
327
+ getPartialSource(sourceId) {
328
+ let _gthis = this;
329
+ return this.finalMaybeHash().then(function (hash) {
330
+ if (hash == null) {
331
+ return _gthis.getSource().then(function (source) {
332
+ return source.filterTo(sourceId);
333
+ });
334
+ } else {
335
+ return _gthis.project.cache.getPartialSource(_gthis, sourceId);
336
+ };
337
+ });
338
+ }
339
+
340
+ /**
341
+ * Called by cache infrastructure. Generates partial source directly,
342
+ * never goes back through cache methods.
343
+ */
344
+ generatePartialSource(sourceId, hash) {
345
+ if (!this.locked) {
346
+ throw new Error("Acquire a lock before generating.");
347
+ };
348
+ let init;
349
+ if (this.config.dependencies != null) {
350
+ let _g = [];
351
+ let _g1 = 0;
352
+ let _g2 = MaybeArray_Fields_.makeArray(this.config.dependencies);
353
+ while (_g1 < _g2.length) _g.push(_g2[_g1++].getSource());
354
+ init = Promise.all(_g);
355
+ } else {
356
+ init = Promise.resolve(null);
357
+ };
358
+ let _gthis = this;
359
+ return init.then(function (_) {
360
+ return _gthis.generatePartial(sourceId, hash).then(function (data) {
361
+ if (data != null) {
362
+ return {"source": new Source(data, hash, _gthis, Date.now() / 1000, false), "complete": false};
363
+ } else {
364
+ return _gthis.generate(hash).then(function (allData) {
365
+ return {"source": new Source(allData, hash, _gthis, Date.now() / 1000, true), "complete": true};
366
+ });
367
+ };
368
+ });
241
369
  });
242
370
  }
243
371
 
@@ -309,6 +437,33 @@ class Stone extends Register.inherits() {
309
437
  });
310
438
  }
311
439
 
440
+ /**
441
+ Get the raw Buffer of the first (or only) output.
442
+ */
443
+ getData() {
444
+ return this.getSource().then(function (s) {
445
+ return s.get().data;
446
+ });
447
+ }
448
+
449
+ /**
450
+ Get the first (or only) output as a UTF-8 string.
451
+ */
452
+ getString() {
453
+ return this.getData().then(function (d) {
454
+ return d.toString("utf-8");
455
+ });
456
+ }
457
+
458
+ /**
459
+ Get the first (or only) output parsed as JSON.
460
+ */
461
+ getJson() {
462
+ return this.getString().then(function (s) {
463
+ return JSON.parse(s);
464
+ });
465
+ }
466
+
312
467
  /**
313
468
  * Convenient function to get CWD-relative path from project-relative one.
314
469
  * Useful for pure JS stones.
@@ -329,4 +484,11 @@ class Stone extends Register.inherits() {
329
484
  return Stone
330
485
  }
331
486
  }
487
+ Stone.prototype.config = null;
488
+ Stone.prototype.ignoreFileHash = null;
489
+ Stone.prototype.id = null;
490
+ Stone.prototype.cacheStrategy = null;
491
+ Stone.prototype.project = null;
492
+ Stone.prototype.lockQueue = null;
493
+ Stone.prototype.locked = null;
332
494
 
@@ -2,4 +2,3 @@ import {Command} from "commander"
2
2
 
3
3
  export const program: Command
4
4
  export const main: () => void
5
- export const executeCommand: (cmd: string[]) => Promise<Command>
package/bin/whet/Whet.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import {Project} from "./Project.js"
2
2
  import {LogLevel, Log} from "./Log.js"
3
3
  import * as Url from "url"
4
- import * as PinoPretty from "pino-pretty"
4
+ import PinoPretty from "pino-pretty"
5
5
  import {Exception} from "../haxe/Exception.js"
6
6
  import {Register} from "../genes/Register.js"
7
+ import * as Fs from "fs"
7
8
  import {Command, CommanderError} from "commander"
8
9
  import {Std} from "../Std.js"
9
10
 
@@ -12,12 +13,25 @@ const $global = Register.$global
12
13
  export const Whet_Fields_ = Register.global("$hxClasses")["whet._Whet.Whet_Fields_"] =
13
14
  class Whet_Fields_ {
14
15
  static main() {
15
- Whet_Fields_.program.enablePositionalOptions().passThroughOptions().description("Project tooling.").usage("[options] [command] [+ [command]...]").version("0.0.33", "-v, --version").allowUnknownOption(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();
16
+ let tmp = process.argv[1];
17
+ let argv1 = (tmp != null) ? tmp : "";
18
+ let realArgv1;
19
+ try {
20
+ realArgv1 = Fs.realpathSync(argv1);
21
+ }catch (_g) {
22
+ realArgv1 = argv1;
23
+ };
24
+ let entryUrl = Url.pathToFileURL(realArgv1).href;
25
+ let thisUrl = new URL('../whet.js',import.meta.url).href;
26
+ if (entryUrl != thisUrl) {
27
+ return;
28
+ };
29
+ Whet_Fields_.program.enablePositionalOptions().passThroughOptions().description("Project tooling.").usage("[options] [command] [+ [command]...]").version("0.1.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").exitOverride();
16
30
  try {
17
31
  Whet_Fields_.program.parse();
18
32
  }catch (_g) {
19
33
  let _g1 = Exception.caught(_g);
20
- if (((_g1.get_native()) instanceof CommanderError) && _g1.get_native().code == "commander.version") {
34
+ if (((_g1.get_native()) instanceof CommanderError) && (_g1.get_native().code == "commander.version" || _g1.get_native().code == "commander.helpDisplayed")) {
21
35
  process.exit();
22
36
  } else {
23
37
  throw Exception.thrown(_g1);
@@ -36,7 +50,7 @@ class Whet_Fields_ {
36
50
  };
37
51
  };
38
52
  if (options.pretty) {
39
- Log.stream = PinoPretty["default"]();
53
+ Log.stream = PinoPretty();
40
54
  };
41
55
  global.setImmediate(Whet_Fields_.init, options);
42
56
  }
@@ -117,18 +131,16 @@ class Whet_Fields_ {
117
131
  nextCommand();
118
132
  });
119
133
  }
120
- static executeCommand(cmd) {
121
- Log.log(10, ...["Executing command.", {"command": cmd}]);
122
- return Whet_Fields_.program.parseAsync(cmd, {"from": "user"});
123
- }
124
134
  static getCommands(args) {
125
135
  let commands = [];
126
136
  let from = 0;
127
137
  let to;
128
138
  do {
129
- to = args.indexOf("+", from);
130
- commands.push((to < 0) ? args.slice(from) : args.slice(from, to));
131
- from = to + 1;
139
+ {
140
+ to = args.indexOf("+", from);
141
+ commands.push((to < 0) ? args.slice(from) : args.slice(from, to));
142
+ from = to + 1;
143
+ }
132
144
  } while (to >= 0);
133
145
  return commands;
134
146
  }
@@ -144,4 +156,3 @@ class Whet_Fields_ {
144
156
  Whet_Fields_.program = new Command("whet")
145
157
  export const program = Whet_Fields_.program
146
158
  export const main = Whet_Fields_.main
147
- export const executeCommand = Whet_Fields_.executeCommand
@@ -5,6 +5,7 @@ import {Source} from "../Source"
5
5
  import {Map as Map__1} from "../../Map"
6
6
 
7
7
  export declare class BaseCache<Key, Value extends {
8
+ complete: boolean,
8
9
  ctime: number,
9
10
  hash: SourceHash
10
11
  }> implements Cache {
@@ -12,8 +13,15 @@ export declare class BaseCache<Key, Value extends {
12
13
  protected cache: Map__1<Key, Value[]>
13
14
  protected rootDir: string
14
15
  get(stone: AnyStone, durability: CacheDurability, check: DurabilityCheck): Promise<Source>
16
+ getPartial(stone: AnyStone, sourceId: string, durability: CacheDurability, check: DurabilityCheck): Promise<null | Source>
15
17
  protected set(source: Source): Promise<Value>
16
18
  getUniqueDir(stone: AnyStone, baseDir: string, hash?: null | SourceHash): string
19
+
20
+ /**
21
+ * Complete a partial cache entry. Tries list() for incremental completion,
22
+ * falls back to full generateSource() if list() returns null.
23
+ */
24
+ protected completePartialEntry(stone: AnyStone, existing: Value, hash: SourceHash): Promise<Value>
17
25
  protected checkDurability(stone: AnyStone, values: Value[], durability: CacheDurability, useIndex: ((arg0: Value) => number), ageIndex: ((arg0: Value) => number)): void
18
26
  protected shouldKeep(stone: AnyStone, val: Value, durability: CacheDurability, useIndex: ((arg0: Value) => number), ageIndex: ((arg0: Value) => number)): boolean
19
27
  protected setRecentUseOrder(values: Value[], value: Value): boolean
@@ -23,5 +31,20 @@ export declare class BaseCache<Key, Value extends {
23
31
  protected source(stone: AnyStone, value: Value): Promise<Source>
24
32
  protected getExistingDirs(stone: AnyStone): string[]
25
33
  protected getDirFor(value: Value): string
34
+
35
+ /**
36
+ Check if entry contains a specific sourceId.
37
+ */
38
+ protected hasSourceId(value: Value, sourceId: string): boolean
39
+
40
+ /**
41
+ Merge partial source data into an existing entry, returns the updated value.
42
+ */
43
+ protected mergePartial(stone: AnyStone, existing: Value, addition: Source, markComplete: boolean): Promise<Value>
44
+
45
+ /**
46
+ Replace an existing entry with a new complete source.
47
+ */
48
+ protected replaceEntry(stone: AnyStone, existing: Value, replacement: Source): Promise<Value>
26
49
  toString(): string
27
50
  }
@@ -12,7 +12,7 @@ const $global = Register.$global
12
12
 
13
13
  export const BaseCache = Register.global("$hxClasses")["whet.cache.BaseCache"] =
14
14
  class BaseCache extends Register.inherits() {
15
- new(rootDir, cache) {
15
+ [Register.new](rootDir, cache) {
16
16
  let id = rootDir;
17
17
  if (!(id.length == 0 || id.charCodeAt(id.length - 1) == 47)) {
18
18
  throw new Error("Root dir is a not a dir.");
@@ -80,6 +80,11 @@ class BaseCache extends Register.inherits() {
80
80
  return _gthis.source(stone, val);
81
81
  });
82
82
  });
83
+ } else if (!src.complete) {
84
+ Log.log(10, ...["Found partial entry in cache, completing.", {"stone": stone, "cache": _gthis}]);
85
+ return _gthis.completePartialEntry(stone, value, hash).then(function (val) {
86
+ return _gthis.source(stone, val);
87
+ });
83
88
  } else {
84
89
  Log.log(10, ...["Found in cache", {"stone": stone, "cache": _gthis}]);
85
90
  return Promise.resolve(src);
@@ -96,6 +101,50 @@ class BaseCache extends Register.inherits() {
96
101
  });
97
102
  });
98
103
  }
104
+ getPartial(stone, sourceId, durability, check) {
105
+ let _gthis = this;
106
+ return stone.acquire(function () {
107
+ return stone.finalMaybeHash().then(function (hash) {
108
+ let values = _gthis.cache.get(_gthis.key(stone));
109
+ let value = null;
110
+ if (values != null && values.length > 0) {
111
+ value = Lambda.find(values, function (v) {
112
+ return SourceHash.equals(v.hash, hash);
113
+ });
114
+ if (value != null) {
115
+ _gthis.setRecentUseOrder(values, value);
116
+ };
117
+ };
118
+ if (value != null && _gthis.hasSourceId(value, sourceId)) {
119
+ return _gthis.source(stone, value).then(function (src) {
120
+ if (src != null) {
121
+ return src.filterTo(sourceId);
122
+ } else {
123
+ return null;
124
+ };
125
+ });
126
+ } else if (value != null && value.complete) {
127
+ return Promise.resolve(null);
128
+ } else {
129
+ return stone.generatePartialSource(sourceId, hash).then(function (result) {
130
+ if (result.complete) {
131
+ return ((value != null) ? _gthis.replaceEntry(stone, value, result.source) : _gthis.set(result.source)).then(function (_) {
132
+ return result.source.filterTo(sourceId);
133
+ });
134
+ } else if (value != null) {
135
+ return _gthis.mergePartial(stone, value, result.source, false).then(function (_) {
136
+ return result.source.filterTo(sourceId);
137
+ });
138
+ } else {
139
+ return _gthis.set(result.source).then(function (_) {
140
+ return result.source.filterTo(sourceId);
141
+ });
142
+ };
143
+ });
144
+ };
145
+ });
146
+ });
147
+ }
99
148
  set(source) {
100
149
  Log.log(10, ...["Setting source in cache.", {"source": source}]);
101
150
  let k = this.key(source.origin);
@@ -137,6 +186,47 @@ class BaseCache extends Register.inherits() {
137
186
  };
138
187
  return Path.posix.join(baseDir, "v" + maxNum + "/");
139
188
  }
189
+
190
+ /**
191
+ * Complete a partial cache entry. Tries list() for incremental completion,
192
+ * falls back to full generateSource() if list() returns null.
193
+ */
194
+ completePartialEntry(stone, existing, hash) {
195
+ let _gthis = this;
196
+ return stone.list().then(function (allIds) {
197
+ if (allIds != null) {
198
+ let _g = [];
199
+ let _g1 = 0;
200
+ while (_g1 < allIds.length) {
201
+ let v = allIds[_g1];
202
+ ++_g1;
203
+ if (!_gthis.hasSourceId(existing, v)) {
204
+ _g.push(v);
205
+ };
206
+ };
207
+ if (_g.length == 0) {
208
+ return _gthis.mergePartial(stone, existing, null, true);
209
+ };
210
+ let chain = Promise.resolve(existing);
211
+ let _g2 = 0;
212
+ while (_g2 < _g.length) {
213
+ let missingId = _g[_g2++];
214
+ chain = chain.then(function (current) {
215
+ return stone.generatePartialSource(missingId, hash).then(function (result) {
216
+ return _gthis.mergePartial(stone, current, result.source, false);
217
+ });
218
+ });
219
+ };
220
+ return chain.then(function (current) {
221
+ return _gthis.mergePartial(stone, current, null, true);
222
+ });
223
+ } else {
224
+ return stone.generateSource(hash).then(function (fullSource) {
225
+ return _gthis.replaceEntry(stone, existing, fullSource);
226
+ });
227
+ };
228
+ });
229
+ }
140
230
  checkDurability(stone, values, durability, useIndex, ageIndex) {
141
231
  Log.log(20, ...["Checking durability.", {"stone": stone, "durability": Std.string(durability)}]);
142
232
  if (values == null || values.length == 0) {
@@ -205,4 +295,6 @@ class BaseCache extends Register.inherits() {
205
295
  return BaseCache
206
296
  }
207
297
  }
298
+ BaseCache.prototype.cache = null;
299
+ BaseCache.prototype.rootDir = null;
208
300
 
@@ -18,6 +18,7 @@ export declare class CacheManager {
18
18
  */
19
19
  defaultFileStrategy: CacheStrategy
20
20
  getSource(stone: AnyStone): Promise<Source>
21
+ getPartialSource(stone: AnyStone, sourceId: string): Promise<null | Source>
21
22
 
22
23
  /**
23
24
  * Re-generates source even if the currently cached value is valid.
@@ -30,4 +31,5 @@ export declare class CacheManager {
30
31
  * The path is not reserved. Caching depends on stone's `cacheStrategy` and success of source generation.
31
32
  */
32
33
  getDir(stone: AnyStone, hash?: null | SourceHash): string
34
+ close(): Promise<void>
33
35
  }