@constela/builder 0.2.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Constela Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,179 @@
1
+ import { LitExpr, StateExpr, VarExpr, BinaryOperator, Expression, BinExpr, NotExpr, CondExpr, GetExpr, NumberField, StringField, ListField, BooleanField, ObjectField, ActionStep, ActionDefinition, SetStep, UpdateOperation, UpdateStep, HttpMethod, FetchStep, NavigateTarget, NavigateStep, EventHandler, ViewNode, ElementNode, TextNode, IfNode, EachNode, ComponentNode, SlotNode, RouteDefinition, StateField, ComponentDef, Program } from '@constela/core';
2
+ export { ActionDefinition, ActionStep, BinExpr, BinaryOperator, BooleanField, ComponentNode, CondExpr, EachNode, ElementNode, EventHandler, Expression, FetchStep, GetExpr, HttpMethod, IfNode, ListField, LitExpr, NavigateStep, NavigateTarget, NotExpr, NumberField, ObjectField, Program, SetStep, SlotNode, StateExpr, StateField, StringField, TextNode, UpdateOperation, UpdateStep, VarExpr, ViewNode } from '@constela/core';
3
+
4
+ /**
5
+ * @constela/builder - Type-safe builders for constructing Constela AST programmatically
6
+ *
7
+ * This package provides a functional composition API for building Constela AST nodes.
8
+ * All builders return strongly-typed AST structures from @constela/core.
9
+ */
10
+
11
+ /**
12
+ * Creates a literal expression
13
+ */
14
+ declare function lit(value: string | number | boolean | null | unknown[]): LitExpr;
15
+ /**
16
+ * Creates a state expression
17
+ */
18
+ declare function state(name: string, path?: string): StateExpr;
19
+ /**
20
+ * Creates a variable expression
21
+ */
22
+ declare function variable(name: string, path?: string): VarExpr;
23
+ /**
24
+ * Creates a binary expression
25
+ */
26
+ declare function bin(op: BinaryOperator, left: Expression, right: Expression): BinExpr;
27
+ declare const add: (left: Expression, right: Expression) => BinExpr;
28
+ declare const sub: (left: Expression, right: Expression) => BinExpr;
29
+ declare const mul: (left: Expression, right: Expression) => BinExpr;
30
+ declare const divide: (left: Expression, right: Expression) => BinExpr;
31
+ declare const eq: (left: Expression, right: Expression) => BinExpr;
32
+ declare const neq: (left: Expression, right: Expression) => BinExpr;
33
+ declare const lt: (left: Expression, right: Expression) => BinExpr;
34
+ declare const lte: (left: Expression, right: Expression) => BinExpr;
35
+ declare const gt: (left: Expression, right: Expression) => BinExpr;
36
+ declare const gte: (left: Expression, right: Expression) => BinExpr;
37
+ declare const and: (left: Expression, right: Expression) => BinExpr;
38
+ declare const or: (left: Expression, right: Expression) => BinExpr;
39
+ /**
40
+ * Creates a not expression
41
+ */
42
+ declare function not(operand: Expression): NotExpr;
43
+ /**
44
+ * Creates a conditional expression
45
+ */
46
+ declare function cond(condition: Expression, thenExpr: Expression, elseExpr: Expression): CondExpr;
47
+ /**
48
+ * Creates a get expression for property access
49
+ */
50
+ declare function get(base: Expression, path: string): GetExpr;
51
+ /**
52
+ * Creates a number field
53
+ */
54
+ declare function numberField(initial: number): NumberField;
55
+ /**
56
+ * Creates a string field
57
+ */
58
+ declare function stringField(initial: string): StringField;
59
+ /**
60
+ * Creates a list field
61
+ */
62
+ declare function listField<T>(initial?: T[]): ListField;
63
+ /**
64
+ * Creates a boolean field
65
+ */
66
+ declare function booleanField(initial: boolean): BooleanField;
67
+ /**
68
+ * Creates an object field
69
+ */
70
+ declare function objectField<T extends Record<string, unknown>>(initial: T): ObjectField;
71
+ /**
72
+ * Creates an action definition
73
+ */
74
+ declare function action(name: string, steps: ActionStep[]): ActionDefinition;
75
+ /**
76
+ * Creates a set step
77
+ */
78
+ declare function set(target: string, value: Expression): SetStep;
79
+ /**
80
+ * Creates an update step
81
+ */
82
+ declare function update(target: string, operation: UpdateOperation, value?: Expression): UpdateStep;
83
+ declare const increment: (target: string, value?: Expression) => UpdateStep;
84
+ declare const decrement: (target: string, value?: Expression) => UpdateStep;
85
+ declare const push: (target: string, value: Expression) => UpdateStep;
86
+ declare const pop: (target: string) => UpdateStep;
87
+ declare const toggle: (target: string) => UpdateStep;
88
+ /**
89
+ * Fetch step options
90
+ */
91
+ interface FetchOptions {
92
+ method?: HttpMethod;
93
+ body?: Expression;
94
+ result?: string;
95
+ onSuccess?: ActionStep[];
96
+ onError?: ActionStep[];
97
+ }
98
+ /**
99
+ * Creates a fetch step
100
+ */
101
+ declare function fetch(url: Expression, options?: FetchOptions): FetchStep;
102
+ /**
103
+ * Navigate step options
104
+ */
105
+ interface NavigateOptions {
106
+ target?: NavigateTarget;
107
+ replace?: boolean;
108
+ }
109
+ /**
110
+ * Creates a navigate step
111
+ */
112
+ declare function navigate(url: Expression, options?: NavigateOptions): NavigateStep;
113
+ /**
114
+ * Creates an element node
115
+ */
116
+ declare function element(tag: string, props?: Record<string, Expression | EventHandler>, children?: ViewNode[]): ElementNode;
117
+ declare const div: (props?: Record<string, Expression | EventHandler>, children?: ViewNode[]) => ElementNode;
118
+ declare const span: (props?: Record<string, Expression | EventHandler>, children?: ViewNode[]) => ElementNode;
119
+ declare const button: (props?: Record<string, Expression | EventHandler>, children?: ViewNode[]) => ElementNode;
120
+ declare const input: (props?: Record<string, Expression | EventHandler>, children?: ViewNode[]) => ElementNode;
121
+ /**
122
+ * Creates a text node
123
+ */
124
+ declare function text(value: Expression): TextNode;
125
+ /**
126
+ * Creates an if node for conditional rendering
127
+ */
128
+ declare function ifNode(condition: Expression, then: ViewNode, elseNode?: ViewNode): IfNode;
129
+ /**
130
+ * Each node options
131
+ */
132
+ interface EachOptions {
133
+ index?: string;
134
+ key?: Expression;
135
+ }
136
+ /**
137
+ * Creates an each node for list rendering
138
+ */
139
+ declare function each(items: Expression, as: string, body: ViewNode, options?: EachOptions): EachNode;
140
+ /**
141
+ * Creates a component node
142
+ */
143
+ declare function component(name: string, props?: Record<string, Expression>, children?: ViewNode[]): ComponentNode;
144
+ /**
145
+ * Creates a slot node
146
+ */
147
+ declare function slot(name?: string): SlotNode;
148
+ /**
149
+ * Creates an onClick event handler
150
+ */
151
+ declare function onClick(action: string, payload?: Expression): EventHandler;
152
+ /**
153
+ * Creates an onInput event handler with default payload
154
+ */
155
+ declare function onInput(action: string, payload?: Expression): EventHandler;
156
+ /**
157
+ * Creates an onChange event handler with default payload
158
+ */
159
+ declare function onChange(action: string, payload?: Expression): EventHandler;
160
+ /**
161
+ * Creates an onSubmit event handler
162
+ */
163
+ declare function onSubmit(action: string, payload?: Expression): EventHandler;
164
+ /**
165
+ * Program builder options
166
+ */
167
+ interface ProgramOptions {
168
+ route?: RouteDefinition;
169
+ state: Record<string, StateField>;
170
+ actions: ActionDefinition[];
171
+ view: ViewNode;
172
+ components?: Record<string, ComponentDef>;
173
+ }
174
+ /**
175
+ * Creates a program
176
+ */
177
+ declare function createProgram(options: ProgramOptions): Program;
178
+
179
+ export { type EachOptions, type FetchOptions, type NavigateOptions, type ProgramOptions, action, add, and, bin, booleanField, button, component, cond, createProgram, decrement, div, divide, each, element, eq, fetch, get, gt, gte, ifNode, increment, input, listField, lit, lt, lte, mul, navigate, neq, not, numberField, objectField, onChange, onClick, onInput, onSubmit, or, pop, push, set, slot, span, state, stringField, sub, text, toggle, update, variable };
package/dist/index.js ADDED
@@ -0,0 +1,237 @@
1
+ // src/index.ts
2
+ function lit(value) {
3
+ return { expr: "lit", value };
4
+ }
5
+ function state(name, path) {
6
+ const result = { expr: "state", name };
7
+ if (path !== void 0) {
8
+ result.path = path;
9
+ }
10
+ return result;
11
+ }
12
+ function variable(name, path) {
13
+ const result = { expr: "var", name };
14
+ if (path !== void 0) {
15
+ result.path = path;
16
+ }
17
+ return result;
18
+ }
19
+ function bin(op, left, right) {
20
+ return { expr: "bin", op, left, right };
21
+ }
22
+ var add = (left, right) => bin("+", left, right);
23
+ var sub = (left, right) => bin("-", left, right);
24
+ var mul = (left, right) => bin("*", left, right);
25
+ var divide = (left, right) => bin("/", left, right);
26
+ var eq = (left, right) => bin("==", left, right);
27
+ var neq = (left, right) => bin("!=", left, right);
28
+ var lt = (left, right) => bin("<", left, right);
29
+ var lte = (left, right) => bin("<=", left, right);
30
+ var gt = (left, right) => bin(">", left, right);
31
+ var gte = (left, right) => bin(">=", left, right);
32
+ var and = (left, right) => bin("&&", left, right);
33
+ var or = (left, right) => bin("||", left, right);
34
+ function not(operand) {
35
+ return { expr: "not", operand };
36
+ }
37
+ function cond(condition, thenExpr, elseExpr) {
38
+ return { expr: "cond", if: condition, then: thenExpr, else: elseExpr };
39
+ }
40
+ function get(base, path) {
41
+ return { expr: "get", base, path };
42
+ }
43
+ function numberField(initial) {
44
+ return { type: "number", initial };
45
+ }
46
+ function stringField(initial) {
47
+ return { type: "string", initial };
48
+ }
49
+ function listField(initial = []) {
50
+ return { type: "list", initial };
51
+ }
52
+ function booleanField(initial) {
53
+ return { type: "boolean", initial };
54
+ }
55
+ function objectField(initial) {
56
+ return { type: "object", initial };
57
+ }
58
+ function action(name, steps) {
59
+ return { name, steps };
60
+ }
61
+ function set(target, value) {
62
+ return { do: "set", target, value };
63
+ }
64
+ function update(target, operation, value) {
65
+ const result = { do: "update", target, operation };
66
+ if (value !== void 0) {
67
+ result.value = value;
68
+ }
69
+ return result;
70
+ }
71
+ var increment = (target, value) => value !== void 0 ? { do: "update", target, operation: "increment", value } : { do: "update", target, operation: "increment" };
72
+ var decrement = (target, value) => value !== void 0 ? { do: "update", target, operation: "decrement", value } : { do: "update", target, operation: "decrement" };
73
+ var push = (target, value) => ({ do: "update", target, operation: "push", value });
74
+ var pop = (target) => ({ do: "update", target, operation: "pop" });
75
+ var toggle = (target) => ({ do: "update", target, operation: "toggle" });
76
+ function fetch(url, options) {
77
+ const result = { do: "fetch", url };
78
+ if (options) {
79
+ if (options.method !== void 0) result.method = options.method;
80
+ if (options.body !== void 0) result.body = options.body;
81
+ if (options.result !== void 0) result.result = options.result;
82
+ if (options.onSuccess !== void 0) result.onSuccess = options.onSuccess;
83
+ if (options.onError !== void 0) result.onError = options.onError;
84
+ }
85
+ return result;
86
+ }
87
+ function navigate(url, options) {
88
+ const result = { do: "navigate", url };
89
+ if (options) {
90
+ if (options.target !== void 0) result.target = options.target;
91
+ if (options.replace !== void 0) result.replace = options.replace;
92
+ }
93
+ return result;
94
+ }
95
+ function element(tag, props, children) {
96
+ const result = { kind: "element", tag };
97
+ if (props !== void 0 && Object.keys(props).length > 0) {
98
+ result.props = props;
99
+ }
100
+ if (children !== void 0 && children.length > 0) {
101
+ result.children = children;
102
+ }
103
+ return result;
104
+ }
105
+ var div = (props, children) => element("div", props, children);
106
+ var span = (props, children) => element("span", props, children);
107
+ var button = (props, children) => element("button", props, children);
108
+ var input = (props, children) => element("input", props, children);
109
+ function text(value) {
110
+ return { kind: "text", value };
111
+ }
112
+ function ifNode(condition, then, elseNode) {
113
+ const result = { kind: "if", condition, then };
114
+ if (elseNode !== void 0) {
115
+ result.else = elseNode;
116
+ }
117
+ return result;
118
+ }
119
+ function each(items, as, body, options) {
120
+ const result = { kind: "each", items, as, body };
121
+ if (options) {
122
+ if (options.index !== void 0) result.index = options.index;
123
+ if (options.key !== void 0) result.key = options.key;
124
+ }
125
+ return result;
126
+ }
127
+ function component(name, props, children) {
128
+ const result = { kind: "component", name };
129
+ if (props !== void 0 && Object.keys(props).length > 0) {
130
+ result.props = props;
131
+ }
132
+ if (children !== void 0 && children.length > 0) {
133
+ result.children = children;
134
+ }
135
+ return result;
136
+ }
137
+ function slot(name) {
138
+ const result = { kind: "slot" };
139
+ if (name !== void 0) {
140
+ result.name = name;
141
+ }
142
+ return result;
143
+ }
144
+ function onClick(action2, payload) {
145
+ const result = { event: "click", action: action2 };
146
+ if (payload !== void 0) {
147
+ result.payload = payload;
148
+ }
149
+ return result;
150
+ }
151
+ function onInput(action2, payload) {
152
+ return {
153
+ event: "input",
154
+ action: action2,
155
+ payload: payload ?? { expr: "var", name: "event", path: "target.value" }
156
+ };
157
+ }
158
+ function onChange(action2, payload) {
159
+ return {
160
+ event: "change",
161
+ action: action2,
162
+ payload: payload ?? { expr: "var", name: "event", path: "target.value" }
163
+ };
164
+ }
165
+ function onSubmit(action2, payload) {
166
+ const result = { event: "submit", action: action2 };
167
+ if (payload !== void 0) {
168
+ result.payload = payload;
169
+ }
170
+ return result;
171
+ }
172
+ function createProgram(options) {
173
+ const result = {
174
+ version: "1.0",
175
+ state: options.state,
176
+ actions: options.actions,
177
+ view: options.view
178
+ };
179
+ if (options.route !== void 0) {
180
+ result.route = options.route;
181
+ }
182
+ if (options.components !== void 0) {
183
+ result.components = options.components;
184
+ }
185
+ return result;
186
+ }
187
+ export {
188
+ action,
189
+ add,
190
+ and,
191
+ bin,
192
+ booleanField,
193
+ button,
194
+ component,
195
+ cond,
196
+ createProgram,
197
+ decrement,
198
+ div,
199
+ divide,
200
+ each,
201
+ element,
202
+ eq,
203
+ fetch,
204
+ get,
205
+ gt,
206
+ gte,
207
+ ifNode,
208
+ increment,
209
+ input,
210
+ listField,
211
+ lit,
212
+ lt,
213
+ lte,
214
+ mul,
215
+ navigate,
216
+ neq,
217
+ not,
218
+ numberField,
219
+ objectField,
220
+ onChange,
221
+ onClick,
222
+ onInput,
223
+ onSubmit,
224
+ or,
225
+ pop,
226
+ push,
227
+ set,
228
+ slot,
229
+ span,
230
+ state,
231
+ stringField,
232
+ sub,
233
+ text,
234
+ toggle,
235
+ update,
236
+ variable
237
+ };
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@constela/builder",
3
+ "version": "0.2.0",
4
+ "description": "Type-safe builders for constructing Constela AST programmatically",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "dependencies": {
18
+ "@constela/core": "0.8.0"
19
+ },
20
+ "devDependencies": {
21
+ "@types/node": "^20.10.0",
22
+ "tsup": "^8.0.0",
23
+ "typescript": "^5.3.0",
24
+ "vitest": "^2.0.0"
25
+ },
26
+ "peerDependencies": {},
27
+ "engines": {
28
+ "node": ">=20.0.0"
29
+ },
30
+ "license": "MIT",
31
+ "scripts": {
32
+ "build": "tsup src/index.ts --format esm --dts --clean",
33
+ "type-check": "tsc --noEmit",
34
+ "test": "vitest run",
35
+ "test:watch": "vitest",
36
+ "clean": "rm -rf dist"
37
+ }
38
+ }