dynim-react 1.0.50 → 1.0.52

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.
@@ -7,7 +7,7 @@
7
7
  * - Shared context for bundles to access React, packages, etc.
8
8
  */
9
9
  import { type ReactNode } from 'react';
10
- import type { CodeMessage } from 'dynim-core';
10
+ import type { CodeMessage, Checkpoint, RestoreResult } from 'dynim-core';
11
11
  export interface DynimConfig {
12
12
  /** Function to fetch a session token for authentication */
13
13
  getSession?: () => Promise<{
@@ -36,6 +36,12 @@ export interface DynimContextValue {
36
36
  saveCode: () => Promise<void>;
37
37
  /** Abandon/discard current edits */
38
38
  abandonCode: () => Promise<void>;
39
+ /** Get active checkpoints for the project */
40
+ getCheckpoints: () => Promise<Checkpoint[]>;
41
+ /** Restore to a specific checkpoint (reloads bundle on success) */
42
+ restoreCheckpoint: (checkpointId: string) => Promise<RestoreResult>;
43
+ /** Whether a checkpoint restore is in progress */
44
+ isRestoring: boolean;
39
45
  /** Current code message state (thinking, edits, etc.) */
40
46
  codeMessage: CodeMessage;
41
47
  /** Whether a bundle is currently loaded */
@@ -1 +1 @@
1
- {"version":3,"file":"DynimProvider.d.ts","sourceRoot":"","sources":["../src/DynimProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAc,EAQZ,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAUf,OAAO,KAAK,EAKV,WAAW,EAEZ,MAAM,YAAY,CAAC;AAIpB,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrE,kCAAkC;IAClC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,KAAK,IAAI,CAAC;IACzC,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,qBAAqB;IACrB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,0CAA0C;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,qCAAqC;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,yBAAyB;IACzB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,oCAAoC;IACpC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,yDAAyD;IACzD,WAAW,EAAE,WAAW,CAAC;IACzB,2CAA2C;IAC3C,cAAc,EAAE,OAAO,CAAC;IACxB,gCAAgC;IAChC,eAAe,EAAE,OAAO,CAAC;CAC1B;AAID,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,MAAW,GACZ,EAAE,kBAAkB,GAAG,GAAG,CAAC,OAAO,CAwYlC;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C"}
1
+ {"version":3,"file":"DynimProvider.d.ts","sourceRoot":"","sources":["../src/DynimProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAc,EAQZ,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAWf,OAAO,KAAK,EAKV,WAAW,EACX,UAAU,EACV,aAAa,EAGd,MAAM,YAAY,CAAC;AAIpB,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrE,kCAAkC;IAClC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,KAAK,IAAI,CAAC;IACzC,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,qBAAqB;IACrB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,0CAA0C;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,qCAAqC;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,yBAAyB;IACzB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,oCAAoC;IACpC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,6CAA6C;IAC7C,cAAc,EAAE,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAC5C,mEAAmE;IACnE,iBAAiB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;IACpE,kDAAkD;IAClD,WAAW,EAAE,OAAO,CAAC;IACrB,yDAAyD;IACzD,WAAW,EAAE,WAAW,CAAC;IACzB,2CAA2C;IAC3C,cAAc,EAAE,OAAO,CAAC;IACxB,gCAAgC;IAChC,eAAe,EAAE,OAAO,CAAC;CAC1B;AAID,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,MAAW,GACZ,EAAE,kBAAkB,GAAG,GAAG,CAAC,OAAO,CAkdlC;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C"}
@@ -9,7 +9,7 @@ import { jsxs as _jsxs, Fragment as _Fragment, jsx as _jsx } from "react/jsx-run
9
9
  */
10
10
  import React, { createContext, useContext, useEffect, useRef, useCallback, useMemo, useState, } from 'react';
11
11
  import ReactDOM from 'react-dom';
12
- import { createBuilderClient, createBuilder, createCodeClient, createBundleLoader, BundleNotFoundError, BundleAuthError, } from 'dynim-core';
12
+ import { createBuilderClient, createBuilder, createCodeClient, createBundleLoader, createCSSLoader, BundleNotFoundError, BundleAuthError, } from 'dynim-core';
13
13
  import { createSharedContext, updateSharedContext, isSharedContextReady } from './inference/sharedContext';
14
14
  import { generateThemeCSS } from './theme';
15
15
  const DynimContext = createContext(null);
@@ -30,6 +30,7 @@ export function DynimProvider({ children, config = {}, }) {
30
30
  const builderRef = useRef(null);
31
31
  const codeClientRef = useRef(null);
32
32
  const bundleLoaderRef = useRef(null);
33
+ const cssLoaderRef = useRef(null);
33
34
  // Track when we're exiting to prevent auto-load from re-triggering
34
35
  const isExitingRef = useRef(false);
35
36
  const hasAttemptedInitialLoadRef = useRef(false);
@@ -40,6 +41,7 @@ export function DynimProvider({ children, config = {}, }) {
40
41
  const [isInitialLoadComplete, setIsInitialLoadComplete] = useState(false);
41
42
  const [TenantApp, setTenantApp] = useState(null);
42
43
  const [bundleError, setBundleError] = useState(null);
44
+ const [isRestoring, setIsRestoring] = useState(false);
43
45
  const [codeMessage, setCodeMessage] = useState({
44
46
  thinking: '',
45
47
  text: '',
@@ -140,7 +142,9 @@ export function DynimProvider({ children, config = {}, }) {
140
142
  codeClientRef.current?.resetMessage();
141
143
  },
142
144
  loadBundle: (bundleUrl) => {
143
- isExitingRef.current = true;
145
+ // Note: isExitingRef is already set by onExitStart for the exit flow.
146
+ // Don't set it here — this callback is also used by checkpoint restore
147
+ // while the builder is still active.
144
148
  return loadBundleRef.current?.(bundleUrl) ?? Promise.resolve();
145
149
  },
146
150
  onEnter: () => {
@@ -154,6 +158,8 @@ export function DynimProvider({ children, config = {}, }) {
154
158
  });
155
159
  return () => {
156
160
  builderRef.current?.destroy();
161
+ // Clean up CSS link element on unmount
162
+ cssLoaderRef.current?.unload();
157
163
  };
158
164
  }, []);
159
165
  // Initialize builder client (only once on mount)
@@ -181,8 +187,20 @@ export function DynimProvider({ children, config = {}, }) {
181
187
  }
182
188
  return bundleLoaderRef.current;
183
189
  }, [getAuthToken]);
184
- // Load bundle
185
- const loadBundle = useCallback(async (bundleUrl) => {
190
+ // Get CSS loader
191
+ const getCSSLoader = useCallback(() => {
192
+ if (!cssLoaderRef.current) {
193
+ cssLoaderRef.current = createCSSLoader({
194
+ linkId: 'dynim-bundle-css',
195
+ onError: (error) => {
196
+ console.warn('[DynimProvider] CSS load failed:', error);
197
+ },
198
+ });
199
+ }
200
+ return cssLoaderRef.current;
201
+ }, []);
202
+ // Load bundle (JS + CSS)
203
+ const loadBundle = useCallback(async (bundleUrl, loadCSS = true) => {
186
204
  const loader = getBundleLoader();
187
205
  if (loader.isLoading())
188
206
  return;
@@ -193,12 +211,28 @@ export function DynimProvider({ children, config = {}, }) {
193
211
  setTenantApp(() => App);
194
212
  setIsBundleLoaded(true);
195
213
  cleanup();
214
+ // Load CSS alongside JS bundle
215
+ if (loadCSS) {
216
+ const cssLoader = getCSSLoader();
217
+ const isTemp = bundleUrl.includes('temp=true');
218
+ const cssUrl = isTemp ? '/api/code/css?temp=true' : '/api/code/css';
219
+ if (isTemp) {
220
+ // Temp/preview CSS - bust cache to get latest
221
+ cssLoader.loadWithCacheBust(cssUrl);
222
+ }
223
+ else {
224
+ // Saved CSS - let browser cache
225
+ cssLoader.load(cssUrl);
226
+ }
227
+ }
196
228
  }
197
229
  catch (error) {
198
230
  // 404 = no bundle, 401 = not authenticated - show children
199
231
  if (error instanceof BundleNotFoundError || error instanceof BundleAuthError) {
200
232
  setTenantApp(null);
201
233
  setIsBundleLoaded(false);
234
+ // Also unload any CSS
235
+ getCSSLoader().unload();
202
236
  return;
203
237
  }
204
238
  setBundleError(error);
@@ -206,7 +240,7 @@ export function DynimProvider({ children, config = {}, }) {
206
240
  finally {
207
241
  setIsBundleLoading(false);
208
242
  }
209
- }, [getBundleLoader]);
243
+ }, [getBundleLoader, getCSSLoader]);
210
244
  // Keep ref updated
211
245
  useEffect(() => {
212
246
  loadBundleRef.current = loadBundle;
@@ -272,7 +306,8 @@ export function DynimProvider({ children, config = {}, }) {
272
306
  }, [fetchTheme]);
273
307
  // Load saved bundle
274
308
  const loadSavedBundle = useCallback(async () => {
275
- await loadBundle('/api/code/bundle');
309
+ // Note: CSS is loaded separately by saveCode/abandonCode with cache busting
310
+ await loadBundle('/api/code/bundle', false);
276
311
  }, [loadBundle]);
277
312
  // Watch for bundleReady
278
313
  useEffect(() => {
@@ -283,7 +318,7 @@ export function DynimProvider({ children, config = {}, }) {
283
318
  }
284
319
  }
285
320
  }, [codeMessage.bundleReady, codeMessage.projectId]);
286
- // Load temp bundle on signal
321
+ // Load temp bundle on signal (JS + CSS with cache busting)
287
322
  useEffect(() => {
288
323
  if (bundleLoadSignal === 0)
289
324
  return;
@@ -292,8 +327,9 @@ export function DynimProvider({ children, config = {}, }) {
292
327
  pendingBundleProjectIdRef.current = null;
293
328
  return;
294
329
  }
330
+ // Load JS bundle with cache busting
295
331
  const bundleUrl = `/api/code/bundle?temp=true&_t=${Date.now()}`;
296
- loadBundleRef.current?.(bundleUrl);
332
+ loadBundleRef.current?.(bundleUrl, true); // true = also load CSS
297
333
  pendingBundleProjectIdRef.current = null;
298
334
  }, [bundleLoadSignal]);
299
335
  // Public methods
@@ -315,11 +351,36 @@ export function DynimProvider({ children, config = {}, }) {
315
351
  const saveCode = useCallback(async () => {
316
352
  await codeClientRef.current?.saveCode();
317
353
  await loadSavedBundle();
318
- }, [loadSavedBundle]);
354
+ // Force reload CSS with cache bust since saved CSS has changed
355
+ getCSSLoader().loadWithCacheBust('/api/code/css');
356
+ }, [loadSavedBundle, getCSSLoader]);
319
357
  const abandonCode = useCallback(async () => {
320
358
  await codeClientRef.current?.abandonCode();
321
359
  await loadSavedBundle();
322
- }, [loadSavedBundle]);
360
+ // Reload saved CSS (may have been showing temp CSS)
361
+ getCSSLoader().loadWithCacheBust('/api/code/css');
362
+ }, [loadSavedBundle, getCSSLoader]);
363
+ const getCheckpoints = useCallback(async () => {
364
+ return codeClientRef.current?.getCheckpoints() ?? [];
365
+ }, []);
366
+ const restoreCheckpoint = useCallback(async (checkpointId) => {
367
+ if (!codeClientRef.current) {
368
+ throw new Error('Code client not initialized');
369
+ }
370
+ setIsRestoring(true);
371
+ try {
372
+ const result = await codeClientRef.current.restoreCheckpoint(checkpointId);
373
+ // Reload bundle + CSS on success (loadBundle handles CSS when loadCSS=true)
374
+ if (result.bundle_ready) {
375
+ const bundleUrl = `/api/code/bundle?temp=true&_t=${Date.now()}`;
376
+ await loadBundleRef.current?.(bundleUrl, true);
377
+ }
378
+ return result;
379
+ }
380
+ finally {
381
+ setIsRestoring(false);
382
+ }
383
+ }, []);
323
384
  const contextValue = useMemo(() => ({
324
385
  enterBuilder,
325
386
  exitBuilder,
@@ -327,6 +388,9 @@ export function DynimProvider({ children, config = {}, }) {
327
388
  sendCode,
328
389
  saveCode,
329
390
  abandonCode,
391
+ getCheckpoints,
392
+ restoreCheckpoint,
393
+ isRestoring,
330
394
  codeMessage,
331
395
  isBundleLoaded,
332
396
  isBundleLoading,
@@ -337,6 +401,9 @@ export function DynimProvider({ children, config = {}, }) {
337
401
  sendCode,
338
402
  saveCode,
339
403
  abandonCode,
404
+ getCheckpoints,
405
+ restoreCheckpoint,
406
+ isRestoring,
340
407
  codeMessage,
341
408
  isBundleLoaded,
342
409
  isBundleLoading,
package/dist/index.d.ts CHANGED
@@ -14,5 +14,5 @@ export { DynimProvider, useDynim } from './DynimProvider';
14
14
  export type { DynimConfig, DynimContextValue, DynimProviderProps } from './DynimProvider';
15
15
  export { defaultTheme } from './theme';
16
16
  export type { DynimTheme } from './theme';
17
- export type { CodeMessage, CodeEdit, Message } from 'dynim-core';
17
+ export type { CodeMessage, CodeEdit, Checkpoint, RestoreResult, Message } from 'dynim-core';
18
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC1D,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG1F,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC1D,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG1F,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dynim-react",
3
- "version": "1.0.50",
3
+ "version": "1.0.52",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -27,7 +27,7 @@
27
27
  "dev": "tsc --watch"
28
28
  },
29
29
  "dependencies": {
30
- "dynim-core": "^1.0.7"
30
+ "dynim-core": "^1.0.26"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "react": ">=17.0.0",
@@ -44,8 +44,8 @@
44
44
  "@types/react-dom": "^18.3.7",
45
45
  "react": "^19.2.3",
46
46
  "react-dom": "^19.2.3",
47
- "vite": "^5.0.11",
48
- "typescript": "^5.9.3"
47
+ "typescript": "^5.9.3",
48
+ "vite": "^5.0.11"
49
49
  },
50
50
  "license": "MIT"
51
51
  }