dynim-vue 1.0.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.
@@ -0,0 +1,87 @@
1
+ /**
2
+ * DynimProvider - Single provider for all Dynim functionality (Vue)
3
+ *
4
+ * Handles:
5
+ * - Loading tenant bundles
6
+ * - Visual builder UI (when user has edit permissions)
7
+ * - Shared context for bundles to access Vue, packages, etc.
8
+ */
9
+ import { type InjectionKey, type PropType } from 'vue';
10
+ import * as Vue from 'vue';
11
+ import type { CodeMessage } from 'dynim-core';
12
+ export interface DynimConfig {
13
+ /** Function to fetch a session token for authentication */
14
+ getSession?: () => Promise<{
15
+ token: string;
16
+ refreshToken?: string;
17
+ }>;
18
+ /** Called when an error occurs */
19
+ onError?: (error: Event | Error) => void;
20
+ /** NPM packages to expose to bundles (e.g., { 'vue-router': VueRouter }) */
21
+ packages?: Record<string, unknown>;
22
+ /** Custom composables/hooks to expose to bundles */
23
+ hooks?: Record<string, unknown>;
24
+ /** Vue contexts (provide/inject values) to expose to bundles */
25
+ contexts?: Record<string, unknown>;
26
+ }
27
+ export interface DynimContextValue {
28
+ /** Enter edit mode (shows builder UI) */
29
+ enterBuilder: () => void;
30
+ /** Exit edit mode */
31
+ exitBuilder: () => void;
32
+ /** Whether builder/edit mode is active */
33
+ isEditing: boolean;
34
+ /** Send a code edit request to AI */
35
+ sendCode: (query: string) => Promise<void>;
36
+ /** Save current edits */
37
+ saveCode: () => Promise<void>;
38
+ /** Abandon/discard current edits */
39
+ abandonCode: () => Promise<void>;
40
+ /** Current code message state (thinking, edits, etc.) */
41
+ codeMessage: CodeMessage;
42
+ /** Whether a bundle is currently loaded */
43
+ isBundleLoaded: boolean;
44
+ /** Whether bundle is loading */
45
+ isBundleLoading: boolean;
46
+ }
47
+ export declare const DynimInjectionKey: InjectionKey<DynimContextValue>;
48
+ /**
49
+ * DynimProvider - Wrap your app with this to enable Dynim functionality
50
+ *
51
+ * @example
52
+ * ```vue
53
+ * <script setup>
54
+ * import { DynimProvider } from 'dynim-vue';
55
+ * </script>
56
+ *
57
+ * <template>
58
+ * <DynimProvider>
59
+ * <App />
60
+ * </DynimProvider>
61
+ * </template>
62
+ * ```
63
+ */
64
+ export declare const DynimProvider: Vue.DefineComponent<Vue.ExtractPropTypes<{
65
+ config: {
66
+ type: PropType<DynimConfig>;
67
+ default: () => {};
68
+ };
69
+ }>, () => (Vue.VNode<Vue.RendererNode, Vue.RendererElement, {
70
+ [key: string]: any;
71
+ }> | (Vue.VNode<Vue.RendererNode, Vue.RendererElement, {
72
+ [key: string]: any;
73
+ }> | Vue.VNode<Vue.RendererNode, Vue.RendererElement, {
74
+ [key: string]: any;
75
+ }>[] | undefined)[] | null | undefined)[], {}, {}, {}, Vue.ComponentOptionsMixin, Vue.ComponentOptionsMixin, {}, string, Vue.PublicProps, Readonly<Vue.ExtractPropTypes<{
76
+ config: {
77
+ type: PropType<DynimConfig>;
78
+ default: () => {};
79
+ };
80
+ }>> & Readonly<{}>, {
81
+ config: DynimConfig;
82
+ }, {}, {}, {}, string, Vue.ComponentProvideOptions, true, {}, any>;
83
+ /**
84
+ * Composable to access Dynim functionality
85
+ */
86
+ export declare function useDynim(): DynimContextValue;
87
+ //# sourceMappingURL=DynimProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DynimProvider.d.ts","sourceRoot":"","sources":["../src/DynimProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAWL,KAAK,YAAY,EACjB,KAAK,QAAQ,EAEd,MAAM,KAAK,CAAC;AACb,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAS3B,OAAO,KAAK,EAIV,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,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,gEAAgE;IAChE,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;AAED,eAAO,MAAM,iBAAiB,EAAE,YAAY,CAAC,iBAAiB,CAAmB,CAAC;AAElF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,aAAa;;cAIJ,QAAQ,CAAC,WAAW,CAAC;;;;;;;;;;;cAArB,QAAQ,CAAC,WAAW,CAAC;;;;;kEA4XzC,CAAC;AAEH;;GAEG;AACH,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C"}
@@ -0,0 +1,385 @@
1
+ /**
2
+ * DynimProvider - Single provider for all Dynim functionality (Vue)
3
+ *
4
+ * Handles:
5
+ * - Loading tenant bundles
6
+ * - Visual builder UI (when user has edit permissions)
7
+ * - Shared context for bundles to access Vue, packages, etc.
8
+ */
9
+ import { defineComponent, ref, reactive, computed, provide, inject, onMounted, onUnmounted, watch, h, } from 'vue';
10
+ import * as Vue from 'vue';
11
+ import { createBuilderClient, createBuilder, createCodeClient, createBundleLoader, BundleNotFoundError, BundleAuthError, } from 'dynim-core';
12
+ import { createSharedContext, updateSharedContext, isSharedContextReady } from './inference/sharedContext';
13
+ import { generateThemeCSS } from './theme';
14
+ export const DynimInjectionKey = Symbol('dynim');
15
+ /**
16
+ * DynimProvider - Wrap your app with this to enable Dynim functionality
17
+ *
18
+ * @example
19
+ * ```vue
20
+ * <script setup>
21
+ * import { DynimProvider } from 'dynim-vue';
22
+ * </script>
23
+ *
24
+ * <template>
25
+ * <DynimProvider>
26
+ * <App />
27
+ * </DynimProvider>
28
+ * </template>
29
+ * ```
30
+ */
31
+ export const DynimProvider = defineComponent({
32
+ name: 'DynimProvider',
33
+ props: {
34
+ config: {
35
+ type: Object,
36
+ default: () => ({}),
37
+ },
38
+ },
39
+ setup(props, { slots }) {
40
+ // Client refs (non-reactive - plain variables)
41
+ let builderClientRef = null;
42
+ let builderRef = null;
43
+ let codeClientRef = null;
44
+ let bundleLoaderRef = null;
45
+ // Track when we're exiting to prevent auto-load from re-triggering
46
+ let isExitingRef = false;
47
+ let hasAttemptedInitialLoadRef = false;
48
+ let isBuilderActiveRef = false;
49
+ // Cached auth token
50
+ let cachedTokenRef = null;
51
+ let tokenPromiseRef = null;
52
+ // Bundle load signal
53
+ let pendingBundleProjectIdRef = null;
54
+ // Theme state ref
55
+ let hasAttemptedThemeLoadRef = false;
56
+ // Load bundle function ref
57
+ let loadBundleRef = null;
58
+ // Reactive state
59
+ const isEditing = ref(false);
60
+ const isBundleLoaded = ref(false);
61
+ const isBundleLoading = ref(false);
62
+ const isInitialLoadComplete = ref(false);
63
+ const TenantApp = ref(null);
64
+ const bundleError = ref(null);
65
+ const bundleLoadSignal = ref(0);
66
+ const theme = ref(null);
67
+ const codeMessage = reactive({
68
+ thinking: '',
69
+ text: '',
70
+ edits: [],
71
+ status: 'idle',
72
+ bundleReady: false,
73
+ bundleError: undefined,
74
+ });
75
+ // Get config reference
76
+ const getConfig = () => props.config;
77
+ // Get auth token (cached after first call)
78
+ const getAuthToken = async () => {
79
+ const config = getConfig();
80
+ // Return cached token if available
81
+ if (cachedTokenRef)
82
+ return cachedTokenRef;
83
+ // Reuse in-flight promise if one exists
84
+ if (tokenPromiseRef)
85
+ return tokenPromiseRef;
86
+ if (config.getSession) {
87
+ tokenPromiseRef = (async () => {
88
+ try {
89
+ const session = await config.getSession();
90
+ cachedTokenRef = session.token;
91
+ return session.token;
92
+ }
93
+ catch {
94
+ return null;
95
+ }
96
+ finally {
97
+ tokenPromiseRef = null;
98
+ }
99
+ })();
100
+ return tokenPromiseRef;
101
+ }
102
+ return null;
103
+ };
104
+ // Get bundle loader
105
+ const getBundleLoader = () => {
106
+ if (!bundleLoaderRef) {
107
+ bundleLoaderRef = createBundleLoader({
108
+ getAuthToken,
109
+ includeCredentials: true,
110
+ onError: (error) => {
111
+ console.error('[DynimProvider] Bundle load failed:', error);
112
+ getConfig().onError?.(error);
113
+ },
114
+ });
115
+ }
116
+ return bundleLoaderRef;
117
+ };
118
+ // Load bundle
119
+ const loadBundle = async (bundleUrl) => {
120
+ const loader = getBundleLoader();
121
+ if (loader.isLoading())
122
+ return;
123
+ isBundleLoading.value = true;
124
+ bundleError.value = null;
125
+ try {
126
+ const { App, cleanup } = await loader.load(bundleUrl);
127
+ TenantApp.value = App;
128
+ isBundleLoaded.value = true;
129
+ cleanup();
130
+ }
131
+ catch (error) {
132
+ // 404 = no bundle, 401 = not authenticated - show children
133
+ if (error instanceof BundleNotFoundError || error instanceof BundleAuthError) {
134
+ TenantApp.value = null;
135
+ isBundleLoaded.value = false;
136
+ return;
137
+ }
138
+ bundleError.value = error;
139
+ }
140
+ finally {
141
+ isBundleLoading.value = false;
142
+ }
143
+ };
144
+ // Load saved bundle
145
+ const loadSavedBundle = async () => {
146
+ await loadBundle('/api/code/bundle');
147
+ };
148
+ // Fetch theme
149
+ const fetchTheme = async () => {
150
+ if (hasAttemptedThemeLoadRef)
151
+ return;
152
+ if (!getConfig().getSession)
153
+ return;
154
+ hasAttemptedThemeLoadRef = true;
155
+ try {
156
+ const token = await getAuthToken();
157
+ const headers = {};
158
+ if (token) {
159
+ headers['Authorization'] = `Bearer ${token}`;
160
+ }
161
+ const response = await fetch('/api/code/theme', {
162
+ headers,
163
+ credentials: 'include',
164
+ });
165
+ if (response.ok) {
166
+ const data = await response.json();
167
+ theme.value = data;
168
+ }
169
+ }
170
+ catch (error) {
171
+ // Theme fetch failed - use defaults (non-critical)
172
+ console.warn('[DynimProvider] Failed to fetch theme:', error);
173
+ }
174
+ };
175
+ // Public methods
176
+ const enterBuilder = () => {
177
+ if (builderRef && !builderRef.isActive()) {
178
+ builderRef.enter();
179
+ // Fetch theme lazily when entering builder
180
+ fetchTheme();
181
+ }
182
+ };
183
+ const exitBuilder = () => {
184
+ if (builderRef && builderRef.isActive()) {
185
+ builderRef.exit();
186
+ }
187
+ };
188
+ const sendCode = async (query) => {
189
+ await codeClientRef?.sendCode(query);
190
+ };
191
+ const saveCode = async () => {
192
+ await codeClientRef?.saveCode();
193
+ await loadSavedBundle();
194
+ };
195
+ const abandonCode = async () => {
196
+ await codeClientRef?.abandonCode();
197
+ await loadSavedBundle();
198
+ };
199
+ // Context value (computed for reactivity)
200
+ const contextValue = computed(() => ({
201
+ enterBuilder,
202
+ exitBuilder,
203
+ isEditing: isEditing.value,
204
+ sendCode,
205
+ saveCode,
206
+ abandonCode,
207
+ codeMessage,
208
+ isBundleLoaded: isBundleLoaded.value,
209
+ isBundleLoading: isBundleLoading.value,
210
+ }));
211
+ // Theme CSS (computed)
212
+ const themeCSS = computed(() => generateThemeCSS(theme.value ?? undefined));
213
+ // Lifecycle: Setup on mount
214
+ onMounted(() => {
215
+ const config = getConfig();
216
+ const { packages = {}, hooks = {}, contexts = {} } = config;
217
+ // Keep loadBundleRef updated
218
+ loadBundleRef = loadBundle;
219
+ // Set up shared context for bundles
220
+ const sdkPackages = {
221
+ 'dynim-vue': { DynimProvider, useDynim },
222
+ ...packages,
223
+ };
224
+ if (!isSharedContextReady()) {
225
+ // Create fresh shared context
226
+ createSharedContext({
227
+ Vue,
228
+ packages: sdkPackages,
229
+ hooks,
230
+ contexts,
231
+ });
232
+ }
233
+ else {
234
+ // Update existing context with packages (handles HMR)
235
+ updateSharedContext({
236
+ packages: sdkPackages,
237
+ hooks,
238
+ contexts,
239
+ });
240
+ }
241
+ // Initialize code client
242
+ codeClientRef = createCodeClient({
243
+ getSession: config.getSession,
244
+ onMessageUpdate: (message) => {
245
+ Object.assign(codeMessage, message);
246
+ },
247
+ onError: (error) => {
248
+ console.error('[DynimProvider] Code error:', error);
249
+ config.onError?.(error);
250
+ },
251
+ });
252
+ // Initialize builder
253
+ builderRef = createBuilder({
254
+ getSession: config.getSession,
255
+ codeClient: codeClientRef ?? undefined,
256
+ onExitStart: () => {
257
+ isExitingRef = true;
258
+ isBuilderActiveRef = false;
259
+ codeClientRef?.abort();
260
+ codeClientRef?.resetMessage();
261
+ },
262
+ loadBundle: (bundleUrl) => {
263
+ isExitingRef = true;
264
+ return loadBundleRef?.(bundleUrl) ?? Promise.resolve();
265
+ },
266
+ onEnter: () => {
267
+ isExitingRef = false;
268
+ isBuilderActiveRef = true;
269
+ isEditing.value = true;
270
+ },
271
+ onExit: () => {
272
+ isEditing.value = false;
273
+ },
274
+ });
275
+ // Initialize builder client
276
+ builderClientRef = createBuilderClient({
277
+ getSession: config.getSession,
278
+ onError: (error) => {
279
+ console.error('[DynimProvider] Error:', error);
280
+ config.onError?.(error);
281
+ },
282
+ });
283
+ // Auto-load saved bundle on mount if auth is available
284
+ if (!hasAttemptedInitialLoadRef) {
285
+ hasAttemptedInitialLoadRef = true;
286
+ // No auth configured = skip bundle load
287
+ if (!config.getSession) {
288
+ isInitialLoadComplete.value = true;
289
+ }
290
+ else {
291
+ // Load bundle with the provided token
292
+ const doInitialLoad = async () => {
293
+ try {
294
+ await loadBundleRef?.('/api/code/bundle');
295
+ }
296
+ catch (error) {
297
+ // Errors handled in loadBundle (404 = no bundle, etc.)
298
+ console.log('[DynimProvider] Initial bundle load:', error.message);
299
+ }
300
+ finally {
301
+ isInitialLoadComplete.value = true;
302
+ }
303
+ };
304
+ doInitialLoad();
305
+ // Prefetch theme after 3s delay (non-blocking, so it's ready when builder opens)
306
+ setTimeout(() => {
307
+ fetchTheme();
308
+ }, 3000);
309
+ }
310
+ }
311
+ });
312
+ // Cleanup on unmount
313
+ onUnmounted(() => {
314
+ builderRef?.destroy();
315
+ });
316
+ // Watch for bundleReady
317
+ watch(() => ({ bundleReady: codeMessage.bundleReady, projectId: codeMessage.projectId }), ({ bundleReady, projectId }) => {
318
+ if (bundleReady && projectId) {
319
+ if (isBuilderActiveRef && !isExitingRef) {
320
+ pendingBundleProjectIdRef = projectId;
321
+ bundleLoadSignal.value++;
322
+ }
323
+ }
324
+ });
325
+ // Watch for bundle load signal
326
+ watch(bundleLoadSignal, (signal) => {
327
+ if (signal === 0)
328
+ return;
329
+ const projectId = pendingBundleProjectIdRef;
330
+ if (!projectId || isExitingRef) {
331
+ pendingBundleProjectIdRef = null;
332
+ return;
333
+ }
334
+ const bundleUrl = `/api/code/bundle?temp=true&_t=${Date.now()}`;
335
+ loadBundleRef?.(bundleUrl);
336
+ pendingBundleProjectIdRef = null;
337
+ });
338
+ // Provide context
339
+ provide(DynimInjectionKey, contextValue.value);
340
+ // Watch for context value changes and update provided value
341
+ watch(contextValue, (newValue) => {
342
+ provide(DynimInjectionKey, newValue);
343
+ });
344
+ // Render function
345
+ return () => {
346
+ // Render content
347
+ const renderContent = () => {
348
+ if (!isInitialLoadComplete.value)
349
+ return null;
350
+ if (bundleError.value) {
351
+ return [
352
+ h('div', {
353
+ style: {
354
+ padding: '12px',
355
+ background: '#fef3c7',
356
+ borderBottom: '1px solid #fcd34d',
357
+ fontSize: '13px',
358
+ color: '#92400e',
359
+ },
360
+ }, `Bundle error: ${bundleError.value.message}`),
361
+ slots.default?.(),
362
+ ];
363
+ }
364
+ if (TenantApp.value) {
365
+ return h(TenantApp.value);
366
+ }
367
+ return slots.default?.();
368
+ };
369
+ return [
370
+ h('style', themeCSS.value),
371
+ renderContent(),
372
+ ];
373
+ };
374
+ },
375
+ });
376
+ /**
377
+ * Composable to access Dynim functionality
378
+ */
379
+ export function useDynim() {
380
+ const context = inject(DynimInjectionKey);
381
+ if (!context) {
382
+ throw new Error('useDynim must be used within a DynimProvider');
383
+ }
384
+ return context;
385
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * dynim-vue - Vue 3 integration for Dynim
3
+ *
4
+ * Simple usage:
5
+ * ```vue
6
+ * <script setup>
7
+ * import { DynimProvider, useDynim } from 'dynim-vue';
8
+ * </script>
9
+ *
10
+ * <template>
11
+ * <DynimProvider>
12
+ * <App />
13
+ * </DynimProvider>
14
+ * </template>
15
+ * ```
16
+ */
17
+ export { DynimProvider, useDynim, DynimInjectionKey } from './DynimProvider';
18
+ export type { DynimConfig, DynimContextValue } from './DynimProvider';
19
+ export { defaultTheme } from './theme';
20
+ export type { DynimTheme } from './theme';
21
+ export type { CodeMessage, CodeEdit, Message } from 'dynim-core';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC7E,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGtE,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"}
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * dynim-vue - Vue 3 integration for Dynim
3
+ *
4
+ * Simple usage:
5
+ * ```vue
6
+ * <script setup>
7
+ * import { DynimProvider, useDynim } from 'dynim-vue';
8
+ * </script>
9
+ *
10
+ * <template>
11
+ * <DynimProvider>
12
+ * <App />
13
+ * </DynimProvider>
14
+ * </template>
15
+ * ```
16
+ */
17
+ // Main exports
18
+ export { DynimProvider, useDynim, DynimInjectionKey } from './DynimProvider';
19
+ // Theme customization
20
+ export { defaultTheme } from './theme';
@@ -0,0 +1,38 @@
1
+ import type { DynimGlobal } from 'dynim-core';
2
+ import type { DynimSDKConfig } from './types';
3
+ /**
4
+ * Creates and registers the shared context on the window object.
5
+ * This makes Vue, hooks, and contexts available to tenant bundles.
6
+ *
7
+ * Uses createSharedRegistry from dynim-core under the hood.
8
+ *
9
+ * @param config - Configuration object containing Vue, hooks, and contexts
10
+ * @returns The created SDK object
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * import { createSharedContext } from 'dynim-vue';
15
+ * import * as Vue from 'vue';
16
+ * import { useAuth, useNotifications } from './composables';
17
+ *
18
+ * createSharedContext({
19
+ * Vue,
20
+ * hooks: { useAuth, useNotifications },
21
+ * });
22
+ * ```
23
+ */
24
+ export declare function createSharedContext(config: DynimSDKConfig): DynimGlobal;
25
+ /**
26
+ * Updates the shared context with additional configuration.
27
+ * Useful for adding packages or hooks after initial creation.
28
+ *
29
+ * @param config - Partial configuration to merge into existing context
30
+ */
31
+ export declare function updateSharedContext(config: Partial<DynimSDKConfig>): void;
32
+ /**
33
+ * Checks if the shared context has been initialized.
34
+ *
35
+ * @returns true if the shared context is available
36
+ */
37
+ export declare function isSharedContextReady(): boolean;
38
+ //# sourceMappingURL=sharedContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sharedContext.d.ts","sourceRoot":"","sources":["../../src/inference/sharedContext.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAkB,MAAM,YAAY,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAK9C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW,CA2BvE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAYzE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C"}
@@ -0,0 +1,75 @@
1
+ import { createSharedRegistry, isSharedRegistryReady, } from 'dynim-core';
2
+ // Keep a reference to the current registry for updates
3
+ let currentRegistry = null;
4
+ /**
5
+ * Creates and registers the shared context on the window object.
6
+ * This makes Vue, hooks, and contexts available to tenant bundles.
7
+ *
8
+ * Uses createSharedRegistry from dynim-core under the hood.
9
+ *
10
+ * @param config - Configuration object containing Vue, hooks, and contexts
11
+ * @returns The created SDK object
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { createSharedContext } from 'dynim-vue';
16
+ * import * as Vue from 'vue';
17
+ * import { useAuth, useNotifications } from './composables';
18
+ *
19
+ * createSharedContext({
20
+ * Vue,
21
+ * hooks: { useAuth, useNotifications },
22
+ * });
23
+ * ```
24
+ */
25
+ export function createSharedContext(config) {
26
+ const { Vue, hooks = {}, contexts = {}, packages = {}, globals = {} } = config;
27
+ // Always include Vue in packages for bundle access
28
+ const allPackages = {
29
+ 'vue': Vue,
30
+ ...packages,
31
+ };
32
+ // Create registry using core's createSharedRegistry
33
+ currentRegistry = createSharedRegistry({
34
+ framework: { Vue },
35
+ packages: allPackages,
36
+ hooks,
37
+ contexts,
38
+ globals: {
39
+ // Include Vue at top level for backwards compatibility
40
+ Vue,
41
+ ...globals,
42
+ },
43
+ // Expose Vue globally for legacy bundles
44
+ exposeFrameworkGlobally: true,
45
+ frameworkGlobalNames: ['Vue'],
46
+ });
47
+ // Return the created SDK object
48
+ return currentRegistry.get();
49
+ }
50
+ /**
51
+ * Updates the shared context with additional configuration.
52
+ * Useful for adding packages or hooks after initial creation.
53
+ *
54
+ * @param config - Partial configuration to merge into existing context
55
+ */
56
+ export function updateSharedContext(config) {
57
+ if (!currentRegistry) {
58
+ console.warn('[sharedContext] Cannot update: shared context not initialized');
59
+ return;
60
+ }
61
+ currentRegistry.update({
62
+ packages: config.packages,
63
+ hooks: config.hooks,
64
+ contexts: config.contexts,
65
+ globals: config.globals,
66
+ });
67
+ }
68
+ /**
69
+ * Checks if the shared context has been initialized.
70
+ *
71
+ * @returns true if the shared context is available
72
+ */
73
+ export function isSharedContextReady() {
74
+ return isSharedRegistryReady();
75
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Configuration for the Dynim SDK registration (Vue)
3
+ */
4
+ export interface DynimSDKConfig {
5
+ /** Vue library instance to expose globally */
6
+ Vue: typeof import('vue');
7
+ /** Custom composables/hooks to expose to tenant bundles */
8
+ hooks?: Record<string, unknown>;
9
+ /** Vue contexts (provide/inject values) to expose to tenant bundles */
10
+ contexts?: Record<string, unknown>;
11
+ /** NPM packages to expose to tenant bundles (e.g., vue-router, pinia) */
12
+ packages?: Record<string, unknown>;
13
+ /** Additional globals to expose */
14
+ globals?: Record<string, unknown>;
15
+ }
16
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/inference/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,8CAA8C;IAC9C,GAAG,EAAE,cAAc,KAAK,CAAC,CAAC;IAC1B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Dynim Theme System
3
+ *
4
+ * Theme is automatically fetched from the API per project.
5
+ * CSS variables are injected with defaults matching the original design.
6
+ */
7
+ export interface DynimTheme {
8
+ accent?: string;
9
+ accentHover?: string;
10
+ builderBg?: string;
11
+ builderText?: string;
12
+ builderFont?: string;
13
+ builderRadius?: string;
14
+ builderOpacity?: string;
15
+ chatAccent?: string;
16
+ chatBg?: string;
17
+ chatText?: string;
18
+ chatFont?: string;
19
+ chatRadius?: string;
20
+ chatOpacity?: string;
21
+ selectionColor?: string;
22
+ hoverColor?: string;
23
+ selectionRadius?: string;
24
+ selectionOpacity?: string;
25
+ hoverOpacity?: string;
26
+ }
27
+ /**
28
+ * Default theme values - matches original SDK styling exactly
29
+ */
30
+ export declare const defaultTheme: Required<DynimTheme>;
31
+ /**
32
+ * Generates CSS variable declarations from a theme object
33
+ */
34
+ export declare function generateThemeCSS(theme?: DynimTheme): string;
35
+ /**
36
+ * CSS variable references for use in styles
37
+ */
38
+ export declare const themeVars: {
39
+ readonly accent: "var(--dynim-accent)";
40
+ readonly accentHover: "var(--dynim-accent-hover)";
41
+ readonly builderBg: "var(--dynim-builder-bg)";
42
+ readonly builderText: "var(--dynim-builder-text)";
43
+ readonly builderFont: "var(--dynim-builder-font)";
44
+ readonly builderRadius: "var(--dynim-builder-radius)";
45
+ readonly builderOpacity: "var(--dynim-builder-opacity)";
46
+ readonly chatAccent: "var(--dynim-chat-accent)";
47
+ readonly chatBg: "var(--dynim-chat-bg)";
48
+ readonly chatText: "var(--dynim-chat-text)";
49
+ readonly chatFont: "var(--dynim-chat-font)";
50
+ readonly chatRadius: "var(--dynim-chat-radius)";
51
+ readonly chatOpacity: "var(--dynim-chat-opacity)";
52
+ readonly selectionColor: "var(--dynim-selection-color)";
53
+ readonly hoverColor: "var(--dynim-hover-color)";
54
+ readonly selectionRadius: "var(--dynim-selection-radius)";
55
+ readonly selectionOpacity: "var(--dynim-selection-opacity)";
56
+ readonly hoverOpacity: "var(--dynim-hover-opacity)";
57
+ };
58
+ //# sourceMappingURL=theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,UAAU;IAEzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IAGxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,UAAU,CAwB7C,CAAC;AA+BF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,GAAE,UAAe,GAAG,MAAM,CAW/D;AAED;;GAEG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;CAwBZ,CAAC"}
package/dist/theme.js ADDED
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Dynim Theme System
3
+ *
4
+ * Theme is automatically fetched from the API per project.
5
+ * CSS variables are injected with defaults matching the original design.
6
+ */
7
+ /**
8
+ * Default theme values - matches original SDK styling exactly
9
+ */
10
+ export const defaultTheme = {
11
+ // Builder Bar - original values
12
+ accent: '#3b82f6',
13
+ accentHover: '#2563eb',
14
+ builderBg: '#000000',
15
+ builderText: '#ffffff',
16
+ builderFont: 'system-ui, -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif',
17
+ builderRadius: '22px',
18
+ builderOpacity: '0.08',
19
+ // Chat Widget - original values
20
+ chatAccent: '#3b82f6',
21
+ chatBg: '#ffffff',
22
+ chatText: '#1f2937',
23
+ chatFont: 'system-ui, -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif',
24
+ chatRadius: '16px',
25
+ chatOpacity: '0.08',
26
+ // Selection - original values
27
+ selectionColor: '#8b5cf6',
28
+ hoverColor: '#0ea5e9',
29
+ selectionRadius: '0',
30
+ selectionOpacity: '0.1',
31
+ hoverOpacity: '0.1',
32
+ };
33
+ /**
34
+ * CSS variable names mapped to theme keys
35
+ */
36
+ const cssVarMap = {
37
+ // Builder Bar
38
+ accent: '--dynim-accent',
39
+ accentHover: '--dynim-accent-hover',
40
+ builderBg: '--dynim-builder-bg',
41
+ builderText: '--dynim-builder-text',
42
+ builderFont: '--dynim-builder-font',
43
+ builderRadius: '--dynim-builder-radius',
44
+ builderOpacity: '--dynim-builder-opacity',
45
+ // Chat Widget
46
+ chatAccent: '--dynim-chat-accent',
47
+ chatBg: '--dynim-chat-bg',
48
+ chatText: '--dynim-chat-text',
49
+ chatFont: '--dynim-chat-font',
50
+ chatRadius: '--dynim-chat-radius',
51
+ chatOpacity: '--dynim-chat-opacity',
52
+ // Selection
53
+ selectionColor: '--dynim-selection-color',
54
+ hoverColor: '--dynim-hover-color',
55
+ selectionRadius: '--dynim-selection-radius',
56
+ selectionOpacity: '--dynim-selection-opacity',
57
+ hoverOpacity: '--dynim-hover-opacity',
58
+ };
59
+ /**
60
+ * Generates CSS variable declarations from a theme object
61
+ */
62
+ export function generateThemeCSS(theme = {}) {
63
+ const merged = { ...defaultTheme, ...theme };
64
+ const vars = Object.entries(merged)
65
+ .map(([key, value]) => {
66
+ const cssVar = cssVarMap[key];
67
+ return `${cssVar}: ${value};`;
68
+ })
69
+ .join('\n ');
70
+ return `:root {\n ${vars}\n}`;
71
+ }
72
+ /**
73
+ * CSS variable references for use in styles
74
+ */
75
+ export const themeVars = {
76
+ // Builder Bar
77
+ accent: 'var(--dynim-accent)',
78
+ accentHover: 'var(--dynim-accent-hover)',
79
+ builderBg: 'var(--dynim-builder-bg)',
80
+ builderText: 'var(--dynim-builder-text)',
81
+ builderFont: 'var(--dynim-builder-font)',
82
+ builderRadius: 'var(--dynim-builder-radius)',
83
+ builderOpacity: 'var(--dynim-builder-opacity)',
84
+ // Chat Widget
85
+ chatAccent: 'var(--dynim-chat-accent)',
86
+ chatBg: 'var(--dynim-chat-bg)',
87
+ chatText: 'var(--dynim-chat-text)',
88
+ chatFont: 'var(--dynim-chat-font)',
89
+ chatRadius: 'var(--dynim-chat-radius)',
90
+ chatOpacity: 'var(--dynim-chat-opacity)',
91
+ // Selection
92
+ selectionColor: 'var(--dynim-selection-color)',
93
+ hoverColor: 'var(--dynim-hover-color)',
94
+ selectionRadius: 'var(--dynim-selection-radius)',
95
+ selectionOpacity: 'var(--dynim-selection-opacity)',
96
+ hoverOpacity: 'var(--dynim-hover-opacity)',
97
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * useDynim composable - Re-exported from DynimProvider for convenience
3
+ */
4
+ export { useDynim, DynimInjectionKey, type DynimContextValue } from './DynimProvider';
5
+ //# sourceMappingURL=useDynim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDynim.d.ts","sourceRoot":"","sources":["../src/useDynim.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * useDynim composable - Re-exported from DynimProvider for convenience
3
+ */
4
+ export { useDynim, DynimInjectionKey } from './DynimProvider';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Vite plugin for Dynim package exposure
3
+ */
4
+ export { dynimPackages, type DynimPackagesOptions, default } from './plugin.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Vite plugin for Dynim package exposure
3
+ */
4
+ export { dynimPackages, default } from './plugin.js';
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Vite plugin for Dynim package exposure
3
+ *
4
+ * Generates a virtual module that exports all specified packages,
5
+ * so you don't have to manually import and map each one.
6
+ *
7
+ * Usage:
8
+ * ```ts
9
+ * // vite.config.ts
10
+ * import { dynimPackages } from 'dynim-vue/vite'
11
+ *
12
+ * export default {
13
+ * plugins: [
14
+ * dynimPackages([
15
+ * 'vue-router',
16
+ * '@tanstack/vue-query',
17
+ * 'axios',
18
+ * ])
19
+ * ]
20
+ * }
21
+ * ```
22
+ *
23
+ * Then in your app:
24
+ * ```ts
25
+ * import packages from 'virtual:dynim-packages'
26
+ *
27
+ * <DynimProvider :config="{ packages }">
28
+ * ```
29
+ */
30
+ import type { Plugin } from 'vite';
31
+ export interface DynimPackagesOptions {
32
+ /**
33
+ * List of package names to expose to dynim bundles.
34
+ * These must be installed in your project's node_modules.
35
+ */
36
+ packages: string[];
37
+ }
38
+ /**
39
+ * Vite plugin that generates a virtual module exporting all specified packages.
40
+ *
41
+ * @param packages - Array of package names, or options object
42
+ * @returns Vite plugin
43
+ *
44
+ * @example
45
+ * // Simple usage - array of package names
46
+ * dynimPackages(['vue-router', 'axios'])
47
+ *
48
+ * @example
49
+ * // Options object
50
+ * dynimPackages({ packages: ['vue-router', 'axios'] })
51
+ */
52
+ export declare function dynimPackages(packagesOrOptions: string[] | DynimPackagesOptions): Plugin;
53
+ export default dynimPackages;
54
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/vite/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAKlC,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,iBAAiB,EAAE,MAAM,EAAE,GAAG,oBAAoB,GACjD,MAAM,CAwCR;AAED,eAAe,aAAa,CAAA"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Vite plugin for Dynim package exposure
3
+ *
4
+ * Generates a virtual module that exports all specified packages,
5
+ * so you don't have to manually import and map each one.
6
+ *
7
+ * Usage:
8
+ * ```ts
9
+ * // vite.config.ts
10
+ * import { dynimPackages } from 'dynim-vue/vite'
11
+ *
12
+ * export default {
13
+ * plugins: [
14
+ * dynimPackages([
15
+ * 'vue-router',
16
+ * '@tanstack/vue-query',
17
+ * 'axios',
18
+ * ])
19
+ * ]
20
+ * }
21
+ * ```
22
+ *
23
+ * Then in your app:
24
+ * ```ts
25
+ * import packages from 'virtual:dynim-packages'
26
+ *
27
+ * <DynimProvider :config="{ packages }">
28
+ * ```
29
+ */
30
+ const VIRTUAL_MODULE_ID = 'virtual:dynim-packages';
31
+ const RESOLVED_VIRTUAL_MODULE_ID = '\0' + VIRTUAL_MODULE_ID;
32
+ /**
33
+ * Vite plugin that generates a virtual module exporting all specified packages.
34
+ *
35
+ * @param packages - Array of package names, or options object
36
+ * @returns Vite plugin
37
+ *
38
+ * @example
39
+ * // Simple usage - array of package names
40
+ * dynimPackages(['vue-router', 'axios'])
41
+ *
42
+ * @example
43
+ * // Options object
44
+ * dynimPackages({ packages: ['vue-router', 'axios'] })
45
+ */
46
+ export function dynimPackages(packagesOrOptions) {
47
+ const packageNames = Array.isArray(packagesOrOptions)
48
+ ? packagesOrOptions
49
+ : packagesOrOptions.packages;
50
+ return {
51
+ name: 'dynim-packages',
52
+ resolveId(id) {
53
+ if (id === VIRTUAL_MODULE_ID) {
54
+ return RESOLVED_VIRTUAL_MODULE_ID;
55
+ }
56
+ },
57
+ load(id) {
58
+ if (id === RESOLVED_VIRTUAL_MODULE_ID) {
59
+ // Generate import statements for each package
60
+ const imports = packageNames
61
+ .map((name, i) => `import * as _pkg${i} from '${name}'`)
62
+ .join('\n');
63
+ // Generate the packages object entries
64
+ // Spread namespace objects into plain objects so exports are enumerable
65
+ const entries = packageNames
66
+ .map((name, i) => ` '${name}': { ..._pkg${i} }`)
67
+ .join(',\n');
68
+ // Return the generated module code
69
+ return `${imports}
70
+
71
+ const packages = {
72
+ ${entries}
73
+ }
74
+
75
+ export default packages
76
+ export { packages }
77
+ `;
78
+ }
79
+ },
80
+ };
81
+ }
82
+ export default dynimPackages;
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "dynim-vue",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ },
12
+ "./vite": {
13
+ "types": "./dist/vite/index.d.ts",
14
+ "import": "./dist/vite/index.js"
15
+ },
16
+ "./vite/virtual-module": {
17
+ "types": "./src/vite/virtual-module.d.ts"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "src/vite/virtual-module.d.ts",
23
+ "README.md"
24
+ ],
25
+ "scripts": {
26
+ "build": "tsc",
27
+ "dev": "tsc --watch"
28
+ },
29
+ "dependencies": {
30
+ "dynim-core": "^1.0.7"
31
+ },
32
+ "peerDependencies": {
33
+ "vue": ">=3.3.0",
34
+ "vite": ">=4.0.0"
35
+ },
36
+ "peerDependenciesMeta": {
37
+ "vite": {
38
+ "optional": true
39
+ }
40
+ },
41
+ "devDependencies": {
42
+ "vue": "^3.5.13",
43
+ "vite": "^5.0.11",
44
+ "typescript": "^5.9.3"
45
+ },
46
+ "license": "MIT"
47
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Type declarations for the virtual:dynim-packages module.
3
+ *
4
+ * To use these types, add to your tsconfig.json:
5
+ * {
6
+ * "compilerOptions": {
7
+ * "types": ["dynim-vue/vite/virtual-module"]
8
+ * }
9
+ * }
10
+ *
11
+ * Or add a reference in a .d.ts file:
12
+ * /// <reference types="dynim-vue/vite/virtual-module" />
13
+ */
14
+
15
+ declare module 'virtual:dynim-packages' {
16
+ /**
17
+ * Object mapping package names to their exports.
18
+ * The actual shape depends on which packages you configured
19
+ * in the dynimPackages() plugin.
20
+ */
21
+ const packages: Record<string, unknown>
22
+ export default packages
23
+ export { packages }
24
+ }