@highstate/cli 0.9.15 → 0.9.16

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/main.js CHANGED
@@ -4,7 +4,7 @@
4
4
  import { Builtins, Cli } from "clipanion";
5
5
 
6
6
  // package.json
7
- var version = "0.9.14";
7
+ var version = "0.9.15";
8
8
 
9
9
  // src/commands/designer.ts
10
10
  import { Command, UsageError } from "clipanion";
@@ -79,1072 +79,7 @@ function getBackendServices() {
79
79
  import { readFile } from "node:fs/promises";
80
80
  import { parseAsync } from "oxc-parser";
81
81
  import { walk } from "oxc-walker";
82
-
83
- // ../../node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
84
- var comma = ",".charCodeAt(0);
85
- var semicolon = ";".charCodeAt(0);
86
- var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
87
- var intToChar = new Uint8Array(64);
88
- var charToInt = new Uint8Array(128);
89
- for (let i = 0; i < chars.length; i++) {
90
- const c = chars.charCodeAt(i);
91
- intToChar[i] = c;
92
- charToInt[c] = i;
93
- }
94
- function encodeInteger(builder, num, relative2) {
95
- let delta = num - relative2;
96
- delta = delta < 0 ? -delta << 1 | 1 : delta << 1;
97
- do {
98
- let clamped = delta & 31;
99
- delta >>>= 5;
100
- if (delta > 0)
101
- clamped |= 32;
102
- builder.write(intToChar[clamped]);
103
- } while (delta > 0);
104
- return num;
105
- }
106
- var bufLength = 1024 * 16;
107
- var td = typeof TextDecoder !== "undefined" ? /* @__PURE__ */ new TextDecoder() : typeof Buffer !== "undefined" ? {
108
- decode(buf) {
109
- const out = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength);
110
- return out.toString();
111
- }
112
- } : {
113
- decode(buf) {
114
- let out = "";
115
- for (let i = 0; i < buf.length; i++) {
116
- out += String.fromCharCode(buf[i]);
117
- }
118
- return out;
119
- }
120
- };
121
- var StringWriter = class {
122
- constructor() {
123
- this.pos = 0;
124
- this.out = "";
125
- this.buffer = new Uint8Array(bufLength);
126
- }
127
- write(v) {
128
- const { buffer } = this;
129
- buffer[this.pos++] = v;
130
- if (this.pos === bufLength) {
131
- this.out += td.decode(buffer);
132
- this.pos = 0;
133
- }
134
- }
135
- flush() {
136
- const { buffer, out, pos } = this;
137
- return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;
138
- }
139
- };
140
- function encode(decoded) {
141
- const writer = new StringWriter();
142
- let sourcesIndex = 0;
143
- let sourceLine = 0;
144
- let sourceColumn = 0;
145
- let namesIndex = 0;
146
- for (let i = 0; i < decoded.length; i++) {
147
- const line = decoded[i];
148
- if (i > 0)
149
- writer.write(semicolon);
150
- if (line.length === 0)
151
- continue;
152
- let genColumn = 0;
153
- for (let j = 0; j < line.length; j++) {
154
- const segment = line[j];
155
- if (j > 0)
156
- writer.write(comma);
157
- genColumn = encodeInteger(writer, segment[0], genColumn);
158
- if (segment.length === 1)
159
- continue;
160
- sourcesIndex = encodeInteger(writer, segment[1], sourcesIndex);
161
- sourceLine = encodeInteger(writer, segment[2], sourceLine);
162
- sourceColumn = encodeInteger(writer, segment[3], sourceColumn);
163
- if (segment.length === 4)
164
- continue;
165
- namesIndex = encodeInteger(writer, segment[4], namesIndex);
166
- }
167
- }
168
- return writer.flush();
169
- }
170
-
171
- // ../../node_modules/magic-string/dist/magic-string.es.mjs
172
- var BitSet = class _BitSet {
173
- constructor(arg) {
174
- this.bits = arg instanceof _BitSet ? arg.bits.slice() : [];
175
- }
176
- add(n2) {
177
- this.bits[n2 >> 5] |= 1 << (n2 & 31);
178
- }
179
- has(n2) {
180
- return !!(this.bits[n2 >> 5] & 1 << (n2 & 31));
181
- }
182
- };
183
- var Chunk = class _Chunk {
184
- constructor(start, end, content) {
185
- this.start = start;
186
- this.end = end;
187
- this.original = content;
188
- this.intro = "";
189
- this.outro = "";
190
- this.content = content;
191
- this.storeName = false;
192
- this.edited = false;
193
- {
194
- this.previous = null;
195
- this.next = null;
196
- }
197
- }
198
- appendLeft(content) {
199
- this.outro += content;
200
- }
201
- appendRight(content) {
202
- this.intro = this.intro + content;
203
- }
204
- clone() {
205
- const chunk = new _Chunk(this.start, this.end, this.original);
206
- chunk.intro = this.intro;
207
- chunk.outro = this.outro;
208
- chunk.content = this.content;
209
- chunk.storeName = this.storeName;
210
- chunk.edited = this.edited;
211
- return chunk;
212
- }
213
- contains(index) {
214
- return this.start < index && index < this.end;
215
- }
216
- eachNext(fn) {
217
- let chunk = this;
218
- while (chunk) {
219
- fn(chunk);
220
- chunk = chunk.next;
221
- }
222
- }
223
- eachPrevious(fn) {
224
- let chunk = this;
225
- while (chunk) {
226
- fn(chunk);
227
- chunk = chunk.previous;
228
- }
229
- }
230
- edit(content, storeName, contentOnly) {
231
- this.content = content;
232
- if (!contentOnly) {
233
- this.intro = "";
234
- this.outro = "";
235
- }
236
- this.storeName = storeName;
237
- this.edited = true;
238
- return this;
239
- }
240
- prependLeft(content) {
241
- this.outro = content + this.outro;
242
- }
243
- prependRight(content) {
244
- this.intro = content + this.intro;
245
- }
246
- reset() {
247
- this.intro = "";
248
- this.outro = "";
249
- if (this.edited) {
250
- this.content = this.original;
251
- this.storeName = false;
252
- this.edited = false;
253
- }
254
- }
255
- split(index) {
256
- const sliceIndex = index - this.start;
257
- const originalBefore = this.original.slice(0, sliceIndex);
258
- const originalAfter = this.original.slice(sliceIndex);
259
- this.original = originalBefore;
260
- const newChunk = new _Chunk(index, this.end, originalAfter);
261
- newChunk.outro = this.outro;
262
- this.outro = "";
263
- this.end = index;
264
- if (this.edited) {
265
- newChunk.edit("", false);
266
- this.content = "";
267
- } else {
268
- this.content = originalBefore;
269
- }
270
- newChunk.next = this.next;
271
- if (newChunk.next) newChunk.next.previous = newChunk;
272
- newChunk.previous = this;
273
- this.next = newChunk;
274
- return newChunk;
275
- }
276
- toString() {
277
- return this.intro + this.content + this.outro;
278
- }
279
- trimEnd(rx) {
280
- this.outro = this.outro.replace(rx, "");
281
- if (this.outro.length) return true;
282
- const trimmed = this.content.replace(rx, "");
283
- if (trimmed.length) {
284
- if (trimmed !== this.content) {
285
- this.split(this.start + trimmed.length).edit("", void 0, true);
286
- if (this.edited) {
287
- this.edit(trimmed, this.storeName, true);
288
- }
289
- }
290
- return true;
291
- } else {
292
- this.edit("", void 0, true);
293
- this.intro = this.intro.replace(rx, "");
294
- if (this.intro.length) return true;
295
- }
296
- }
297
- trimStart(rx) {
298
- this.intro = this.intro.replace(rx, "");
299
- if (this.intro.length) return true;
300
- const trimmed = this.content.replace(rx, "");
301
- if (trimmed.length) {
302
- if (trimmed !== this.content) {
303
- const newChunk = this.split(this.end - trimmed.length);
304
- if (this.edited) {
305
- newChunk.edit(trimmed, this.storeName, true);
306
- }
307
- this.edit("", void 0, true);
308
- }
309
- return true;
310
- } else {
311
- this.edit("", void 0, true);
312
- this.outro = this.outro.replace(rx, "");
313
- if (this.outro.length) return true;
314
- }
315
- }
316
- };
317
- function getBtoa() {
318
- if (typeof globalThis !== "undefined" && typeof globalThis.btoa === "function") {
319
- return (str) => globalThis.btoa(unescape(encodeURIComponent(str)));
320
- } else if (typeof Buffer === "function") {
321
- return (str) => Buffer.from(str, "utf-8").toString("base64");
322
- } else {
323
- return () => {
324
- throw new Error("Unsupported environment: `window.btoa` or `Buffer` should be supported.");
325
- };
326
- }
327
- }
328
- var btoa = /* @__PURE__ */ getBtoa();
329
- var SourceMap = class {
330
- constructor(properties) {
331
- this.version = 3;
332
- this.file = properties.file;
333
- this.sources = properties.sources;
334
- this.sourcesContent = properties.sourcesContent;
335
- this.names = properties.names;
336
- this.mappings = encode(properties.mappings);
337
- if (typeof properties.x_google_ignoreList !== "undefined") {
338
- this.x_google_ignoreList = properties.x_google_ignoreList;
339
- }
340
- if (typeof properties.debugId !== "undefined") {
341
- this.debugId = properties.debugId;
342
- }
343
- }
344
- toString() {
345
- return JSON.stringify(this);
346
- }
347
- toUrl() {
348
- return "data:application/json;charset=utf-8;base64," + btoa(this.toString());
349
- }
350
- };
351
- function guessIndent(code) {
352
- const lines = code.split("\n");
353
- const tabbed = lines.filter((line) => /^\t+/.test(line));
354
- const spaced = lines.filter((line) => /^ {2,}/.test(line));
355
- if (tabbed.length === 0 && spaced.length === 0) {
356
- return null;
357
- }
358
- if (tabbed.length >= spaced.length) {
359
- return " ";
360
- }
361
- const min = spaced.reduce((previous, current) => {
362
- const numSpaces = /^ +/.exec(current)[0].length;
363
- return Math.min(numSpaces, previous);
364
- }, Infinity);
365
- return new Array(min + 1).join(" ");
366
- }
367
- function getRelativePath(from, to) {
368
- const fromParts = from.split(/[/\\]/);
369
- const toParts = to.split(/[/\\]/);
370
- fromParts.pop();
371
- while (fromParts[0] === toParts[0]) {
372
- fromParts.shift();
373
- toParts.shift();
374
- }
375
- if (fromParts.length) {
376
- let i = fromParts.length;
377
- while (i--) fromParts[i] = "..";
378
- }
379
- return fromParts.concat(toParts).join("/");
380
- }
381
- var toString = Object.prototype.toString;
382
- function isObject(thing) {
383
- return toString.call(thing) === "[object Object]";
384
- }
385
- function getLocator(source) {
386
- const originalLines = source.split("\n");
387
- const lineOffsets = [];
388
- for (let i = 0, pos = 0; i < originalLines.length; i++) {
389
- lineOffsets.push(pos);
390
- pos += originalLines[i].length + 1;
391
- }
392
- return function locate(index) {
393
- let i = 0;
394
- let j = lineOffsets.length;
395
- while (i < j) {
396
- const m = i + j >> 1;
397
- if (index < lineOffsets[m]) {
398
- j = m;
399
- } else {
400
- i = m + 1;
401
- }
402
- }
403
- const line = i - 1;
404
- const column = index - lineOffsets[line];
405
- return { line, column };
406
- };
407
- }
408
- var wordRegex = /\w/;
409
- var Mappings = class {
410
- constructor(hires) {
411
- this.hires = hires;
412
- this.generatedCodeLine = 0;
413
- this.generatedCodeColumn = 0;
414
- this.raw = [];
415
- this.rawSegments = this.raw[this.generatedCodeLine] = [];
416
- this.pending = null;
417
- }
418
- addEdit(sourceIndex, content, loc, nameIndex) {
419
- if (content.length) {
420
- const contentLengthMinusOne = content.length - 1;
421
- let contentLineEnd = content.indexOf("\n", 0);
422
- let previousContentLineEnd = -1;
423
- while (contentLineEnd >= 0 && contentLengthMinusOne > contentLineEnd) {
424
- const segment2 = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
425
- if (nameIndex >= 0) {
426
- segment2.push(nameIndex);
427
- }
428
- this.rawSegments.push(segment2);
429
- this.generatedCodeLine += 1;
430
- this.raw[this.generatedCodeLine] = this.rawSegments = [];
431
- this.generatedCodeColumn = 0;
432
- previousContentLineEnd = contentLineEnd;
433
- contentLineEnd = content.indexOf("\n", contentLineEnd + 1);
434
- }
435
- const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
436
- if (nameIndex >= 0) {
437
- segment.push(nameIndex);
438
- }
439
- this.rawSegments.push(segment);
440
- this.advance(content.slice(previousContentLineEnd + 1));
441
- } else if (this.pending) {
442
- this.rawSegments.push(this.pending);
443
- this.advance(content);
444
- }
445
- this.pending = null;
446
- }
447
- addUneditedChunk(sourceIndex, chunk, original, loc, sourcemapLocations) {
448
- let originalCharIndex = chunk.start;
449
- let first = true;
450
- let charInHiresBoundary = false;
451
- while (originalCharIndex < chunk.end) {
452
- if (original[originalCharIndex] === "\n") {
453
- loc.line += 1;
454
- loc.column = 0;
455
- this.generatedCodeLine += 1;
456
- this.raw[this.generatedCodeLine] = this.rawSegments = [];
457
- this.generatedCodeColumn = 0;
458
- first = true;
459
- charInHiresBoundary = false;
460
- } else {
461
- if (this.hires || first || sourcemapLocations.has(originalCharIndex)) {
462
- const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
463
- if (this.hires === "boundary") {
464
- if (wordRegex.test(original[originalCharIndex])) {
465
- if (!charInHiresBoundary) {
466
- this.rawSegments.push(segment);
467
- charInHiresBoundary = true;
468
- }
469
- } else {
470
- this.rawSegments.push(segment);
471
- charInHiresBoundary = false;
472
- }
473
- } else {
474
- this.rawSegments.push(segment);
475
- }
476
- }
477
- loc.column += 1;
478
- this.generatedCodeColumn += 1;
479
- first = false;
480
- }
481
- originalCharIndex += 1;
482
- }
483
- this.pending = null;
484
- }
485
- advance(str) {
486
- if (!str) return;
487
- const lines = str.split("\n");
488
- if (lines.length > 1) {
489
- for (let i = 0; i < lines.length - 1; i++) {
490
- this.generatedCodeLine++;
491
- this.raw[this.generatedCodeLine] = this.rawSegments = [];
492
- }
493
- this.generatedCodeColumn = 0;
494
- }
495
- this.generatedCodeColumn += lines[lines.length - 1].length;
496
- }
497
- };
498
- var n = "\n";
499
- var warned = {
500
- insertLeft: false,
501
- insertRight: false,
502
- storeName: false
503
- };
504
- var MagicString = class _MagicString {
505
- constructor(string, options = {}) {
506
- const chunk = new Chunk(0, string.length, string);
507
- Object.defineProperties(this, {
508
- original: { writable: true, value: string },
509
- outro: { writable: true, value: "" },
510
- intro: { writable: true, value: "" },
511
- firstChunk: { writable: true, value: chunk },
512
- lastChunk: { writable: true, value: chunk },
513
- lastSearchedChunk: { writable: true, value: chunk },
514
- byStart: { writable: true, value: {} },
515
- byEnd: { writable: true, value: {} },
516
- filename: { writable: true, value: options.filename },
517
- indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },
518
- sourcemapLocations: { writable: true, value: new BitSet() },
519
- storedNames: { writable: true, value: {} },
520
- indentStr: { writable: true, value: void 0 },
521
- ignoreList: { writable: true, value: options.ignoreList },
522
- offset: { writable: true, value: options.offset || 0 }
523
- });
524
- this.byStart[0] = chunk;
525
- this.byEnd[string.length] = chunk;
526
- }
527
- addSourcemapLocation(char) {
528
- this.sourcemapLocations.add(char);
529
- }
530
- append(content) {
531
- if (typeof content !== "string") throw new TypeError("outro content must be a string");
532
- this.outro += content;
533
- return this;
534
- }
535
- appendLeft(index, content) {
536
- index = index + this.offset;
537
- if (typeof content !== "string") throw new TypeError("inserted content must be a string");
538
- this._split(index);
539
- const chunk = this.byEnd[index];
540
- if (chunk) {
541
- chunk.appendLeft(content);
542
- } else {
543
- this.intro += content;
544
- }
545
- return this;
546
- }
547
- appendRight(index, content) {
548
- index = index + this.offset;
549
- if (typeof content !== "string") throw new TypeError("inserted content must be a string");
550
- this._split(index);
551
- const chunk = this.byStart[index];
552
- if (chunk) {
553
- chunk.appendRight(content);
554
- } else {
555
- this.outro += content;
556
- }
557
- return this;
558
- }
559
- clone() {
560
- const cloned = new _MagicString(this.original, { filename: this.filename, offset: this.offset });
561
- let originalChunk = this.firstChunk;
562
- let clonedChunk = cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone();
563
- while (originalChunk) {
564
- cloned.byStart[clonedChunk.start] = clonedChunk;
565
- cloned.byEnd[clonedChunk.end] = clonedChunk;
566
- const nextOriginalChunk = originalChunk.next;
567
- const nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();
568
- if (nextClonedChunk) {
569
- clonedChunk.next = nextClonedChunk;
570
- nextClonedChunk.previous = clonedChunk;
571
- clonedChunk = nextClonedChunk;
572
- }
573
- originalChunk = nextOriginalChunk;
574
- }
575
- cloned.lastChunk = clonedChunk;
576
- if (this.indentExclusionRanges) {
577
- cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
578
- }
579
- cloned.sourcemapLocations = new BitSet(this.sourcemapLocations);
580
- cloned.intro = this.intro;
581
- cloned.outro = this.outro;
582
- return cloned;
583
- }
584
- generateDecodedMap(options) {
585
- options = options || {};
586
- const sourceIndex = 0;
587
- const names = Object.keys(this.storedNames);
588
- const mappings = new Mappings(options.hires);
589
- const locate = getLocator(this.original);
590
- if (this.intro) {
591
- mappings.advance(this.intro);
592
- }
593
- this.firstChunk.eachNext((chunk) => {
594
- const loc = locate(chunk.start);
595
- if (chunk.intro.length) mappings.advance(chunk.intro);
596
- if (chunk.edited) {
597
- mappings.addEdit(
598
- sourceIndex,
599
- chunk.content,
600
- loc,
601
- chunk.storeName ? names.indexOf(chunk.original) : -1
602
- );
603
- } else {
604
- mappings.addUneditedChunk(sourceIndex, chunk, this.original, loc, this.sourcemapLocations);
605
- }
606
- if (chunk.outro.length) mappings.advance(chunk.outro);
607
- });
608
- return {
609
- file: options.file ? options.file.split(/[/\\]/).pop() : void 0,
610
- sources: [
611
- options.source ? getRelativePath(options.file || "", options.source) : options.file || ""
612
- ],
613
- sourcesContent: options.includeContent ? [this.original] : void 0,
614
- names,
615
- mappings: mappings.raw,
616
- x_google_ignoreList: this.ignoreList ? [sourceIndex] : void 0
617
- };
618
- }
619
- generateMap(options) {
620
- return new SourceMap(this.generateDecodedMap(options));
621
- }
622
- _ensureindentStr() {
623
- if (this.indentStr === void 0) {
624
- this.indentStr = guessIndent(this.original);
625
- }
626
- }
627
- _getRawIndentString() {
628
- this._ensureindentStr();
629
- return this.indentStr;
630
- }
631
- getIndentString() {
632
- this._ensureindentStr();
633
- return this.indentStr === null ? " " : this.indentStr;
634
- }
635
- indent(indentStr, options) {
636
- const pattern = /^[^\r\n]/gm;
637
- if (isObject(indentStr)) {
638
- options = indentStr;
639
- indentStr = void 0;
640
- }
641
- if (indentStr === void 0) {
642
- this._ensureindentStr();
643
- indentStr = this.indentStr || " ";
644
- }
645
- if (indentStr === "") return this;
646
- options = options || {};
647
- const isExcluded = {};
648
- if (options.exclude) {
649
- const exclusions = typeof options.exclude[0] === "number" ? [options.exclude] : options.exclude;
650
- exclusions.forEach((exclusion) => {
651
- for (let i = exclusion[0]; i < exclusion[1]; i += 1) {
652
- isExcluded[i] = true;
653
- }
654
- });
655
- }
656
- let shouldIndentNextCharacter = options.indentStart !== false;
657
- const replacer = (match) => {
658
- if (shouldIndentNextCharacter) return `${indentStr}${match}`;
659
- shouldIndentNextCharacter = true;
660
- return match;
661
- };
662
- this.intro = this.intro.replace(pattern, replacer);
663
- let charIndex = 0;
664
- let chunk = this.firstChunk;
665
- while (chunk) {
666
- const end = chunk.end;
667
- if (chunk.edited) {
668
- if (!isExcluded[charIndex]) {
669
- chunk.content = chunk.content.replace(pattern, replacer);
670
- if (chunk.content.length) {
671
- shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === "\n";
672
- }
673
- }
674
- } else {
675
- charIndex = chunk.start;
676
- while (charIndex < end) {
677
- if (!isExcluded[charIndex]) {
678
- const char = this.original[charIndex];
679
- if (char === "\n") {
680
- shouldIndentNextCharacter = true;
681
- } else if (char !== "\r" && shouldIndentNextCharacter) {
682
- shouldIndentNextCharacter = false;
683
- if (charIndex === chunk.start) {
684
- chunk.prependRight(indentStr);
685
- } else {
686
- this._splitChunk(chunk, charIndex);
687
- chunk = chunk.next;
688
- chunk.prependRight(indentStr);
689
- }
690
- }
691
- }
692
- charIndex += 1;
693
- }
694
- }
695
- charIndex = chunk.end;
696
- chunk = chunk.next;
697
- }
698
- this.outro = this.outro.replace(pattern, replacer);
699
- return this;
700
- }
701
- insert() {
702
- throw new Error(
703
- "magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)"
704
- );
705
- }
706
- insertLeft(index, content) {
707
- if (!warned.insertLeft) {
708
- console.warn(
709
- "magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead"
710
- );
711
- warned.insertLeft = true;
712
- }
713
- return this.appendLeft(index, content);
714
- }
715
- insertRight(index, content) {
716
- if (!warned.insertRight) {
717
- console.warn(
718
- "magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead"
719
- );
720
- warned.insertRight = true;
721
- }
722
- return this.prependRight(index, content);
723
- }
724
- move(start, end, index) {
725
- start = start + this.offset;
726
- end = end + this.offset;
727
- index = index + this.offset;
728
- if (index >= start && index <= end) throw new Error("Cannot move a selection inside itself");
729
- this._split(start);
730
- this._split(end);
731
- this._split(index);
732
- const first = this.byStart[start];
733
- const last = this.byEnd[end];
734
- const oldLeft = first.previous;
735
- const oldRight = last.next;
736
- const newRight = this.byStart[index];
737
- if (!newRight && last === this.lastChunk) return this;
738
- const newLeft = newRight ? newRight.previous : this.lastChunk;
739
- if (oldLeft) oldLeft.next = oldRight;
740
- if (oldRight) oldRight.previous = oldLeft;
741
- if (newLeft) newLeft.next = first;
742
- if (newRight) newRight.previous = last;
743
- if (!first.previous) this.firstChunk = last.next;
744
- if (!last.next) {
745
- this.lastChunk = first.previous;
746
- this.lastChunk.next = null;
747
- }
748
- first.previous = newLeft;
749
- last.next = newRight || null;
750
- if (!newLeft) this.firstChunk = first;
751
- if (!newRight) this.lastChunk = last;
752
- return this;
753
- }
754
- overwrite(start, end, content, options) {
755
- options = options || {};
756
- return this.update(start, end, content, { ...options, overwrite: !options.contentOnly });
757
- }
758
- update(start, end, content, options) {
759
- start = start + this.offset;
760
- end = end + this.offset;
761
- if (typeof content !== "string") throw new TypeError("replacement content must be a string");
762
- if (this.original.length !== 0) {
763
- while (start < 0) start += this.original.length;
764
- while (end < 0) end += this.original.length;
765
- }
766
- if (end > this.original.length) throw new Error("end is out of bounds");
767
- if (start === end)
768
- throw new Error(
769
- "Cannot overwrite a zero-length range \u2013 use appendLeft or prependRight instead"
770
- );
771
- this._split(start);
772
- this._split(end);
773
- if (options === true) {
774
- if (!warned.storeName) {
775
- console.warn(
776
- "The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string"
777
- );
778
- warned.storeName = true;
779
- }
780
- options = { storeName: true };
781
- }
782
- const storeName = options !== void 0 ? options.storeName : false;
783
- const overwrite = options !== void 0 ? options.overwrite : false;
784
- if (storeName) {
785
- const original = this.original.slice(start, end);
786
- Object.defineProperty(this.storedNames, original, {
787
- writable: true,
788
- value: true,
789
- enumerable: true
790
- });
791
- }
792
- const first = this.byStart[start];
793
- const last = this.byEnd[end];
794
- if (first) {
795
- let chunk = first;
796
- while (chunk !== last) {
797
- if (chunk.next !== this.byStart[chunk.end]) {
798
- throw new Error("Cannot overwrite across a split point");
799
- }
800
- chunk = chunk.next;
801
- chunk.edit("", false);
802
- }
803
- first.edit(content, storeName, !overwrite);
804
- } else {
805
- const newChunk = new Chunk(start, end, "").edit(content, storeName);
806
- last.next = newChunk;
807
- newChunk.previous = last;
808
- }
809
- return this;
810
- }
811
- prepend(content) {
812
- if (typeof content !== "string") throw new TypeError("outro content must be a string");
813
- this.intro = content + this.intro;
814
- return this;
815
- }
816
- prependLeft(index, content) {
817
- index = index + this.offset;
818
- if (typeof content !== "string") throw new TypeError("inserted content must be a string");
819
- this._split(index);
820
- const chunk = this.byEnd[index];
821
- if (chunk) {
822
- chunk.prependLeft(content);
823
- } else {
824
- this.intro = content + this.intro;
825
- }
826
- return this;
827
- }
828
- prependRight(index, content) {
829
- index = index + this.offset;
830
- if (typeof content !== "string") throw new TypeError("inserted content must be a string");
831
- this._split(index);
832
- const chunk = this.byStart[index];
833
- if (chunk) {
834
- chunk.prependRight(content);
835
- } else {
836
- this.outro = content + this.outro;
837
- }
838
- return this;
839
- }
840
- remove(start, end) {
841
- start = start + this.offset;
842
- end = end + this.offset;
843
- if (this.original.length !== 0) {
844
- while (start < 0) start += this.original.length;
845
- while (end < 0) end += this.original.length;
846
- }
847
- if (start === end) return this;
848
- if (start < 0 || end > this.original.length) throw new Error("Character is out of bounds");
849
- if (start > end) throw new Error("end must be greater than start");
850
- this._split(start);
851
- this._split(end);
852
- let chunk = this.byStart[start];
853
- while (chunk) {
854
- chunk.intro = "";
855
- chunk.outro = "";
856
- chunk.edit("");
857
- chunk = end > chunk.end ? this.byStart[chunk.end] : null;
858
- }
859
- return this;
860
- }
861
- reset(start, end) {
862
- start = start + this.offset;
863
- end = end + this.offset;
864
- if (this.original.length !== 0) {
865
- while (start < 0) start += this.original.length;
866
- while (end < 0) end += this.original.length;
867
- }
868
- if (start === end) return this;
869
- if (start < 0 || end > this.original.length) throw new Error("Character is out of bounds");
870
- if (start > end) throw new Error("end must be greater than start");
871
- this._split(start);
872
- this._split(end);
873
- let chunk = this.byStart[start];
874
- while (chunk) {
875
- chunk.reset();
876
- chunk = end > chunk.end ? this.byStart[chunk.end] : null;
877
- }
878
- return this;
879
- }
880
- lastChar() {
881
- if (this.outro.length) return this.outro[this.outro.length - 1];
882
- let chunk = this.lastChunk;
883
- do {
884
- if (chunk.outro.length) return chunk.outro[chunk.outro.length - 1];
885
- if (chunk.content.length) return chunk.content[chunk.content.length - 1];
886
- if (chunk.intro.length) return chunk.intro[chunk.intro.length - 1];
887
- } while (chunk = chunk.previous);
888
- if (this.intro.length) return this.intro[this.intro.length - 1];
889
- return "";
890
- }
891
- lastLine() {
892
- let lineIndex = this.outro.lastIndexOf(n);
893
- if (lineIndex !== -1) return this.outro.substr(lineIndex + 1);
894
- let lineStr = this.outro;
895
- let chunk = this.lastChunk;
896
- do {
897
- if (chunk.outro.length > 0) {
898
- lineIndex = chunk.outro.lastIndexOf(n);
899
- if (lineIndex !== -1) return chunk.outro.substr(lineIndex + 1) + lineStr;
900
- lineStr = chunk.outro + lineStr;
901
- }
902
- if (chunk.content.length > 0) {
903
- lineIndex = chunk.content.lastIndexOf(n);
904
- if (lineIndex !== -1) return chunk.content.substr(lineIndex + 1) + lineStr;
905
- lineStr = chunk.content + lineStr;
906
- }
907
- if (chunk.intro.length > 0) {
908
- lineIndex = chunk.intro.lastIndexOf(n);
909
- if (lineIndex !== -1) return chunk.intro.substr(lineIndex + 1) + lineStr;
910
- lineStr = chunk.intro + lineStr;
911
- }
912
- } while (chunk = chunk.previous);
913
- lineIndex = this.intro.lastIndexOf(n);
914
- if (lineIndex !== -1) return this.intro.substr(lineIndex + 1) + lineStr;
915
- return this.intro + lineStr;
916
- }
917
- slice(start = 0, end = this.original.length - this.offset) {
918
- start = start + this.offset;
919
- end = end + this.offset;
920
- if (this.original.length !== 0) {
921
- while (start < 0) start += this.original.length;
922
- while (end < 0) end += this.original.length;
923
- }
924
- let result = "";
925
- let chunk = this.firstChunk;
926
- while (chunk && (chunk.start > start || chunk.end <= start)) {
927
- if (chunk.start < end && chunk.end >= end) {
928
- return result;
929
- }
930
- chunk = chunk.next;
931
- }
932
- if (chunk && chunk.edited && chunk.start !== start)
933
- throw new Error(`Cannot use replaced character ${start} as slice start anchor.`);
934
- const startChunk = chunk;
935
- while (chunk) {
936
- if (chunk.intro && (startChunk !== chunk || chunk.start === start)) {
937
- result += chunk.intro;
938
- }
939
- const containsEnd = chunk.start < end && chunk.end >= end;
940
- if (containsEnd && chunk.edited && chunk.end !== end)
941
- throw new Error(`Cannot use replaced character ${end} as slice end anchor.`);
942
- const sliceStart = startChunk === chunk ? start - chunk.start : 0;
943
- const sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;
944
- result += chunk.content.slice(sliceStart, sliceEnd);
945
- if (chunk.outro && (!containsEnd || chunk.end === end)) {
946
- result += chunk.outro;
947
- }
948
- if (containsEnd) {
949
- break;
950
- }
951
- chunk = chunk.next;
952
- }
953
- return result;
954
- }
955
- // TODO deprecate this? not really very useful
956
- snip(start, end) {
957
- const clone = this.clone();
958
- clone.remove(0, start);
959
- clone.remove(end, clone.original.length);
960
- return clone;
961
- }
962
- _split(index) {
963
- if (this.byStart[index] || this.byEnd[index]) return;
964
- let chunk = this.lastSearchedChunk;
965
- const searchForward = index > chunk.end;
966
- while (chunk) {
967
- if (chunk.contains(index)) return this._splitChunk(chunk, index);
968
- chunk = searchForward ? this.byStart[chunk.end] : this.byEnd[chunk.start];
969
- }
970
- }
971
- _splitChunk(chunk, index) {
972
- if (chunk.edited && chunk.content.length) {
973
- const loc = getLocator(this.original)(index);
974
- throw new Error(
975
- `Cannot split a chunk that has already been edited (${loc.line}:${loc.column} \u2013 "${chunk.original}")`
976
- );
977
- }
978
- const newChunk = chunk.split(index);
979
- this.byEnd[index] = chunk;
980
- this.byStart[index] = newChunk;
981
- this.byEnd[newChunk.end] = newChunk;
982
- if (chunk === this.lastChunk) this.lastChunk = newChunk;
983
- this.lastSearchedChunk = chunk;
984
- return true;
985
- }
986
- toString() {
987
- let str = this.intro;
988
- let chunk = this.firstChunk;
989
- while (chunk) {
990
- str += chunk.toString();
991
- chunk = chunk.next;
992
- }
993
- return str + this.outro;
994
- }
995
- isEmpty() {
996
- let chunk = this.firstChunk;
997
- do {
998
- if (chunk.intro.length && chunk.intro.trim() || chunk.content.length && chunk.content.trim() || chunk.outro.length && chunk.outro.trim())
999
- return false;
1000
- } while (chunk = chunk.next);
1001
- return true;
1002
- }
1003
- length() {
1004
- let chunk = this.firstChunk;
1005
- let length = 0;
1006
- do {
1007
- length += chunk.intro.length + chunk.content.length + chunk.outro.length;
1008
- } while (chunk = chunk.next);
1009
- return length;
1010
- }
1011
- trimLines() {
1012
- return this.trim("[\\r\\n]");
1013
- }
1014
- trim(charType) {
1015
- return this.trimStart(charType).trimEnd(charType);
1016
- }
1017
- trimEndAborted(charType) {
1018
- const rx = new RegExp((charType || "\\s") + "+$");
1019
- this.outro = this.outro.replace(rx, "");
1020
- if (this.outro.length) return true;
1021
- let chunk = this.lastChunk;
1022
- do {
1023
- const end = chunk.end;
1024
- const aborted = chunk.trimEnd(rx);
1025
- if (chunk.end !== end) {
1026
- if (this.lastChunk === chunk) {
1027
- this.lastChunk = chunk.next;
1028
- }
1029
- this.byEnd[chunk.end] = chunk;
1030
- this.byStart[chunk.next.start] = chunk.next;
1031
- this.byEnd[chunk.next.end] = chunk.next;
1032
- }
1033
- if (aborted) return true;
1034
- chunk = chunk.previous;
1035
- } while (chunk);
1036
- return false;
1037
- }
1038
- trimEnd(charType) {
1039
- this.trimEndAborted(charType);
1040
- return this;
1041
- }
1042
- trimStartAborted(charType) {
1043
- const rx = new RegExp("^" + (charType || "\\s") + "+");
1044
- this.intro = this.intro.replace(rx, "");
1045
- if (this.intro.length) return true;
1046
- let chunk = this.firstChunk;
1047
- do {
1048
- const end = chunk.end;
1049
- const aborted = chunk.trimStart(rx);
1050
- if (chunk.end !== end) {
1051
- if (chunk === this.lastChunk) this.lastChunk = chunk.next;
1052
- this.byEnd[chunk.end] = chunk;
1053
- this.byStart[chunk.next.start] = chunk.next;
1054
- this.byEnd[chunk.next.end] = chunk.next;
1055
- }
1056
- if (aborted) return true;
1057
- chunk = chunk.next;
1058
- } while (chunk);
1059
- return false;
1060
- }
1061
- trimStart(charType) {
1062
- this.trimStartAborted(charType);
1063
- return this;
1064
- }
1065
- hasChanged() {
1066
- return this.original !== this.toString();
1067
- }
1068
- _replaceRegexp(searchValue, replacement) {
1069
- function getReplacement(match, str) {
1070
- if (typeof replacement === "string") {
1071
- return replacement.replace(/\$(\$|&|\d+)/g, (_, i) => {
1072
- if (i === "$") return "$";
1073
- if (i === "&") return match[0];
1074
- const num = +i;
1075
- if (num < match.length) return match[+i];
1076
- return `$${i}`;
1077
- });
1078
- } else {
1079
- return replacement(...match, match.index, str, match.groups);
1080
- }
1081
- }
1082
- function matchAll(re, str) {
1083
- let match;
1084
- const matches = [];
1085
- while (match = re.exec(str)) {
1086
- matches.push(match);
1087
- }
1088
- return matches;
1089
- }
1090
- if (searchValue.global) {
1091
- const matches = matchAll(searchValue, this.original);
1092
- matches.forEach((match) => {
1093
- if (match.index != null) {
1094
- const replacement2 = getReplacement(match, this.original);
1095
- if (replacement2 !== match[0]) {
1096
- this.overwrite(match.index, match.index + match[0].length, replacement2);
1097
- }
1098
- }
1099
- });
1100
- } else {
1101
- const match = this.original.match(searchValue);
1102
- if (match && match.index != null) {
1103
- const replacement2 = getReplacement(match, this.original);
1104
- if (replacement2 !== match[0]) {
1105
- this.overwrite(match.index, match.index + match[0].length, replacement2);
1106
- }
1107
- }
1108
- }
1109
- return this;
1110
- }
1111
- _replaceString(string, replacement) {
1112
- const { original } = this;
1113
- const index = original.indexOf(string);
1114
- if (index !== -1) {
1115
- this.overwrite(index, index + string.length, replacement);
1116
- }
1117
- return this;
1118
- }
1119
- replace(searchValue, replacement) {
1120
- if (typeof searchValue === "string") {
1121
- return this._replaceString(searchValue, replacement);
1122
- }
1123
- return this._replaceRegexp(searchValue, replacement);
1124
- }
1125
- _replaceAllString(string, replacement) {
1126
- const { original } = this;
1127
- const stringLength = string.length;
1128
- for (let index = original.indexOf(string); index !== -1; index = original.indexOf(string, index + stringLength)) {
1129
- const previous = original.slice(index, index + stringLength);
1130
- if (previous !== replacement) this.overwrite(index, index + stringLength, replacement);
1131
- }
1132
- return this;
1133
- }
1134
- replaceAll(searchValue, replacement) {
1135
- if (typeof searchValue === "string") {
1136
- return this._replaceAllString(searchValue, replacement);
1137
- }
1138
- if (!searchValue.global) {
1139
- throw new TypeError(
1140
- "MagicString.prototype.replaceAll called with a non-global RegExp argument"
1141
- );
1142
- }
1143
- return this._replaceRegexp(searchValue, replacement);
1144
- }
1145
- };
1146
-
1147
- // src/shared/schema-transformer.ts
82
+ import MagicString from "magic-string";
1148
83
  var schemaTransformerPlugin = {
1149
84
  name: "schema-transformer",
1150
85
  setup(build2) {
@@ -1160,27 +95,101 @@ var schemaTransformerPlugin = {
1160
95
  async function applySchemaTransformations(content) {
1161
96
  const magicString = new MagicString(content);
1162
97
  const { program, comments } = await parseAsync("file.ts", content);
98
+ const parentStack = [];
1163
99
  walk(program, {
1164
100
  enter(node) {
101
+ parentStack.push(node);
1165
102
  if (node.type !== "Property" || node.key.type !== "Identifier") {
1166
103
  return;
1167
104
  }
105
+ const parentKey = getParentObjectKey(parentStack) || getMarkerFunctionName(parentStack);
106
+ if (!parentKey || !["inputs", "outputs", "args", "secrets"].includes(parentKey)) {
107
+ return;
108
+ }
1168
109
  const jsdoc = comments.find((comment) => isLeadingComment(content, node, comment));
1169
- if (!jsdoc || !jsdoc.value.includes("@schema")) {
110
+ if (!jsdoc) {
1170
111
  return;
1171
112
  }
1172
- magicString.update(
1173
- node.value.start,
1174
- node.value.end,
1175
- `{
1176
- ...${content.substring(node.value.start, node.value.end)},
1177
- description: \`${cleanJsdoc(jsdoc.value)}\`,
113
+ const description = cleanJsdoc(jsdoc.value);
114
+ const originalValue = content.substring(node.value.start, node.value.end);
115
+ const entityField = ["inputs", "outputs"].includes(parentKey) ? "entity" : "schema";
116
+ const isAlreadyStructured = isStructuredValue(originalValue, entityField);
117
+ if (isAlreadyStructured) {
118
+ const modifiedValue = injectDescriptionIntoObject(originalValue, description);
119
+ magicString.update(node.value.start, node.value.end, modifiedValue);
120
+ } else {
121
+ magicString.update(
122
+ node.value.start,
123
+ node.value.end,
124
+ `{
125
+ ${entityField}: ${originalValue},
126
+ meta: {
127
+ description: \`${description}\`,
128
+ },
1178
129
  }`
1179
- );
130
+ );
131
+ }
132
+ },
133
+ leave() {
134
+ parentStack.pop();
1180
135
  }
1181
136
  });
1182
137
  return magicString.toString();
1183
138
  }
139
+ function injectDescriptionIntoObject(objectString, description) {
140
+ const trimmed = objectString.trim();
141
+ const metaRegex = /meta\s*:\s*\{/;
142
+ if (metaRegex.test(trimmed)) {
143
+ return trimmed.replace(
144
+ /meta\s*:\s*\{/,
145
+ `meta: {
146
+ description: \`${description}\`,`
147
+ );
148
+ } else {
149
+ const lastBraceIndex = trimmed.lastIndexOf("}");
150
+ if (lastBraceIndex === -1) {
151
+ return trimmed;
152
+ }
153
+ const beforeBrace = trimmed.substring(0, lastBraceIndex);
154
+ const afterBrace = trimmed.substring(lastBraceIndex);
155
+ const needsComma = beforeBrace.trim().length > 1 && !beforeBrace.trim().endsWith(",");
156
+ const comma = needsComma ? "," : "";
157
+ return `${beforeBrace}${comma}
158
+ meta: {
159
+ description: \`${description}\`,
160
+ },
161
+ ${afterBrace}`;
162
+ }
163
+ }
164
+ function isStructuredValue(value, expectedField) {
165
+ const trimmed = value.trim();
166
+ if (!trimmed.startsWith("{")) {
167
+ return false;
168
+ }
169
+ const fieldPattern = new RegExp(`^\\s*{[^}]*\\b${expectedField}\\s*:`, "s");
170
+ return fieldPattern.test(trimmed);
171
+ }
172
+ function getMarkerFunctionName(parentStack) {
173
+ for (let i = parentStack.length - 1; i >= 0; i--) {
174
+ const node = parentStack[i];
175
+ if (node.type === "CallExpression" && node.callee.type === "Identifier") {
176
+ const functionName = node.callee.name;
177
+ if (functionName.startsWith("$") && ["$args", "$inputs", "$outputs", "$secrets"].includes(functionName)) {
178
+ return functionName.substring(1);
179
+ }
180
+ }
181
+ }
182
+ return null;
183
+ }
184
+ function getParentObjectKey(parentStack) {
185
+ for (let i = parentStack.length - 2; i >= 0; i--) {
186
+ const node = parentStack[i];
187
+ if (node.type === "Property" && node.key.type === "Identifier") {
188
+ return node.key.name;
189
+ }
190
+ }
191
+ return null;
192
+ }
1184
193
  function isLeadingComment(content, node, comment) {
1185
194
  if (comment.end > node.start) {
1186
195
  return false;
@@ -1189,7 +198,7 @@ function isLeadingComment(content, node, comment) {
1189
198
  return contentRange.trim().length === 0;
1190
199
  }
1191
200
  function cleanJsdoc(str) {
1192
- return str.replace(/^\s*\*/gm, "").replace("@schema", "").replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\${/g, "\\${").trim();
201
+ return str.replace(/^\s*\*/gm, "").replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\${/g, "\\${").trim();
1193
202
  }
1194
203
 
1195
204
  // src/shared/source-hash-calculator.ts
@@ -1197,8 +206,37 @@ import { dirname, relative, resolve } from "node:path";
1197
206
  import { readFile as readFile2, writeFile } from "node:fs/promises";
1198
207
  import { fileURLToPath, pathToFileURL } from "node:url";
1199
208
  import { readPackageJSON, resolvePackageJSON } from "pkg-types";
1200
- import { sha256 } from "crypto-hash";
209
+ import { crc32 } from "@aws-crypto/crc32";
1201
210
  import { resolve as importMetaResolve } from "import-meta-resolve";
211
+ import { z as z2 } from "zod";
212
+ import { int32ToBytes } from "@highstate/backend/shared";
213
+
214
+ // src/shared/schemas.ts
215
+ import { z } from "zod";
216
+ var sourceHashConfigSchema = z.discriminatedUnion("mode", [
217
+ z.object({
218
+ mode: z.literal("manual"),
219
+ version: z.string()
220
+ }),
221
+ z.object({
222
+ mode: z.literal("auto")
223
+ }),
224
+ z.object({
225
+ mode: z.literal("version")
226
+ }),
227
+ z.object({
228
+ mode: z.literal("none")
229
+ })
230
+ ]);
231
+ var highstateConfigSchema = z.object({
232
+ type: z.enum(["source", "library", "worker"]).default("source"),
233
+ sourceHash: z.union([sourceHashConfigSchema, z.record(z.string(), sourceHashConfigSchema)]).optional()
234
+ });
235
+ var highstateManifestSchema = z.object({
236
+ sourceHashes: z.record(z.string(), z.number()).optional()
237
+ });
238
+
239
+ // src/shared/source-hash-calculator.ts
1202
240
  var SourceHashCalculator = class {
1203
241
  constructor(packageJsonPath, packageJson, logger2) {
1204
242
  this.packageJsonPath = packageJsonPath;
@@ -1207,16 +245,93 @@ var SourceHashCalculator = class {
1207
245
  }
1208
246
  dependencyHashes = /* @__PURE__ */ new Map();
1209
247
  fileHashes = /* @__PURE__ */ new Map();
1210
- async writeHighstateManifest(distBasePath, distPaths) {
248
+ /**
249
+ * Calculates CRC32 hash of a string.
250
+ */
251
+ hashString(input) {
252
+ return crc32(Buffer.from(input));
253
+ }
254
+ /**
255
+ * Gets the highstate configuration from package.json with defaults.
256
+ */
257
+ getHighstateConfig(packageJson) {
258
+ const rawConfig = packageJson.highstate;
259
+ if (!rawConfig) {
260
+ return { type: "source" };
261
+ }
262
+ try {
263
+ return highstateConfigSchema.parse(rawConfig);
264
+ } catch (error) {
265
+ this.logger.warn(
266
+ { error, packageName: packageJson.name },
267
+ "invalid highstate configuration, using defaults"
268
+ );
269
+ return { type: "source" };
270
+ }
271
+ }
272
+ /**
273
+ * Gets the effective source hash configuration with defaults for a specific output.
274
+ */
275
+ getSourceHashConfig(highstateConfig, exportKey) {
276
+ if (highstateConfig.sourceHash) {
277
+ const singleConfigResult = sourceHashConfigSchema.safeParse(highstateConfig.sourceHash);
278
+ if (singleConfigResult.success) {
279
+ return singleConfigResult.data;
280
+ }
281
+ const recordConfigResult = z2.record(z2.string(), sourceHashConfigSchema).safeParse(highstateConfig.sourceHash);
282
+ if (recordConfigResult.success && exportKey) {
283
+ const perOutputConfig = recordConfigResult.data[exportKey];
284
+ if (perOutputConfig) {
285
+ return perOutputConfig;
286
+ }
287
+ }
288
+ }
289
+ if (highstateConfig.type === "library") {
290
+ return { mode: "none" };
291
+ }
292
+ return { mode: "auto" };
293
+ }
294
+ async writeHighstateManifest(distBasePath, distPathToExportKey) {
295
+ const highstateConfig = this.getHighstateConfig(this.packageJson);
1211
296
  const promises = [];
1212
- for (const distPath of distPaths) {
297
+ for (const [distPath, exportKey] of distPathToExportKey) {
1213
298
  const fullPath = resolve(distPath);
1214
- promises.push(
1215
- this.getFileHash(fullPath).then((hash) => ({
1216
- distPath,
1217
- hash
1218
- }))
1219
- );
299
+ const sourceHashConfig = this.getSourceHashConfig(highstateConfig, exportKey);
300
+ switch (sourceHashConfig.mode) {
301
+ case "manual":
302
+ promises.push(
303
+ Promise.resolve({
304
+ distPath,
305
+ hash: this.hashString(sourceHashConfig.version)
306
+ })
307
+ );
308
+ break;
309
+ case "version":
310
+ promises.push(
311
+ Promise.resolve({
312
+ distPath,
313
+ hash: this.hashString(this.packageJson.version ?? "")
314
+ })
315
+ );
316
+ break;
317
+ case "none":
318
+ promises.push(
319
+ Promise.resolve({
320
+ distPath,
321
+ hash: 0
322
+ })
323
+ );
324
+ break;
325
+ case "auto":
326
+ default:
327
+ promises.push(
328
+ this.getFileHash(fullPath).then((hash) => ({
329
+ distPath,
330
+ hash
331
+ }))
332
+ );
333
+ break;
334
+ }
1220
335
  }
1221
336
  const manifest = {
1222
337
  sourceHashes: {}
@@ -1241,10 +356,10 @@ var SourceHashCalculator = class {
1241
356
  const content = await readFile2(fullPath, "utf8");
1242
357
  const fileDeps = this.parseDependencies(fullPath, content);
1243
358
  const hashes = await Promise.all([
1244
- sha256(content),
359
+ this.hashString(content),
1245
360
  ...fileDeps.map((dep) => this.getDependencyHash(dep))
1246
361
  ]);
1247
- return await sha256(hashes.join(""));
362
+ return crc32(Buffer.concat(hashes.map(int32ToBytes)));
1248
363
  }
1249
364
  getDependencyHash(dependency) {
1250
365
  const existingHash = this.dependencyHashes.get(dependency.id);
@@ -1293,7 +408,7 @@ var SourceHashCalculator = class {
1293
408
  let manifest;
1294
409
  try {
1295
410
  const manifestContent = await readFile2(highstateManifestPath, "utf8");
1296
- manifest = JSON.parse(manifestContent);
411
+ manifest = highstateManifestSchema.parse(JSON.parse(manifestContent));
1297
412
  } catch (error) {
1298
413
  this.logger.debug(
1299
414
  { error },
@@ -1307,7 +422,7 @@ var SourceHashCalculator = class {
1307
422
  return sourceHash;
1308
423
  }
1309
424
  this.logger.debug(`using package version as a fallback hash for "%s"`, packageName);
1310
- return depPackageJson.version ?? "0.0.0";
425
+ return this.hashString(depPackageJson.version ?? "0.0.0");
1311
426
  }
1312
427
  }
1313
428
  }
@@ -1392,10 +507,10 @@ var DesignerCommand = class extends Command {
1392
507
  const port = await getPort();
1393
508
  process.env.NITRO_PORT = port.toString();
1394
509
  process.env.NITRO_HOST = "0.0.0.0";
1395
- await new Promise((resolve2) => {
510
+ await new Promise((resolve3) => {
1396
511
  console.log = (message) => {
1397
512
  if (message.startsWith("Listening on")) {
1398
- resolve2();
513
+ resolve3();
1399
514
  }
1400
515
  };
1401
516
  const path = "@highstate/designer/.output/server/index.mjs";
@@ -1421,10 +536,13 @@ var DesignerCommand = class extends Command {
1421
536
  };
1422
537
 
1423
538
  // src/commands/build.ts
539
+ import { resolve as resolve2 } from "node:path";
540
+ import { writeFile as writeFile2 } from "node:fs/promises";
1424
541
  import { Command as Command2, Option } from "clipanion";
1425
542
  import { readPackageJSON as readPackageJSON3, resolvePackageJSON as resolvePackageJSON2 } from "pkg-types";
1426
543
  import { mapKeys, mapValues, pipe } from "remeda";
1427
544
  import { build } from "tsup";
545
+ import { encode } from "@msgpack/msgpack";
1428
546
  var BuildCommand = class extends Command2 {
1429
547
  static paths = [["build"]];
1430
548
  static usage = Command2.Usage({
@@ -1434,8 +552,16 @@ var BuildCommand = class extends Command2 {
1434
552
  watch = Option.Boolean("--watch", false);
1435
553
  library = Option.Boolean("--library", false);
1436
554
  silent = Option.Boolean("--silent", true);
555
+ noSourceHash = Option.Boolean("--no-source-hash", false);
1437
556
  async execute() {
1438
557
  const packageJson = await readPackageJSON3();
558
+ const highstateConfig = highstateConfigSchema.parse(packageJson.highstate ?? {});
559
+ if (highstateConfig.type === "library") {
560
+ this.library = true;
561
+ }
562
+ if (highstateConfig.type === "worker") {
563
+ this.noSourceHash = true;
564
+ }
1439
565
  const exports = packageJson.exports;
1440
566
  let bin = packageJson.bin;
1441
567
  if (!packageJson.name) {
@@ -1486,7 +612,8 @@ var BuildCommand = class extends Command2 {
1486
612
  entryPoint: `./src/${targetName}.ts`,
1487
613
  targetName,
1488
614
  distPath,
1489
- isBin
615
+ isBin,
616
+ key
1490
617
  };
1491
618
  }),
1492
619
  mapKeys((_, value) => value.targetName)
@@ -1506,22 +633,55 @@ var BuildCommand = class extends Command2 {
1506
633
  sourcemap: true,
1507
634
  clean: true,
1508
635
  format: "esm",
1509
- target: "esnext",
636
+ target: "es2024",
637
+ platform: "node",
1510
638
  external: ["@pulumi/pulumi"],
1511
639
  esbuildPlugins,
640
+ treeshake: true,
1512
641
  silent: this.silent || ["warn", "error", "fatal"].includes(logger.level)
1513
642
  });
1514
643
  const packageJsonPath = await resolvePackageJSON2();
1515
644
  const upToDatePackageJson = await readPackageJSON3();
1516
- if (!this.library) {
645
+ if (!this.noSourceHash) {
1517
646
  const sourceHashCalculator = new SourceHashCalculator(
1518
647
  packageJsonPath,
1519
648
  upToDatePackageJson,
1520
649
  logger
1521
650
  );
1522
- const distPaths = Object.values(entry).map((value) => value.distPath);
1523
- await sourceHashCalculator.writeHighstateManifest("./dist", distPaths);
651
+ const distPathToExportKey = /* @__PURE__ */ new Map();
652
+ for (const value of Object.values(entry)) {
653
+ distPathToExportKey.set(value.distPath, value.key);
654
+ }
655
+ await sourceHashCalculator.writeHighstateManifest("./dist", distPathToExportKey);
656
+ }
657
+ if (this.library) {
658
+ const { loadLibrary } = await import("./library-loader-CGEPTS4L.js");
659
+ const fullModulePaths = Object.values(entry).map((value) => resolve2(value.distPath));
660
+ logger.info("evaluating library components from modules: %s", fullModulePaths.join(", "));
661
+ const library = await loadLibrary(logger, fullModulePaths);
662
+ const libraryPath = resolve2("./dist", "highstate.library.msgpack");
663
+ await writeFile2(libraryPath, encode(library), "utf8");
1524
664
  }
665
+ logger.info("build completed successfully");
666
+ }
667
+ };
668
+
669
+ // src/commands/backend/identity.ts
670
+ import { Command as Command3 } from "clipanion";
671
+ import { identityToRecipient } from "age-encryption";
672
+ var BackendIdentityCommand = class extends Command3 {
673
+ static paths = [["backend", "identity"]];
674
+ static usage = Command3.Usage({
675
+ category: "Backend",
676
+ description: "Ensures the backend identity is set up and returns the recipient."
677
+ });
678
+ async execute() {
679
+ const backendLogger = logger.child({}, { msgPrefix: "[backend] " });
680
+ const { getOrCreateBackendIdentity } = await import("@highstate/backend");
681
+ const backendIdentity = await getOrCreateBackendIdentity(backendLogger);
682
+ const recipient = await identityToRecipient(backendIdentity);
683
+ logger.info(`stored backend identity is: ${recipient}`);
684
+ logger.info(`run "highstate backend unlock-method add ${recipient}" on other authorized device`);
1525
685
  }
1526
686
  };
1527
687
 
@@ -1533,6 +693,7 @@ var cli = new Cli({
1533
693
  });
1534
694
  cli.register(BuildCommand);
1535
695
  cli.register(DesignerCommand);
696
+ cli.register(BackendIdentityCommand);
1536
697
  cli.register(Builtins.HelpCommand);
1537
698
  cli.register(Builtins.VersionCommand);
1538
699
  await cli.runExit(process.argv.slice(2));