@cadit-app/script-params 0.1.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) 2026 CADit
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.
package/README.md ADDED
@@ -0,0 +1,136 @@
1
+ # @cadit-app/script-params
2
+
3
+ Type-safe parameter definitions for CADit parametric scripts.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @cadit-app/script-params
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { defineParams } from '@cadit-app/script-params';
15
+
16
+ export default defineParams({
17
+ size: { type: 'number', default: 10, min: 1, max: 100 },
18
+ label: { type: 'text', default: 'Hello' },
19
+ hollow: { type: 'boolean', default: false },
20
+ }, (params) => {
21
+ // params.size is number
22
+ // params.label is string
23
+ // params.hollow is boolean
24
+ return createModel(params.size, params.label, params.hollow);
25
+ });
26
+ ```
27
+
28
+ ## Features
29
+
30
+ - **Type-safe parameters** - Full TypeScript inference without `as const`
31
+ - **Default values** - Scripts work standalone when params are undefined
32
+ - **UI generation** - Schema can be converted to UI controls
33
+ - **Simple API** - Just one function to learn
34
+
35
+ ## Parameter Types
36
+
37
+ | Type | Value Type | Additional Options |
38
+ |------|------------|-------------------|
39
+ | `number` | `number` | `min`, `max`, `step` |
40
+ | `int` | `number` | `min`, `max`, `step` |
41
+ | `text` | `string` | `maxLength`, `placeholder` |
42
+ | `boolean` | `boolean` | - |
43
+ | `choice` | `string` | `options: string[]` |
44
+ | `slider` | `number` | `min`, `max`, `step` (required: `min`, `max`) |
45
+ | `image` | `ImageData \| null` | - |
46
+
47
+ ## API Reference
48
+
49
+ ### `defineParams(schema)` / `defineParams(schema, main)`
50
+
51
+ Define parameters for a script.
52
+
53
+ **Schema only:**
54
+ ```typescript
55
+ const params = defineParams({
56
+ size: { type: 'number', default: 10 },
57
+ });
58
+ // Returns the schema itself
59
+ ```
60
+
61
+ **With callback:**
62
+ ```typescript
63
+ export default defineParams({
64
+ size: { type: 'number', default: 10 },
65
+ }, (params) => {
66
+ return Manifold.cube([params.size, params.size, params.size]);
67
+ });
68
+ // Returns a callable module with .params property
69
+ ```
70
+
71
+ ### `createMain(schema, main)`
72
+
73
+ Create an executable script from a schema and main function. Useful when defining the main function separately.
74
+
75
+ ```typescript
76
+ const params = defineParams({
77
+ size: { type: 'number', default: 10 },
78
+ });
79
+
80
+ function main(p: Params<typeof params>) {
81
+ return Manifold.cube([p.size, p.size, p.size]);
82
+ }
83
+
84
+ export default createMain(params, main);
85
+ ```
86
+
87
+ ### `Params<S>`
88
+
89
+ Type helper to get the params object type from a schema.
90
+
91
+ ```typescript
92
+ const schema = defineParams({
93
+ size: { type: 'number', default: 10 },
94
+ });
95
+
96
+ type MyParams = Params<typeof schema>;
97
+ // { size: number }
98
+ ```
99
+
100
+ ### `schemaToArray(schema)`
101
+
102
+ Convert object-based schema to array format for legacy UI compatibility.
103
+
104
+ ```typescript
105
+ const array = schemaToArray({
106
+ size: { type: 'number', default: 10 },
107
+ });
108
+ // [{ name: 'size', type: 'number', default: 10 }]
109
+ ```
110
+
111
+ ### `getDefaults(schema)`
112
+
113
+ Extract default values from a schema.
114
+
115
+ ```typescript
116
+ const defaults = getDefaults({
117
+ size: { type: 'number', default: 10 },
118
+ label: { type: 'text', default: 'Hi' },
119
+ });
120
+ // { size: 10, label: 'Hi' }
121
+ ```
122
+
123
+ ### `isScriptModule(value)`
124
+
125
+ Check if a value is a script module created by `defineParams`.
126
+
127
+ ```typescript
128
+ const mod = await import('./script.ts');
129
+ if (isScriptModule(mod.default)) {
130
+ const result = mod.default({ size: 20 });
131
+ }
132
+ ```
133
+
134
+ ## License
135
+
136
+ MIT
@@ -0,0 +1,332 @@
1
+ /**
2
+ * @cadit-app/script-params
3
+ *
4
+ * Type-safe parameter definitions for CADit parametric scripts.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { defineParams } from '@cadit-app/script-params';
9
+ *
10
+ * export default defineParams({
11
+ * size: { type: 'number', default: 10 },
12
+ * label: { type: 'text', default: 'Hello' },
13
+ * }, (params) => {
14
+ * // params.size is number, params.label is string
15
+ * return Manifold.cube([params.size, params.size, params.size]);
16
+ * });
17
+ * ```
18
+ */
19
+ /**
20
+ * Base properties shared by all parameter types.
21
+ */
22
+ interface ParamDefBase {
23
+ /** Human-readable label for the parameter. If omitted, the key is used. */
24
+ label?: string;
25
+ /** Description shown as tooltip or help text. */
26
+ description?: string;
27
+ }
28
+ /**
29
+ * Number parameter - floating point values.
30
+ */
31
+ export interface NumberParamDef extends ParamDefBase {
32
+ type: 'number';
33
+ default: number;
34
+ min?: number;
35
+ max?: number;
36
+ step?: number;
37
+ }
38
+ /**
39
+ * Integer parameter - whole number values.
40
+ */
41
+ export interface IntParamDef extends ParamDefBase {
42
+ type: 'int';
43
+ default: number;
44
+ min?: number;
45
+ max?: number;
46
+ step?: number;
47
+ }
48
+ /**
49
+ * Text parameter - string values.
50
+ */
51
+ export interface TextParamDef extends ParamDefBase {
52
+ type: 'text';
53
+ default: string;
54
+ maxLength?: number;
55
+ placeholder?: string;
56
+ }
57
+ /**
58
+ * Boolean parameter - true/false toggle.
59
+ */
60
+ export interface BooleanParamDef extends ParamDefBase {
61
+ type: 'boolean';
62
+ default: boolean;
63
+ }
64
+ /**
65
+ * Choice parameter - select from predefined options.
66
+ */
67
+ export interface ChoiceParamDef extends ParamDefBase {
68
+ type: 'choice';
69
+ default: string;
70
+ options: readonly string[];
71
+ }
72
+ /**
73
+ * Slider parameter - number with visual slider control.
74
+ */
75
+ export interface SliderParamDef extends ParamDefBase {
76
+ type: 'slider';
77
+ default: number;
78
+ min: number;
79
+ max: number;
80
+ step?: number;
81
+ }
82
+ /**
83
+ * Image parameter - ImageData for image-based operations.
84
+ */
85
+ export interface ImageParamDef extends ParamDefBase {
86
+ type: 'image';
87
+ default: ImageData | null;
88
+ }
89
+ /**
90
+ * Option for buttonGrid parameter.
91
+ * Each option can have an image, caption, or both.
92
+ */
93
+ export interface ButtonGridOption {
94
+ /** The value returned when this option is selected. */
95
+ value: string;
96
+ /** Optional image URL (absolute or relative to script location). */
97
+ image?: string;
98
+ /** Optional caption/label for the button. Used as alt text if image is present. */
99
+ caption?: string;
100
+ }
101
+ /**
102
+ * ButtonGrid parameter - visual grid of buttons with images/captions.
103
+ * Useful for pattern selection, style options, etc.
104
+ *
105
+ * @example
106
+ * ```typescript
107
+ * pattern: {
108
+ * type: 'buttonGrid',
109
+ * default: 'style1',
110
+ * options: [
111
+ * { value: 'style1', image: './images/style1.svg', caption: 'Style 1' },
112
+ * { value: 'style2', image: './images/style2.svg', caption: 'Style 2' },
113
+ * ]
114
+ * }
115
+ * ```
116
+ */
117
+ export interface ButtonGridParamDef extends ParamDefBase {
118
+ type: 'buttonGrid';
119
+ default: string;
120
+ options: readonly ButtonGridOption[];
121
+ }
122
+ /**
123
+ * Embedded parameter - nests another script's parameters.
124
+ * The embedded params can be enabled/disabled and expanded/collapsed.
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * import qrCodeScript from './qr-code';
129
+ *
130
+ * export default defineParams({
131
+ * size: { type: 'number', default: 10 },
132
+ * qrCode: {
133
+ * type: 'embedded',
134
+ * label: 'QR Code (Optional)',
135
+ * params: qrCodeScript.params,
136
+ * enabled: false,
137
+ * showSettings: false
138
+ * }
139
+ * }, (p) => {
140
+ * if (p.qrCode.enabled) {
141
+ * const qrMesh = qrCodeScript(p.qrCode.params);
142
+ * // combine meshes...
143
+ * }
144
+ * });
145
+ * ```
146
+ */
147
+ export interface EmbeddedParamDef extends ParamDefBase {
148
+ type: 'embedded';
149
+ /** The nested parameter schema. */
150
+ params: ParamSchema;
151
+ /** Whether the embedded feature is initially enabled. */
152
+ enabled?: boolean;
153
+ /** Whether the settings panel is initially expanded. */
154
+ showSettings?: boolean;
155
+ }
156
+ /**
157
+ * Value type for embedded parameters.
158
+ * Contains the enabled state, showSettings state, and the resolved param values.
159
+ */
160
+ export interface EmbeddedParamValue<S extends ParamSchema = ParamSchema> {
161
+ enabled: boolean;
162
+ showSettings: boolean;
163
+ params: Params<S>;
164
+ }
165
+ /**
166
+ * Union of all parameter definition types.
167
+ */
168
+ export type ParamDef = NumberParamDef | IntParamDef | TextParamDef | BooleanParamDef | ChoiceParamDef | SliderParamDef | ImageParamDef | ButtonGridParamDef | EmbeddedParamDef;
169
+ /**
170
+ * A schema defining all parameters for a script.
171
+ * Keys are parameter names, values are parameter definitions.
172
+ */
173
+ export type ParamSchema = Record<string, ParamDef>;
174
+ /**
175
+ * Infer the runtime value type from a parameter definition.
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * type T = ParamValue<{ type: 'number'; default: 10 }>; // number
180
+ * type S = ParamValue<{ type: 'text'; default: 'hi' }>; // string
181
+ * ```
182
+ */
183
+ export type ParamValue<P extends ParamDef> = P['type'] extends 'number' | 'int' | 'slider' ? number : P['type'] extends 'text' | 'choice' | 'buttonGrid' ? string : P['type'] extends 'boolean' ? boolean : P['type'] extends 'image' ? ImageData | null : P['type'] extends 'embedded' ? P extends EmbeddedParamDef ? EmbeddedParamValue<P['params']> : EmbeddedParamValue : never;
184
+ /**
185
+ * Infer the full params object type from a schema.
186
+ *
187
+ * @example
188
+ * ```typescript
189
+ * const schema = {
190
+ * size: { type: 'number', default: 10 },
191
+ * label: { type: 'text', default: 'Hi' },
192
+ * } as const;
193
+ *
194
+ * type P = Params<typeof schema>;
195
+ * // { size: number; label: string }
196
+ * ```
197
+ */
198
+ export type Params<S extends ParamSchema> = {
199
+ [K in keyof S]: ParamValue<S[K]>;
200
+ };
201
+ /**
202
+ * The result returned by defineParams when a main function is provided.
203
+ * Contains both the schema (for UI) and the executable function.
204
+ */
205
+ export interface ScriptModule<S extends ParamSchema, R> {
206
+ /** The parameter schema for UI generation. */
207
+ params: S;
208
+ /**
209
+ * Execute the script with optional parameter overrides.
210
+ * Missing parameters use their default values.
211
+ */
212
+ (inputParams?: Partial<Params<S>>): R;
213
+ }
214
+ /**
215
+ * Define parameters for a parametric script.
216
+ *
217
+ * This function has two overloads:
218
+ * 1. Schema only - returns the schema for use with `createMain`
219
+ * 2. Schema + callback - returns an executable module with defaults
220
+ *
221
+ * @example Schema only (for separate main function)
222
+ * ```typescript
223
+ * const params = defineParams({
224
+ * size: { type: 'number', default: 10 },
225
+ * });
226
+ *
227
+ * function main(p: Params<typeof params>) {
228
+ * return Manifold.cube([p.size, p.size, p.size]);
229
+ * }
230
+ *
231
+ * export default createMain(params, main);
232
+ * ```
233
+ *
234
+ * @example With callback (recommended)
235
+ * ```typescript
236
+ * export default defineParams({
237
+ * size: { type: 'number', default: 10 },
238
+ * }, (params) => {
239
+ * return Manifold.cube([params.size, params.size, params.size]);
240
+ * });
241
+ * ```
242
+ */
243
+ export declare function defineParams<const S extends ParamSchema>(schema: S): S;
244
+ export declare function defineParams<const S extends ParamSchema, R>(schema: S, main: (params: Params<S>) => R): ScriptModule<S, R>;
245
+ /**
246
+ * Create an executable script module from a schema and main function.
247
+ *
248
+ * Use this when you want to define your main function separately,
249
+ * for example when it's complex or needs to be tested independently.
250
+ *
251
+ * @example
252
+ * ```typescript
253
+ * const params = defineParams({
254
+ * size: { type: 'number', default: 10 },
255
+ * });
256
+ *
257
+ * function main(p: Params<typeof params>) {
258
+ * return Manifold.cube([p.size, p.size, p.size]);
259
+ * }
260
+ *
261
+ * export default createMain(params, main);
262
+ * ```
263
+ */
264
+ export declare function createMain<S extends ParamSchema, R>(schema: S, main: (params: Params<S>) => R): ScriptModule<S, R>;
265
+ /**
266
+ * Convert an object-based schema to array format for legacy UI compatibility.
267
+ *
268
+ * This function transforms the script-params schema format into the
269
+ * ObjectMakerParam[] format expected by the Core UI.
270
+ *
271
+ * @example
272
+ * ```typescript
273
+ * const schema = { size: { type: 'number', default: 10 } };
274
+ * const array = schemaToArray(schema);
275
+ * // [{ name: 'size', type: 'number', initial: 10, caption: 'size' }]
276
+ * ```
277
+ */
278
+ export declare function schemaToArray<S extends ParamSchema>(schema: S): Array<Record<string, unknown>>;
279
+ /**
280
+ * Extract defaults from a schema as a plain object.
281
+ *
282
+ * @example
283
+ * ```typescript
284
+ * const schema = {
285
+ * size: { type: 'number', default: 10 },
286
+ * label: { type: 'text', default: 'Hi' },
287
+ * };
288
+ * const defaults = getDefaults(schema);
289
+ * // { size: 10, label: 'Hi' }
290
+ * ```
291
+ */
292
+ export declare function getDefaults<S extends ParamSchema>(schema: S): Params<S>;
293
+ /**
294
+ * Check if a module export uses the defineParams format.
295
+ *
296
+ * @example
297
+ * ```typescript
298
+ * const mod = await import('./script.ts');
299
+ * if (isScriptModule(mod.default)) {
300
+ * const result = mod.default({ size: 20 });
301
+ * }
302
+ * ```
303
+ */
304
+ export declare function isScriptModule(value: unknown): value is ScriptModule<ParamSchema, unknown>;
305
+ /**
306
+ * Extract the parameter schema from a ScriptModule or plain schema.
307
+ * Useful for embedding another script's parameters.
308
+ *
309
+ * @example
310
+ * ```typescript
311
+ * import qrCodeScript from './qr-code';
312
+ *
313
+ * // Works with ScriptModule
314
+ * const qrParams = getParams(qrCodeScript);
315
+ *
316
+ * // Also works with plain schema
317
+ * const schema = { size: { type: 'number', default: 10 } } as const;
318
+ * const plainParams = getParams(schema);
319
+ *
320
+ * // Use in embedded param definition
321
+ * export default defineParams({
322
+ * qrCode: {
323
+ * type: 'embedded',
324
+ * params: getParams(qrCodeScript),
325
+ * enabled: false,
326
+ * }
327
+ * });
328
+ * ```
329
+ */
330
+ export declare function getParams<S extends ParamSchema>(source: ScriptModule<S, unknown> | S): S;
331
+ export {};
332
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,209 @@
1
+ /**
2
+ * @cadit-app/script-params
3
+ *
4
+ * Type-safe parameter definitions for CADit parametric scripts.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { defineParams } from '@cadit-app/script-params';
9
+ *
10
+ * export default defineParams({
11
+ * size: { type: 'number', default: 10 },
12
+ * label: { type: 'text', default: 'Hello' },
13
+ * }, (params) => {
14
+ * // params.size is number, params.label is string
15
+ * return Manifold.cube([params.size, params.size, params.size]);
16
+ * });
17
+ * ```
18
+ */
19
+ // =============================================================================
20
+ // Core Functions
21
+ // =============================================================================
22
+ /**
23
+ * Build default values object from a schema.
24
+ * @internal
25
+ */
26
+ function buildDefaults(schema) {
27
+ const defaults = {};
28
+ for (const [key, def] of Object.entries(schema)) {
29
+ if (def.type === 'embedded') {
30
+ // For embedded params, build a nested default object
31
+ const embeddedDef = def;
32
+ defaults[key] = {
33
+ enabled: embeddedDef.enabled ?? false,
34
+ showSettings: embeddedDef.showSettings ?? false,
35
+ params: buildDefaults(embeddedDef.params),
36
+ };
37
+ }
38
+ else {
39
+ defaults[key] = def.default;
40
+ }
41
+ }
42
+ return defaults;
43
+ }
44
+ export function defineParams(schema, main) {
45
+ if (!main) {
46
+ return schema;
47
+ }
48
+ const defaults = buildDefaults(schema);
49
+ const scriptModule = ((inputParams) => {
50
+ const merged = { ...defaults, ...inputParams };
51
+ return main(merged);
52
+ });
53
+ scriptModule.params = schema;
54
+ return scriptModule;
55
+ }
56
+ /**
57
+ * Create an executable script module from a schema and main function.
58
+ *
59
+ * Use this when you want to define your main function separately,
60
+ * for example when it's complex or needs to be tested independently.
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * const params = defineParams({
65
+ * size: { type: 'number', default: 10 },
66
+ * });
67
+ *
68
+ * function main(p: Params<typeof params>) {
69
+ * return Manifold.cube([p.size, p.size, p.size]);
70
+ * }
71
+ *
72
+ * export default createMain(params, main);
73
+ * ```
74
+ */
75
+ export function createMain(schema, main) {
76
+ return defineParams(schema, main);
77
+ }
78
+ // =============================================================================
79
+ // Utility Functions
80
+ // =============================================================================
81
+ /**
82
+ * Convert a single param def to ObjectMakerParam format.
83
+ * Handles special cases like embedded params that need recursive conversion.
84
+ * @internal
85
+ */
86
+ function convertParamDef(name, def) {
87
+ const base = {
88
+ name,
89
+ type: def.type,
90
+ caption: def.label ?? name,
91
+ };
92
+ // Copy common properties
93
+ if ('default' in def) {
94
+ base.initial = def.default;
95
+ }
96
+ if ('min' in def)
97
+ base.min = def.min;
98
+ if ('max' in def)
99
+ base.max = def.max;
100
+ if ('step' in def)
101
+ base.step = def.step;
102
+ if ('maxLength' in def)
103
+ base.maxLength = def.maxLength;
104
+ // Handle type-specific conversions
105
+ switch (def.type) {
106
+ case 'choice':
107
+ base.values = def.options;
108
+ break;
109
+ case 'buttonGrid': {
110
+ // Convert buttonGrid options to ObjectMakerButtonGridParam format
111
+ base.options = def.options.map((opt) => ({
112
+ value: opt.value,
113
+ image: opt.image,
114
+ caption: opt.caption,
115
+ }));
116
+ break;
117
+ }
118
+ case 'embedded': {
119
+ // Convert embedded params recursively
120
+ const embeddedDef = def;
121
+ base.parameters = schemaToArray(embeddedDef.params);
122
+ base.enabled = embeddedDef.enabled ?? false;
123
+ base.showSettings = embeddedDef.showSettings ?? false;
124
+ break;
125
+ }
126
+ }
127
+ return base;
128
+ }
129
+ /**
130
+ * Convert an object-based schema to array format for legacy UI compatibility.
131
+ *
132
+ * This function transforms the script-params schema format into the
133
+ * ObjectMakerParam[] format expected by the Core UI.
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * const schema = { size: { type: 'number', default: 10 } };
138
+ * const array = schemaToArray(schema);
139
+ * // [{ name: 'size', type: 'number', initial: 10, caption: 'size' }]
140
+ * ```
141
+ */
142
+ export function schemaToArray(schema) {
143
+ return Object.entries(schema).map(([name, def]) => convertParamDef(name, def));
144
+ }
145
+ /**
146
+ * Extract defaults from a schema as a plain object.
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * const schema = {
151
+ * size: { type: 'number', default: 10 },
152
+ * label: { type: 'text', default: 'Hi' },
153
+ * };
154
+ * const defaults = getDefaults(schema);
155
+ * // { size: 10, label: 'Hi' }
156
+ * ```
157
+ */
158
+ export function getDefaults(schema) {
159
+ return buildDefaults(schema);
160
+ }
161
+ /**
162
+ * Check if a module export uses the defineParams format.
163
+ *
164
+ * @example
165
+ * ```typescript
166
+ * const mod = await import('./script.ts');
167
+ * if (isScriptModule(mod.default)) {
168
+ * const result = mod.default({ size: 20 });
169
+ * }
170
+ * ```
171
+ */
172
+ export function isScriptModule(value) {
173
+ return (typeof value === 'function' &&
174
+ 'params' in value &&
175
+ typeof value.params === 'object' &&
176
+ value.params !== null);
177
+ }
178
+ /**
179
+ * Extract the parameter schema from a ScriptModule or plain schema.
180
+ * Useful for embedding another script's parameters.
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * import qrCodeScript from './qr-code';
185
+ *
186
+ * // Works with ScriptModule
187
+ * const qrParams = getParams(qrCodeScript);
188
+ *
189
+ * // Also works with plain schema
190
+ * const schema = { size: { type: 'number', default: 10 } } as const;
191
+ * const plainParams = getParams(schema);
192
+ *
193
+ * // Use in embedded param definition
194
+ * export default defineParams({
195
+ * qrCode: {
196
+ * type: 'embedded',
197
+ * params: getParams(qrCodeScript),
198
+ * enabled: false,
199
+ * }
200
+ * });
201
+ * ```
202
+ */
203
+ export function getParams(source) {
204
+ if (isScriptModule(source)) {
205
+ return source.params;
206
+ }
207
+ return source;
208
+ }
209
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@cadit-app/script-params",
3
+ "version": "0.1.0",
4
+ "description": "Type-safe parameter definitions for CADit scripts",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "keywords": [
18
+ "cad",
19
+ "parametric",
20
+ "3d",
21
+ "manifold",
22
+ "scripts"
23
+ ],
24
+ "author": "CADit",
25
+ "license": "MIT",
26
+ "devDependencies": {
27
+ "typescript": "^5.7.2",
28
+ "vitest": "^2.1.8"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "scripts": {
34
+ "build": "tsc",
35
+ "dev": "tsc --watch",
36
+ "test": "vitest"
37
+ }
38
+ }