tjs-lang 0.8.7 → 0.9.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 (75) hide show
  1. package/CLAUDE.md +12 -4
  2. package/dist/experiments/ambient/probe.d.ts +52 -0
  3. package/dist/index.js +115 -171
  4. package/dist/index.js.map +4 -4
  5. package/dist/scripts/build-editors.d.ts +19 -0
  6. package/dist/src/css/dimensions.d.ts +23 -0
  7. package/dist/src/css/index.d.ts +85 -0
  8. package/dist/src/css/predicates.d.ts +38 -0
  9. package/dist/src/css/shorthands.d.ts +31 -0
  10. package/dist/src/css/style.d.ts +48 -0
  11. package/dist/src/lang/emitters/js.d.ts +9 -1
  12. package/dist/src/lang/index.d.ts +2 -2
  13. package/dist/src/lang/parser-transforms.d.ts +9 -5
  14. package/dist/src/lang/parser.d.ts +2 -0
  15. package/dist/src/lang/predicate.d.ts +60 -0
  16. package/dist/src/lang/transpiler.d.ts +3 -2
  17. package/dist/src/lang/types.d.ts +16 -0
  18. package/dist/src/schema/index.d.ts +12 -0
  19. package/dist/tjs-browser-from-ts.js +20 -20
  20. package/dist/tjs-browser-from-ts.js.map +3 -3
  21. package/dist/tjs-browser.js +100 -90
  22. package/dist/tjs-browser.js.map +4 -4
  23. package/dist/tjs-css.js +193 -0
  24. package/dist/tjs-css.js.map +7 -0
  25. package/dist/tjs-eval.js +43 -42
  26. package/dist/tjs-eval.js.map +4 -4
  27. package/dist/tjs-from-ts.js +13 -13
  28. package/dist/tjs-from-ts.js.map +2 -2
  29. package/dist/tjs-lang.js +102 -92
  30. package/dist/tjs-lang.js.map +4 -4
  31. package/dist/tjs-runtime.js +10 -0
  32. package/dist/tjs-runtime.js.map +7 -0
  33. package/dist/tjs-schema.js +6 -0
  34. package/dist/tjs-schema.js.map +7 -0
  35. package/dist/tjs-vm.js +55 -54
  36. package/dist/tjs-vm.js.map +4 -4
  37. package/docs/ambient-contracts.md +261 -0
  38. package/editors/ace/ajs-mode.js +214 -233
  39. package/editors/codemirror/ajs-language.js +1570 -233
  40. package/editors/editors-build.test.ts +29 -0
  41. package/editors/monaco/ajs-monarch.js +239 -195
  42. package/llms.txt +4 -0
  43. package/package.json +35 -4
  44. package/src/css/css.test.ts +122 -0
  45. package/src/css/dimensions.test.ts +112 -0
  46. package/src/css/dimensions.ts +146 -0
  47. package/src/css/index.ts +243 -0
  48. package/src/css/perf.bench.test.ts +109 -0
  49. package/src/css/predicates.ts +232 -0
  50. package/src/css/property-aware.test.ts +84 -0
  51. package/src/css/shorthands.test.ts +90 -0
  52. package/src/css/shorthands.ts +113 -0
  53. package/src/css/style.test.ts +125 -0
  54. package/src/css/style.ts +134 -0
  55. package/src/index-tsfree.test.ts +58 -0
  56. package/src/lang/emit-verified-predicate.test.ts +95 -0
  57. package/src/lang/emitters/dts.test.ts +31 -0
  58. package/src/lang/emitters/dts.ts +23 -4
  59. package/src/lang/emitters/js.ts +33 -1
  60. package/src/lang/from-ts.test.ts +1 -1
  61. package/src/lang/generic-verified-predicate.test.ts +39 -0
  62. package/src/lang/index.ts +14 -5
  63. package/src/lang/parser-transforms.ts +109 -14
  64. package/src/lang/parser.ts +9 -2
  65. package/src/lang/predicate-evaluator.test.ts +49 -0
  66. package/src/lang/predicate-report.test.ts +54 -0
  67. package/src/lang/predicate.ts +268 -0
  68. package/src/lang/redos-lint.test.ts +81 -0
  69. package/src/lang/transpiler.ts +13 -0
  70. package/src/lang/type-verified-predicate.test.ts +83 -0
  71. package/src/lang/types.ts +17 -0
  72. package/src/lang/typescript-syntax.test.ts +2 -1
  73. package/src/schema/index.ts +62 -0
  74. package/src/schema/schema.test.ts +66 -0
  75. package/src/use-cases/bootstrap.test.ts +14 -4
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env bun
2
+ export declare const ROOT: string;
3
+ export interface EditorTarget {
4
+ name: string;
5
+ entry: string;
6
+ outfile: string;
7
+ external: string[];
8
+ description: string;
9
+ }
10
+ /**
11
+ * Bundle one editor target. With `write: true` (default) it writes the `.js` in
12
+ * place and returns its bytes; with `write: false` it returns the bytes without
13
+ * touching disk (used by the anti-drift guard test to compare against the
14
+ * committed file).
15
+ */
16
+ export declare function bundleEditor(target: EditorTarget, { write }?: {
17
+ write?: boolean;
18
+ }): string;
19
+ export declare const editorTargets: EditorTarget[];
@@ -0,0 +1,23 @@
1
+ /**
2
+ * CSS dimension / numeric value grammar (phase 2) — the other big family of leaf
3
+ * values: lengths, percentages, angles, times, resolutions, plain numbers, and
4
+ * the CSS-wide global keywords. Same rules as the color cluster: pure,
5
+ * synchronous, ReDoS-clean (flat character classes / bounded alternation only),
6
+ * with `var(--…)`/`calc(…)` as the open escapes.
7
+ *
8
+ * The numeric core `[+-]?(\d*\.\d+|\d+)` is a bounded alternation (each branch a
9
+ * single quantifier — no nesting), so it passes the verifier's ReDoS lint.
10
+ */
11
+ /** Absolute + relative + container + viewport length units (CSS Values 4). */
12
+ export declare const CSS_LENGTH_UNITS: string[];
13
+ /** CSS-wide keywords valid on any property. */
14
+ export declare const CSS_GLOBAL_KEYWORDS: string[];
15
+ /**
16
+ * Dimension predicate cluster (source). Entry points cover each numeric family
17
+ * plus `isDimension` (any of them) and `isGlobalKeyword`. Units are ordered
18
+ * longest-first inside the alternation so e.g. `rem` isn't shadowed by `em`
19
+ * (belt-and-suspenders — the `$` anchor already forces a full match).
20
+ */
21
+ export declare const CSS_DIMENSION_SOURCE: string;
22
+ /** Entry predicates exported by the dimension cluster (for compile/suggest). */
23
+ export declare const CSS_DIMENSION_ENTRIES: readonly ["isNumber", "isInteger", "isPercentage", "isLength", "isAngle", "isTime", "isResolution", "isGlobalKeyword", "isDimension"];
@@ -0,0 +1,85 @@
1
+ /**
2
+ * `tjs-lang/css` — CSS validation built from verified-safe predicates.
3
+ *
4
+ * The "computational half" of a CSS schema: precise, total validators for the
5
+ * open value grammars TS/JSON-Schema cave to `string` on (colors here in
6
+ * phase 1; lengths, shorthands and the recursive style-object structure land in
7
+ * later phases — see TODO.md #4). Every validator is compiled from a
8
+ * predicate-safe source cluster (`./predicates`), so it is pure, synchronous,
9
+ * fuel-bounded, and ReDoS-clean — safe to run on untrusted input.
10
+ *
11
+ * Autocomplete rides the same source: `suggestColor()` mines the named-color set
12
+ * and the open functional stubs (`var(--`, `color-mix(`, …), validating mined
13
+ * values through the compiled predicate so completions are guaranteed valid.
14
+ */
15
+ import { type PredicateVerifyResult, type Suggestion } from '../lang/predicate';
16
+ export { CSS_COLOR_SOURCE, CSS_COLOR_ENTRIES, CSS_NAMED_COLORS, } from './predicates';
17
+ export { CSS_DIMENSION_SOURCE, CSS_DIMENSION_ENTRIES, CSS_LENGTH_UNITS, CSS_GLOBAL_KEYWORDS, } from './dimensions';
18
+ export { CSS_STYLE_SOURCE, CSS_STYLE_ENTRIES, cssStyleSchema, cssColorSchema, cssDimensionSchema, } from './style';
19
+ export { CSS_SHORTHAND_SOURCE, CSS_SHORTHAND_ENTRIES, cssAnimationSchema, cssTransitionSchema, } from './shorthands';
20
+ /** Is `v` a valid CSS color (named, hex, rgb/hsl, modern fn, or `var(--…)`)? */
21
+ export declare const isColor: (v: unknown) => boolean;
22
+ /** Like {@link isColor}, but tolerates a trailing `!important`. */
23
+ export declare const isColorValue: (v: unknown) => boolean;
24
+ /** Is `v` a CSS named color (incl. `transparent`/`currentcolor`)? */
25
+ export declare const isNamedColor: (v: unknown) => boolean;
26
+ /** Is `v` a CSS hex color (`#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`)? */
27
+ export declare const isHexColor: (v: unknown) => boolean;
28
+ /** Is `v` a CSS `<length>` (unit'd, unitless `0`, or `var()`/`calc()`)? */
29
+ export declare const isLength: (v: unknown) => boolean;
30
+ /** Is `v` a CSS `<percentage>` (`50%`)? */
31
+ export declare const isPercentage: (v: unknown) => boolean;
32
+ /** Is `v` a CSS `<number>` (numeric, or a numeric string)? */
33
+ export declare const isNumber: (v: unknown) => boolean;
34
+ /** Is `v` a CSS `<integer>`? */
35
+ export declare const isInteger: (v: unknown) => boolean;
36
+ /** Is `v` a CSS `<angle>` (`45deg`, `1turn`, `1.5rad`, `100grad`)? */
37
+ export declare const isAngle: (v: unknown) => boolean;
38
+ /** Is `v` a CSS `<time>` (`200ms`, `1s`)? */
39
+ export declare const isTime: (v: unknown) => boolean;
40
+ /** Is `v` any CSS dimension/number (length, %, angle, time, resolution, number)? */
41
+ export declare const isDimension: (v: unknown) => boolean;
42
+ /** Is `v` a CSS-wide keyword (`inherit`/`initial`/`unset`/`revert`/`revert-layer`)? */
43
+ export declare const isGlobalKeyword: (v: unknown) => boolean;
44
+ /**
45
+ * Is `v` a valid CSS **style object** — an open, recursive map of CSS properties
46
+ * to values and selectors/at-rules to nested style objects? Validates the whole
47
+ * structure (keys are properties or selectors; property values are style values,
48
+ * selector values are nested rules), recursively and fuel-bounded. This is the
49
+ * shape TS/JSON-Schema can't express.
50
+ */
51
+ export declare const isStyleObject: (v: unknown) => boolean;
52
+ /** Is `v` a valid leaf CSS value (a known color/dimension/keyword, else a non-empty string / finite number)? */
53
+ export declare const isStyleValue: (v: unknown) => boolean;
54
+ /**
55
+ * Property-AWARE leaf check: given the property name, tightens the closed value
56
+ * grammars (color/animation/transition) so `isStyleValueFor('color', 'notacolor')`
57
+ * is `false` while `isStyleValueFor('padding', 'anything')` stays permissive.
58
+ * This is what makes {@link isStyleObject} catch real value errors.
59
+ */
60
+ export declare const isStyleValueFor: (prop: unknown, val: unknown) => boolean;
61
+ /** Is `k` a CSS property name (`color`, `--custom`, `-webkit-foo`)? */
62
+ export declare const isCssProperty: (k: unknown) => boolean;
63
+ /** Is `k` a selector or at-rule key (nests a rule) rather than a property? */
64
+ export declare const isSelectorOrAtRule: (k: unknown) => boolean;
65
+ /** Is `v` a valid CSS `animation` shorthand (comma-separated, order-free tokens)? */
66
+ export declare const isAnimation: (v: unknown) => boolean;
67
+ /** Is `v` a valid CSS `transition` shorthand (comma-separated layers)? */
68
+ export declare const isTransition: (v: unknown) => boolean;
69
+ /** Is `v` a CSS `<easing-function>` (keyword, `cubic-bezier(…)`, `steps(…)`, `linear(…)`)? */
70
+ export declare const isTimingFunction: (v: unknown) => boolean;
71
+ /**
72
+ * Verify every CSS predicate-source cluster is predicate-safe (pure,
73
+ * synchronous, ReDoS-clean). Returns the combined result (safe iff all clusters
74
+ * are; diagnostics carry the cluster name). Always safe for the shipped source —
75
+ * exposed so downstream tools (and the drift test) can assert it, and so a
76
+ * consumer embedding a source in a `$predicate` schema can re-check before
77
+ * trusting it.
78
+ */
79
+ export declare function verifyCss(): PredicateVerifyResult;
80
+ /**
81
+ * Autocomplete candidates for a CSS color value. Returns concrete named colors
82
+ * (validated through the compiled predicate) plus open-ended stubs mined from
83
+ * the functional forms (`var(--`, `color-mix(`, `oklch(`, …). Prefix-filtered.
84
+ */
85
+ export declare function suggestColor(prefix?: string, limit?: number): Suggestion[];
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The CSS predicate library — canonical **source** form.
3
+ *
4
+ * Predicates are authored as source strings, not native functions, because the
5
+ * source is the serializable, portable artifact: it feeds the verifier
6
+ * (`verifyPredicate` — certifies pure/synchronous/ReDoS-clean), compiles to the
7
+ * native fast path (`compilePredicate`), mines autocomplete (`suggest`), and
8
+ * embeds into JSON Schema's `$predicate` keyword. This is the "computational
9
+ * half" JSON Schema and TS structural types can't express — CSS is the torture
10
+ * test (open value grammars, order-flexible shorthands, recursive structure).
11
+ *
12
+ * Style rules for anything added here (so it stays verifiable):
13
+ * - pure & synchronous: no IO, no `await`, no `new`, no loops (use
14
+ * `every`/`some`/`map`/recursion — fuel bounds them at function entry);
15
+ * - regexes must be ReDoS-clean (no nested unbounded quantifiers — the
16
+ * verifier rejects `(a+)+` and friends, so keep character classes flat);
17
+ * - compose with `||` and named predicates as callbacks (`toks.every(isX)`).
18
+ *
19
+ * Phase 1 ships the color grammar. Later phases add lengths/dimensions,
20
+ * shorthands, and the recursive style-object structure — see TODO.md (#4).
21
+ */
22
+ /**
23
+ * The CSS Color Module Level 4 named colors (+ the CSS-wide `transparent` and
24
+ * `currentcolor`), lower-cased. Data, kept in the source so the whole cluster
25
+ * stays serializable as one artifact.
26
+ */
27
+ export declare const CSS_NAMED_COLORS: string[];
28
+ /**
29
+ * Color predicate cluster (source). Entry points: `isColor` (any CSS color) and
30
+ * `isColorValue` (a color, tolerating a trailing `!important`). Regexes are
31
+ * flat-class (ReDoS-clean). The functional-color forms (`hwb`/`lab`/`lch`/
32
+ * `oklab`/`oklch`/`color`/`color-mix`) are matched by name + balanced parens
33
+ * rather than validating their args — precise enough for validation, open
34
+ * enough not to reject valid modern CSS.
35
+ */
36
+ export declare const CSS_COLOR_SOURCE: string;
37
+ /** Entry predicates exported by the color cluster (for compile/suggest). */
38
+ export declare const CSS_COLOR_ENTRIES: readonly ["isColor", "isColorValue", "isNamedColor", "isHexColor", "isRgbColor", "isHslColor"];
@@ -0,0 +1,31 @@
1
+ /**
2
+ * CSS order-flexible shorthands (phase 3) — the second torture case from the
3
+ * PoC: a shorthand like `animation` or `transition` is a comma-separated list of
4
+ * layers, each a whitespace-separated bag of tokens whose *order is free*
5
+ * (`3s ease-in 1s infinite alternate slidein` ≡ any permutation). TS unions and
6
+ * JSON Schema can't express "a set of tokens, each classifiable, in any order";
7
+ * a predicate tokenizes and classifies (`toks.every(isAnimToken)`).
8
+ *
9
+ * Built on the dimension leaf cluster (for `isTime`/`isCssVar`/`isCssCalc`).
10
+ * Same rules as the other clusters: pure, synchronous, ReDoS-clean (the split
11
+ * regexes are single-quantifier `\s+` / `,`; classifier regexes are flat).
12
+ */
13
+ import type { PredicateSchema } from '../lang/predicate-schema';
14
+ /**
15
+ * The shorthand classifiers alone (no leaf cluster prepended). Exported so the
16
+ * combined style cluster (`style.ts`) can compose them for property-aware
17
+ * validation without re-including the dimension source.
18
+ */
19
+ export declare const CSS_SHORTHAND_FRAGMENT = "\nvar ANIM_TIMING = ['linear','ease','ease-in','ease-out','ease-in-out','step-start','step-end']\nvar ANIM_DIRECTION = ['normal','reverse','alternate','alternate-reverse']\nvar ANIM_FILLMODE = ['none','forwards','backwards','both']\nvar ANIM_PLAYSTATE = ['running','paused']\n\nfunction isTimingFunction(t) {\n if (typeof t !== 'string') { return false }\n if (ANIM_TIMING.includes(t)) { return true }\n return (t.startsWith('cubic-bezier(') || t.startsWith('steps(') || t.startsWith('linear(')) && t.endsWith(')')\n}\nfunction isIterationCount(t) {\n return t === 'infinite' || (typeof t === 'string' && /^[0-9]*\\.?[0-9]+$/.test(t))\n}\nfunction isAnimName(t) {\n // any custom-ident (also matches keywords, which classify earlier anyway)\n return typeof t === 'string' && /^-?[a-z_][a-z0-9_-]*$/i.test(t)\n}\n// Tokenize a whole shorthand value. A function token like cubic-bezier(a, b) is\n// kept whole (arg spaces/commas must not split it); top-level commas (layer\n// separators) and whitespace are delimiters, so they're dropped. Loops are\n// banned in predicates, so this is one .match with a FLAT (ReDoS-clean) regex \u2014\n// note a paren-aware comma *splitter* would be a nested quantifier the verifier\n// rejects, so we tokenize instead and guard empty layers separately.\nfunction cssTokens(v) {\n return typeof v === 'string' ? v.match(/[a-z-]+\\([^)]*\\)|[^\\s,]+/gi) : null\n}\n// Reject leading/trailing/double commas (empty layers). Flat, ReDoS-clean.\nfunction hasEmptyLayer(v) {\n return typeof v === 'string' && /^\\s*,|,\\s*$|,\\s*,/.test(v)\n}\nfunction isAnimToken(t) {\n return isTime(t) || isIterationCount(t) || isTimingFunction(t)\n || ANIM_DIRECTION.includes(t) || ANIM_FILLMODE.includes(t) || ANIM_PLAYSTATE.includes(t)\n || isCssVar(t) || isCssCalc(t) || isAnimName(t)\n}\nfunction isAnimation(v) {\n if (typeof v !== 'string' || v.length === 0 || hasEmptyLayer(v)) { return false }\n var toks = cssTokens(v)\n return toks !== null && toks.length > 0 && toks.every(isAnimToken)\n}\n\nfunction isTransitionProperty(t) {\n return t === 'all' || t === 'none' || isAnimName(t)\n}\nfunction isTransitionToken(t) {\n return isTime(t) || isTimingFunction(t) || isCssVar(t) || isCssCalc(t) || isTransitionProperty(t)\n}\nfunction isTransition(v) {\n if (typeof v !== 'string' || v.length === 0 || hasEmptyLayer(v)) { return false }\n var toks = cssTokens(v)\n return toks !== null && toks.length > 0 && toks.every(isTransitionToken)\n}\n";
20
+ /**
21
+ * Shorthand predicate cluster (source) = dimension leaves + the shorthand
22
+ * classifiers. Entry predicates: `isAnimation`, `isTransition` (each accepts a
23
+ * comma-separated list of order-free token layers).
24
+ */
25
+ export declare const CSS_SHORTHAND_SOURCE: string;
26
+ /** Entry predicates exported by the shorthand cluster (for compile/verify). */
27
+ export declare const CSS_SHORTHAND_ENTRIES: readonly ["isTimingFunction", "isAnimation", "isTransition"];
28
+ /** `$predicate` schema for a CSS `animation` shorthand value. */
29
+ export declare function cssAnimationSchema(): PredicateSchema;
30
+ /** `$predicate` schema for a CSS `transition` shorthand value. */
31
+ export declare function cssTransitionSchema(): PredicateSchema;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * CSS style-object structure (phase 4) — the recursive, open shape TS structural
3
+ * types and JSON Schema can't express, and the `$predicate` schemas that carry
4
+ * it. This is the thesis deliverable: a JSON-Schema node whose *structural* part
5
+ * (`type: 'object'`) a naive validator checks, and whose `$predicate` a
6
+ * predicate-aware validator runs to validate the whole recursive CSS structure —
7
+ * progressive enhancement, one serializable artifact.
8
+ *
9
+ * The combined source concatenates the color + dimension leaf clusters and adds
10
+ * the structure predicates, so `isStyleValue`/`isStyleObject` compose the leaves
11
+ * directly. `isStyleObject` is LAST — the entry the `$predicate` schema runs.
12
+ *
13
+ * Value precision is intentionally two-tier (as in the PoC): the *structure* is
14
+ * validated strictly (keys must be CSS properties or selectors/at-rules; a
15
+ * property maps to a value, a selector to a nested rule), while a generic leaf
16
+ * value falls back to "non-empty string or finite number" so a valid-but-
17
+ * unmodelled value (a shorthand, a not-yet-covered property) is never rejected.
18
+ * Per-property precision comes from the specific value schemas (`cssColorSchema`
19
+ * etc.) and, later, property-aware validation (phase 3 shorthands).
20
+ */
21
+ import type { PredicateSchema } from '../lang/predicate-schema';
22
+ /**
23
+ * The full CSS style predicate cluster: color + dimension + shorthand leaves +
24
+ * recursive, property-aware structure. Entry = `isStyleObject` (last function).
25
+ * Serializable — this is exactly what a `$predicate` schema carries.
26
+ */
27
+ export declare const CSS_STYLE_SOURCE: string;
28
+ /** Entry predicates exported by the style cluster (for compile/verify). */
29
+ export declare const CSS_STYLE_ENTRIES: readonly ["isCssProperty", "isSelectorOrAtRule", "isStyleValue", "isStyleValueFor", "isStyleObject"];
30
+ /**
31
+ * A `$predicate` JSON-Schema for a CSS style object (à la a tosijs styleSpec):
32
+ * naive validators check only `type: 'object'`; predicate-aware validators run
33
+ * `isStyleObject`, validating the whole recursive structure (nested selectors,
34
+ * property/value shapes). Progressive enhancement from one serializable schema.
35
+ */
36
+ export declare function cssStyleSchema(): PredicateSchema;
37
+ /**
38
+ * A `$predicate` schema for a single CSS **color** value (entry `isColorValue`,
39
+ * so a trailing `!important` is tolerated). Naive validators check `type:
40
+ * 'string'`; aware ones validate the color grammar.
41
+ */
42
+ export declare function cssColorSchema(): PredicateSchema;
43
+ /**
44
+ * A `$predicate` schema for a CSS **dimension** value (length/%/angle/time/
45
+ * number; entry `isDimension`). No structural `type` — a dimension may be a
46
+ * string (`10px`) or a number — so aware validators do all the work.
47
+ */
48
+ export declare function cssDimensionSchema(): PredicateSchema;
@@ -45,7 +45,7 @@
45
45
  * See also: demo/src/tjs-playground.ts which has a manual __tjs stub that
46
46
  * must stay in sync with the runtime - a symptom of this leaky abstraction.
47
47
  */
48
- import type { TypeDescriptor, ParameterDescriptor } from '../types';
48
+ import type { TypeDescriptor, ParameterDescriptor, PredicateVerification } from '../types';
49
49
  export { stripModuleSyntax, stripTjsPreamble } from './js-tests';
50
50
  export interface TJSTranspileOptions {
51
51
  /** Filename for error messages */
@@ -108,6 +108,14 @@ export interface TJSTranspileResult {
108
108
  metadata: Record<string, TJSTypeInfo>;
109
109
  /** Any warnings during transpilation */
110
110
  warnings?: string[];
111
+ /**
112
+ * Per-`Type`/`Generic` predicate verification status: `verified` → compiled to
113
+ * a fuel-bounded, DoS-safe native guard; `!verified` → fell back to a plain
114
+ * function (valid, but not fuel-bounded / not safe on untrusted data — its
115
+ * `reason` is the verifier diagnostic). Unverified entries are also mirrored
116
+ * into `warnings`. Lets tools flag unverifiable predicates.
117
+ */
118
+ predicates?: PredicateVerification[];
111
119
  /** Generated test runner code (if tests were present) - DEPRECATED, tests now run at transpile time */
112
120
  testRunner?: string;
113
121
  /** Number of tests extracted */
@@ -25,12 +25,12 @@ import type { TranspileOptions, TranspileResult, FunctionSignature } from './typ
25
25
  export * from './types';
26
26
  export { parse, preprocess, extractTDoc, validateSingleFunction, extractFunctions, } from './parser';
27
27
  export { dialectForFilename, sourceKindForFilename, type Dialect, type SourceKind, } from './dialect';
28
- export { verifyPredicate, compilePredicate, suggest, effectfulFromAtoms, formatPredicateDiagnostics, PredicateFuelExhausted, type PredicateDiagnostic, type PredicateVerifyResult, type VerifyPredicateOptions, type CompilePredicateOptions, type Suggestion, type SuggestOptions, } from './predicate';
28
+ export { verifyPredicate, compilePredicate, emitVerifiedPredicate, createPredicateEvaluator, suggest, effectfulFromAtoms, formatPredicateDiagnostics, PredicateFuelExhausted, type PredicateDiagnostic, type PredicateVerifyResult, type VerifyPredicateOptions, type CompilePredicateOptions, type EmitPredicateResult, type PredicateEvaluatorOptions, type Suggestion, type SuggestOptions, } from './predicate';
29
29
  export { compilePredicateSchema, validatePredicateSchema, type PredicateSchema, type SchemaError, type SchemaValidationResult, type PredicateSchemaOptions, } from './predicate-schema';
30
30
  export { transformFunction } from './emitters/ast';
31
31
  export { transpileToJS, stripModuleSyntax, stripTjsPreamble, type TJSTranspileOptions, type TJSTranspileResult, type TJSTypeInfo, } from './emitters/js';
32
32
  export { generateDTS, typeDescriptorToTS, type GenerateDTSOptions, } from './emitters/dts';
33
- export { fromTS, type FromTSOptions, type FromTSResult, } from './emitters/from-ts';
33
+ export type { FromTSOptions, FromTSResult } from './emitters/from-ts';
34
34
  export * from './inference';
35
35
  export { Schema } from './schema';
36
36
  export { typeDescriptorToJSONSchema, exampleToJSONSchema, functionMetaToJSONSchema, type JSONSchemaObject, } from './json-schema';
@@ -5,6 +5,7 @@
5
5
  * These operate on raw source strings before Acorn parsing.
6
6
  */
7
7
  import type { WasmBlock, TestBlock } from './parser-types';
8
+ import type { PredicateVerification } from './types';
8
9
  export declare function transformTryWithoutCatch(source: string): string;
9
10
  /**
10
11
  * Extract WASM blocks from source and replace with runtime dispatch code
@@ -144,12 +145,15 @@ export declare function transformIsOperators(source: string): string;
144
145
  */
145
146
  export declare function insertAsiProtection(source: string): string;
146
147
  /**
147
- * Transform == and != to Is() and IsNot() calls
148
+ * Transform == and != to Eq() and NotEq() calls
148
149
  *
149
150
  * In TJS normal mode:
150
- * a == b -> Is(a, b) (structural equality)
151
- * a != b -> IsNot(a, b) (structural inequality)
151
+ * a == b -> Eq(a, b) (footgun-free ===: unwraps boxed primitives,
152
+ * null == undefined, but does NOT coerce types and
153
+ * is NOT structural — see PRINCIPLES/guides)
154
+ * a != b -> NotEq(a, b)
152
155
  * a === b -> a === b (identity, unchanged)
156
+ * (For deep structural equality use the explicit `Is`/`IsNot` operators.)
153
157
  *
154
158
  * Uses a two-pass algorithm:
155
159
  * 1. Find all == and != positions (outside strings/comments/regex)
@@ -169,7 +173,7 @@ export declare function transformEqualityToStructural(source: string): string;
169
173
  *
170
174
  * When predicate + example: auto-generate type guard from example
171
175
  */
172
- export declare function transformTypeDeclarations(source: string): string;
176
+ export declare function transformTypeDeclarations(source: string, report?: PredicateVerification[]): string;
173
177
  /**
174
178
  * Transform FunctionPredicate declarations
175
179
  *
@@ -203,7 +207,7 @@ export declare function transformFunctionPredicateDeclarations(source: string):
203
207
  * const Pair = Generic(['T', 'U'], (obj, checkT, checkU) => { ... }, '...')
204
208
  * const Container = Generic(['T', ['U', '']], (obj, checkT, checkU) => { ... }, '...')
205
209
  */
206
- export declare function transformGenericDeclarations(source: string): string;
210
+ export declare function transformGenericDeclarations(source: string, report?: PredicateVerification[]): string;
207
211
  /**
208
212
  * Transform Union declarations
209
213
  *
@@ -5,6 +5,7 @@
5
5
  * Transform functions are in parser-transforms.ts, param processing in parser-params.ts.
6
6
  */
7
7
  import type { Program, FunctionDeclaration } from 'acorn';
8
+ import type { PredicateVerification } from './types';
8
9
  export type { ParseOptions, WasmBlock, TestBlock, PreprocessOptions, TjsModes, } from './parser-types';
9
10
  import type { ParseOptions, WasmBlock, TestBlock, PreprocessOptions, TjsModes } from './parser-types';
10
11
  export { transformExtensionCalls } from './parser-transforms';
@@ -30,6 +31,7 @@ export declare function preprocess(source: string, options?: PreprocessOptions):
30
31
  polymorphicNames: Set<string>;
31
32
  extensions: Map<string, Set<string>>;
32
33
  letAnnotations: Map<string, string>;
34
+ predicates: PredicateVerification[];
33
35
  };
34
36
  /**
35
37
  * Parse source code into an Acorn AST
@@ -101,3 +101,63 @@ export interface CompilePredicateOptions extends VerifyPredicateOptions {
101
101
  * opt-in). Emission is offset-spliced source, not a full AJS-AST→JS codegen.
102
102
  */
103
103
  export declare function compilePredicate(source: string, exportNames: string[], opts?: CompilePredicateOptions): Record<string, (...args: any[]) => any>;
104
+ export interface EmitPredicateResult {
105
+ /** True iff the cluster passed predicate-safety verification. */
106
+ safe: boolean;
107
+ /**
108
+ * When `safe`, a self-contained JS **expression** that evaluates to the guard
109
+ * function `(...args) => boolean`. Inline it directly into transpiler output —
110
+ * it carries its own fuel counter (no global `__fuel`, no runtime dependency
111
+ * on the predicate engine or the `PredicateFuelExhausted` class). Undefined
112
+ * when `!safe`.
113
+ */
114
+ code?: string;
115
+ /** Verifier diagnostics (the reasons, when `!safe`). */
116
+ diagnostics: PredicateDiagnostic[];
117
+ }
118
+ /**
119
+ * Verify a predicate cluster and, if safe, emit a **self-contained source
120
+ * expression** for its guard — the transpile-time counterpart to
121
+ * `compilePredicate` (which evals to live closures). This is what lets a
122
+ * verified `Type`/`FunctionPredicate` predicate compile to a fuel-bounded native
123
+ * guard in standalone output: no import of this module, no shared runtime.
124
+ *
125
+ * Fuel model mirrors `compilePredicate` (function-entry `__fuel()` bounds all
126
+ * iteration since loops are rejected), but because a guard answers a boolean
127
+ * question, a runaway input **returns `false`** ("not a valid instance of this
128
+ * type") instead of throwing — DoS-safe validation that never crashes the caller.
129
+ * A deep-recursion stack overflow is the same runaway signal, normalized the
130
+ * same way.
131
+ *
132
+ * The runtime effectful-global shadow that `compilePredicate` applies is omitted
133
+ * here on purpose: a `safe` cluster provably references no effectful global (the
134
+ * static verifier guarantees it), so the shadow would only bloat emitted output.
135
+ *
136
+ * @param source the predicate cluster (one or more `function` declarations)
137
+ * @param entryName which declared function is the guard entry point
138
+ * @param opts verify options + `fuel` budget (default 1,000,000)
139
+ */
140
+ export declare function emitVerifiedPredicate(source: string, entryName: string, opts?: CompilePredicateOptions): EmitPredicateResult;
141
+ export interface PredicateEvaluatorOptions extends CompilePredicateOptions {
142
+ /**
143
+ * Called once per source that fails to verify/compile. Default: `console.warn`.
144
+ * The evaluator fails **closed** on such a source (returns `false`), so an
145
+ * unverifiable `$predicate` can never validate a value as `true`.
146
+ */
147
+ onUnsafe?: (source: string, error: Error) => void;
148
+ }
149
+ /**
150
+ * Build a pluggable `$predicate` evaluator: `(source, value) => boolean`.
151
+ *
152
+ * This is the bridge for a predicate-aware JSON-Schema validator that lives in
153
+ * another package (e.g. `tosijs-schema`, which cannot depend on `tjs-lang` — the
154
+ * dependency runs the other way). Such a validator stays zero-dep and exposes a
155
+ * hook; a consumer that has this engine injects an evaluator built here.
156
+ *
157
+ * Each distinct source is verified + compiled **once** and cached, so repeated
158
+ * validation is just a native call. Semantics match `compilePredicateSchema`:
159
+ * the LAST top-level function is the entry; a source that isn't predicate-safe
160
+ * (or throws / exhausts fuel at runtime) yields `false` — never a thrown error
161
+ * mid-validation, never a silent pass.
162
+ */
163
+ export declare function createPredicateEvaluator(opts?: PredicateEvaluatorOptions): (source: string, value: unknown) => boolean;
@@ -12,9 +12,10 @@
12
12
  export { transpile, ajs, tjs, createAgent, getToolDefinitions } from './core';
13
13
  export { parse, preprocess, extractTDoc } from './parser';
14
14
  export { dialectForFilename, sourceKindForFilename, type Dialect, type SourceKind, } from './dialect';
15
- export { verifyPredicate, compilePredicate, suggest, effectfulFromAtoms, formatPredicateDiagnostics, PredicateFuelExhausted, type PredicateDiagnostic, type PredicateVerifyResult, type VerifyPredicateOptions, type CompilePredicateOptions, type Suggestion, type SuggestOptions, } from './predicate';
15
+ export { verifyPredicate, compilePredicate, emitVerifiedPredicate, createPredicateEvaluator, suggest, effectfulFromAtoms, formatPredicateDiagnostics, PredicateFuelExhausted, type PredicateDiagnostic, type PredicateVerifyResult, type VerifyPredicateOptions, type CompilePredicateOptions, type EmitPredicateResult, type PredicateEvaluatorOptions, type Suggestion, type SuggestOptions, } from './predicate';
16
16
  export { compilePredicateSchema, validatePredicateSchema, type PredicateSchema, type SchemaError, type SchemaValidationResult, type PredicateSchemaOptions, } from './predicate-schema';
17
17
  export { transformFunction } from './emitters/ast';
18
+ export { generateDTS, typeDescriptorToTS, type GenerateDTSOptions, } from './emitters/dts';
18
19
  export { transpileToJS } from './emitters/js';
19
20
  export type { TJSTranspileOptions, TJSTranspileResult, TJSTypeInfo, } from './emitters/js';
20
21
  export * from './inference';
@@ -25,4 +26,4 @@ export { extractTests, assertFunction, expectFunction, testUtils, } from './test
25
26
  export type { ExtractedTest, ExtractedMock, TestExtractionResult, } from './tests';
26
27
  export { runtime, installRuntime, isError, error, typeOf, checkType, validateArgs, wrap, emitRuntimeWrapper, TJS_VERSION, } from './runtime';
27
28
  export type { TJSError } from './runtime';
28
- export type { TypeDescriptor, ParameterDescriptor, FunctionSignature, TranspileOptions, TranspileResult, TranspileWarning, } from './types';
29
+ export type { TypeDescriptor, ParameterDescriptor, FunctionSignature, TranspileOptions, TranspileResult, TranspileWarning, PredicateVerification, } from './types';
@@ -77,6 +77,22 @@ export interface TranspileWarning {
77
77
  column: number;
78
78
  source?: string;
79
79
  }
80
+ /**
81
+ * Per-declaration report of whether a `Type`/`Generic` predicate body verified
82
+ * as predicate-safe (→ compiled to a fuel-bounded, DoS-safe native guard) or
83
+ * fell back to a plain unverified function (still valid — TJS ⊇ JS — but not
84
+ * fuel-bounded or safe to run on untrusted data). Surfaced on the transpile
85
+ * result so tools can flag unverifiable predicates.
86
+ */
87
+ export interface PredicateVerification {
88
+ /** The `Type` / `Generic` declaration name. */
89
+ name: string;
90
+ kind: 'Type' | 'Generic';
91
+ /** True → verified + compiled to a native guard; false → raw-function fallback. */
92
+ verified: boolean;
93
+ /** When `!verified`, the verifier's reason(s). */
94
+ reason?: string;
95
+ }
80
96
  /** Source map for debugging */
81
97
  export interface SourceMap {
82
98
  version: 3;
@@ -0,0 +1,12 @@
1
+ import { type PredicateEvaluatorOptions } from '../lang/predicate';
2
+ export * from 'tosijs-schema';
3
+ export { createPredicateEvaluator, type PredicateEvaluatorOptions, } from '../lang/predicate';
4
+ /**
5
+ * Register tjs-lang's predicate engine as tosijs-schema's `$predicate` evaluator.
6
+ * Called automatically when this module is imported; exposed so callers can
7
+ * re-install with custom {@link PredicateEvaluatorOptions} (e.g. a smaller fuel
8
+ * budget, or an atom-aware effectful set) after opting out.
9
+ */
10
+ export declare function installPredicateSupport(opts?: PredicateEvaluatorOptions): void;
11
+ /** True once predicate support has been installed (and not since cleared). */
12
+ export declare function predicateSupportInstalled(): boolean;