@hyperscale0/hsx 1.0.0-rc.1 → 1.0.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 (88) hide show
  1. package/CHANGELOG.md +18 -1
  2. package/README.md +4 -2
  3. package/bin/hsx.ts +2 -0
  4. package/dist/bin/hsx.js +2 -0
  5. package/dist/bin/hsx.js.map +1 -1
  6. package/dist/src/ast.d.ts +6 -0
  7. package/dist/src/ast.d.ts.map +1 -1
  8. package/dist/src/ast.js +24 -0
  9. package/dist/src/ast.js.map +1 -1
  10. package/dist/src/cli.d.ts +3 -1
  11. package/dist/src/cli.d.ts.map +1 -1
  12. package/dist/src/cli.js +25 -5
  13. package/dist/src/cli.js.map +1 -1
  14. package/dist/src/compile.d.ts +1 -3
  15. package/dist/src/compile.d.ts.map +1 -1
  16. package/dist/src/compile.js +1 -2
  17. package/dist/src/compile.js.map +1 -1
  18. package/dist/src/emit.d.ts +1 -2
  19. package/dist/src/emit.d.ts.map +1 -1
  20. package/dist/src/emit.js +1 -223
  21. package/dist/src/emit.js.map +1 -1
  22. package/dist/src/index.d.ts +2 -1
  23. package/dist/src/index.d.ts.map +1 -1
  24. package/dist/src/index.js +2 -0
  25. package/dist/src/index.js.map +1 -1
  26. package/dist/src/lsp/server.d.ts +32 -0
  27. package/dist/src/lsp/server.d.ts.map +1 -0
  28. package/dist/src/lsp/server.js +391 -0
  29. package/dist/src/lsp/server.js.map +1 -0
  30. package/dist/src/modules.d.ts +2 -0
  31. package/dist/src/modules.d.ts.map +1 -1
  32. package/dist/src/modules.js +7 -11
  33. package/dist/src/modules.js.map +1 -1
  34. package/dist/src/std-bundle.d.ts +2 -0
  35. package/dist/src/std-bundle.d.ts.map +1 -0
  36. package/dist/src/std-bundle.js +88 -0
  37. package/dist/src/std-bundle.js.map +1 -0
  38. package/dist/src/std-library.d.ts +5 -0
  39. package/dist/src/std-library.d.ts.map +1 -0
  40. package/dist/src/std-library.js +9 -0
  41. package/dist/src/std-library.js.map +1 -0
  42. package/dist/src/version.d.ts +1 -1
  43. package/dist/src/version.d.ts.map +1 -1
  44. package/dist/src/version.js +1 -1
  45. package/dist/src/version.js.map +1 -1
  46. package/docs/README.md +3 -0
  47. package/docs/guide/01-first-program.md +1 -1
  48. package/docs/llms-full.txt +7 -6
  49. package/docs/llms.txt +2 -2
  50. package/docs/playground.md +54 -0
  51. package/docs/reference/cli.md +5 -3
  52. package/docs/reference/diagnostics.md +1 -1
  53. package/docs/reference/grammar.md +1 -1
  54. package/docs/reference/std/advance.md +1 -1
  55. package/docs/reference/std/cancellable_booking.md +1 -1
  56. package/docs/reference/std/captured_payment.md +1 -1
  57. package/docs/reference/std/conditional_disbursement.md +1 -1
  58. package/docs/reference/std/credit_facility.md +1 -1
  59. package/docs/reference/std/held_payment.md +1 -1
  60. package/docs/reference/std/instant_transfer.md +1 -1
  61. package/docs/reference/std/metered.md +1 -1
  62. package/docs/reference/std/pooled_split.md +1 -1
  63. package/docs/reference/std/premium_forward.md +1 -1
  64. package/docs/reference/std/reconciled_payout.md +1 -1
  65. package/docs/reference/std/recurring_collection.md +1 -1
  66. package/docs/reference/std/rotating_pool.md +1 -1
  67. package/docs/reference/std/scheduled.md +1 -1
  68. package/docs/reference/std/security_deposit.md +1 -1
  69. package/docs/reference/std/settlement_batch.md +1 -1
  70. package/docs/reference/std/swap.md +1 -1
  71. package/docs/reference/std/threshold_pool.md +1 -1
  72. package/docs/reference/std/weighted_distribution.md +1 -1
  73. package/docs/reference/types.md +1 -1
  74. package/docs/reference/udl-output.md +2 -3
  75. package/examples/02-imports-and-archetypes/README.md +1 -4
  76. package/examples/04-complete-product/README.md +0 -3
  77. package/package.json +11 -3
  78. package/skills/hsx/SKILL.md +1 -1
  79. package/src/ast.ts +30 -0
  80. package/src/cli.ts +28 -9
  81. package/src/compile.ts +1 -4
  82. package/src/emit.ts +2 -248
  83. package/src/index.ts +8 -6
  84. package/src/lsp/server.ts +460 -0
  85. package/src/modules.ts +12 -10
  86. package/src/std-bundle.ts +91 -0
  87. package/src/std-library.ts +12 -0
  88. package/src/version.ts +1 -1
package/src/emit.ts CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  type UdlDocument,
5
5
  type UdlIssueCode,
6
6
  } from "@hyperscale0/udl";
7
- import type { JsonValue, TypedInstrument, TypedProgram } from "./ir.ts";
7
+ import type { TypedInstrument, TypedProgram } from "./ir.ts";
8
8
 
9
9
  export interface OriginMapEntry {
10
10
  readonly path: string;
@@ -27,7 +27,6 @@ export type GeneralLowerResult =
27
27
  readonly value: {
28
28
  readonly canonicalUdl: string;
29
29
  readonly document: UdlDocument;
30
- readonly frame: Record<string, JsonValue>;
31
30
  readonly originMap: readonly OriginMapEntry[];
32
31
  };
33
32
  };
@@ -58,11 +57,7 @@ export function lowerGeneralProgram(program: TypedProgram): GeneralLowerResult {
58
57
  udl: 1,
59
58
  version: 1,
60
59
  };
61
- const frame = frameFor(program);
62
- const unresolved = [
63
- ...unresolvedCompilerMarkers(candidate),
64
- ...unresolvedCompilerMarkers(frame, "$.frame"),
65
- ];
60
+ const unresolved = unresolvedCompilerMarkers(candidate);
66
61
  if (unresolved.length > 0) {
67
62
  const origins = originMapFor(program);
68
63
  return {
@@ -101,7 +96,6 @@ export function lowerGeneralProgram(program: TypedProgram): GeneralLowerResult {
101
96
  value: {
102
97
  canonicalUdl: serializeUdl(document),
103
98
  document,
104
- frame,
105
99
  originMap: originMapFor(program),
106
100
  },
107
101
  };
@@ -182,240 +176,6 @@ export function requiredFields(instrument: TypedInstrument): string[] {
182
176
  ];
183
177
  }
184
178
 
185
- function frameFor(program: TypedProgram): Record<string, JsonValue> {
186
- const actors = new Map<string, Record<string, JsonValue>>();
187
- const moneyEvents: Record<string, JsonValue>[] = [];
188
- const design: string[] = [];
189
- const fees: Record<string, JsonValue>[] = [];
190
- const mechanics = new Set<string>();
191
- const eventKeys = new Set<string>();
192
- const ensureActor = (rawKey: string, role: string): string => {
193
- const key = frameKey(rawKey);
194
- if (!actors.has(key)) {
195
- actors.set(key, {
196
- key,
197
- label: titleize(key),
198
- maxCount: 1,
199
- minCount: 1,
200
- role,
201
- });
202
- }
203
- return key;
204
- };
205
- const uniqueEventKey = (raw: string): string => {
206
- const base = frameKey(raw);
207
- let key = base;
208
- let ordinal = 2;
209
- while (eventKeys.has(key)) {
210
- const suffix = `_${ordinal}`;
211
- key = `${base.slice(0, 40 - suffix.length)}${suffix}`;
212
- ordinal += 1;
213
- }
214
- eventKeys.add(key);
215
- return key;
216
- };
217
- for (const instrument of program.instruments) {
218
- const actorByField = new Map<string, string>();
219
- const parties = instrument.slots.parties;
220
- if (parties && typeof parties === "object" && !Array.isArray(parties)) {
221
- for (const [role, value] of Object.entries(parties)) {
222
- if (typeof value !== "string") continue;
223
- const actor = ensureActor(role, frameActorRole(role, "source"));
224
- actorByField.set(value, actor);
225
- }
226
- }
227
- for (const action of instrument.actions) {
228
- if (action.slots.due) mechanics.add("recurring_billing");
229
- const moves = action.slots.moves;
230
- if (!Array.isArray(moves)) continue;
231
- moves.forEach((move, index) => {
232
- if (moneyEvents.length >= 20) return;
233
- if (!move || typeof move !== "object" || Array.isArray(move)) return;
234
- const bind =
235
- move.bind &&
236
- typeof move.bind === "object" &&
237
- !Array.isArray(move.bind)
238
- ? move.bind
239
- : {};
240
- const source = frameActorForBinding(
241
- bind.sourceAccountId,
242
- actorByField,
243
- "source",
244
- ensureActor,
245
- );
246
- const destination = frameActorForBinding(
247
- bind.destinationAccountId,
248
- actorByField,
249
- "destination",
250
- ensureActor,
251
- );
252
- const operation =
253
- typeof move.operation === "string" ? move.operation : "transfer";
254
- if (source === "escrow" || destination === "escrow") {
255
- mechanics.add("escrow");
256
- }
257
- moneyEvents.push({
258
- allocationTotalBps: 0,
259
- amount: bindingWords(bind.amount) || "the declared amount",
260
- amountDependencies: [],
261
- amountMode: "fixed",
262
- amountSchedule: [],
263
- distribution: "single",
264
- fromActor: source,
265
- key: uniqueEventKey(
266
- typeof move.key === "string"
267
- ? move.key
268
- : `${instrument.id}_${action.name}_${index + 1}`,
269
- ),
270
- kind: frameEventKind(operation, source, destination),
271
- label: `${titleize(action.name)} movement`,
272
- occurrence: action.slots.due ? "repeatable" : "once",
273
- timing: action.name === "create" ? "on_create" : "on_lifecycle",
274
- toActor: destination,
275
- trigger: `when ${action.name.replaceAll("_", " ")} runs`,
276
- });
277
- });
278
- }
279
- if (design.length < 10) {
280
- design.push(
281
- `${instrument.id}: ${instrument.fields.length} fields and ${instrument.actions.length} actions`,
282
- );
283
- }
284
- const feeRules = instrument.slots.feeRules;
285
- if (Array.isArray(feeRules)) {
286
- feeRules.forEach((fee, index) => {
287
- if (fees.length >= 4) return;
288
- if (!fee || typeof fee !== "object" || Array.isArray(fee)) return;
289
- fees.push({
290
- label: `${titleize(instrument.id)} fee ${index + 1}`,
291
- on:
292
- typeof fee.baseField === "string"
293
- ? fee.baseField
294
- : `${instrument.id} movement`,
295
- structure:
296
- typeof fee.position === "string"
297
- ? `${fee.position.replaceAll("_", " ")} fee`
298
- : "declared fee",
299
- });
300
- });
301
- }
302
- }
303
- if (actors.size === 0) ensureActor("platform", "platform");
304
- if (moneyEvents.length === 0) {
305
- const actor = actors.keys().next().value ?? "platform";
306
- moneyEvents.push({
307
- allocationTotalBps: 0,
308
- amount: "the declared settlement amount",
309
- amountDependencies: [],
310
- amountMode: "fixed",
311
- amountSchedule: [],
312
- distribution: "single",
313
- fromActor: actor,
314
- key: uniqueEventKey(`${program.name}_create`),
315
- kind: "charge",
316
- label: `${program.title} movement`,
317
- occurrence: "once",
318
- timing: "on_create",
319
- toActor: actor,
320
- trigger: "when the settlement is created",
321
- });
322
- }
323
- if (mechanics.size === 0) mechanics.add("escrow");
324
- return {
325
- actors: [...actors.values()],
326
- confidence: "high",
327
- conservationGroups: [],
328
- design,
329
- feePolicy: fees.length > 0 ? "defined" : "none",
330
- fees,
331
- headline: program.title,
332
- mechanics: [...mechanics],
333
- moneyEvents,
334
- offPlatform: [],
335
- openQuestions: [],
336
- rules: [],
337
- subjects: program.subjects.map((subject) => ({
338
- kind: subject.kind,
339
- title: subject.title,
340
- })),
341
- summary: `${program.title} compiles ${program.instruments.length} financial instrument${program.instruments.length === 1 ? "" : "s"}.`,
342
- };
343
- }
344
-
345
- function frameActorForBinding(
346
- value: JsonValue | undefined,
347
- actorByField: ReadonlyMap<string, string>,
348
- direction: "destination" | "source",
349
- ensureActor: (key: string, role: string) => string,
350
- ): string {
351
- const path = bindingWords(value);
352
- if (path.includes("escrowAccountId")) return "escrow";
353
- const field = path.startsWith("fields.")
354
- ? path.slice("fields.".length)
355
- : path;
356
- const declared = actorByField.get(field);
357
- if (declared) return declared;
358
- if (field.toLowerCase().includes("platform")) {
359
- return ensureActor("platform", "platform");
360
- }
361
- return ensureActor(
362
- direction === "source" ? "payer" : "beneficiary",
363
- direction === "source" ? "payer" : "beneficiary",
364
- );
365
- }
366
-
367
- function frameActorRole(
368
- role: string,
369
- direction: "destination" | "source",
370
- ): string {
371
- return [
372
- "payer",
373
- "beneficiary",
374
- "platform",
375
- "provider",
376
- "guardian",
377
- "holder",
378
- ].includes(role)
379
- ? role
380
- : direction === "source"
381
- ? "payer"
382
- : "beneficiary";
383
- }
384
-
385
- function frameEventKind(
386
- operation: string,
387
- source: string,
388
- destination: string,
389
- ): string {
390
- if (operation.endsWith(".reserve")) return "hold";
391
- if (operation.endsWith(".void") || operation.endsWith(".return")) {
392
- return "refund";
393
- }
394
- if (operation.startsWith("payout.")) return "payout";
395
- if (source === "escrow" || destination === "escrow") return "release";
396
- return "charge";
397
- }
398
-
399
- function frameKey(value: string): string {
400
- const snake = value
401
- .replace(/([a-z0-9])([A-Z])/g, "$1_$2")
402
- .replace(/[^A-Za-z0-9]+/g, "_")
403
- .replace(/^_+|_+$/g, "")
404
- .toLowerCase();
405
- const leading = /^[a-z]/.test(snake) ? snake : `event_${snake}`;
406
- return leading.slice(0, 40) || "event";
407
- }
408
-
409
- function bindingWords(value: JsonValue | undefined): string {
410
- if (typeof value === "string") return value;
411
- if (!value || typeof value !== "object" || Array.isArray(value)) return "";
412
- const binding = value as Readonly<Record<string, JsonValue>>;
413
- if (binding.from === "const" && typeof binding.value === "string")
414
- return binding.value;
415
- if (typeof binding.path === "string") return binding.path;
416
- return "";
417
- }
418
-
419
179
  function originMapFor(program: TypedProgram): OriginMapEntry[] {
420
180
  const entries: OriginMapEntry[] = [{ path: "$", span: program.origin }];
421
181
  program.subjects.forEach((subject, index) => {
@@ -439,9 +199,3 @@ function originMapFor(program: TypedProgram): OriginMapEntry[] {
439
199
  });
440
200
  return entries;
441
201
  }
442
-
443
- function titleize(value: string): string {
444
- return value
445
- .replaceAll("_", " ")
446
- .replace(/\b[a-z]/g, (letter) => letter.toUpperCase());
447
- }
package/src/index.ts CHANGED
@@ -30,10 +30,12 @@ export { type OriginMapEntry } from "./emit.ts";
30
30
  export { lowerGeneralProgram } from "./emit.ts";
31
31
  export { parseProgram } from "./parse.ts";
32
32
  export { checkGeneralProgram, type GeneralCheckOptions } from "./typecheck.ts";
33
- export type {
34
- BlockExpr,
35
- ExposeDecl,
36
- Program,
37
- ProgramDecl,
38
- UseDecl,
33
+ export {
34
+ byteOffsetToCodeUnit,
35
+ type BlockExpr,
36
+ type ExposeDecl,
37
+ type Program,
38
+ type ProgramDecl,
39
+ type UseDecl,
39
40
  } from "./ast.ts";
41
+ export { bundledStandardLibrary, type StandardLibrary } from "./std-library.ts";