@intentius/chant 0.18.16 → 0.18.18

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 (30) hide show
  1. package/dist/cli/commands/init-lexicon/templates/lint.d.ts.map +1 -1
  2. package/dist/cli/commands/init-lexicon/templates/project.d.ts +8 -0
  3. package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
  4. package/dist/cli/commands/init-lexicon/templates/spec.d.ts.map +1 -1
  5. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  6. package/dist/components/verbs/cloud-executor.d.ts.map +1 -1
  7. package/dist/components/verbs/wait-verify.d.ts +2 -0
  8. package/dist/components/verbs/wait-verify.d.ts.map +1 -1
  9. package/dist/stack-output.d.ts +6 -3
  10. package/dist/stack-output.d.ts.map +1 -1
  11. package/dist/yaml.d.ts.map +1 -1
  12. package/package.json +1 -1
  13. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +4 -4
  14. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/generate.ts +2 -2
  15. package/src/cli/commands/__fixtures__/init-lexicon-output/src/lint/rules/index.ts +6 -0
  16. package/src/cli/commands/__fixtures__/init-lexicon-output/src/spec/fetch.ts +8 -7
  17. package/src/cli/commands/__fixtures__/init-lexicon-output/src/validate-cli.ts +2 -1
  18. package/src/cli/commands/__fixtures__/init-lexicon-output/tsconfig.build.json +27 -0
  19. package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +2 -2
  20. package/src/cli/commands/init-lexicon/templates/codegen.ts +2 -2
  21. package/src/cli/commands/init-lexicon/templates/lint.ts +7 -1
  22. package/src/cli/commands/init-lexicon/templates/project.ts +36 -5
  23. package/src/cli/commands/init-lexicon/templates/spec.ts +8 -7
  24. package/src/cli/commands/init-lexicon.test.ts +33 -0
  25. package/src/cli/commands/init-lexicon.ts +2 -1
  26. package/src/components/verbs/cloud-executor.ts +6 -1
  27. package/src/components/verbs/wait-verify.ts +11 -2
  28. package/src/stack-output.ts +27 -5
  29. package/src/yaml.test.ts +33 -0
  30. package/src/yaml.ts +106 -4
@@ -1 +1 @@
1
- {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/init-lexicon/templates/lint.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAoB1E;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CAGjD"}
1
+ {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/init-lexicon/templates/lint.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAoB1E;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CASjD"}
@@ -5,6 +5,14 @@ export declare function generatePackageJson(name: string, names: {
5
5
  packageName: string;
6
6
  }): string;
7
7
  export declare function generateTsConfig(): string;
8
+ /**
9
+ * Build config used by `npm run build` (and CI's `tsc --noEmit`). Uses `bundler`
10
+ * resolution + the `development` condition so `@intentius/chant/*` resolves to the
11
+ * workspace source, and excludes tests/docs — the same setup the shipped lexicons
12
+ * use. (The plain `tsconfig.json` extends the monorepo root and can't be tsc'd on
13
+ * its own.)
14
+ */
15
+ export declare function generateTsConfigBuild(): string;
8
16
  export declare function generateJustfile(name: string): string;
9
17
  export declare function generateGitignore(): string;
10
18
  export declare function generateReadme(name: string, names: {
@@ -1 +1 @@
1
- {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/init-lexicon/templates/project.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CA6BxF;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAWzC;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA4BrD;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAK1C;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CA4BnF;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CA0BnH;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA8BvD;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAM9C"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/init-lexicon/templates/project.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CA+BxF;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAWzC;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAmB9C;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA4BrD;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAK1C;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CA4BnF;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CA0BnH;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA8BvD;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAO9C"}
@@ -1 +1 @@
1
- {"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/init-lexicon/templates/spec.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wBAAgB,mBAAmB,IAAI,MAAM,CAuB5C;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CA2B5C"}
1
+ {"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/init-lexicon/templates/spec.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wBAAgB,mBAAmB,IAAI,MAAM,CAwB5C;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CA2B5C"}
@@ -1 +1 @@
1
- {"version":3,"file":"init-lexicon.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init-lexicon.ts"],"names":[],"mappings":"AAeA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAQD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM;;;;;EAQvC;AAqBD;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAoHhG;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBrF"}
1
+ {"version":3,"file":"init-lexicon.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init-lexicon.ts"],"names":[],"mappings":"AAeA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAQD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM;;;;;EAQvC;AAqBD;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAqHhG;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBrF"}
@@ -1 +1 @@
1
- {"version":3,"file":"cloud-executor.d.ts","sourceRoot":"","sources":["../../../src/components/verbs/cloud-executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAI1C,eAAO,MAAM,aAAa,2BAAkB,CAAC;AAI7C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gGAAgG;IAChG,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,kFAAkF;IAClF,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1D,uDAAuD;IACvD,IAAI,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,4FAA4F;IAC5F,IAAI,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,yEAAyE;IACzE,GAAG,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,uFAAuF;IACvF,IAAI,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,mGAAmG;IACnG,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C;AAID,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,KAAK,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/E;AAID,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,kBAAkB,CAAC;CAC3B;AAcD,eAAO,MAAM,UAAU,EAAE,YA+BxB,CAAC;AA6BF,wHAAwH;AACxH,wBAAgB,iBAAiB,IAAI,aAAa,CAEjD;AAKD,+FAA+F;AAC/F,wBAAgB,oBAAoB,IAAI,aAAa,CAGpD;AAED,sFAAsF;AACtF,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C"}
1
+ {"version":3,"file":"cloud-executor.d.ts","sourceRoot":"","sources":["../../../src/components/verbs/cloud-executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAK1C,eAAO,MAAM,aAAa,2BAAkB,CAAC;AAI7C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gGAAgG;IAChG,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,kFAAkF;IAClF,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1D,uDAAuD;IACvD,IAAI,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,4FAA4F;IAC5F,IAAI,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,yEAAyE;IACzE,GAAG,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,uFAAuF;IACvF,IAAI,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,mGAAmG;IACnG,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C;AAID,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,KAAK,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/E;AAID,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,kBAAkB,CAAC;CAC3B;AAcD,eAAO,MAAM,UAAU,EAAE,YAmCxB,CAAC;AA6BF,wHAAwH;AACxH,wBAAgB,iBAAiB,IAAI,aAAa,CAEjD;AAKD,+FAA+F;AAC/F,wBAAgB,oBAAoB,IAAI,aAAa,CAGpD;AAED,sFAAsF;AACtF,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C"}
@@ -68,6 +68,8 @@ export declare const waitEndpointCapability: Capability<WaitEndpointInput, WaitE
68
68
  export interface HealthGateInput {
69
69
  /** Health check path or full URL. */
70
70
  path: string;
71
+ /** Optional base URL (scheme + host) composed with `path` via `new URL(path, host)`. May be a cross-stack Wiring value; a bare host gets `http://` prepended. */
72
+ host?: string;
71
73
  /** Number of consecutive successes required. Default: 1. */
72
74
  consecutiveSuccesses?: number;
73
75
  /** Poll interval in ms. Default: 5000. */
@@ -1 +1 @@
1
- {"version":3,"file":"wait-verify.d.ts","sourceRoot":"","sources":["../../../src/components/verbs/wait-verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEnF,yGAAyG;AACzG,KAAK,OAAO,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAKzE,MAAM,WAAW,uBAAuB;IACtC;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uGAAuG;IACvG,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,0CAA0C;IAC1C,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,kCAAkC,CAChD,QAAQ,GAAE,aAAsC,GAC/C,UAAU,CAAC,uBAAuB,EAAE,wBAAwB,CAAC,CAoB/D;AAED,qFAAqF;AACrF,eAAO,MAAM,4BAA4B,EAAE,UAAU,CAAC,uBAAuB,EAAE,wBAAwB,CACjE,CAAC;AAIvC,MAAM,WAAW,iBAAiB;IAChC,mBAAmB;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,0FAA0F;AAC1F,wBAAgB,4BAA4B,CAAC,OAAO,GAAE,OAAwB,GAAG,UAAU,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAsBjI;AAED,wEAAwE;AACxE,eAAO,MAAM,sBAAsB,EAAE,UAAU,CAAC,iBAAiB,EAAE,kBAAkB,CAAkC,CAAC;AAIxH,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,iHAAiH;AACjH,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,OAAwB,GAAG,UAAU,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAyB3H;AAED,sEAAsE;AACtE,eAAO,MAAM,oBAAoB,EAAE,UAAU,CAAC,eAAe,EAAE,gBAAgB,CAAgC,CAAC"}
1
+ {"version":3,"file":"wait-verify.d.ts","sourceRoot":"","sources":["../../../src/components/verbs/wait-verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEnF,yGAAyG;AACzG,KAAK,OAAO,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAKzE,MAAM,WAAW,uBAAuB;IACtC;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uGAAuG;IACvG,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,0CAA0C;IAC1C,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,kCAAkC,CAChD,QAAQ,GAAE,aAAsC,GAC/C,UAAU,CAAC,uBAAuB,EAAE,wBAAwB,CAAC,CAoB/D;AAED,qFAAqF;AACrF,eAAO,MAAM,4BAA4B,EAAE,UAAU,CAAC,uBAAuB,EAAE,wBAAwB,CACjE,CAAC;AAIvC,MAAM,WAAW,iBAAiB;IAChC,mBAAmB;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,0FAA0F;AAC1F,wBAAgB,4BAA4B,CAAC,OAAO,GAAE,OAAwB,GAAG,UAAU,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAsBjI;AAED,wEAAwE;AACxE,eAAO,MAAM,sBAAsB,EAAE,UAAU,CAAC,iBAAiB,EAAE,kBAAkB,CAAkC,CAAC;AAIxH,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,iKAAiK;IACjK,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;CAClB;AASD,iHAAiH;AACjH,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,OAAwB,GAAG,UAAU,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAyB3H;AAED,sEAAsE;AACtE,eAAO,MAAM,oBAAoB,EAAE,UAAU,CAAC,eAAe,EAAE,gBAAgB,CAAgC,CAAC"}
@@ -6,7 +6,8 @@
6
6
  * it via `nestedStack().outputs.name`.
7
7
  */
8
8
  import { DECLARABLE_MARKER, type Declarable } from "./declarable.js";
9
- import type { AttrRef } from "./attrref.js";
9
+ import { AttrRef } from "./attrref.js";
10
+ import { type Intrinsic } from "./intrinsic.js";
10
11
  /**
11
12
  * Marker symbol for stack output identification.
12
13
  */
@@ -21,7 +22,9 @@ export interface StackOutput extends Declarable {
21
22
  readonly lexicon: string;
22
23
  readonly entityType: string;
23
24
  readonly kind: "output";
24
- readonly sourceRef: AttrRef;
25
+ /** The exported value: a bare attribute reference, or an intrinsic wrapping
26
+ * one (e.g. `Join(",", zone.NameServers)`). */
27
+ readonly sourceRef: AttrRef | Intrinsic;
25
28
  readonly description?: string;
26
29
  }
27
30
  /**
@@ -46,7 +49,7 @@ export declare function isStackOutput(value: unknown): value is StackOutput;
46
49
  * });
47
50
  * ```
48
51
  */
49
- export declare function stackOutput(ref: AttrRef, options?: {
52
+ export declare function stackOutput(ref: AttrRef | Intrinsic, options?: {
50
53
  description?: string;
51
54
  }): StackOutput;
52
55
  //# sourceMappingURL=stack-output.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stack-output.d.ts","sourceRoot":"","sources":["../src/stack-output.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC;;GAEG;AACH,eAAO,MAAM,mBAAmB,eAAkC,CAAC;AAEnE;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,QAAQ,CAAC,CAAC,mBAAmB,CAAC,EAAE,IAAI,CAAC;IACrC,QAAQ,CAAC,CAAC,iBAAiB,CAAC,EAAE,IAAI,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAOlE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACjC,WAAW,CAkBb"}
1
+ {"version":3,"file":"stack-output.d.ts","sourceRoot":"","sources":["../src/stack-output.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE1D;;GAEG;AACH,eAAO,MAAM,mBAAmB,eAAkC,CAAC;AAEnE;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,QAAQ,CAAC,CAAC,mBAAmB,CAAC,EAAE,IAAI,CAAC;IACrC,QAAQ,CAAC,CAAC,iBAAiB,CAAC,EAAE,IAAI,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB;mDAC+C;IAC/C,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAgBD;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAOlE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,GAAG,SAAS,EACxB,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACjC,WAAW,CAuBb"}
@@ -1 +1 @@
1
- {"version":3,"file":"yaml.d.ts","sourceRoot":"","sources":["../src/yaml.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CA2G/D;AAMD,sCAAsC;AACtC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASlE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,WAAW,CAuEb;AAsDD;;GAEG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,WAAW,CAkEb;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAelD"}
1
+ {"version":3,"file":"yaml.d.ts","sourceRoot":"","sources":["../src/yaml.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CA2G/D;AAMD,sCAAsC;AACtC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASlE;AAiFD;;GAEG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,WAAW,CA8Eb;AA+DD;;GAEG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,WAAW,CAyEb;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAelD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant",
3
- "version": "0.18.16",
3
+ "version": "0.18.18",
4
4
  "description": "Declarative infrastructure-as-code toolkit — TypeScript on Node.js",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://intentius.io/chant",
@@ -18,12 +18,12 @@
18
18
  "generate": "npx tsx src/codegen/generate-cli.ts",
19
19
  "validate": "npx tsx src/validate-cli.ts",
20
20
  "docs": "npx tsx src/codegen/docs-cli.ts",
21
- "prepack": "npm run generate && npm run validate"
22
- },
23
- "dependencies": {
24
- "@intentius/chant": "workspace:*"
21
+ "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
22
+ "prepack": "npm run generate && npm run validate && npm run build"
25
23
  },
26
24
  "devDependencies": {
25
+ "@intentius/chant": "*",
26
+ "tsc-alias": "^1.8.17",
27
27
  "typescript": "^5.9.3"
28
28
  }
29
29
  }
@@ -8,7 +8,7 @@ import { fileURLToPath } from "url";
8
8
  *
9
9
  * Each callback has a TODO describing what to implement.
10
10
  */
11
- export async function generate(options?: { verbose?: boolean }): Promise<GenerateResult> {
11
+ export async function generate(options?: { verbose?: boolean; force?: boolean }): Promise<GenerateResult> {
12
12
  const result = await generatePipeline({
13
13
  // Must return Map<typeName, Buffer> — each entry is one schema file.
14
14
  // Example: fetch a zip, extract JSON files, key by type name.
@@ -49,7 +49,7 @@ export async function generate(options?: { verbose?: boolean }): Promise<Generat
49
49
  generateRuntimeIndex: (results, naming) => {
50
50
  throw new Error("TODO: implement generateRuntimeIndex — produce index.ts content");
51
51
  },
52
- });
52
+ }, options);
53
53
 
54
54
  if (options?.verbose) {
55
55
  console.error(`Generated ${result.resources} resources, ${result.properties} property types`);
@@ -1 +1,7 @@
1
+ import type { LintRule } from "@intentius/chant/lint/rule";
2
+ import { sampleRule } from "./sample";
3
+
1
4
  export { sampleRule } from "./sample";
5
+
6
+ /** All lint rules provided by this lexicon (imported by plugin.ts's lintRules()). */
7
+ export const rules: LintRule[] = [sampleRule];
@@ -9,13 +9,14 @@ const CACHE_FILE = ".cache/schemas.zip";
9
9
  *
10
10
  * TODO: Point SCHEMA_URL at your real upstream schema source.
11
11
  */
12
- export async function fetchSchemas(options?: { force?: boolean }): Promise<Map<string, string>> {
13
- const zipData = await fetchWithCache({
14
- url: SCHEMA_URL,
15
- cacheFile: CACHE_FILE,
16
- force: options?.force,
17
- });
12
+ export async function fetchSchemas(options?: { force?: boolean }): Promise<Map<string, Buffer>> {
13
+ // `force` is the second argument to fetchWithCache (not a FetchConfig field).
14
+ const zipData = await fetchWithCache(
15
+ { url: SCHEMA_URL, cacheFile: CACHE_FILE },
16
+ options?.force,
17
+ );
18
18
 
19
- // TODO: Adjust the filter to match your schema file names
19
+ // TODO: Adjust the filter to match your schema file names. extractFromZip yields
20
+ // Buffers — decode with `.toString()` in parse.ts as needed.
20
21
  return extractFromZip(zipData, (name) => name.endsWith(".json"));
21
22
  }
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env tsx
2
2
  import { validate } from "./validate";
3
3
 
4
- await validate({ verbose: true });
4
+ // `validate` takes an optional { basePath }; defaults to the lexicon root.
5
+ await validate();
@@ -0,0 +1,27 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "noEmit": false,
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "outDir": "dist",
8
+ "rootDir": "src",
9
+ "paths": {},
10
+ "moduleResolution": "bundler",
11
+ "customConditions": [
12
+ "development"
13
+ ]
14
+ },
15
+ "include": [
16
+ "src/**/*"
17
+ ],
18
+ "exclude": [
19
+ "**/*.test.ts",
20
+ "node_modules",
21
+ "dist",
22
+ "docs"
23
+ ],
24
+ "tsc-alias": {
25
+ "resolveFullPaths": true
26
+ }
27
+ }
@@ -11,7 +11,7 @@ import { fileURLToPath } from "url";
11
11
  *
12
12
  * Each callback has a TODO describing what to implement.
13
13
  */
14
- export async function generate(options?: { verbose?: boolean }): Promise<GenerateResult> {
14
+ export async function generate(options?: { verbose?: boolean; force?: boolean }): Promise<GenerateResult> {
15
15
  const result = await generatePipeline({
16
16
  // Must return Map<typeName, Buffer> — each entry is one schema file.
17
17
  // Example: fetch a zip, extract JSON files, key by type name.
@@ -52,7 +52,7 @@ export async function generate(options?: { verbose?: boolean }): Promise<Generat
52
52
  generateRuntimeIndex: (results, naming) => {
53
53
  throw new Error("TODO: implement generateRuntimeIndex — produce index.ts content");
54
54
  },
55
- });
55
+ }, options);
56
56
 
57
57
  if (options?.verbose) {
58
58
  console.error(\`Generated \${result.resources} resources, \${result.properties} property types\`);
@@ -13,7 +13,7 @@ import { fileURLToPath } from "url";
13
13
  *
14
14
  * Each callback has a TODO describing what to implement.
15
15
  */
16
- export async function generate(options?: { verbose?: boolean }): Promise<GenerateResult> {
16
+ export async function generate(options?: { verbose?: boolean; force?: boolean }): Promise<GenerateResult> {
17
17
  const result = await generatePipeline({
18
18
  // Must return Map<typeName, Buffer> — each entry is one schema file.
19
19
  // Example: fetch a zip, extract JSON files, key by type name.
@@ -54,7 +54,7 @@ export async function generate(options?: { verbose?: boolean }): Promise<Generat
54
54
  generateRuntimeIndex: (results, naming) => {
55
55
  throw new Error("TODO: implement generateRuntimeIndex — produce index.ts content");
56
56
  },
57
- });
57
+ }, options);
58
58
 
59
59
  if (options?.verbose) {
60
60
  console.error(\`Generated \${result.resources} resources, \${result.properties} property types\`);
@@ -25,6 +25,12 @@ export const sampleRule: LintRule = {
25
25
  }
26
26
 
27
27
  export function generateLintRulesIndexTs(): string {
28
- return `export { sampleRule } from "./sample";
28
+ return `import type { LintRule } from "@intentius/chant/lint/rule";
29
+ import { sampleRule } from "./sample";
30
+
31
+ export { sampleRule } from "./sample";
32
+
33
+ /** All lint rules provided by this lexicon (imported by plugin.ts's lintRules()). */
34
+ export const rules: LintRule[] = [sampleRule];
29
35
  `;
30
36
  }
@@ -20,12 +20,14 @@ export function generatePackageJson(name: string, names: { packageName: string }
20
20
  generate: "npx tsx src/codegen/generate-cli.ts",
21
21
  validate: "npx tsx src/validate-cli.ts",
22
22
  docs: "npx tsx src/codegen/docs-cli.ts",
23
- prepack: "npm run generate && npm run validate",
24
- },
25
- dependencies: {
26
- "@intentius/chant": "workspace:*",
23
+ build: "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
24
+ prepack: "npm run generate && npm run validate && npm run build",
27
25
  },
28
26
  devDependencies: {
27
+ // `*` (not `workspace:*`) so a fresh lexicon `npm install`s under plain npm
28
+ // (the `workspace:` protocol is rejected outside a workspace).
29
+ "@intentius/chant": "*",
30
+ "tsc-alias": "^1.8.17",
29
31
  typescript: "^5.9.3",
30
32
  },
31
33
  };
@@ -46,6 +48,34 @@ export function generateTsConfig(): string {
46
48
  return JSON.stringify(config, null, 2) + "\n";
47
49
  }
48
50
 
51
+ /**
52
+ * Build config used by `npm run build` (and CI's `tsc --noEmit`). Uses `bundler`
53
+ * resolution + the `development` condition so `@intentius/chant/*` resolves to the
54
+ * workspace source, and excludes tests/docs — the same setup the shipped lexicons
55
+ * use. (The plain `tsconfig.json` extends the monorepo root and can't be tsc'd on
56
+ * its own.)
57
+ */
58
+ export function generateTsConfigBuild(): string {
59
+ const config = {
60
+ extends: "../../tsconfig.json",
61
+ compilerOptions: {
62
+ noEmit: false,
63
+ declaration: true,
64
+ declarationMap: true,
65
+ outDir: "dist",
66
+ rootDir: "src",
67
+ paths: {},
68
+ moduleResolution: "bundler",
69
+ customConditions: ["development"],
70
+ },
71
+ include: ["src/**/*"],
72
+ exclude: ["**/*.test.ts", "node_modules", "dist", "docs"],
73
+ "tsc-alias": { resolveFullPaths: true },
74
+ };
75
+
76
+ return JSON.stringify(config, null, 2) + "\n";
77
+ }
78
+
49
79
  export function generateJustfile(name: string): string {
50
80
  return `# Default recipe - list all available commands
51
81
  default:
@@ -177,6 +207,7 @@ export function generateValidateCliTs(): string {
177
207
  return `#!/usr/bin/env tsx
178
208
  import { validate } from "./validate";
179
209
 
180
- await validate({ verbose: true });
210
+ // \`validate\` takes an optional { basePath }; defaults to the lexicon root.
211
+ await validate();
181
212
  `;
182
213
  }
@@ -14,14 +14,15 @@ const CACHE_FILE = ".cache/schemas.zip";
14
14
  *
15
15
  * TODO: Point SCHEMA_URL at your real upstream schema source.
16
16
  */
17
- export async function fetchSchemas(options?: { force?: boolean }): Promise<Map<string, string>> {
18
- const zipData = await fetchWithCache({
19
- url: SCHEMA_URL,
20
- cacheFile: CACHE_FILE,
21
- force: options?.force,
22
- });
17
+ export async function fetchSchemas(options?: { force?: boolean }): Promise<Map<string, Buffer>> {
18
+ // \`force\` is the second argument to fetchWithCache (not a FetchConfig field).
19
+ const zipData = await fetchWithCache(
20
+ { url: SCHEMA_URL, cacheFile: CACHE_FILE },
21
+ options?.force,
22
+ );
23
23
 
24
- // TODO: Adjust the filter to match your schema file names
24
+ // TODO: Adjust the filter to match your schema file names. extractFromZip yields
25
+ // Buffers — decode with \`.toString()\` in parse.ts as needed.
25
26
  return extractFromZip(zipData, (name) => name.endsWith(".json"));
26
27
  }
27
28
  `;
@@ -232,6 +232,39 @@ describe("scaffold content validation", () => {
232
232
  // AWS references
233
233
  expect(content).toContain("lexicons/aws/");
234
234
  });
235
+
236
+ // Drift guards — keep the scaffold compiling/installing against current core (#749).
237
+ test("package.json installs under plain npm and can build (#749)", () => {
238
+ const pkg = JSON.parse(readFileSync(join(targetDir, "package.json"), "utf-8"));
239
+ expect(JSON.stringify(pkg)).not.toContain("workspace:"); // rejected by plain npm
240
+ expect(pkg.devDependencies["@intentius/chant"]).toBe("*");
241
+ expect(pkg.dependencies).toBeUndefined();
242
+ expect(pkg.devDependencies["tsc-alias"]).toBeTruthy();
243
+ expect(pkg.scripts.build).toContain("tsconfig.build.json");
244
+ });
245
+
246
+ test("tsconfig.build.json uses bundler resolution + the development condition (#749)", () => {
247
+ const cfg = JSON.parse(readFileSync(join(targetDir, "tsconfig.build.json"), "utf-8"));
248
+ expect(cfg.compilerOptions.moduleResolution).toBe("bundler");
249
+ expect(cfg.compilerOptions.customConditions).toContain("development");
250
+ });
251
+
252
+ test("spec/fetch.ts matches fetchWithCache(config, force) → Map<string, Buffer> (#749)", () => {
253
+ const content = readFileSync(join(targetDir, "src/spec/fetch.ts"), "utf-8");
254
+ expect(content).toContain("Promise<Map<string, Buffer>>");
255
+ expect(content).not.toMatch(/force:\s*options/); // force is the 2nd arg, not a FetchConfig field
256
+ });
257
+
258
+ test("validate-cli.ts calls validate() with no verbose arg (#749)", () => {
259
+ const content = readFileSync(join(targetDir, "src/validate-cli.ts"), "utf-8");
260
+ expect(content).toContain("await validate();");
261
+ expect(content).not.toContain("verbose");
262
+ });
263
+
264
+ test("lint/rules/index.ts exports a `rules` array (plugin.ts imports it) (#749)", () => {
265
+ const content = readFileSync(join(targetDir, "src/lint/rules/index.ts"), "utf-8");
266
+ expect(content).toContain("export const rules");
267
+ });
235
268
  });
236
269
 
237
270
  // ── Fixture snapshot tests ──────────────────────────────────────────
@@ -8,7 +8,7 @@ import { generateCodegenGenerateTs, generateCodegenGenerateCliTs, generateCodege
8
8
  import { generateSpecFetchTs, generateSpecParseTs } from "./init-lexicon/templates/spec";
9
9
  import { generateSampleRuleTs, generateLintRulesIndexTs } from "./init-lexicon/templates/lint";
10
10
  import { generateLspCompletionsTs, generateLspHoverTs } from "./init-lexicon/templates/lsp";
11
- import { generatePackageJson, generateTsConfig, generateJustfile, generateGitignore, generateReadme, generateSerializerTs, generateValidateTs, generateValidateCliTs } from "./init-lexicon/templates/project";
11
+ import { generatePackageJson, generateTsConfig, generateTsConfigBuild, generateJustfile, generateGitignore, generateReadme, generateSerializerTs, generateValidateTs, generateValidateCliTs } from "./init-lexicon/templates/project";
12
12
  import { generatePluginTestTs, generateSerializerTestTs, generateCompletionsTestTs, generateHoverTestTs } from "./init-lexicon/templates/tests";
13
13
  import { generateDocsPackageJson, generateDocsTsConfig, generateDocsAstroConfig, generateDocsContentConfig, generateDocsIndexMdx } from "./init-lexicon/templates/docs";
14
14
  import { generateExamplePackageJson, generateExampleInfraTs } from "./init-lexicon/templates/examples";
@@ -150,6 +150,7 @@ export async function initLexiconCommand(options: InitLexiconOptions): Promise<I
150
150
  "src/validate-cli.ts": generateValidateCliTs(),
151
151
  "package.json": generatePackageJson(name, names),
152
152
  "tsconfig.json": generateTsConfig(),
153
+ "tsconfig.build.json": generateTsConfigBuild(),
153
154
  "justfile": generateJustfile(name),
154
155
  ".gitignore": generateGitignore(),
155
156
  "README.md": generateReadme(name, names),
@@ -19,6 +19,7 @@
19
19
  import { exec } from "node:child_process";
20
20
  import { createConnection } from "node:net";
21
21
  import { promisify } from "node:util";
22
+ import { isAbsolute, join } from "node:path";
22
23
 
23
24
  export const execFileAsync = promisify(exec);
24
25
 
@@ -104,7 +105,11 @@ function q(value: string): string {
104
105
  export const realDocker: DockerClient = {
105
106
  async build(args) {
106
107
  const parts = [`docker build`, `-t ${q(args.tag)}`];
107
- if (args.dockerfile) parts.push(`-f ${q(args.dockerfile)}`);
108
+ if (args.dockerfile) {
109
+ // dockerfile is relative to `context` (its documented contract); docker's `-f` resolves a relative path against cwd, not the context dir, so join them here (chant#936).
110
+ const dockerfilePath = isAbsolute(args.dockerfile) ? args.dockerfile : join(args.context, args.dockerfile);
111
+ parts.push(`-f ${q(dockerfilePath)}`);
112
+ }
108
113
  if (args.target) parts.push(`--target ${q(args.target)}`);
109
114
  for (const [k, v] of Object.entries(args.buildArgs ?? {})) parts.push(`--build-arg ${q(`${k}=${v}`)}`);
110
115
  parts.push(q(args.context));
@@ -128,6 +128,8 @@ export const waitEndpointCapability: Capability<WaitEndpointInput, WaitEndpointO
128
128
  export interface HealthGateInput {
129
129
  /** Health check path or full URL. */
130
130
  path: string;
131
+ /** Optional base URL (scheme + host) composed with `path` via `new URL(path, host)`. May be a cross-stack Wiring value; a bare host gets `http://` prepended. */
132
+ host?: string;
131
133
  /** Number of consecutive successes required. Default: 1. */
132
134
  consecutiveSuccesses?: number;
133
135
  /** Poll interval in ms. Default: 5000. */
@@ -139,6 +141,13 @@ export interface HealthGateOutput {
139
141
  healthy: boolean;
140
142
  }
141
143
 
144
+ /** Compose the fetchable URL: `host` set → resolve `path` against it (bare host → `http://` prepended); else `path` as-is. */
145
+ function healthGateUrl(input: HealthGateInput): string {
146
+ if (!input.host) return input.path;
147
+ const base = /^https?:\/\//.test(input.host) ? input.host : `http://${input.host}`;
148
+ return new URL(input.path, base).toString();
149
+ }
150
+
142
151
  /** Block progression until a health check passes — the generic post-deploy verification gate. Cloud-agnostic. */
143
152
  export function createHealthGateCapability(fetcher: Fetcher = defaultFetcher): Capability<HealthGateInput, HealthGateOutput> {
144
153
  return {
@@ -152,14 +161,14 @@ export function createHealthGateCapability(fetcher: Fetcher = defaultFetcher): C
152
161
  for (;;) {
153
162
  let ok = false;
154
163
  try {
155
- ok = (await fetcher(input.path)).ok;
164
+ ok = (await fetcher(healthGateUrl(input))).ok;
156
165
  } catch {
157
166
  ok = false;
158
167
  }
159
168
  streak = ok ? streak + 1 : 0;
160
169
  if (streak >= need) return { healthy: true };
161
170
  if (Date.now() >= deadline) {
162
- throw new Error(`health-gate: ${input.path} did not reach ${need} consecutive healthy check(s) within 300000ms`);
171
+ throw new Error(`health-gate: ${healthGateUrl(input)} did not reach ${need} consecutive healthy check(s) within 300000ms`);
163
172
  }
164
173
  await sleep(intervalMs);
165
174
  }
@@ -7,7 +7,8 @@
7
7
  */
8
8
 
9
9
  import { DECLARABLE_MARKER, type Declarable } from "./declarable";
10
- import type { AttrRef } from "./attrref";
10
+ import { AttrRef } from "./attrref";
11
+ import { isIntrinsic, type Intrinsic } from "./intrinsic";
11
12
 
12
13
  /**
13
14
  * Marker symbol for stack output identification.
@@ -24,10 +25,26 @@ export interface StackOutput extends Declarable {
24
25
  readonly lexicon: string;
25
26
  readonly entityType: string;
26
27
  readonly kind: "output";
27
- readonly sourceRef: AttrRef;
28
+ /** The exported value: a bare attribute reference, or an intrinsic wrapping
29
+ * one (e.g. `Join(",", zone.NameServers)`). */
30
+ readonly sourceRef: AttrRef | Intrinsic;
28
31
  readonly description?: string;
29
32
  }
30
33
 
34
+ /** Find the first AttrRef anywhere inside a value (walking intrinsics/objects/
35
+ * arrays), so a wrapping intrinsic can still borrow its parent's lexicon. */
36
+ function firstAttrRef(value: unknown, seen = new Set<unknown>()): AttrRef | undefined {
37
+ if (value === null || typeof value !== "object" || seen.has(value)) return undefined;
38
+ if (value instanceof AttrRef) return value;
39
+ seen.add(value);
40
+ const children = Array.isArray(value) ? value : Object.values(value as Record<string, unknown>);
41
+ for (const child of children) {
42
+ const found = firstAttrRef(child, seen);
43
+ if (found) return found;
44
+ }
45
+ return undefined;
46
+ }
47
+
31
48
  /**
32
49
  * Type guard for StackOutput.
33
50
  */
@@ -59,11 +76,16 @@ export function isStackOutput(value: unknown): value is StackOutput {
59
76
  * ```
60
77
  */
61
78
  export function stackOutput(
62
- ref: AttrRef,
79
+ ref: AttrRef | Intrinsic,
63
80
  options?: { description?: string },
64
81
  ): StackOutput {
65
- // Derive lexicon from the AttrRef's parent entity
66
- const parent = ref.parent.deref();
82
+ if (!(ref instanceof AttrRef) && !isIntrinsic(ref)) {
83
+ throw new Error("stackOutput(ref): ref must be an attribute reference or an intrinsic wrapping one");
84
+ }
85
+ // Derive lexicon from the referenced entity — for a bare AttrRef, its parent;
86
+ // for an intrinsic (Join etc.), the first AttrRef nested inside it.
87
+ const anchor = ref instanceof AttrRef ? ref : firstAttrRef(ref);
88
+ const parent = anchor?.parent.deref();
67
89
  const lexicon = parent && typeof (parent as Record<string, unknown>).lexicon === "string"
68
90
  ? (parent as Record<string, unknown>).lexicon as string
69
91
  : "unknown";
package/src/yaml.test.ts CHANGED
@@ -211,3 +211,36 @@ describe("parseScalar", () => {
211
211
  expect(parseScalar("hello")).toBe("hello");
212
212
  });
213
213
  });
214
+
215
+ // Block scalars (#910) — round-trip parity with js-yaml for literal/folded/chomping,
216
+ // including block scalars nested inside array items (the case that mis-parsed).
217
+ describe("parseYAML block scalars (#910)", () => {
218
+ test("top-level literal | keeps newlines, clips to one trailing", () => {
219
+ expect(parseYAML("run: |\n line1\n line2\n")).toEqual({ run: "line1\nline2\n" });
220
+ });
221
+
222
+ test("literal | nested inside a later array item (the reported bug)", () => {
223
+ expect(
224
+ parseYAML("steps:\n - name: first\n run: echo hi\n - name: second\n run: |\n line1\n line2\n"),
225
+ ).toEqual({
226
+ steps: [
227
+ { name: "first", run: "echo hi" },
228
+ { name: "second", run: "line1\nline2\n" },
229
+ ],
230
+ });
231
+ });
232
+
233
+ test("block scalar as an array item's first key, with a sibling key after", () => {
234
+ expect(parseYAML("steps:\n - run: |\n a\n b\n name: x\n")).toEqual({
235
+ steps: [{ run: "a\nb\n", name: "x" }],
236
+ });
237
+ });
238
+
239
+ test("strip |- drops the trailing newline; a sibling key after still parses", () => {
240
+ expect(parseYAML("a: |-\n x\n y\nb: 2\n")).toEqual({ a: "x\ny", b: 2 });
241
+ });
242
+
243
+ test("folded > folds line breaks to spaces, blank line to one newline", () => {
244
+ expect(parseYAML("msg: >\n a\n b\n\n c\n")).toEqual({ msg: "a b\nc\n" });
245
+ });
246
+ });
package/src/yaml.ts CHANGED
@@ -155,6 +155,85 @@ export function parseYAML(content: string): Record<string, unknown> {
155
155
  return parseYAMLLines(lines, 0, 0).value as Record<string, unknown>;
156
156
  }
157
157
 
158
+ /**
159
+ * A block-scalar header: `|` (literal, keep newlines) or `>` (folded, newlines →
160
+ * spaces), with a chomping indicator (`-` strip trailing newlines, `+` keep them,
161
+ * default clip to a single one). Returns null when `inline` isn't a block header.
162
+ */
163
+ interface BlockScalarHeader {
164
+ style: "literal" | "folded";
165
+ chomp: "clip" | "strip" | "keep";
166
+ }
167
+ function blockScalarHeader(inline: string): BlockScalarHeader | null {
168
+ const m = inline.match(/^([|>])([+-]?)(?:\s+#.*)?$/);
169
+ if (!m) return null;
170
+ return {
171
+ style: m[1] === "|" ? "literal" : "folded",
172
+ chomp: m[2] === "-" ? "strip" : m[2] === "+" ? "keep" : "clip",
173
+ };
174
+ }
175
+
176
+ /**
177
+ * Parse a block scalar's body — the lines indented past `parentIndent`, dedented
178
+ * by the block's own indent (the first content line's). Handles literal/folded
179
+ * styles and clip/strip/keep chomping, matching js-yaml. Returns the string value
180
+ * and the index of the first line that is NOT part of the block.
181
+ */
182
+ function parseBlockScalar(
183
+ lines: string[],
184
+ startIndex: number,
185
+ parentIndent: number,
186
+ header: BlockScalarHeader,
187
+ ): { value: string; endIndex: number } {
188
+ const raw: string[] = [];
189
+ let blockIndent = -1;
190
+ let i = startIndex;
191
+ for (; i < lines.length; i++) {
192
+ const line = lines[i];
193
+ if (line.trim() === "") {
194
+ raw.push(""); // a blank line is part of the block (kept/chomped later)
195
+ continue;
196
+ }
197
+ const ni = line.search(/\S/);
198
+ if (ni <= parentIndent) break; // dedented out of the block
199
+ if (blockIndent === -1) blockIndent = ni;
200
+ if (ni < blockIndent) break;
201
+ raw.push(line.slice(blockIndent));
202
+ }
203
+ // Trailing blank lines belong to the block (chomping decides their fate).
204
+ let text: string;
205
+ if (header.style === "folded") {
206
+ // Fold each run of non-empty lines into a space-joined paragraph; a run of N
207
+ // blank lines between paragraphs becomes N newlines (a single blank → one
208
+ // newline), matching YAML folded semantics.
209
+ text = "";
210
+ let buf: string[] = [];
211
+ let blankRun = 0;
212
+ let wrote = false;
213
+ const flush = (): void => {
214
+ if (buf.length === 0) return;
215
+ if (wrote) text += "\n".repeat(blankRun);
216
+ text += buf.join(" ");
217
+ buf = [];
218
+ blankRun = 0;
219
+ wrote = true;
220
+ };
221
+ for (const l of raw) {
222
+ if (l === "") { flush(); blankRun++; }
223
+ else buf.push(l);
224
+ }
225
+ flush();
226
+ } else {
227
+ text = raw.join("\n");
228
+ }
229
+ const trailing = text.match(/\n*$/)?.[0].length ?? 0;
230
+ const stripped = text.replace(/\n+$/, "");
231
+ if (header.chomp === "strip") text = stripped;
232
+ else if (header.chomp === "keep") text = stripped + "\n".repeat(Math.max(trailing, raw.length > 0 ? 1 : 0));
233
+ else text = stripped === "" ? "" : stripped + "\n"; // clip
234
+ return { value: text, endIndex: i };
235
+ }
236
+
158
237
  /**
159
238
  * Parse indentation-based YAML lines into a key-value object.
160
239
  */
@@ -222,8 +301,15 @@ export function parseYAMLLines(
222
301
  }
223
302
  i++;
224
303
  } else {
225
- result[key] = parseScalar(inlineValue);
226
- i++;
304
+ const header = blockScalarHeader(inlineValue);
305
+ if (header) {
306
+ const block = parseBlockScalar(lines, i + 1, indent, header);
307
+ result[key] = block.value;
308
+ i = block.endIndex;
309
+ } else {
310
+ result[key] = parseScalar(inlineValue);
311
+ i++;
312
+ }
227
313
  }
228
314
  } else if (line.trimStart().startsWith("- ")) {
229
315
  break;
@@ -246,6 +332,15 @@ function parseArrayItemValue(
246
332
  childIndent: number,
247
333
  ): unknown {
248
334
  if (inlineValue !== "" && !inlineValue.startsWith("#")) {
335
+ const header = blockScalarHeader(inlineValue);
336
+ if (header) {
337
+ // Block scalar nested under an array-item key (e.g. `- name: x\n run: |`).
338
+ // The body is indented past the key's column. On a `- key: |` line the key
339
+ // sits 2 cols past the dash; on its own line it's the line's indent (#910).
340
+ const dash = lines[currentIndex].match(/^(\s*)- /);
341
+ const keyIndent = dash ? dash[1].length + 2 : lines[currentIndex].search(/\S/);
342
+ return parseBlockScalar(lines, currentIndex + 1, keyIndent, header).value;
343
+ }
249
344
  if (inlineValue.startsWith("[")) {
250
345
  try { return JSON.parse(inlineValue); } catch { return inlineValue; }
251
346
  }
@@ -323,9 +418,13 @@ export function parseYAMLArray(
323
418
  obj[kvMatch[1].trim()] = parseArrayItemValue(kvMatch[2].trim(), lines, i, indent + 2);
324
419
  // Check for more keys at indent+2
325
420
  const nextIndent = indent + 2;
326
- let j = kvMatch[2].trim() === "" || kvMatch[2].trim().startsWith("#")
421
+ const firstVal = kvMatch[2].trim();
422
+ let j = firstVal === "" || firstVal.startsWith("#")
327
423
  ? skipNestedBlock(lines, i + 1, nextIndent)
328
- : i + 1;
424
+ : blockScalarHeader(firstVal)
425
+ // Block body is indented past the key (nextIndent); skip it (#910).
426
+ ? skipNestedBlock(lines, i + 1, nextIndent + 1)
427
+ : i + 1;
329
428
  while (j < lines.length) {
330
429
  const nextLine = lines[j];
331
430
  if (nextLine.trim() === "" || nextLine.trim().startsWith("#")) {
@@ -341,6 +440,9 @@ export function parseYAMLArray(
341
440
  obj[nextKV[2].trim()] = parseArrayItemValue(nextVal, lines, j, ni + 2);
342
441
  if (nextVal === "" || nextVal.startsWith("#")) {
343
442
  j = skipNestedBlock(lines, j + 1, ni + 2);
443
+ } else if (blockScalarHeader(nextVal)) {
444
+ // Skip the block body (indented past this key at `ni`) (#910).
445
+ j = skipNestedBlock(lines, j + 1, ni + 1);
344
446
  } else {
345
447
  j++;
346
448
  }