theme-ops-sdk 1.0.0 → 1.0.2

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 CHANGED
@@ -21,25 +21,37 @@ npm install react react-dom
21
21
  ## Usage
22
22
 
23
23
  ```tsx
24
+ import { useEffect, useMemo, useState } from 'react';
25
+
26
+ import { ConfigProvider, theme } from 'antd';
27
+
24
28
  import { useThemeOps } from 'theme-ops-sdk';
25
29
 
26
30
  function App() {
27
- const { isLoading, theme, insertStyles } = useThemeOps({
31
+ const [colorMode, setColorMode] = useState('light');
32
+
33
+ const { isLoading, getTheme, insertStyles } = useThemeOps({
28
34
  organizationId: 'your-org-id',
29
35
  appId: 'your-app-id', // optional
30
36
  });
31
37
 
32
- // Insert CSS stylesheet into the document head
33
- insertStyles();
38
+ useEffect(() => {
39
+ if (!isLoading) {
40
+ insertStyles();
41
+ }
42
+ }, [isLoading, insertStyles]);
34
43
 
35
- if (isLoading) return <div>Loading theme...</div>;
44
+ const antdTheme = useMemo(() => ({
45
+ cssVar: { key: 'theme-ops' },
46
+ ...getTheme(colorMode),
47
+ algorithm:
48
+ colorMode === 'dark' ? theme.darkAlgorithm : theme.defaultAlgorithm,
49
+ }), [colorMode, getTheme]);
36
50
 
37
- // Use theme tokens with your design system (e.g. Ant Design)
38
- const lightTokens = theme('light');
39
- const darkTokens = theme('dark');
51
+ if (isLoading) return <div>Loading theme...</div>;
40
52
 
41
53
  return (
42
- <ConfigProvider theme={lightTokens}>
54
+ <ConfigProvider theme={antdTheme}>
43
55
  <YourApp />
44
56
  </ConfigProvider>
45
57
  );
@@ -64,7 +76,7 @@ Main hook that fetches theme assets from the Theme Ops CDN.
64
76
  | Property | Type | Description |
65
77
  | -------------- | -------------------------------------------- | -------------------------------------------------------- |
66
78
  | `isLoading` | `boolean` | `true` while fetching theme assets from the CDN |
67
- | `theme` | `(mode: 'light' \| 'dark') => ThemeConfig` | Returns design tokens for the given color mode |
79
+ | `getTheme` | `(mode: 'light' \| 'dark') => ThemeConfig` | Returns design tokens for the given color mode |
68
80
  | `insertStyles` | `() => void` | Inserts a `<link>` stylesheet into `document.head` |
69
81
 
70
82
  ## Types
package/dist/index.cjs CHANGED
@@ -176,7 +176,7 @@ function useThemeOps(options) {
176
176
  };
177
177
  }, [organizationId, appId, releaseId, apiUrl]);
178
178
  const resolvedThemeState = state.status === "ready" ? state.themeState : EMPTY_THEME_STATE;
179
- const theme = react.useCallback(
179
+ const getTheme = react.useCallback(
180
180
  (mode) => resolveThemeTokens(mode, resolvedThemeState),
181
181
  [resolvedThemeState]
182
182
  );
@@ -189,7 +189,7 @@ function useThemeOps(options) {
189
189
  insertStylesIntoDOM(resolvedThemeState.cssUrl);
190
190
  }
191
191
  }, [resolvedThemeState.cssUrl, resolvedThemeState.cssContent]);
192
- return { isLoading: state.status === "loading", theme, insertStyles };
192
+ return { isLoading: state.status === "loading", getTheme, insertStyles };
193
193
  }
194
194
 
195
195
  exports.useThemeOps = useThemeOps;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/buildCdnUrls.ts","../src/fetchReleaseFromApi.ts","../src/fetchThemeAssets.ts","../src/insertStylesIntoDOM.ts","../src/useThemeOps.ts"],"names":["themeLight","themeDark","appendCacheBuster","useReducer","useRef","useEffect","useCallback"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { BuildCdnUrlsOptions, CdnUrls } from \"./types\";\n\nconst CDN_BASE_URL = \"https://theme-ops.s3.sa-east-1.amazonaws.com\";\n\nfunction buildBasePath(organizationId: string, appId?: string): string {\n return appId ? `${organizationId}/${appId}` : organizationId;\n}\n\nexport function buildCdnUrls({\n organizationId,\n appId,\n}: BuildCdnUrlsOptions): CdnUrls {\n const assetPath = buildBasePath(organizationId, appId);\n\n return {\n theme: `${CDN_BASE_URL}/${assetPath}/theme.json`,\n themeFallback: `${CDN_BASE_URL}/${assetPath}/theme-fallback.json`,\n css: `${CDN_BASE_URL}/${assetPath}/css.css`,\n };\n}\n","import type { ApiReleaseResponse, ThemeState } from \"./types\";\n\nfunction buildReleaseUrl(apiUrl: string, releaseId: string): string {\n const base = apiUrl.replace(/\\/+$/, \"\");\n return `${base}/sdk/releases/${releaseId}`;\n}\n\nexport async function fetchReleaseFromApi(\n apiUrl: string,\n releaseId: string,\n): Promise<ThemeState> {\n const url = buildReleaseUrl(apiUrl, releaseId);\n\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch release: ${response.status}`);\n }\n\n const data = (await response.json()) as ApiReleaseResponse;\n\n return {\n themeLight: data.themeLight,\n themeDark: data.themeDark,\n cssUrl: null,\n cssContent: data.css || null,\n };\n}\n","import type { CdnUrls, ThemeAssets, ThemeJson, ThemeTokens } from \"./types\";\n\nfunction appendCacheBuster(url: string): string {\n const separator = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${separator}_t=${Date.now()}`;\n}\n\nasync function fetchJson<T>(url: string): Promise<T | null> {\n try {\n const response = await fetch(appendCacheBuster(url));\n if (!response.ok) return null;\n\n return (await response.json()) as T;\n } catch {\n return null;\n }\n}\n\nfunction extractThemesFromJson(json: ThemeJson | null): {\n themeLight: ThemeTokens | null;\n themeDark: ThemeTokens | null;\n} {\n return {\n themeLight: json?.light ?? null,\n themeDark: json?.dark ?? null,\n };\n}\n\nfunction isThemeJsonValid(json: ThemeJson | null): boolean {\n return json !== null && (json.light !== undefined || json.dark !== undefined);\n}\n\nexport async function fetchThemeAssets(urls: CdnUrls): Promise<ThemeAssets> {\n const activeJson = await fetchJson<ThemeJson>(urls.theme);\n const cacheBustedCssUrl = appendCacheBuster(urls.css);\n\n if (isThemeJsonValid(activeJson)) {\n const { themeLight, themeDark } = extractThemesFromJson(activeJson);\n return { themeLight, themeDark, cssUrl: cacheBustedCssUrl, usingFallback: false };\n }\n\n const fallbackJson = await fetchJson<ThemeJson>(urls.themeFallback);\n const { themeLight, themeDark } = extractThemesFromJson(fallbackJson);\n\n return {\n themeLight,\n themeDark,\n cssUrl: cacheBustedCssUrl,\n usingFallback: true,\n };\n}\n","const LINK_ELEMENT_ID = \"theme-ops-css\";\nconst STYLE_ELEMENT_ID = \"theme-ops-css-inline\";\n\nfunction appendCacheBuster(url: string): string {\n const baseUrl = url.replace(/[?&]_t=\\d+/, \"\");\n const separator = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n return `${baseUrl}${separator}_t=${Date.now()}`;\n}\n\nfunction findExistingLinkElement(): HTMLLinkElement | null {\n return document.getElementById(LINK_ELEMENT_ID) as HTMLLinkElement | null;\n}\n\nfunction findExistingInlineStyle(): HTMLStyleElement | null {\n return document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n}\n\nfunction createLinkElement(href: string): HTMLLinkElement {\n const link = document.createElement(\"link\");\n link.id = LINK_ELEMENT_ID;\n link.rel = \"stylesheet\";\n link.href = href;\n return link;\n}\n\nfunction removeElement(id: string): void {\n document.getElementById(id)?.remove();\n}\n\nexport function insertStylesIntoDOM(cssUrl: string): void {\n removeElement(STYLE_ELEMENT_ID);\n\n const freshUrl = appendCacheBuster(cssUrl);\n const existing = findExistingLinkElement();\n\n if (existing) {\n existing.href = freshUrl;\n return;\n }\n\n const link = createLinkElement(freshUrl);\n document.head.appendChild(link);\n}\n\nexport function insertInlineStylesIntoDOM(cssContent: string): void {\n removeElement(LINK_ELEMENT_ID);\n\n const existing = findExistingInlineStyle();\n\n if (existing) {\n existing.textContent = cssContent;\n return;\n }\n\n const style = document.createElement(\"style\");\n style.id = STYLE_ELEMENT_ID;\n style.textContent = cssContent;\n document.head.appendChild(style);\n}\n","import { useCallback, useEffect, useReducer, useRef } from \"react\";\n\nimport { buildCdnUrls } from \"./buildCdnUrls\";\nimport { fetchReleaseFromApi } from \"./fetchReleaseFromApi\";\nimport { fetchThemeAssets } from \"./fetchThemeAssets\";\nimport {\n insertInlineStylesIntoDOM,\n insertStylesIntoDOM,\n} from \"./insertStylesIntoDOM\";\nimport type {\n ThemeConfig,\n ThemeState,\n UseThemeOpsOptions,\n UseThemeOpsResult,\n} from \"./types\";\n\ntype HookState =\n | { status: \"loading\" }\n | { status: \"ready\"; themeState: ThemeState };\n\ntype HookAction =\n | { type: \"FETCH_START\" }\n | { type: \"FETCH_SUCCESS\"; payload: ThemeState };\n\nfunction hookReducer(_state: HookState, action: HookAction): HookState {\n switch (action.type) {\n case \"FETCH_START\":\n return { status: \"loading\" };\n case \"FETCH_SUCCESS\":\n return { status: \"ready\", themeState: action.payload };\n }\n}\n\nconst EMPTY_THEME_STATE: ThemeState = {\n themeLight: null,\n themeDark: null,\n cssUrl: null,\n cssContent: null,\n};\n\nfunction resolveThemeTokens(\n mode: \"light\" | \"dark\",\n themeState: ThemeState,\n): ThemeConfig {\n const tokens = mode === \"dark\" ? themeState.themeDark : themeState.themeLight;\n if (!tokens) return {};\n\n return tokens as ThemeConfig;\n}\n\nfunction isReleasePreview(\n options: UseThemeOpsOptions,\n): options is UseThemeOpsOptions & { releaseId: string; apiUrl: string } {\n return Boolean(options.releaseId && options.apiUrl);\n}\n\nexport function useThemeOps(options: UseThemeOpsOptions): UseThemeOpsResult {\n const { organizationId, appId, releaseId, apiUrl } = options;\n const [state, dispatch] = useReducer(hookReducer, { status: \"loading\" });\n\n const isMountedRef = useRef(true);\n\n useEffect(() => {\n isMountedRef.current = true;\n\n dispatch({ type: \"FETCH_START\" });\n\n const fetchPromise = isReleasePreview(options)\n ? fetchReleaseFromApi(options.apiUrl, options.releaseId)\n : fetchThemeAssets(buildCdnUrls({ organizationId, appId })).then(\n (assets) => ({\n themeLight: assets.themeLight,\n themeDark: assets.themeDark,\n cssUrl: assets.cssUrl,\n cssContent: null,\n }),\n );\n\n fetchPromise.then((payload) => {\n if (!isMountedRef.current) return;\n\n dispatch({ type: \"FETCH_SUCCESS\", payload });\n });\n\n return () => {\n isMountedRef.current = false;\n };\n }, [organizationId, appId, releaseId, apiUrl]);\n\n const resolvedThemeState =\n state.status === \"ready\" ? state.themeState : EMPTY_THEME_STATE;\n\n const theme = useCallback(\n (mode: \"light\" | \"dark\"): ThemeConfig =>\n resolveThemeTokens(mode, resolvedThemeState),\n [resolvedThemeState],\n );\n\n const insertStyles = useCallback(() => {\n if (resolvedThemeState.cssContent) {\n insertInlineStylesIntoDOM(resolvedThemeState.cssContent);\n return;\n }\n\n if (resolvedThemeState.cssUrl) {\n insertStylesIntoDOM(resolvedThemeState.cssUrl);\n }\n }, [resolvedThemeState.cssUrl, resolvedThemeState.cssContent]);\n\n return { isLoading: state.status === \"loading\", theme, insertStyles };\n}\n"]}
1
+ {"version":3,"sources":["../src/buildCdnUrls.ts","../src/fetchReleaseFromApi.ts","../src/fetchThemeAssets.ts","../src/insertStylesIntoDOM.ts","../src/useThemeOps.ts"],"names":["themeLight","themeDark","appendCacheBuster","useReducer","useRef","useEffect","useCallback"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { BuildCdnUrlsOptions, CdnUrls } from \"./types\";\n\nconst CDN_BASE_URL = \"https://theme-ops.s3.sa-east-1.amazonaws.com\";\n\nfunction buildBasePath(organizationId: string, appId?: string): string {\n return appId ? `${organizationId}/${appId}` : organizationId;\n}\n\nexport function buildCdnUrls({\n organizationId,\n appId,\n}: BuildCdnUrlsOptions): CdnUrls {\n const assetPath = buildBasePath(organizationId, appId);\n\n return {\n theme: `${CDN_BASE_URL}/${assetPath}/theme.json`,\n themeFallback: `${CDN_BASE_URL}/${assetPath}/theme-fallback.json`,\n css: `${CDN_BASE_URL}/${assetPath}/css.css`,\n };\n}\n","import type { ApiReleaseResponse, ThemeState } from \"./types\";\n\nfunction buildReleaseUrl(apiUrl: string, releaseId: string): string {\n const base = apiUrl.replace(/\\/+$/, \"\");\n return `${base}/sdk/releases/${releaseId}`;\n}\n\nexport async function fetchReleaseFromApi(\n apiUrl: string,\n releaseId: string,\n): Promise<ThemeState> {\n const url = buildReleaseUrl(apiUrl, releaseId);\n\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch release: ${response.status}`);\n }\n\n const data = (await response.json()) as ApiReleaseResponse;\n\n return {\n themeLight: data.themeLight,\n themeDark: data.themeDark,\n cssUrl: null,\n cssContent: data.css || null,\n };\n}\n","import type { CdnUrls, ThemeAssets, ThemeJson, ThemeTokens } from \"./types\";\n\nfunction appendCacheBuster(url: string): string {\n const separator = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${separator}_t=${Date.now()}`;\n}\n\nasync function fetchJson<T>(url: string): Promise<T | null> {\n try {\n const response = await fetch(appendCacheBuster(url));\n if (!response.ok) return null;\n\n return (await response.json()) as T;\n } catch {\n return null;\n }\n}\n\nfunction extractThemesFromJson(json: ThemeJson | null): {\n themeLight: ThemeTokens | null;\n themeDark: ThemeTokens | null;\n} {\n return {\n themeLight: json?.light ?? null,\n themeDark: json?.dark ?? null,\n };\n}\n\nfunction isThemeJsonValid(json: ThemeJson | null): boolean {\n return json !== null && (json.light !== undefined || json.dark !== undefined);\n}\n\nexport async function fetchThemeAssets(urls: CdnUrls): Promise<ThemeAssets> {\n const activeJson = await fetchJson<ThemeJson>(urls.theme);\n const cacheBustedCssUrl = appendCacheBuster(urls.css);\n\n if (isThemeJsonValid(activeJson)) {\n const { themeLight, themeDark } = extractThemesFromJson(activeJson);\n return { themeLight, themeDark, cssUrl: cacheBustedCssUrl, usingFallback: false };\n }\n\n const fallbackJson = await fetchJson<ThemeJson>(urls.themeFallback);\n const { themeLight, themeDark } = extractThemesFromJson(fallbackJson);\n\n return {\n themeLight,\n themeDark,\n cssUrl: cacheBustedCssUrl,\n usingFallback: true,\n };\n}\n","const LINK_ELEMENT_ID = \"theme-ops-css\";\nconst STYLE_ELEMENT_ID = \"theme-ops-css-inline\";\n\nfunction appendCacheBuster(url: string): string {\n const baseUrl = url.replace(/[?&]_t=\\d+/, \"\");\n const separator = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n return `${baseUrl}${separator}_t=${Date.now()}`;\n}\n\nfunction findExistingLinkElement(): HTMLLinkElement | null {\n return document.getElementById(LINK_ELEMENT_ID) as HTMLLinkElement | null;\n}\n\nfunction findExistingInlineStyle(): HTMLStyleElement | null {\n return document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n}\n\nfunction createLinkElement(href: string): HTMLLinkElement {\n const link = document.createElement(\"link\");\n link.id = LINK_ELEMENT_ID;\n link.rel = \"stylesheet\";\n link.href = href;\n return link;\n}\n\nfunction removeElement(id: string): void {\n document.getElementById(id)?.remove();\n}\n\nexport function insertStylesIntoDOM(cssUrl: string): void {\n removeElement(STYLE_ELEMENT_ID);\n\n const freshUrl = appendCacheBuster(cssUrl);\n const existing = findExistingLinkElement();\n\n if (existing) {\n existing.href = freshUrl;\n return;\n }\n\n const link = createLinkElement(freshUrl);\n document.head.appendChild(link);\n}\n\nexport function insertInlineStylesIntoDOM(cssContent: string): void {\n removeElement(LINK_ELEMENT_ID);\n\n const existing = findExistingInlineStyle();\n\n if (existing) {\n existing.textContent = cssContent;\n return;\n }\n\n const style = document.createElement(\"style\");\n style.id = STYLE_ELEMENT_ID;\n style.textContent = cssContent;\n document.head.appendChild(style);\n}\n","import { useCallback, useEffect, useReducer, useRef } from \"react\";\n\nimport { buildCdnUrls } from \"./buildCdnUrls\";\nimport { fetchReleaseFromApi } from \"./fetchReleaseFromApi\";\nimport { fetchThemeAssets } from \"./fetchThemeAssets\";\nimport {\n insertInlineStylesIntoDOM,\n insertStylesIntoDOM,\n} from \"./insertStylesIntoDOM\";\nimport type {\n ThemeConfig,\n ThemeState,\n UseThemeOpsOptions,\n UseThemeOpsResult,\n} from \"./types\";\n\ntype HookState =\n | { status: \"loading\" }\n | { status: \"ready\"; themeState: ThemeState };\n\ntype HookAction =\n | { type: \"FETCH_START\" }\n | { type: \"FETCH_SUCCESS\"; payload: ThemeState };\n\nfunction hookReducer(_state: HookState, action: HookAction): HookState {\n switch (action.type) {\n case \"FETCH_START\":\n return { status: \"loading\" };\n case \"FETCH_SUCCESS\":\n return { status: \"ready\", themeState: action.payload };\n }\n}\n\nconst EMPTY_THEME_STATE: ThemeState = {\n themeLight: null,\n themeDark: null,\n cssUrl: null,\n cssContent: null,\n};\n\nfunction resolveThemeTokens(\n mode: \"light\" | \"dark\",\n themeState: ThemeState,\n): ThemeConfig {\n const tokens = mode === \"dark\" ? themeState.themeDark : themeState.themeLight;\n if (!tokens) return {};\n\n return tokens as ThemeConfig;\n}\n\nfunction isReleasePreview(\n options: UseThemeOpsOptions,\n): options is UseThemeOpsOptions & { releaseId: string; apiUrl: string } {\n return Boolean(options.releaseId && options.apiUrl);\n}\n\nexport function useThemeOps(options: UseThemeOpsOptions): UseThemeOpsResult {\n const { organizationId, appId, releaseId, apiUrl } = options;\n const [state, dispatch] = useReducer(hookReducer, { status: \"loading\" });\n\n const isMountedRef = useRef(true);\n\n useEffect(() => {\n isMountedRef.current = true;\n\n dispatch({ type: \"FETCH_START\" });\n\n const fetchPromise = isReleasePreview(options)\n ? fetchReleaseFromApi(options.apiUrl, options.releaseId)\n : fetchThemeAssets(buildCdnUrls({ organizationId, appId })).then(\n (assets) => ({\n themeLight: assets.themeLight,\n themeDark: assets.themeDark,\n cssUrl: assets.cssUrl,\n cssContent: null,\n }),\n );\n\n fetchPromise.then((payload) => {\n if (!isMountedRef.current) return;\n\n dispatch({ type: \"FETCH_SUCCESS\", payload });\n });\n\n return () => {\n isMountedRef.current = false;\n };\n }, [organizationId, appId, releaseId, apiUrl]);\n\n const resolvedThemeState =\n state.status === \"ready\" ? state.themeState : EMPTY_THEME_STATE;\n\n const getTheme = useCallback(\n (mode: \"light\" | \"dark\"): ThemeConfig =>\n resolveThemeTokens(mode, resolvedThemeState),\n [resolvedThemeState],\n );\n\n const insertStyles = useCallback(() => {\n if (resolvedThemeState.cssContent) {\n insertInlineStylesIntoDOM(resolvedThemeState.cssContent);\n return;\n }\n\n if (resolvedThemeState.cssUrl) {\n insertStylesIntoDOM(resolvedThemeState.cssUrl);\n }\n }, [resolvedThemeState.cssUrl, resolvedThemeState.cssContent]);\n\n return { isLoading: state.status === \"loading\", getTheme, insertStyles };\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -10,7 +10,7 @@ interface UseThemeOpsOptions {
10
10
  }
11
11
  interface UseThemeOpsResult {
12
12
  isLoading: boolean;
13
- theme: (mode: "light" | "dark") => ThemeConfig;
13
+ getTheme: (mode: "light" | "dark") => ThemeConfig;
14
14
  insertStyles: () => void;
15
15
  }
16
16
 
package/dist/index.d.ts CHANGED
@@ -10,7 +10,7 @@ interface UseThemeOpsOptions {
10
10
  }
11
11
  interface UseThemeOpsResult {
12
12
  isLoading: boolean;
13
- theme: (mode: "light" | "dark") => ThemeConfig;
13
+ getTheme: (mode: "light" | "dark") => ThemeConfig;
14
14
  insertStyles: () => void;
15
15
  }
16
16
 
package/dist/index.js CHANGED
@@ -174,7 +174,7 @@ function useThemeOps(options) {
174
174
  };
175
175
  }, [organizationId, appId, releaseId, apiUrl]);
176
176
  const resolvedThemeState = state.status === "ready" ? state.themeState : EMPTY_THEME_STATE;
177
- const theme = useCallback(
177
+ const getTheme = useCallback(
178
178
  (mode) => resolveThemeTokens(mode, resolvedThemeState),
179
179
  [resolvedThemeState]
180
180
  );
@@ -187,7 +187,7 @@ function useThemeOps(options) {
187
187
  insertStylesIntoDOM(resolvedThemeState.cssUrl);
188
188
  }
189
189
  }, [resolvedThemeState.cssUrl, resolvedThemeState.cssContent]);
190
- return { isLoading: state.status === "loading", theme, insertStyles };
190
+ return { isLoading: state.status === "loading", getTheme, insertStyles };
191
191
  }
192
192
 
193
193
  export { useThemeOps };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/buildCdnUrls.ts","../src/fetchReleaseFromApi.ts","../src/fetchThemeAssets.ts","../src/insertStylesIntoDOM.ts","../src/useThemeOps.ts"],"names":["themeLight","themeDark","appendCacheBuster"],"mappings":"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","file":"index.js","sourcesContent":["import type { BuildCdnUrlsOptions, CdnUrls } from \"./types\";\n\nconst CDN_BASE_URL = \"https://theme-ops.s3.sa-east-1.amazonaws.com\";\n\nfunction buildBasePath(organizationId: string, appId?: string): string {\n return appId ? `${organizationId}/${appId}` : organizationId;\n}\n\nexport function buildCdnUrls({\n organizationId,\n appId,\n}: BuildCdnUrlsOptions): CdnUrls {\n const assetPath = buildBasePath(organizationId, appId);\n\n return {\n theme: `${CDN_BASE_URL}/${assetPath}/theme.json`,\n themeFallback: `${CDN_BASE_URL}/${assetPath}/theme-fallback.json`,\n css: `${CDN_BASE_URL}/${assetPath}/css.css`,\n };\n}\n","import type { ApiReleaseResponse, ThemeState } from \"./types\";\n\nfunction buildReleaseUrl(apiUrl: string, releaseId: string): string {\n const base = apiUrl.replace(/\\/+$/, \"\");\n return `${base}/sdk/releases/${releaseId}`;\n}\n\nexport async function fetchReleaseFromApi(\n apiUrl: string,\n releaseId: string,\n): Promise<ThemeState> {\n const url = buildReleaseUrl(apiUrl, releaseId);\n\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch release: ${response.status}`);\n }\n\n const data = (await response.json()) as ApiReleaseResponse;\n\n return {\n themeLight: data.themeLight,\n themeDark: data.themeDark,\n cssUrl: null,\n cssContent: data.css || null,\n };\n}\n","import type { CdnUrls, ThemeAssets, ThemeJson, ThemeTokens } from \"./types\";\n\nfunction appendCacheBuster(url: string): string {\n const separator = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${separator}_t=${Date.now()}`;\n}\n\nasync function fetchJson<T>(url: string): Promise<T | null> {\n try {\n const response = await fetch(appendCacheBuster(url));\n if (!response.ok) return null;\n\n return (await response.json()) as T;\n } catch {\n return null;\n }\n}\n\nfunction extractThemesFromJson(json: ThemeJson | null): {\n themeLight: ThemeTokens | null;\n themeDark: ThemeTokens | null;\n} {\n return {\n themeLight: json?.light ?? null,\n themeDark: json?.dark ?? null,\n };\n}\n\nfunction isThemeJsonValid(json: ThemeJson | null): boolean {\n return json !== null && (json.light !== undefined || json.dark !== undefined);\n}\n\nexport async function fetchThemeAssets(urls: CdnUrls): Promise<ThemeAssets> {\n const activeJson = await fetchJson<ThemeJson>(urls.theme);\n const cacheBustedCssUrl = appendCacheBuster(urls.css);\n\n if (isThemeJsonValid(activeJson)) {\n const { themeLight, themeDark } = extractThemesFromJson(activeJson);\n return { themeLight, themeDark, cssUrl: cacheBustedCssUrl, usingFallback: false };\n }\n\n const fallbackJson = await fetchJson<ThemeJson>(urls.themeFallback);\n const { themeLight, themeDark } = extractThemesFromJson(fallbackJson);\n\n return {\n themeLight,\n themeDark,\n cssUrl: cacheBustedCssUrl,\n usingFallback: true,\n };\n}\n","const LINK_ELEMENT_ID = \"theme-ops-css\";\nconst STYLE_ELEMENT_ID = \"theme-ops-css-inline\";\n\nfunction appendCacheBuster(url: string): string {\n const baseUrl = url.replace(/[?&]_t=\\d+/, \"\");\n const separator = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n return `${baseUrl}${separator}_t=${Date.now()}`;\n}\n\nfunction findExistingLinkElement(): HTMLLinkElement | null {\n return document.getElementById(LINK_ELEMENT_ID) as HTMLLinkElement | null;\n}\n\nfunction findExistingInlineStyle(): HTMLStyleElement | null {\n return document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n}\n\nfunction createLinkElement(href: string): HTMLLinkElement {\n const link = document.createElement(\"link\");\n link.id = LINK_ELEMENT_ID;\n link.rel = \"stylesheet\";\n link.href = href;\n return link;\n}\n\nfunction removeElement(id: string): void {\n document.getElementById(id)?.remove();\n}\n\nexport function insertStylesIntoDOM(cssUrl: string): void {\n removeElement(STYLE_ELEMENT_ID);\n\n const freshUrl = appendCacheBuster(cssUrl);\n const existing = findExistingLinkElement();\n\n if (existing) {\n existing.href = freshUrl;\n return;\n }\n\n const link = createLinkElement(freshUrl);\n document.head.appendChild(link);\n}\n\nexport function insertInlineStylesIntoDOM(cssContent: string): void {\n removeElement(LINK_ELEMENT_ID);\n\n const existing = findExistingInlineStyle();\n\n if (existing) {\n existing.textContent = cssContent;\n return;\n }\n\n const style = document.createElement(\"style\");\n style.id = STYLE_ELEMENT_ID;\n style.textContent = cssContent;\n document.head.appendChild(style);\n}\n","import { useCallback, useEffect, useReducer, useRef } from \"react\";\n\nimport { buildCdnUrls } from \"./buildCdnUrls\";\nimport { fetchReleaseFromApi } from \"./fetchReleaseFromApi\";\nimport { fetchThemeAssets } from \"./fetchThemeAssets\";\nimport {\n insertInlineStylesIntoDOM,\n insertStylesIntoDOM,\n} from \"./insertStylesIntoDOM\";\nimport type {\n ThemeConfig,\n ThemeState,\n UseThemeOpsOptions,\n UseThemeOpsResult,\n} from \"./types\";\n\ntype HookState =\n | { status: \"loading\" }\n | { status: \"ready\"; themeState: ThemeState };\n\ntype HookAction =\n | { type: \"FETCH_START\" }\n | { type: \"FETCH_SUCCESS\"; payload: ThemeState };\n\nfunction hookReducer(_state: HookState, action: HookAction): HookState {\n switch (action.type) {\n case \"FETCH_START\":\n return { status: \"loading\" };\n case \"FETCH_SUCCESS\":\n return { status: \"ready\", themeState: action.payload };\n }\n}\n\nconst EMPTY_THEME_STATE: ThemeState = {\n themeLight: null,\n themeDark: null,\n cssUrl: null,\n cssContent: null,\n};\n\nfunction resolveThemeTokens(\n mode: \"light\" | \"dark\",\n themeState: ThemeState,\n): ThemeConfig {\n const tokens = mode === \"dark\" ? themeState.themeDark : themeState.themeLight;\n if (!tokens) return {};\n\n return tokens as ThemeConfig;\n}\n\nfunction isReleasePreview(\n options: UseThemeOpsOptions,\n): options is UseThemeOpsOptions & { releaseId: string; apiUrl: string } {\n return Boolean(options.releaseId && options.apiUrl);\n}\n\nexport function useThemeOps(options: UseThemeOpsOptions): UseThemeOpsResult {\n const { organizationId, appId, releaseId, apiUrl } = options;\n const [state, dispatch] = useReducer(hookReducer, { status: \"loading\" });\n\n const isMountedRef = useRef(true);\n\n useEffect(() => {\n isMountedRef.current = true;\n\n dispatch({ type: \"FETCH_START\" });\n\n const fetchPromise = isReleasePreview(options)\n ? fetchReleaseFromApi(options.apiUrl, options.releaseId)\n : fetchThemeAssets(buildCdnUrls({ organizationId, appId })).then(\n (assets) => ({\n themeLight: assets.themeLight,\n themeDark: assets.themeDark,\n cssUrl: assets.cssUrl,\n cssContent: null,\n }),\n );\n\n fetchPromise.then((payload) => {\n if (!isMountedRef.current) return;\n\n dispatch({ type: \"FETCH_SUCCESS\", payload });\n });\n\n return () => {\n isMountedRef.current = false;\n };\n }, [organizationId, appId, releaseId, apiUrl]);\n\n const resolvedThemeState =\n state.status === \"ready\" ? state.themeState : EMPTY_THEME_STATE;\n\n const theme = useCallback(\n (mode: \"light\" | \"dark\"): ThemeConfig =>\n resolveThemeTokens(mode, resolvedThemeState),\n [resolvedThemeState],\n );\n\n const insertStyles = useCallback(() => {\n if (resolvedThemeState.cssContent) {\n insertInlineStylesIntoDOM(resolvedThemeState.cssContent);\n return;\n }\n\n if (resolvedThemeState.cssUrl) {\n insertStylesIntoDOM(resolvedThemeState.cssUrl);\n }\n }, [resolvedThemeState.cssUrl, resolvedThemeState.cssContent]);\n\n return { isLoading: state.status === \"loading\", theme, insertStyles };\n}\n"]}
1
+ {"version":3,"sources":["../src/buildCdnUrls.ts","../src/fetchReleaseFromApi.ts","../src/fetchThemeAssets.ts","../src/insertStylesIntoDOM.ts","../src/useThemeOps.ts"],"names":["themeLight","themeDark","appendCacheBuster"],"mappings":"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","file":"index.js","sourcesContent":["import type { BuildCdnUrlsOptions, CdnUrls } from \"./types\";\n\nconst CDN_BASE_URL = \"https://theme-ops.s3.sa-east-1.amazonaws.com\";\n\nfunction buildBasePath(organizationId: string, appId?: string): string {\n return appId ? `${organizationId}/${appId}` : organizationId;\n}\n\nexport function buildCdnUrls({\n organizationId,\n appId,\n}: BuildCdnUrlsOptions): CdnUrls {\n const assetPath = buildBasePath(organizationId, appId);\n\n return {\n theme: `${CDN_BASE_URL}/${assetPath}/theme.json`,\n themeFallback: `${CDN_BASE_URL}/${assetPath}/theme-fallback.json`,\n css: `${CDN_BASE_URL}/${assetPath}/css.css`,\n };\n}\n","import type { ApiReleaseResponse, ThemeState } from \"./types\";\n\nfunction buildReleaseUrl(apiUrl: string, releaseId: string): string {\n const base = apiUrl.replace(/\\/+$/, \"\");\n return `${base}/sdk/releases/${releaseId}`;\n}\n\nexport async function fetchReleaseFromApi(\n apiUrl: string,\n releaseId: string,\n): Promise<ThemeState> {\n const url = buildReleaseUrl(apiUrl, releaseId);\n\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch release: ${response.status}`);\n }\n\n const data = (await response.json()) as ApiReleaseResponse;\n\n return {\n themeLight: data.themeLight,\n themeDark: data.themeDark,\n cssUrl: null,\n cssContent: data.css || null,\n };\n}\n","import type { CdnUrls, ThemeAssets, ThemeJson, ThemeTokens } from \"./types\";\n\nfunction appendCacheBuster(url: string): string {\n const separator = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${separator}_t=${Date.now()}`;\n}\n\nasync function fetchJson<T>(url: string): Promise<T | null> {\n try {\n const response = await fetch(appendCacheBuster(url));\n if (!response.ok) return null;\n\n return (await response.json()) as T;\n } catch {\n return null;\n }\n}\n\nfunction extractThemesFromJson(json: ThemeJson | null): {\n themeLight: ThemeTokens | null;\n themeDark: ThemeTokens | null;\n} {\n return {\n themeLight: json?.light ?? null,\n themeDark: json?.dark ?? null,\n };\n}\n\nfunction isThemeJsonValid(json: ThemeJson | null): boolean {\n return json !== null && (json.light !== undefined || json.dark !== undefined);\n}\n\nexport async function fetchThemeAssets(urls: CdnUrls): Promise<ThemeAssets> {\n const activeJson = await fetchJson<ThemeJson>(urls.theme);\n const cacheBustedCssUrl = appendCacheBuster(urls.css);\n\n if (isThemeJsonValid(activeJson)) {\n const { themeLight, themeDark } = extractThemesFromJson(activeJson);\n return { themeLight, themeDark, cssUrl: cacheBustedCssUrl, usingFallback: false };\n }\n\n const fallbackJson = await fetchJson<ThemeJson>(urls.themeFallback);\n const { themeLight, themeDark } = extractThemesFromJson(fallbackJson);\n\n return {\n themeLight,\n themeDark,\n cssUrl: cacheBustedCssUrl,\n usingFallback: true,\n };\n}\n","const LINK_ELEMENT_ID = \"theme-ops-css\";\nconst STYLE_ELEMENT_ID = \"theme-ops-css-inline\";\n\nfunction appendCacheBuster(url: string): string {\n const baseUrl = url.replace(/[?&]_t=\\d+/, \"\");\n const separator = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n return `${baseUrl}${separator}_t=${Date.now()}`;\n}\n\nfunction findExistingLinkElement(): HTMLLinkElement | null {\n return document.getElementById(LINK_ELEMENT_ID) as HTMLLinkElement | null;\n}\n\nfunction findExistingInlineStyle(): HTMLStyleElement | null {\n return document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n}\n\nfunction createLinkElement(href: string): HTMLLinkElement {\n const link = document.createElement(\"link\");\n link.id = LINK_ELEMENT_ID;\n link.rel = \"stylesheet\";\n link.href = href;\n return link;\n}\n\nfunction removeElement(id: string): void {\n document.getElementById(id)?.remove();\n}\n\nexport function insertStylesIntoDOM(cssUrl: string): void {\n removeElement(STYLE_ELEMENT_ID);\n\n const freshUrl = appendCacheBuster(cssUrl);\n const existing = findExistingLinkElement();\n\n if (existing) {\n existing.href = freshUrl;\n return;\n }\n\n const link = createLinkElement(freshUrl);\n document.head.appendChild(link);\n}\n\nexport function insertInlineStylesIntoDOM(cssContent: string): void {\n removeElement(LINK_ELEMENT_ID);\n\n const existing = findExistingInlineStyle();\n\n if (existing) {\n existing.textContent = cssContent;\n return;\n }\n\n const style = document.createElement(\"style\");\n style.id = STYLE_ELEMENT_ID;\n style.textContent = cssContent;\n document.head.appendChild(style);\n}\n","import { useCallback, useEffect, useReducer, useRef } from \"react\";\n\nimport { buildCdnUrls } from \"./buildCdnUrls\";\nimport { fetchReleaseFromApi } from \"./fetchReleaseFromApi\";\nimport { fetchThemeAssets } from \"./fetchThemeAssets\";\nimport {\n insertInlineStylesIntoDOM,\n insertStylesIntoDOM,\n} from \"./insertStylesIntoDOM\";\nimport type {\n ThemeConfig,\n ThemeState,\n UseThemeOpsOptions,\n UseThemeOpsResult,\n} from \"./types\";\n\ntype HookState =\n | { status: \"loading\" }\n | { status: \"ready\"; themeState: ThemeState };\n\ntype HookAction =\n | { type: \"FETCH_START\" }\n | { type: \"FETCH_SUCCESS\"; payload: ThemeState };\n\nfunction hookReducer(_state: HookState, action: HookAction): HookState {\n switch (action.type) {\n case \"FETCH_START\":\n return { status: \"loading\" };\n case \"FETCH_SUCCESS\":\n return { status: \"ready\", themeState: action.payload };\n }\n}\n\nconst EMPTY_THEME_STATE: ThemeState = {\n themeLight: null,\n themeDark: null,\n cssUrl: null,\n cssContent: null,\n};\n\nfunction resolveThemeTokens(\n mode: \"light\" | \"dark\",\n themeState: ThemeState,\n): ThemeConfig {\n const tokens = mode === \"dark\" ? themeState.themeDark : themeState.themeLight;\n if (!tokens) return {};\n\n return tokens as ThemeConfig;\n}\n\nfunction isReleasePreview(\n options: UseThemeOpsOptions,\n): options is UseThemeOpsOptions & { releaseId: string; apiUrl: string } {\n return Boolean(options.releaseId && options.apiUrl);\n}\n\nexport function useThemeOps(options: UseThemeOpsOptions): UseThemeOpsResult {\n const { organizationId, appId, releaseId, apiUrl } = options;\n const [state, dispatch] = useReducer(hookReducer, { status: \"loading\" });\n\n const isMountedRef = useRef(true);\n\n useEffect(() => {\n isMountedRef.current = true;\n\n dispatch({ type: \"FETCH_START\" });\n\n const fetchPromise = isReleasePreview(options)\n ? fetchReleaseFromApi(options.apiUrl, options.releaseId)\n : fetchThemeAssets(buildCdnUrls({ organizationId, appId })).then(\n (assets) => ({\n themeLight: assets.themeLight,\n themeDark: assets.themeDark,\n cssUrl: assets.cssUrl,\n cssContent: null,\n }),\n );\n\n fetchPromise.then((payload) => {\n if (!isMountedRef.current) return;\n\n dispatch({ type: \"FETCH_SUCCESS\", payload });\n });\n\n return () => {\n isMountedRef.current = false;\n };\n }, [organizationId, appId, releaseId, apiUrl]);\n\n const resolvedThemeState =\n state.status === \"ready\" ? state.themeState : EMPTY_THEME_STATE;\n\n const getTheme = useCallback(\n (mode: \"light\" | \"dark\"): ThemeConfig =>\n resolveThemeTokens(mode, resolvedThemeState),\n [resolvedThemeState],\n );\n\n const insertStyles = useCallback(() => {\n if (resolvedThemeState.cssContent) {\n insertInlineStylesIntoDOM(resolvedThemeState.cssContent);\n return;\n }\n\n if (resolvedThemeState.cssUrl) {\n insertStylesIntoDOM(resolvedThemeState.cssUrl);\n }\n }, [resolvedThemeState.cssUrl, resolvedThemeState.cssContent]);\n\n return { isLoading: state.status === \"loading\", getTheme, insertStyles };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "theme-ops-sdk",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "React SDK for Theme Ops — fetch and apply themes from CDN",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -56,4 +56,4 @@
56
56
  "publishConfig": {
57
57
  "access": "public"
58
58
  }
59
- }
59
+ }