@seljs/checker 1.0.0 → 1.0.1

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 (124) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/_virtual/_rolldown/runtime.cjs +23 -0
  3. package/dist/checker/checker.cjs +482 -0
  4. package/dist/checker/checker.d.cts +176 -0
  5. package/dist/checker/checker.d.mts +176 -0
  6. package/dist/checker/checker.mjs +481 -0
  7. package/dist/checker/diagnostics.cjs +66 -0
  8. package/dist/checker/diagnostics.mjs +66 -0
  9. package/dist/checker/index.cjs +2 -0
  10. package/dist/checker/index.d.mts +2 -0
  11. package/dist/checker/index.mjs +3 -0
  12. package/dist/checker/type-compatibility.cjs +70 -0
  13. package/dist/checker/type-compatibility.d.cts +8 -0
  14. package/dist/checker/type-compatibility.d.mts +8 -0
  15. package/dist/checker/type-compatibility.mjs +69 -0
  16. package/dist/constants.cjs +14 -0
  17. package/dist/constants.d.cts +7 -0
  18. package/dist/constants.d.mts +7 -0
  19. package/dist/constants.mjs +13 -0
  20. package/dist/debug.cjs +7 -0
  21. package/dist/debug.mjs +5 -0
  22. package/dist/environment/codec-registry.cjs +109 -0
  23. package/dist/environment/codec-registry.d.cts +45 -0
  24. package/dist/environment/codec-registry.d.mts +45 -0
  25. package/dist/environment/codec-registry.mjs +108 -0
  26. package/dist/environment/hydrate.cjs +163 -0
  27. package/dist/environment/hydrate.d.cts +52 -0
  28. package/dist/environment/hydrate.d.mts +52 -0
  29. package/dist/environment/hydrate.mjs +160 -0
  30. package/dist/environment/index.cjs +4 -0
  31. package/dist/environment/index.d.mts +4 -0
  32. package/dist/environment/index.mjs +5 -0
  33. package/dist/environment/register-types.cjs +107 -0
  34. package/dist/environment/register-types.d.cts +15 -0
  35. package/dist/environment/register-types.d.mts +15 -0
  36. package/dist/environment/register-types.mjs +106 -0
  37. package/dist/environment/value-wrappers.cjs +44 -0
  38. package/dist/environment/value-wrappers.d.cts +20 -0
  39. package/dist/environment/value-wrappers.d.mts +20 -0
  40. package/dist/environment/value-wrappers.mjs +41 -0
  41. package/dist/index.cjs +27 -0
  42. package/dist/index.d.cts +11 -0
  43. package/dist/index.d.mts +11 -0
  44. package/dist/index.mjs +13 -0
  45. package/dist/rules/defaults/deferred-call.cjs +107 -0
  46. package/dist/rules/defaults/deferred-call.mjs +106 -0
  47. package/dist/rules/defaults/index.cjs +6 -0
  48. package/dist/rules/defaults/index.mjs +7 -0
  49. package/dist/rules/defaults/no-constant-condition.cjs +31 -0
  50. package/dist/rules/defaults/no-constant-condition.mjs +31 -0
  51. package/dist/rules/defaults/no-mixed-operators.cjs +39 -0
  52. package/dist/rules/defaults/no-mixed-operators.mjs +39 -0
  53. package/dist/rules/defaults/no-redundant-bool.cjs +26 -0
  54. package/dist/rules/defaults/no-redundant-bool.mjs +26 -0
  55. package/dist/rules/defaults/no-self-comparison.cjs +44 -0
  56. package/dist/rules/defaults/no-self-comparison.mjs +43 -0
  57. package/dist/rules/defaults/require-type.cjs +18 -0
  58. package/dist/rules/defaults/require-type.mjs +18 -0
  59. package/dist/rules/facade.cjs +31 -0
  60. package/dist/rules/facade.d.cts +20 -0
  61. package/dist/rules/facade.d.mts +20 -0
  62. package/dist/rules/facade.mjs +31 -0
  63. package/dist/rules/index.cjs +2 -0
  64. package/dist/rules/index.d.mts +3 -0
  65. package/dist/rules/index.mjs +3 -0
  66. package/dist/rules/runner.cjs +40 -0
  67. package/dist/rules/runner.d.cts +27 -0
  68. package/dist/rules/runner.d.mts +27 -0
  69. package/dist/rules/runner.mjs +40 -0
  70. package/dist/rules/types.d.cts +77 -0
  71. package/dist/rules/types.d.mts +77 -0
  72. package/dist/utils/ast-utils.cjs +164 -0
  73. package/dist/utils/ast-utils.mjs +162 -0
  74. package/package.json +24 -17
  75. package/dist/checker/checker.d.ts +0 -173
  76. package/dist/checker/checker.js +0 -567
  77. package/dist/checker/diagnostics.d.ts +0 -10
  78. package/dist/checker/diagnostics.js +0 -80
  79. package/dist/checker/index.d.ts +0 -2
  80. package/dist/checker/index.js +0 -2
  81. package/dist/checker/type-compatibility.d.ts +0 -16
  82. package/dist/checker/type-compatibility.js +0 -59
  83. package/dist/constants.d.ts +0 -4
  84. package/dist/constants.js +0 -10
  85. package/dist/debug.d.ts +0 -2
  86. package/dist/debug.js +0 -2
  87. package/dist/environment/codec-registry.d.ts +0 -42
  88. package/dist/environment/codec-registry.js +0 -146
  89. package/dist/environment/hydrate.d.ts +0 -48
  90. package/dist/environment/hydrate.js +0 -198
  91. package/dist/environment/index.d.ts +0 -4
  92. package/dist/environment/index.js +0 -4
  93. package/dist/environment/register-types.d.ts +0 -14
  94. package/dist/environment/register-types.js +0 -154
  95. package/dist/environment/value-wrappers.d.ts +0 -17
  96. package/dist/environment/value-wrappers.js +0 -65
  97. package/dist/index.d.ts +0 -4
  98. package/dist/index.js +0 -4
  99. package/dist/rules/defaults/deferred-call.d.ts +0 -13
  100. package/dist/rules/defaults/deferred-call.js +0 -162
  101. package/dist/rules/defaults/index.d.ts +0 -6
  102. package/dist/rules/defaults/index.js +0 -6
  103. package/dist/rules/defaults/no-constant-condition.d.ts +0 -7
  104. package/dist/rules/defaults/no-constant-condition.js +0 -36
  105. package/dist/rules/defaults/no-mixed-operators.d.ts +0 -9
  106. package/dist/rules/defaults/no-mixed-operators.js +0 -44
  107. package/dist/rules/defaults/no-redundant-bool.d.ts +0 -5
  108. package/dist/rules/defaults/no-redundant-bool.js +0 -27
  109. package/dist/rules/defaults/no-self-comparison.d.ts +0 -9
  110. package/dist/rules/defaults/no-self-comparison.js +0 -31
  111. package/dist/rules/defaults/require-type.d.ts +0 -7
  112. package/dist/rules/defaults/require-type.js +0 -19
  113. package/dist/rules/facade.d.ts +0 -22
  114. package/dist/rules/facade.js +0 -29
  115. package/dist/rules/index.d.ts +0 -3
  116. package/dist/rules/index.js +0 -3
  117. package/dist/rules/runner.d.ts +0 -16
  118. package/dist/rules/runner.js +0 -30
  119. package/dist/rules/types.d.ts +0 -73
  120. package/dist/rules/types.js +0 -1
  121. package/dist/utils/ast-utils.d.ts +0 -55
  122. package/dist/utils/ast-utils.js +0 -255
  123. package/dist/utils/index.d.ts +0 -1
  124. package/dist/utils/index.js +0 -1
@@ -1,59 +0,0 @@
1
- const LOGICAL_OPERATORS = new Set(["&&", "||"]);
2
- const ARITHMETIC_OPERATORS = new Set(["+", "-", "*", "/", "%"]);
3
- const COMPARISON_OPERATORS = new Set(["<", "<=", ">", ">="]);
4
- const EQUALITY_OPERATORS = new Set(["==", "!="]);
5
- /** Types that support arithmetic operators (same-type only). */
6
- const ARITHMETIC_TYPES = new Set(["int", "uint", "double", "sol_int"]);
7
- /** Types that support the + operator for concatenation. */
8
- const CONCATENATION_TYPES = new Set(["string", "list", "bytes"]);
9
- /** Types that support comparison operators (same-type only). */
10
- const COMPARISON_TYPES = new Set([
11
- "int",
12
- "uint",
13
- "double",
14
- "string",
15
- "bytes",
16
- "sol_address",
17
- "sol_int",
18
- ]);
19
- /**
20
- * Given the type of the left operand and the operator,
21
- * returns the expected type for the right operand.
22
- *
23
- * Based on the registered operators in register-types.ts.
24
- * Type compatibility is strictly same-type (no implicit coercion).
25
- *
26
- * Returns undefined when the type/operator combination is unknown,
27
- * signaling that no narrowing should occur.
28
- */
29
- export const expectedTypeForOperator = (leftType, operator) => {
30
- if (LOGICAL_OPERATORS.has(operator)) {
31
- return "bool";
32
- }
33
- if (ARITHMETIC_OPERATORS.has(operator)) {
34
- if (ARITHMETIC_TYPES.has(leftType)) {
35
- return leftType;
36
- }
37
- if (operator === "+" && CONCATENATION_TYPES.has(leftType)) {
38
- return leftType;
39
- }
40
- return undefined;
41
- }
42
- if (COMPARISON_OPERATORS.has(operator)) {
43
- return COMPARISON_TYPES.has(leftType) ? leftType : undefined;
44
- }
45
- if (EQUALITY_OPERATORS.has(operator)) {
46
- return leftType;
47
- }
48
- return undefined;
49
- };
50
- /**
51
- * Check if a candidate type is compatible with an expected type.
52
- * "dyn" is a wildcard — compatible with anything in either direction.
53
- */
54
- export const isTypeCompatible = (candidateType, expectedType) => {
55
- if (expectedType === "dyn" || candidateType === "dyn") {
56
- return true;
57
- }
58
- return candidateType === expectedType;
59
- };
@@ -1,4 +0,0 @@
1
- /** Comprehension macro names that introduce scoped iteration variables. */
2
- export declare const COMPREHENSION_MACROS: Set<string>;
3
- /** Solidity scalar wrapper functions (pass-through for arg classification). */
4
- export declare const SCALAR_WRAPPER_FUNCTIONS: Set<string>;
package/dist/constants.js DELETED
@@ -1,10 +0,0 @@
1
- /** Comprehension macro names that introduce scoped iteration variables. */
2
- export const COMPREHENSION_MACROS = new Set([
3
- "map",
4
- "filter",
5
- "exists",
6
- "all",
7
- "exists_one",
8
- ]);
9
- /** Solidity scalar wrapper functions (pass-through for arg classification). */
10
- export const SCALAR_WRAPPER_FUNCTIONS = new Set(["solInt", "solAddress"]);
package/dist/debug.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import createDebug from "debug";
2
- export declare const createLogger: (namespace: string) => createDebug.Debugger;
package/dist/debug.js DELETED
@@ -1,2 +0,0 @@
1
- import createDebug from "debug";
2
- export const createLogger = (namespace) => createDebug(`sel:checker:${namespace}`);
@@ -1,42 +0,0 @@
1
- import { z } from "zod";
2
- type AnyCodec = z.ZodType;
3
- /**
4
- * Struct descriptor provided to CelCodecRegistry.
5
- */
6
- export interface StructCodecDescriptor {
7
- name: string;
8
- ctor: new () => object;
9
- fieldNames: string[];
10
- fieldTypes: Record<string, string>;
11
- }
12
- /**
13
- * Options for constructing a CelCodecRegistry.
14
- */
15
- export interface CelCodecRegistryOptions {
16
- structs?: StructCodecDescriptor[];
17
- }
18
- /**
19
- * Registry that maps CEL type strings to bidirectional Zod 4 codecs.
20
- * Immutable after construction — all codecs resolved eagerly.
21
- */
22
- export declare class CelCodecRegistry {
23
- private readonly codecs;
24
- private readonly structMetas;
25
- constructor(options?: CelCodecRegistryOptions);
26
- /**
27
- * Resolve a codec for the given CEL type string.
28
- * Handles `list<T>` container types by composing element codecs.
29
- * Unknown types fall back to z.unknown().
30
- */
31
- resolve(celType: string): AnyCodec;
32
- /**
33
- * Encode a CEL value back to its raw form using the codec for the given type.
34
- * For bidirectional codecs (SolidityAddress, SolidityInt) this calls .encode().
35
- * For structs, it recursively encodes each field.
36
- * For passthrough types (bool, string, int), returns the value as-is.
37
- */
38
- encode(celType: string, value: unknown): unknown;
39
- private buildStructCodec;
40
- private decodeField;
41
- }
42
- export {};
@@ -1,146 +0,0 @@
1
- import { SolidityAddressTypeWrapper, SolidityIntTypeWrapper, } from "@seljs/types";
2
- import { z } from "zod";
3
- const solidityAddressCodec = z.codec(z.string(), z.instanceof(SolidityAddressTypeWrapper), {
4
- decode: (s) => new SolidityAddressTypeWrapper(s),
5
- encode: (w) => w.value,
6
- });
7
- const solidityIntCodec = z.codec(z.union([z.bigint(), z.number().transform((n) => BigInt(n))]), z.instanceof(SolidityIntTypeWrapper), {
8
- decode: (n) => new SolidityIntTypeWrapper(n),
9
- encode: (w) => w.value,
10
- });
11
- /**
12
- * Registry that maps CEL type strings to bidirectional Zod 4 codecs.
13
- * Immutable after construction — all codecs resolved eagerly.
14
- */
15
- export class CelCodecRegistry {
16
- codecs;
17
- structMetas;
18
- constructor(options) {
19
- this.codecs = new Map();
20
- this.structMetas = new Map();
21
- // Register base codecs
22
- this.codecs.set("sol_address", solidityAddressCodec);
23
- this.codecs.set("sol_int", solidityIntCodec);
24
- this.codecs.set("bool", z.boolean());
25
- this.codecs.set("string", z.string());
26
- this.codecs.set("int", z.bigint());
27
- this.codecs.set("bytes", z.union([
28
- z.instanceof(Uint8Array),
29
- z.string().transform((s) => {
30
- const hex = s.startsWith("0x") ? s.slice(2) : s;
31
- const bytes = new Uint8Array(hex.length / 2);
32
- for (let i = 0; i < bytes.length; i++) {
33
- bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
34
- }
35
- return bytes;
36
- }),
37
- ]));
38
- this.codecs.set("dyn", z
39
- .unknown()
40
- .transform((v) => typeof v === "bigint" ? new SolidityIntTypeWrapper(v) : v));
41
- // Register struct codecs eagerly
42
- for (const desc of options?.structs ?? []) {
43
- this.codecs.set(desc.name, this.buildStructCodec(desc));
44
- this.structMetas.set(desc.name, {
45
- fieldNames: desc.fieldNames,
46
- fieldTypes: desc.fieldTypes,
47
- });
48
- }
49
- }
50
- /**
51
- * Resolve a codec for the given CEL type string.
52
- * Handles `list<T>` container types by composing element codecs.
53
- * Unknown types fall back to z.unknown().
54
- */
55
- resolve(celType) {
56
- // Handle list<T> container type
57
- const listMatch = /^list<(.+)>$/.exec(celType);
58
- if (listMatch) {
59
- const elementCodec = this.resolve(listMatch[1]);
60
- return z.array(elementCodec);
61
- }
62
- return this.codecs.get(celType) ?? z.unknown();
63
- }
64
- /**
65
- * Encode a CEL value back to its raw form using the codec for the given type.
66
- * For bidirectional codecs (SolidityAddress, SolidityInt) this calls .encode().
67
- * For structs, it recursively encodes each field.
68
- * For passthrough types (bool, string, int), returns the value as-is.
69
- */
70
- encode(celType, value) {
71
- // Handle bytes — convert Uint8Array back to hex string for viem
72
- if (celType === "bytes") {
73
- if (value instanceof Uint8Array) {
74
- return ("0x" +
75
- Array.from(value)
76
- .map((b) => b.toString(16).padStart(2, "0"))
77
- .join(""));
78
- }
79
- return value;
80
- }
81
- // Handle dyn — unwrap known wrapper types
82
- if (celType === "dyn") {
83
- if (value instanceof SolidityIntTypeWrapper) {
84
- return value.value;
85
- }
86
- if (value instanceof SolidityAddressTypeWrapper) {
87
- return value.value;
88
- }
89
- return value;
90
- }
91
- // Handle list<T>
92
- const listMatch = /^list<(.+)>$/.exec(celType);
93
- if (listMatch && Array.isArray(value)) {
94
- const elementType = listMatch[1];
95
- return value.map((item) => this.encode(elementType, item));
96
- }
97
- // Handle structs — recurse into fields
98
- const structMeta = this.structMetas.get(celType);
99
- if (structMeta) {
100
- const raw = value;
101
- const result = {};
102
- for (const name of structMeta.fieldNames) {
103
- result[name] = this.encode(structMeta.fieldTypes[name] ?? "dyn", raw[name]);
104
- }
105
- return result;
106
- }
107
- // For bidirectional codecs, use .encode(); for passthrough, return as-is
108
- const codec = this.codecs.get(celType);
109
- if (!codec) {
110
- return value;
111
- }
112
- try {
113
- return codec.encode(value);
114
- }
115
- catch {
116
- return value;
117
- }
118
- }
119
- buildStructCodec(desc) {
120
- const { ctor, fieldNames, fieldTypes } = desc;
121
- // Build a transform that accepts array (positional) or object input
122
- return z.unknown().transform((input) => {
123
- let data;
124
- if (Array.isArray(input)) {
125
- // Positional multi-return from viem
126
- data = Object.fromEntries(fieldNames.map((name, i) => [
127
- name,
128
- this.decodeField(fieldTypes[name] ?? "dyn", input[i]),
129
- ]));
130
- }
131
- else {
132
- // Named-field object
133
- const raw = input;
134
- data = Object.fromEntries(fieldNames.map((name) => [
135
- name,
136
- this.decodeField(fieldTypes[name] ?? "dyn", raw[name]),
137
- ]));
138
- }
139
- // eslint-disable-next-line new-cap
140
- return Object.assign(new ctor(), data);
141
- });
142
- }
143
- decodeField(celType, value) {
144
- return this.resolve(celType).parse(value);
145
- }
146
- }
@@ -1,48 +0,0 @@
1
- import { Environment } from "@marcbachmann/cel-js";
2
- import { CelCodecRegistry } from "./codec-registry.js";
3
- import type { SELSchema } from "@seljs/schema";
4
- /**
5
- * CEL environment limits configuration.
6
- */
7
- export interface CelLimits {
8
- maxAstNodes?: number;
9
- maxDepth?: number;
10
- maxListElements?: number;
11
- maxMapEntries?: number;
12
- maxCallArguments?: number;
13
- }
14
- /**
15
- * Handler called when a contract method is invoked at runtime.
16
- */
17
- export type ContractCallHandler = (contractName: string, methodName: string, args: unknown[]) => unknown;
18
- /**
19
- * Create a base CEL environment with Solidity types registered.
20
- * No contracts, no variables — just the type system.
21
- *
22
- * Use this when you need to register contracts and variables yourself
23
- * (e.g., runtime evaluation with real async handlers).
24
- */
25
- export declare const createBaseEnvironment: (options?: {
26
- limits?: CelLimits;
27
- }) => Environment;
28
- /**
29
- * Create a fully hydrated checker environment from a SELSchema.
30
- *
31
- * Registers Solidity primitive types, contract types with their methods
32
- * (using no-op handlers since the checker only needs type information),
33
- * schema variables, and built-in functions.
34
- */
35
- export declare const createCheckerEnvironment: (schema: SELSchema) => Environment;
36
- export interface RuntimeEnvironmentResult {
37
- env: Environment;
38
- contractBindings: Record<string, unknown>;
39
- codecRegistry: CelCodecRegistry;
40
- }
41
- /**
42
- * Create a fully hydrated runtime environment from a SELSchema with a
43
- * real async handler for contract method calls.
44
- */
45
- export declare const createRuntimeEnvironment: (schema: SELSchema, handler: ContractCallHandler, options?: {
46
- limits?: CelLimits;
47
- unlistedVariablesAreDyn?: boolean;
48
- }) => RuntimeEnvironmentResult;
@@ -1,198 +0,0 @@
1
- import { Environment } from "@marcbachmann/cel-js";
2
- import { contractTypeName } from "@seljs/common";
3
- import { createLogger } from "../debug.js";
4
- import { CelCodecRegistry } from "./codec-registry.js";
5
- import { registerSolidityTypes } from "./register-types.js";
6
- import { toCelLiteralType } from "./value-wrappers.js";
7
- const debug = createLogger("hydrate");
8
- const hydrateEnvironment = (env, schema, handler) => {
9
- const contractBindings = {};
10
- const structRegistry = new Map();
11
- // Register struct types from schema (nested types appear before parents)
12
- for (const type of schema.types) {
13
- if (type.kind === "struct" && type.fields) {
14
- const fields = {};
15
- for (const field of type.fields) {
16
- fields[field.name] = field.type;
17
- }
18
- try {
19
- if (handler !== undefined) {
20
- // Runtime mode: register WITH ctor so structs can be instantiated
21
- // eslint-disable-next-line @typescript-eslint/no-extraneous-class
22
- const StructCtor = class {
23
- };
24
- env.registerType(type.name, { ctor: StructCtor, fields });
25
- structRegistry.set(type.name, {
26
- ctor: StructCtor,
27
- fieldNames: Object.keys(fields),
28
- fieldTypes: fields,
29
- });
30
- }
31
- else {
32
- // Checker mode: no ctor needed
33
- env.registerType(type.name, { fields });
34
- }
35
- }
36
- catch (err) {
37
- debug("skipped type %s: %O", type.name, err);
38
- }
39
- }
40
- }
41
- const codecRegistry = handler !== undefined
42
- ? new CelCodecRegistry({
43
- structs: Array.from(structRegistry.entries()).map(([name, info]) => ({
44
- name,
45
- ...info,
46
- })),
47
- })
48
- : undefined;
49
- // Register contract types and methods
50
- for (const contract of schema.contracts) {
51
- const typeName = contractTypeName(contract.name);
52
- class ContractType {
53
- name;
54
- constructor(name) {
55
- this.name = name;
56
- }
57
- }
58
- env
59
- .registerType(typeName, { ctor: ContractType, fields: {} })
60
- .registerVariable(contract.name, typeName);
61
- contractBindings[contract.name] = new ContractType(contract.name);
62
- /* eslint-disable @typescript-eslint/no-unsafe-argument */
63
- for (const method of contract.methods) {
64
- const returnType = method.returns || "dyn";
65
- const methodHandler = handler !== undefined
66
- ? async (...args) => {
67
- const raw = await handler(contract.name, method.name, args.slice(1));
68
- if (!codecRegistry) {
69
- throw new Error("codecRegistry is required when handler is provided");
70
- }
71
- return codecRegistry.resolve(returnType).parse(raw);
72
- }
73
- : () => undefined;
74
- // Primary overload with schema param types
75
- try {
76
- env.registerFunction({
77
- name: method.name,
78
- receiverType: typeName,
79
- returnType,
80
- handler: methodHandler,
81
- params: method.params.map((param) => ({
82
- name: param.name,
83
- type: param.type,
84
- })),
85
- }, undefined);
86
- }
87
- catch (err) {
88
- debug("skipped method %s.%s: %O", contract.name, method.name, err);
89
- }
90
- // CEL literal type overloads for SolidityInt/SolidityAddress params
91
- const hasCustomParams = method.params.some((p) => toCelLiteralType(p.type) !== null);
92
- if (hasCustomParams) {
93
- try {
94
- env.registerFunction({
95
- name: method.name,
96
- receiverType: typeName,
97
- returnType,
98
- handler: methodHandler,
99
- params: method.params.map((param) => ({
100
- name: param.name,
101
- type: toCelLiteralType(param.type) ?? param.type,
102
- })),
103
- }, undefined);
104
- }
105
- catch (err) {
106
- debug("skipped literal overload %s.%s: %O", contract.name, method.name, err);
107
- }
108
- }
109
- }
110
- /* eslint-enable @typescript-eslint/no-unsafe-argument */
111
- }
112
- // Register variables
113
- for (const variable of schema.variables) {
114
- try {
115
- env.registerVariable(variable.name, variable.type);
116
- }
117
- catch (err) {
118
- debug("variable %s: fallback to dyn: %O", variable.name, err);
119
- env.registerVariable(variable.name, "dyn");
120
- }
121
- }
122
- // Register schema functions with receiverType for type-checking
123
- for (const fn of schema.functions) {
124
- if (!fn.receiverType) {
125
- continue;
126
- }
127
- try {
128
- /* eslint-disable @typescript-eslint/no-unsafe-argument */
129
- env.registerFunction({
130
- name: fn.name,
131
- receiverType: fn.receiverType,
132
- returnType: fn.returns,
133
- handler: () => undefined,
134
- params: fn.params.map((param) => ({
135
- name: param.name,
136
- type: param.type,
137
- })),
138
- }, undefined);
139
- /* eslint-enable @typescript-eslint/no-unsafe-argument */
140
- }
141
- catch (err) {
142
- // Skip functions that are already registered as CEL builtins
143
- if (!(err instanceof Error) ||
144
- !err.message.includes("overlaps with existing overload")) {
145
- throw err;
146
- }
147
- debug("skipped overlapping overload: %O", err);
148
- }
149
- }
150
- return { contractBindings, codecRegistry };
151
- };
152
- /**
153
- * Create a base CEL environment with Solidity types registered.
154
- * No contracts, no variables — just the type system.
155
- *
156
- * Use this when you need to register contracts and variables yourself
157
- * (e.g., runtime evaluation with real async handlers).
158
- */
159
- export const createBaseEnvironment = (options) => {
160
- const env = new Environment({
161
- unlistedVariablesAreDyn: false,
162
- ...(options?.limits ? { limits: options.limits } : {}),
163
- });
164
- registerSolidityTypes(env);
165
- return env;
166
- };
167
- /**
168
- * Create a fully hydrated checker environment from a SELSchema.
169
- *
170
- * Registers Solidity primitive types, contract types with their methods
171
- * (using no-op handlers since the checker only needs type information),
172
- * schema variables, and built-in functions.
173
- */
174
- export const createCheckerEnvironment = (schema) => {
175
- const env = createBaseEnvironment();
176
- hydrateEnvironment(env, schema);
177
- return env;
178
- };
179
- /**
180
- * Create a fully hydrated runtime environment from a SELSchema with a
181
- * real async handler for contract method calls.
182
- */
183
- export const createRuntimeEnvironment = (schema, handler, options) => {
184
- const env = new Environment({
185
- unlistedVariablesAreDyn: options?.unlistedVariablesAreDyn ?? false,
186
- ...(options?.limits ? { limits: options.limits } : {}),
187
- });
188
- registerSolidityTypes(env);
189
- const result = hydrateEnvironment(env, schema, handler);
190
- if (!result.codecRegistry) {
191
- throw new Error("codecRegistry is required when handler is provided");
192
- }
193
- return {
194
- env,
195
- contractBindings: result.contractBindings,
196
- codecRegistry: result.codecRegistry,
197
- };
198
- };
@@ -1,4 +0,0 @@
1
- export * from "./codec-registry.js";
2
- export * from "./hydrate.js";
3
- export * from "./register-types.js";
4
- export * from "./value-wrappers.js";
@@ -1,4 +0,0 @@
1
- export * from "./codec-registry.js";
2
- export * from "./hydrate.js";
3
- export * from "./register-types.js";
4
- export * from "./value-wrappers.js";
@@ -1,14 +0,0 @@
1
- import type { Environment } from "@marcbachmann/cel-js";
2
- /**
3
- * Subset of the CEL Environment API needed for Solidity type registration.
4
- * Mirrors the parameter signatures from Environment but drops the return type
5
- * to void — registerSolidityTypes never chains the return value.
6
- */
7
- type SolidityTypeHost = {
8
- [K in "registerType" | "registerOperator" | "registerFunction"]: (...args: Parameters<Environment[K]>) => void;
9
- };
10
- /**
11
- * Register all Solidity primitive types on a CEL Environment.
12
- */
13
- export declare const registerSolidityTypes: (env: SolidityTypeHost) => void;
14
- export {};