@nexart/codemode-sdk 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/README.md ADDED
@@ -0,0 +1,304 @@
1
+ # NexArt Code Mode Runtime SDK
2
+
3
+ Version: 0.1.0
4
+
5
+ A minimal, deterministic rendering engine for generative art.
6
+
7
+ ---
8
+
9
+ > **This SDK enforces the NexArt Code Mode Runtime Execution Specification (v0.x).**
10
+ >
11
+ > **This is NOT the protocol-stable GSL v1.**
12
+
13
+ ---
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npm install @nexart/codemode-sdk
19
+ ```
20
+
21
+ ---
22
+
23
+ ## Usage
24
+
25
+ ```typescript
26
+ import { createEngine } from '@nexart/codemode-sdk';
27
+
28
+ const engine = createEngine({ mode: 'static' });
29
+
30
+ await engine.run({
31
+ code: `
32
+ function setup() {
33
+ background(255);
34
+ fill(0);
35
+ ellipse(width/2, height/2, 100);
36
+ }
37
+ `,
38
+ onComplete: (result) => {
39
+ console.log(result.type); // 'image'
40
+ console.log(result.blob); // PNG Blob
41
+ }
42
+ });
43
+ ```
44
+
45
+ ---
46
+
47
+ ## What This SDK Is
48
+
49
+ This SDK provides a headless runtime for executing p5.js-style generative art code and producing deterministic output:
50
+
51
+ - **Static Mode**: Executes `setup()` only, outputs PNG
52
+ - **Loop Mode**: Frame-authoritative rendering, outputs MP4
53
+
54
+ ---
55
+
56
+ ## What This SDK Is NOT
57
+
58
+ - **Not a protocol layer** — Does not validate protocol claims, system hashes, or GSL v1
59
+ - **Not a UI library** — No React components, no wallet integration
60
+ - **Not an IPFS client** — Does not handle storage or minting
61
+ - **Not p5.js** — Uses a minimal subset of p5.js-like functions
62
+
63
+ ---
64
+
65
+ ## Target Version
66
+
67
+ **Code Mode Runtime v0.x**
68
+
69
+ This SDK extracts the current NexArt Code Mode execution logic. Future versions may introduce:
70
+ - GSL v1 SDK (protocol layer) — separate package
71
+ - Extended p5.js compatibility
72
+
73
+ ---
74
+
75
+ ## API
76
+
77
+ ### `createEngine(config: EngineConfig): Engine`
78
+
79
+ Create a rendering engine instance.
80
+
81
+ ```typescript
82
+ import { createEngine } from '@nexart/codemode-sdk';
83
+
84
+ const engine = createEngine({
85
+ mode: 'static', // 'static' | 'loop'
86
+ width: 1950, // Optional, default: 1950
87
+ height: 2400, // Optional, default: 2400
88
+ duration: 2, // Loop mode only, 1-4 seconds
89
+ fps: 30, // Loop mode only, default: 30
90
+ });
91
+ ```
92
+
93
+ ### `engine.run(options: RunOptions): Promise<void>`
94
+
95
+ Execute code and produce output.
96
+
97
+ ```typescript
98
+ await engine.run({
99
+ code: `
100
+ function setup() {
101
+ background(255);
102
+ fill(0);
103
+ ellipse(width/2, height/2, 100);
104
+ }
105
+ `,
106
+ onPreview: (canvas) => {
107
+ // Optional: called with canvas after first frame
108
+ },
109
+ onProgress: (info) => {
110
+ // Optional: progress updates
111
+ console.log(info.message, info.percent + '%');
112
+ },
113
+ onComplete: (result) => {
114
+ // Required: called with final result
115
+ console.log(result.type); // 'image' | 'video'
116
+ console.log(result.blob); // Blob
117
+ },
118
+ onError: (error) => {
119
+ // Optional: called on error
120
+ console.error(error);
121
+ },
122
+ });
123
+ ```
124
+
125
+ ### `engine.stop(): void`
126
+
127
+ Cancel a running render (Loop mode only).
128
+
129
+ ### `engine.getConfig(): EngineConfig`
130
+
131
+ Get the resolved engine configuration.
132
+
133
+ ---
134
+
135
+ ## Execution Rules
136
+
137
+ ### Static Mode
138
+
139
+ 1. `setup()` is executed once
140
+ 2. `draw()` is **NOT** executed
141
+ 3. Canvas is captured as PNG
142
+ 4. Time variables are all `0`
143
+
144
+ ### Loop Mode
145
+
146
+ 1. `setup()` is executed once
147
+ 2. `draw()` is executed once per frame
148
+ 3. Canvas is **cleared** before each `draw()` call
149
+ 4. If artist calls `background()` in draw, it paints over the clear
150
+ 5. No canvas persistence between frames
151
+
152
+ **Time Variables:**
153
+
154
+ | Variable | Type | Description |
155
+ |----------|------|-------------|
156
+ | `frameCount` | int | Current frame (0, 1, 2, ...) |
157
+ | `t` | float | Normalized time [0.0, 1.0) |
158
+ | `time` | float | Elapsed seconds |
159
+ | `tGlobal` | float | Alias for `t` |
160
+
161
+ ---
162
+
163
+ ## Forbidden Patterns
164
+
165
+ These patterns will throw errors:
166
+
167
+ - `createCanvas()` — Canvas is pre-initialized by the SDK
168
+ - `setTimeout()`, `setInterval()`, `requestAnimationFrame()` — Async timing breaks determinism
169
+ - `noLoop()` in Loop Mode — Incompatible with frame capture
170
+
171
+ ---
172
+
173
+ ## Example: Static Mode
174
+
175
+ ```typescript
176
+ import { createEngine } from '@nexart/codemode-sdk';
177
+
178
+ const engine = createEngine({ mode: 'static' });
179
+
180
+ await engine.run({
181
+ code: `
182
+ function setup() {
183
+ background(30);
184
+ noStroke();
185
+ for (let i = 0; i < 100; i++) {
186
+ fill(random(255), random(255), random(255));
187
+ ellipse(random(width), random(height), 50);
188
+ }
189
+ }
190
+ `,
191
+ onComplete: (result) => {
192
+ // result.type === 'image'
193
+ // result.blob is a PNG Blob
194
+ const url = URL.createObjectURL(result.blob);
195
+ document.body.innerHTML = `<img src="${url}" />`;
196
+ },
197
+ });
198
+ ```
199
+
200
+ ---
201
+
202
+ ## Example: Loop Mode
203
+
204
+ ```typescript
205
+ import { createEngine } from '@nexart/codemode-sdk';
206
+
207
+ const engine = createEngine({
208
+ mode: 'loop',
209
+ duration: 2, // 2 second loop
210
+ });
211
+
212
+ await engine.run({
213
+ code: `
214
+ function setup() {
215
+ // Called once
216
+ }
217
+
218
+ function draw() {
219
+ background(30);
220
+
221
+ // t goes from 0 to 1 over the loop duration
222
+ let x = width/2 + cos(t * TWO_PI) * 200;
223
+ let y = height/2 + sin(t * TWO_PI) * 200;
224
+
225
+ fill(255);
226
+ ellipse(x, y, 80);
227
+ }
228
+ `,
229
+ onProgress: (info) => {
230
+ console.log(info.message);
231
+ },
232
+ onComplete: (result) => {
233
+ // result.type === 'video'
234
+ // result.blob is an MP4 Blob
235
+ const url = URL.createObjectURL(result.blob);
236
+ document.body.innerHTML = `<video src="${url}" autoplay loop />`;
237
+ },
238
+ });
239
+ ```
240
+
241
+ ---
242
+
243
+ ## Supported Functions
244
+
245
+ The SDK includes a minimal p5.js-like runtime with:
246
+
247
+ **Drawing:**
248
+ `background`, `clear`, `fill`, `noFill`, `stroke`, `noStroke`, `strokeWeight`
249
+
250
+ **Shapes:**
251
+ `ellipse`, `circle`, `rect`, `square`, `line`, `point`, `triangle`, `quad`, `arc`
252
+
253
+ **Vertex:**
254
+ `beginShape`, `vertex`, `endShape`
255
+
256
+ **Transform:**
257
+ `push`, `pop`, `translate`, `rotate`, `scale`, `resetMatrix`
258
+
259
+ **Color:**
260
+ `colorMode`, `color`, `lerpColor`
261
+
262
+ **Math:**
263
+ `random`, `noise`, `map`, `constrain`, `lerp`, `dist`, `mag`, `norm`
264
+
265
+ **Trig:**
266
+ `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `atan2`, `radians`, `degrees`
267
+
268
+ **Constants:**
269
+ `PI`, `TWO_PI`, `HALF_PI`, `QUARTER_PI`, `width`, `height`, `frameCount`
270
+
271
+ ---
272
+
273
+ ## Video Encoding
274
+
275
+ Loop Mode requires server-side video encoding. The SDK calls:
276
+
277
+ ```
278
+ POST /api/encode-loop
279
+ ```
280
+
281
+ Ensure your server has this endpoint available, or provide your own encoding solution.
282
+
283
+ ---
284
+
285
+ ## Files
286
+
287
+ ```
288
+ @nexart/codemode-sdk/
289
+ ├── index.ts # Main export
290
+ ├── engine.ts # createEngine entry point
291
+ ├── types.ts # TypeScript types
292
+ ├── static-engine.ts # Static mode implementation
293
+ ├── loop-engine.ts # Loop mode implementation
294
+ ├── p5-runtime.ts # p5.js-like runtime
295
+ └── README.md # This file
296
+ ```
297
+
298
+ ---
299
+
300
+ ## License
301
+
302
+ MIT License
303
+
304
+ Copyright (c) 2024 NexArt
@@ -0,0 +1,24 @@
1
+ /**
2
+ * NexArt Code Mode Runtime SDK
3
+ * Version: 0.1.0
4
+ *
5
+ * Main entry point for the Code Mode runtime engine.
6
+ *
7
+ * Usage:
8
+ * const engine = createEngine({ mode: 'static' });
9
+ * engine.run({
10
+ * code: 'function setup() { background(255); ellipse(width/2, height/2, 100); }',
11
+ * onComplete: (result) => console.log(result.blob)
12
+ * });
13
+ */
14
+ import type { Engine, EngineConfig } from './types';
15
+ /**
16
+ * Create a NexArt Code Mode rendering engine.
17
+ *
18
+ * @param config - Engine configuration
19
+ * @returns Engine instance
20
+ */
21
+ export declare function createEngine(config: EngineConfig): Engine;
22
+ export type { Engine, EngineConfig, RunOptions, RenderResult, ProgressInfo } from './types';
23
+ export { DEFAULT_CONFIG } from './types';
24
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAc,MAAM,SAAS,CAAC;AAKhE;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CA+CzD;AAGD,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC"}
package/dist/engine.js ADDED
@@ -0,0 +1,67 @@
1
+ /**
2
+ * NexArt Code Mode Runtime SDK
3
+ * Version: 0.1.0
4
+ *
5
+ * Main entry point for the Code Mode runtime engine.
6
+ *
7
+ * Usage:
8
+ * const engine = createEngine({ mode: 'static' });
9
+ * engine.run({
10
+ * code: 'function setup() { background(255); ellipse(width/2, height/2, 100); }',
11
+ * onComplete: (result) => console.log(result.blob)
12
+ * });
13
+ */
14
+ import { DEFAULT_CONFIG } from './types';
15
+ import { runStaticMode } from './static-engine';
16
+ import { runLoopMode, cancelLoopMode } from './loop-engine';
17
+ /**
18
+ * Create a NexArt Code Mode rendering engine.
19
+ *
20
+ * @param config - Engine configuration
21
+ * @returns Engine instance
22
+ */
23
+ export function createEngine(config) {
24
+ const resolvedConfig = {
25
+ mode: config.mode,
26
+ width: config.width ?? DEFAULT_CONFIG.width,
27
+ height: config.height ?? DEFAULT_CONFIG.height,
28
+ duration: config.duration ?? DEFAULT_CONFIG.duration,
29
+ fps: config.fps ?? DEFAULT_CONFIG.fps,
30
+ };
31
+ let isRunning = false;
32
+ const run = async (options) => {
33
+ if (isRunning) {
34
+ throw new Error('Engine is already running. Call stop() first.');
35
+ }
36
+ isRunning = true;
37
+ try {
38
+ if (resolvedConfig.mode === 'static') {
39
+ await runStaticMode(resolvedConfig, options);
40
+ }
41
+ else if (resolvedConfig.mode === 'loop') {
42
+ await runLoopMode(resolvedConfig, options);
43
+ }
44
+ else {
45
+ throw new Error(`Unknown mode: ${resolvedConfig.mode}`);
46
+ }
47
+ }
48
+ finally {
49
+ isRunning = false;
50
+ }
51
+ };
52
+ const stop = () => {
53
+ if (resolvedConfig.mode === 'loop') {
54
+ cancelLoopMode();
55
+ }
56
+ isRunning = false;
57
+ };
58
+ const getConfig = () => {
59
+ return { ...resolvedConfig };
60
+ };
61
+ return {
62
+ run,
63
+ stop,
64
+ getConfig,
65
+ };
66
+ }
67
+ export { DEFAULT_CONFIG } from './types';
@@ -0,0 +1,31 @@
1
+ /**
2
+ * NexArt Code Mode Runtime SDK
3
+ * Version: 0.1.0
4
+ *
5
+ * A minimal, deterministic rendering engine for generative art.
6
+ * Supports Static (PNG) and Loop (MP4) modes.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { createEngine } from '@nexart/codemode-sdk';
11
+ *
12
+ * const engine = createEngine({ mode: 'static' });
13
+ *
14
+ * engine.run({
15
+ * code: `
16
+ * function setup() {
17
+ * background(255);
18
+ * fill(0);
19
+ * ellipse(width/2, height/2, 100);
20
+ * }
21
+ * `,
22
+ * onComplete: (result) => {
23
+ * console.log('Rendered:', result.type, result.blob.size, 'bytes');
24
+ * }
25
+ * });
26
+ * ```
27
+ */
28
+ export { createEngine } from './engine';
29
+ export type { Engine, EngineConfig, RunOptions, RenderResult, ProgressInfo, RenderMode, TimeVariables, } from './types';
30
+ export { DEFAULT_CONFIG } from './types';
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EACV,MAAM,EACN,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * NexArt Code Mode Runtime SDK
3
+ * Version: 0.1.0
4
+ *
5
+ * A minimal, deterministic rendering engine for generative art.
6
+ * Supports Static (PNG) and Loop (MP4) modes.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { createEngine } from '@nexart/codemode-sdk';
11
+ *
12
+ * const engine = createEngine({ mode: 'static' });
13
+ *
14
+ * engine.run({
15
+ * code: `
16
+ * function setup() {
17
+ * background(255);
18
+ * fill(0);
19
+ * ellipse(width/2, height/2, 100);
20
+ * }
21
+ * `,
22
+ * onComplete: (result) => {
23
+ * console.log('Rendered:', result.type, result.blob.size, 'bytes');
24
+ * }
25
+ * });
26
+ * ```
27
+ */
28
+ export { createEngine } from './engine';
29
+ export { DEFAULT_CONFIG } from './types';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * NexArt Code Mode Runtime SDK - Loop Engine
3
+ * Version: 0.1.0
4
+ *
5
+ * Loop mode renderer: frame-authoritative, stateless execution.
6
+ * - Executes setup() once
7
+ * - Executes draw() once per frame
8
+ * - Clears canvas before each frame (transparent)
9
+ * - Injects normalized time variables
10
+ * - No canvas persistence between frames
11
+ */
12
+ import type { EngineConfig, RunOptions } from './types';
13
+ export declare function cancelLoopMode(): void;
14
+ export declare function runLoopMode(config: EngineConfig, options: RunOptions): Promise<void>;
15
+ //# sourceMappingURL=loop-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop-engine.d.ts","sourceRoot":"","sources":["../loop-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAA+B,MAAM,SAAS,CAAC;AAMrF,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,IAAI,CAAC,CA4Lf"}
@@ -0,0 +1,208 @@
1
+ /**
2
+ * NexArt Code Mode Runtime SDK - Loop Engine
3
+ * Version: 0.1.0
4
+ *
5
+ * Loop mode renderer: frame-authoritative, stateless execution.
6
+ * - Executes setup() once
7
+ * - Executes draw() once per frame
8
+ * - Clears canvas before each frame (transparent)
9
+ * - Injects normalized time variables
10
+ * - No canvas persistence between frames
11
+ */
12
+ import { DEFAULT_CONFIG } from './types';
13
+ import { createP5Runtime } from './p5-runtime';
14
+ let isCancelled = false;
15
+ export function cancelLoopMode() {
16
+ isCancelled = true;
17
+ }
18
+ export async function runLoopMode(config, options) {
19
+ const { code, onPreview, onProgress, onComplete, onError } = options;
20
+ const width = config.width ?? DEFAULT_CONFIG.width;
21
+ const height = config.height ?? DEFAULT_CONFIG.height;
22
+ const duration = Math.max(DEFAULT_CONFIG.minDuration, Math.min(DEFAULT_CONFIG.maxDuration, config.duration ?? DEFAULT_CONFIG.duration));
23
+ const fps = config.fps ?? DEFAULT_CONFIG.fps;
24
+ const totalFrames = Math.floor(duration * fps);
25
+ isCancelled = false;
26
+ try {
27
+ onProgress?.({
28
+ phase: 'setup',
29
+ percent: 0,
30
+ message: 'Initializing canvas...',
31
+ });
32
+ // Create canvas
33
+ const canvas = document.createElement('canvas');
34
+ canvas.width = width;
35
+ canvas.height = height;
36
+ // Create p5 runtime
37
+ const p = createP5Runtime(canvas, width, height);
38
+ // Validate code
39
+ const hasDrawFunction = /function\s+draw\s*\(\s*\)/.test(code);
40
+ if (!hasDrawFunction) {
41
+ throw new Error('Loop Mode requires a draw() function.');
42
+ }
43
+ const forbiddenPatterns = [
44
+ { pattern: /noLoop\s*\(\s*\)/, name: 'noLoop()' },
45
+ { pattern: /setTimeout\s*\(/, name: 'setTimeout' },
46
+ { pattern: /setInterval\s*\(/, name: 'setInterval' },
47
+ { pattern: /requestAnimationFrame\s*\(/, name: 'requestAnimationFrame' },
48
+ ];
49
+ for (const { pattern, name } of forbiddenPatterns) {
50
+ if (pattern.test(code)) {
51
+ throw new Error(`Forbidden function in Loop Mode: ${name}`);
52
+ }
53
+ }
54
+ onProgress?.({
55
+ phase: 'setup',
56
+ percent: 5,
57
+ message: 'Parsing code...',
58
+ });
59
+ // Extract setup() and draw() functions
60
+ const setupMatch = code.match(/function\s+setup\s*\(\s*\)\s*\{([\s\S]*?)\}(?=\s*function|\s*$)/);
61
+ const drawMatch = code.match(/function\s+draw\s*\(\s*\)\s*\{([\s\S]*?)\}(?=\s*function|\s*$)/);
62
+ const setupCode = setupMatch ? setupMatch[1].trim() : '';
63
+ const drawCode = drawMatch ? drawMatch[1].trim() : '';
64
+ if (!drawCode) {
65
+ throw new Error('Loop Mode requires a draw() function with content.');
66
+ }
67
+ // Create wrapped functions with p5 context and time variables
68
+ const wrappedSetup = new Function('p', 'frameCount', 't', 'time', 'tGlobal', `with(p) { ${setupCode} }`);
69
+ const wrappedDraw = new Function('p', 'frameCount', 't', 'time', 'tGlobal', `with(p) { ${drawCode} }`);
70
+ onProgress?.({
71
+ phase: 'setup',
72
+ percent: 10,
73
+ message: 'Executing setup()...',
74
+ });
75
+ // Execute setup() once with time = 0
76
+ wrappedSetup(p, 0, 0, 0, 0);
77
+ // Capture frames
78
+ const frames = [];
79
+ onProgress?.({
80
+ phase: 'rendering',
81
+ frame: 0,
82
+ totalFrames,
83
+ percent: 10,
84
+ message: `Rendering frames (0/${totalFrames})...`,
85
+ });
86
+ for (let frame = 0; frame < totalFrames; frame++) {
87
+ if (isCancelled) {
88
+ throw new Error('Rendering cancelled');
89
+ }
90
+ // Calculate normalized time variables
91
+ // t = frame / totalFrames (range [0, 1))
92
+ const t = frame / totalFrames;
93
+ const time = t * duration;
94
+ // Update p5 runtime frameCount
95
+ p.frameCount = frame;
96
+ // CRITICAL: Clear canvas before each draw() call
97
+ // This enforces stateless, frame-authoritative rendering
98
+ // Preserves artist-defined backgrounds (if they call background() in draw)
99
+ p.clear();
100
+ // Execute draw() with time variables
101
+ wrappedDraw(p, frame, t, time, t);
102
+ // Capture frame as PNG blob
103
+ const blob = await new Promise((resolve, reject) => {
104
+ canvas.toBlob((b) => b ? resolve(b) : reject(new Error(`Failed to capture frame ${frame}`)), 'image/png');
105
+ });
106
+ frames.push(blob);
107
+ // Provide preview on first frame
108
+ if (frame === 0) {
109
+ onPreview?.(canvas);
110
+ }
111
+ // Update progress
112
+ const percent = 10 + Math.floor((frame / totalFrames) * 60);
113
+ onProgress?.({
114
+ phase: 'rendering',
115
+ frame: frame + 1,
116
+ totalFrames,
117
+ percent,
118
+ message: `Rendering frames (${frame + 1}/${totalFrames})...`,
119
+ });
120
+ // Yield to prevent blocking UI
121
+ if (frame % 10 === 0) {
122
+ await new Promise(resolve => setTimeout(resolve, 0));
123
+ }
124
+ }
125
+ onProgress?.({
126
+ phase: 'encoding',
127
+ frame: totalFrames,
128
+ totalFrames,
129
+ percent: 70,
130
+ message: 'Encoding video...',
131
+ });
132
+ // Encode to video (MP4)
133
+ const videoBlob = await encodeFramesToMP4(frames, fps, width, height, (progress) => {
134
+ const percent = 70 + Math.floor(progress * 30);
135
+ onProgress?.({
136
+ phase: 'encoding',
137
+ frame: totalFrames,
138
+ totalFrames,
139
+ percent,
140
+ message: `Encoding video (${Math.floor(progress * 100)}%)...`,
141
+ });
142
+ });
143
+ onProgress?.({
144
+ phase: 'complete',
145
+ frame: totalFrames,
146
+ totalFrames,
147
+ percent: 100,
148
+ message: 'Complete',
149
+ });
150
+ const result = {
151
+ type: 'video',
152
+ blob: videoBlob,
153
+ frames: totalFrames,
154
+ duration,
155
+ };
156
+ onComplete(result);
157
+ }
158
+ catch (error) {
159
+ const err = error instanceof Error ? error : new Error(String(error));
160
+ onError?.(err);
161
+ }
162
+ }
163
+ /**
164
+ * Encode frames to MP4 video
165
+ * Uses server-side encoding endpoint for cross-browser reliability
166
+ */
167
+ async function encodeFramesToMP4(frames, fps, width, height, onProgress) {
168
+ // Convert frames to base64 for server transport
169
+ const frameDataUrls = [];
170
+ for (let i = 0; i < frames.length; i++) {
171
+ const reader = new FileReader();
172
+ const dataUrl = await new Promise((resolve, reject) => {
173
+ reader.onload = () => resolve(reader.result);
174
+ reader.onerror = reject;
175
+ reader.readAsDataURL(frames[i]);
176
+ });
177
+ frameDataUrls.push(dataUrl);
178
+ onProgress?.(i / frames.length * 0.3);
179
+ }
180
+ // Send to server for encoding
181
+ const response = await fetch('/api/encode-loop', {
182
+ method: 'POST',
183
+ headers: { 'Content-Type': 'application/json' },
184
+ body: JSON.stringify({
185
+ frames: frameDataUrls,
186
+ fps,
187
+ width,
188
+ height,
189
+ }),
190
+ });
191
+ if (!response.ok) {
192
+ const errorText = await response.text();
193
+ throw new Error(`Video encoding failed: ${errorText}`);
194
+ }
195
+ onProgress?.(0.8);
196
+ const data = await response.json();
197
+ if (!data.video) {
198
+ throw new Error('No video data returned from encoder');
199
+ }
200
+ // Convert base64 to blob
201
+ const binaryString = atob(data.video.split(',')[1] || data.video);
202
+ const bytes = new Uint8Array(binaryString.length);
203
+ for (let i = 0; i < binaryString.length; i++) {
204
+ bytes[i] = binaryString.charCodeAt(i);
205
+ }
206
+ onProgress?.(1);
207
+ return new Blob([bytes], { type: 'video/mp4' });
208
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * NexArt Code Mode Runtime SDK - p5-like Runtime
3
+ * Version: 0.1.0
4
+ *
5
+ * Minimal p5.js-like runtime for deterministic generative art execution.
6
+ * This is a headless runtime - no UI dependencies.
7
+ */
8
+ import type { TimeVariables } from './types';
9
+ export interface P5Runtime {
10
+ [key: string]: any;
11
+ width: number;
12
+ height: number;
13
+ frameCount: number;
14
+ PI: number;
15
+ TWO_PI: number;
16
+ HALF_PI: number;
17
+ QUARTER_PI: number;
18
+ }
19
+ export declare function createP5Runtime(canvas: HTMLCanvasElement, width: number, height: number): P5Runtime;
20
+ export declare function injectTimeVariables(p: P5Runtime, time: TimeVariables): void;
21
+ //# sourceMappingURL=p5-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"p5-runtime.d.ts","sourceRoot":"","sources":["../p5-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,MAAM,WAAW,SAAS;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,SAAS,CAkVX;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,CAE3E"}
@@ -0,0 +1,315 @@
1
+ /**
2
+ * NexArt Code Mode Runtime SDK - p5-like Runtime
3
+ * Version: 0.1.0
4
+ *
5
+ * Minimal p5.js-like runtime for deterministic generative art execution.
6
+ * This is a headless runtime - no UI dependencies.
7
+ */
8
+ export function createP5Runtime(canvas, width, height) {
9
+ const ctx = canvas.getContext('2d', { willReadFrequently: true });
10
+ let currentFill = 'rgba(255, 255, 255, 1)';
11
+ let currentStroke = 'rgba(0, 0, 0, 1)';
12
+ let strokeEnabled = true;
13
+ let fillEnabled = true;
14
+ let currentStrokeWeight = 1;
15
+ let colorModeSettings = { mode: 'RGB', maxR: 255, maxG: 255, maxB: 255, maxA: 255 };
16
+ const parseColor = (...args) => {
17
+ if (args.length === 0)
18
+ return 'rgba(0, 0, 0, 1)';
19
+ const { mode, maxR, maxG, maxB, maxA } = colorModeSettings;
20
+ if (args.length === 1) {
21
+ const val = args[0];
22
+ if (typeof val === 'string')
23
+ return val;
24
+ if (mode === 'HSB') {
25
+ return `hsla(${val}, 100%, 50%, 1)`;
26
+ }
27
+ const gray = Math.round((val / maxR) * 255);
28
+ return `rgba(${gray}, ${gray}, ${gray}, 1)`;
29
+ }
30
+ if (args.length === 2) {
31
+ const [gray, alpha] = args;
32
+ const g = Math.round((gray / maxR) * 255);
33
+ const a = alpha / maxA;
34
+ return `rgba(${g}, ${g}, ${g}, ${a})`;
35
+ }
36
+ if (args.length === 3) {
37
+ const [r, g, b] = args;
38
+ if (mode === 'HSB') {
39
+ return `hsla(${(r / maxR) * 360}, ${(g / maxG) * 100}%, ${(b / maxB) * 100}%, 1)`;
40
+ }
41
+ return `rgba(${Math.round((r / maxR) * 255)}, ${Math.round((g / maxG) * 255)}, ${Math.round((b / maxB) * 255)}, 1)`;
42
+ }
43
+ if (args.length === 4) {
44
+ const [r, g, b, a] = args;
45
+ if (mode === 'HSB') {
46
+ return `hsla(${(r / maxR) * 360}, ${(g / maxG) * 100}%, ${(b / maxB) * 100}%, ${a / maxA})`;
47
+ }
48
+ return `rgba(${Math.round((r / maxR) * 255)}, ${Math.round((g / maxG) * 255)}, ${Math.round((b / maxB) * 255)}, ${a / maxA})`;
49
+ }
50
+ return 'rgba(0, 0, 0, 1)';
51
+ };
52
+ const p = {
53
+ width,
54
+ height,
55
+ frameCount: 0,
56
+ // Constants
57
+ PI: Math.PI,
58
+ TWO_PI: Math.PI * 2,
59
+ HALF_PI: Math.PI / 2,
60
+ QUARTER_PI: Math.PI / 4,
61
+ // Shape mode constants
62
+ CORNER: 'corner',
63
+ CENTER: 'center',
64
+ CORNERS: 'corners',
65
+ RADIUS: 'radius',
66
+ ROUND: 'round',
67
+ SQUARE: 'square',
68
+ PROJECT: 'project',
69
+ MITER: 'miter',
70
+ BEVEL: 'bevel',
71
+ CLOSE: 'close',
72
+ // Canvas operations
73
+ background: (...args) => {
74
+ ctx.save();
75
+ ctx.fillStyle = parseColor(...args);
76
+ ctx.fillRect(0, 0, width, height);
77
+ ctx.restore();
78
+ },
79
+ clear: () => {
80
+ ctx.clearRect(0, 0, width, height);
81
+ },
82
+ // Color functions
83
+ fill: (...args) => {
84
+ fillEnabled = true;
85
+ currentFill = parseColor(...args);
86
+ ctx.fillStyle = currentFill;
87
+ },
88
+ noFill: () => {
89
+ fillEnabled = false;
90
+ },
91
+ stroke: (...args) => {
92
+ strokeEnabled = true;
93
+ currentStroke = parseColor(...args);
94
+ ctx.strokeStyle = currentStroke;
95
+ },
96
+ noStroke: () => {
97
+ strokeEnabled = false;
98
+ },
99
+ strokeWeight: (weight) => {
100
+ currentStrokeWeight = weight;
101
+ ctx.lineWidth = weight;
102
+ },
103
+ colorMode: (mode, max1, max2, max3, maxA) => {
104
+ colorModeSettings = {
105
+ mode: mode.toUpperCase(),
106
+ maxR: max1 ?? 255,
107
+ maxG: max2 ?? max1 ?? 255,
108
+ maxB: max3 ?? max1 ?? 255,
109
+ maxA: maxA ?? 255,
110
+ };
111
+ },
112
+ color: (...args) => parseColor(...args),
113
+ lerpColor: (c1, c2, amt) => {
114
+ return c1; // Simplified - full implementation would blend colors
115
+ },
116
+ // Shape functions
117
+ ellipse: (x, y, w, h) => {
118
+ const rw = w / 2;
119
+ const rh = (h ?? w) / 2;
120
+ ctx.beginPath();
121
+ ctx.ellipse(x, y, rw, rh, 0, 0, Math.PI * 2);
122
+ if (fillEnabled)
123
+ ctx.fill();
124
+ if (strokeEnabled)
125
+ ctx.stroke();
126
+ },
127
+ circle: (x, y, d) => {
128
+ p.ellipse(x, y, d, d);
129
+ },
130
+ rect: (x, y, w, h, r) => {
131
+ const height = h ?? w;
132
+ ctx.beginPath();
133
+ if (r && r > 0) {
134
+ ctx.roundRect(x, y, w, height, r);
135
+ }
136
+ else {
137
+ ctx.rect(x, y, w, height);
138
+ }
139
+ if (fillEnabled)
140
+ ctx.fill();
141
+ if (strokeEnabled)
142
+ ctx.stroke();
143
+ },
144
+ square: (x, y, s, r) => {
145
+ p.rect(x, y, s, s, r);
146
+ },
147
+ line: (x1, y1, x2, y2) => {
148
+ ctx.beginPath();
149
+ ctx.moveTo(x1, y1);
150
+ ctx.lineTo(x2, y2);
151
+ if (strokeEnabled)
152
+ ctx.stroke();
153
+ },
154
+ point: (x, y) => {
155
+ ctx.beginPath();
156
+ ctx.arc(x, y, currentStrokeWeight / 2, 0, Math.PI * 2);
157
+ ctx.fillStyle = currentStroke;
158
+ ctx.fill();
159
+ },
160
+ triangle: (x1, y1, x2, y2, x3, y3) => {
161
+ ctx.beginPath();
162
+ ctx.moveTo(x1, y1);
163
+ ctx.lineTo(x2, y2);
164
+ ctx.lineTo(x3, y3);
165
+ ctx.closePath();
166
+ if (fillEnabled)
167
+ ctx.fill();
168
+ if (strokeEnabled)
169
+ ctx.stroke();
170
+ },
171
+ quad: (x1, y1, x2, y2, x3, y3, x4, y4) => {
172
+ ctx.beginPath();
173
+ ctx.moveTo(x1, y1);
174
+ ctx.lineTo(x2, y2);
175
+ ctx.lineTo(x3, y3);
176
+ ctx.lineTo(x4, y4);
177
+ ctx.closePath();
178
+ if (fillEnabled)
179
+ ctx.fill();
180
+ if (strokeEnabled)
181
+ ctx.stroke();
182
+ },
183
+ arc: (x, y, w, h, start, stop, mode) => {
184
+ ctx.beginPath();
185
+ ctx.ellipse(x, y, w / 2, h / 2, 0, start, stop);
186
+ if (mode === 'pie' || mode === 'PIE') {
187
+ ctx.lineTo(x, y);
188
+ ctx.closePath();
189
+ }
190
+ else if (mode === 'chord' || mode === 'CHORD') {
191
+ ctx.closePath();
192
+ }
193
+ if (fillEnabled)
194
+ ctx.fill();
195
+ if (strokeEnabled)
196
+ ctx.stroke();
197
+ },
198
+ // Vertex-based shapes
199
+ beginShape: () => {
200
+ ctx.beginPath();
201
+ },
202
+ vertex: (x, y) => {
203
+ if (ctx.isPointInPath(x, y)) {
204
+ ctx.lineTo(x, y);
205
+ }
206
+ else {
207
+ ctx.moveTo(x, y);
208
+ ctx.lineTo(x, y);
209
+ }
210
+ },
211
+ endShape: (mode) => {
212
+ if (mode === 'close' || mode === 'CLOSE') {
213
+ ctx.closePath();
214
+ }
215
+ if (fillEnabled)
216
+ ctx.fill();
217
+ if (strokeEnabled)
218
+ ctx.stroke();
219
+ },
220
+ // Transform functions
221
+ push: () => {
222
+ ctx.save();
223
+ },
224
+ pop: () => {
225
+ ctx.restore();
226
+ ctx.fillStyle = currentFill;
227
+ ctx.strokeStyle = currentStroke;
228
+ ctx.lineWidth = currentStrokeWeight;
229
+ },
230
+ translate: (x, y) => {
231
+ ctx.translate(x, y);
232
+ },
233
+ rotate: (angle) => {
234
+ ctx.rotate(angle);
235
+ },
236
+ scale: (sx, sy) => {
237
+ ctx.scale(sx, sy ?? sx);
238
+ },
239
+ resetMatrix: () => {
240
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
241
+ },
242
+ // Math functions
243
+ random: (min, max) => {
244
+ if (min === undefined)
245
+ return Math.random();
246
+ if (max === undefined)
247
+ return Math.random() * min;
248
+ return min + Math.random() * (max - min);
249
+ },
250
+ randomSeed: (seed) => {
251
+ // Simplified - would need proper seeded random
252
+ },
253
+ noise: (x, y, z) => {
254
+ // Simplified Perlin-like noise
255
+ const hash = (n) => {
256
+ const s = Math.sin(n) * 43758.5453123;
257
+ return s - Math.floor(s);
258
+ };
259
+ const xVal = x ?? 0;
260
+ const yVal = y ?? 0;
261
+ const zVal = z ?? 0;
262
+ return hash(xVal * 12.9898 + yVal * 78.233 + zVal * 37.719);
263
+ },
264
+ noiseSeed: (seed) => { },
265
+ noiseDetail: (lod, falloff) => { },
266
+ map: (value, start1, stop1, start2, stop2) => {
267
+ return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
268
+ },
269
+ constrain: (n, low, high) => {
270
+ return Math.max(low, Math.min(high, n));
271
+ },
272
+ lerp: (start, stop, amt) => {
273
+ return start + (stop - start) * amt;
274
+ },
275
+ dist: (x1, y1, x2, y2) => {
276
+ return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
277
+ },
278
+ mag: (x, y) => {
279
+ return Math.sqrt(x * x + y * y);
280
+ },
281
+ norm: (value, start, stop) => {
282
+ return (value - start) / (stop - start);
283
+ },
284
+ // Trig functions
285
+ sin: Math.sin,
286
+ cos: Math.cos,
287
+ tan: Math.tan,
288
+ asin: Math.asin,
289
+ acos: Math.acos,
290
+ atan: Math.atan,
291
+ atan2: Math.atan2,
292
+ radians: (degrees) => degrees * (Math.PI / 180),
293
+ degrees: (radians) => radians * (180 / Math.PI),
294
+ // Utility functions
295
+ abs: Math.abs,
296
+ ceil: Math.ceil,
297
+ floor: Math.floor,
298
+ round: Math.round,
299
+ sqrt: Math.sqrt,
300
+ pow: Math.pow,
301
+ exp: Math.exp,
302
+ log: Math.log,
303
+ min: Math.min,
304
+ max: Math.max,
305
+ // Loop control (no-ops for SDK)
306
+ noLoop: () => { },
307
+ loop: () => { },
308
+ redraw: () => { },
309
+ frameRate: (fps) => { },
310
+ };
311
+ return p;
312
+ }
313
+ export function injectTimeVariables(p, time) {
314
+ p.frameCount = time.frameCount;
315
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * NexArt Code Mode Runtime SDK - Static Engine
3
+ * Version: 0.1.0
4
+ *
5
+ * Static mode renderer: executes setup() only, captures single PNG.
6
+ * Does NOT execute draw() - per NexArt Execution Specification v1.
7
+ */
8
+ import type { EngineConfig, RunOptions } from './types';
9
+ export declare function runStaticMode(config: EngineConfig, options: RunOptions): Promise<void>;
10
+ //# sourceMappingURL=static-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-engine.d.ts","sourceRoot":"","sources":["../static-engine.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAgB,MAAM,SAAS,CAAC;AAItE,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,IAAI,CAAC,CA+Ff"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * NexArt Code Mode Runtime SDK - Static Engine
3
+ * Version: 0.1.0
4
+ *
5
+ * Static mode renderer: executes setup() only, captures single PNG.
6
+ * Does NOT execute draw() - per NexArt Execution Specification v1.
7
+ */
8
+ import { DEFAULT_CONFIG } from './types';
9
+ import { createP5Runtime, injectTimeVariables } from './p5-runtime';
10
+ export async function runStaticMode(config, options) {
11
+ const { code, onPreview, onProgress, onComplete, onError } = options;
12
+ const width = config.width ?? DEFAULT_CONFIG.width;
13
+ const height = config.height ?? DEFAULT_CONFIG.height;
14
+ try {
15
+ onProgress?.({
16
+ phase: 'setup',
17
+ percent: 0,
18
+ message: 'Initializing canvas...',
19
+ });
20
+ // Create offscreen canvas
21
+ const canvas = document.createElement('canvas');
22
+ canvas.width = width;
23
+ canvas.height = height;
24
+ // Create p5 runtime
25
+ const p = createP5Runtime(canvas, width, height);
26
+ // Inject time variables (static = frame 0, t = 0)
27
+ injectTimeVariables(p, {
28
+ frameCount: 0,
29
+ t: 0,
30
+ time: 0,
31
+ tGlobal: 0,
32
+ });
33
+ onProgress?.({
34
+ phase: 'setup',
35
+ percent: 10,
36
+ message: 'Parsing code...',
37
+ });
38
+ // Extract setup() function only - draw() is NOT executed in Static Mode
39
+ const setupMatch = code.match(/function\s+setup\s*\(\s*\)\s*\{([\s\S]*?)\}(?=\s*function|\s*$)/);
40
+ const setupCode = setupMatch ? setupMatch[1].trim() : code;
41
+ // Validate - no forbidden patterns
42
+ const forbiddenPatterns = ['setTimeout', 'setInterval', 'requestAnimationFrame'];
43
+ for (const pattern of forbiddenPatterns) {
44
+ if (code.includes(pattern)) {
45
+ throw new Error(`Forbidden async timing function: ${pattern}`);
46
+ }
47
+ }
48
+ onProgress?.({
49
+ phase: 'rendering',
50
+ percent: 30,
51
+ message: 'Executing setup()...',
52
+ });
53
+ // Create wrapped setup function with p5 context
54
+ const wrappedSetup = new Function('p', 'frameCount', 't', 'time', 'tGlobal', `with(p) { ${setupCode} }`);
55
+ // Execute setup() only
56
+ wrappedSetup(p, 0, 0, 0, 0);
57
+ // Provide preview callback
58
+ onPreview?.(canvas);
59
+ onProgress?.({
60
+ phase: 'encoding',
61
+ percent: 70,
62
+ message: 'Capturing PNG...',
63
+ });
64
+ // Capture as PNG
65
+ const blob = await new Promise((resolve, reject) => {
66
+ canvas.toBlob((b) => b ? resolve(b) : reject(new Error('Failed to capture PNG')), 'image/png');
67
+ });
68
+ onProgress?.({
69
+ phase: 'complete',
70
+ percent: 100,
71
+ message: 'Complete',
72
+ });
73
+ const result = {
74
+ type: 'image',
75
+ blob,
76
+ };
77
+ onComplete(result);
78
+ }
79
+ catch (error) {
80
+ const err = error instanceof Error ? error : new Error(String(error));
81
+ onError?.(err);
82
+ }
83
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * NexArt Code Mode Runtime SDK - Types
3
+ * Version: 0.1.0
4
+ *
5
+ * Type definitions for the Code Mode runtime engine.
6
+ */
7
+ export type RenderMode = 'static' | 'loop';
8
+ export interface EngineConfig {
9
+ mode: RenderMode;
10
+ width?: number;
11
+ height?: number;
12
+ duration?: number;
13
+ fps?: number;
14
+ }
15
+ export interface RenderResult {
16
+ type: 'image' | 'video';
17
+ blob: Blob;
18
+ frames?: number;
19
+ duration?: number;
20
+ }
21
+ export interface RunOptions {
22
+ code: string;
23
+ onPreview?: (canvas: HTMLCanvasElement) => void;
24
+ onProgress?: (progress: ProgressInfo) => void;
25
+ onComplete: (result: RenderResult) => void;
26
+ onError?: (error: Error) => void;
27
+ }
28
+ export interface ProgressInfo {
29
+ phase: 'setup' | 'rendering' | 'encoding' | 'complete';
30
+ frame?: number;
31
+ totalFrames?: number;
32
+ percent: number;
33
+ message: string;
34
+ }
35
+ export interface Engine {
36
+ run: (options: RunOptions) => Promise<void>;
37
+ stop: () => void;
38
+ getConfig: () => Readonly<EngineConfig>;
39
+ }
40
+ export interface TimeVariables {
41
+ frameCount: number;
42
+ t: number;
43
+ time: number;
44
+ tGlobal: number;
45
+ }
46
+ export declare const DEFAULT_CONFIG: {
47
+ readonly width: 1950;
48
+ readonly height: 2400;
49
+ readonly duration: 2;
50
+ readonly fps: 30;
51
+ readonly minDuration: 1;
52
+ readonly maxDuration: 4;
53
+ };
54
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE3C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAChD,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9C,UAAU,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAC3C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAAC;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,MAAM;IACrB,GAAG,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,SAAS,EAAE,MAAM,QAAQ,CAAC,YAAY,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,cAAc;;;;;;;CAOjB,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * NexArt Code Mode Runtime SDK - Types
3
+ * Version: 0.1.0
4
+ *
5
+ * Type definitions for the Code Mode runtime engine.
6
+ */
7
+ export const DEFAULT_CONFIG = {
8
+ width: 1950,
9
+ height: 2400,
10
+ duration: 2,
11
+ fps: 30,
12
+ minDuration: 1,
13
+ maxDuration: 4,
14
+ };
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@nexart/codemode-sdk",
3
+ "version": "0.1.0",
4
+ "description": "NexArt Code Mode Runtime SDK - Deterministic generative art rendering engine",
5
+ "license": "MIT",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "type": "module",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "devDependencies": {
17
+ "typescript": "^5.0.0"
18
+ },
19
+ "keywords": [
20
+ "generative-art",
21
+ "p5js",
22
+ "canvas",
23
+ "rendering",
24
+ "deterministic",
25
+ "nft",
26
+ "creative-coding"
27
+ ],
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/artnames/nexart-codemode-sdk.git"
31
+ },
32
+ "author": "NexArt",
33
+ "publishConfig": {
34
+ "access": "public"
35
+ }
36
+ }