dh-remixer-sdk 0.0.28-e1df2dd → 0.0.28
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/package.json +1 -1
- package/scripts/sdk-update/cmd-utils.mjs +4 -22
- package/scripts/sdk-update/sdk-utils.mjs +0 -13
- package/scripts/ssg-helmet/build-sitemap-xml.mjs +1 -7
- package/scripts/ssg-helmet/prerenderer.mjs +0 -9
- package/templates/base/filemap.json +1 -10
- package/templates/base/index.tsx +4 -7
- package/templates/base/package.json +2 -2
- package/templates/base/supabase.ts +10 -21
- package/templates/base/vite.config.ts +148 -42
- package/templates/ecommerce/shipping.ts +59 -11
- package/templates/ecommerce/stripe-checkout.ts +53 -16
- package/templates/ecommerce/supabase.ts +10 -21
- package/templates/landing-page/package.json +1 -1
- package/templates/base/SEOHead.tsx +0 -43
- package/templates/base/remixer/actions.ts +0 -5
- package/templates/base/remixer/auth.ts +0 -21
- package/templates/base/remixer/core.ts +0 -49
- package/templates/base/remixer/data.ts +0 -223
- package/templates/base/remixer/ecommerce.ts +0 -179
- package/templates/base/remixer/runtime.ts +0 -131
- package/templates/base/remixer/storage.ts +0 -11
- package/templates/base/remixer.ts +0 -49
- package/templates/immersive/Anchor3D.tsx +0 -62
- package/templates/immersive/Atmosphere.tsx +0 -134
- package/templates/immersive/ImmersiveStory.tsx +0 -130
- package/templates/immersive/ScrollStory.tsx +0 -136
- package/templates/immersive/Stage3D.tsx +0 -194
- package/templates/immersive/StageContext.ts +0 -37
- package/templates/immersive/anchors.tsx +0 -77
- package/templates/immersive/cleanup.json +0 -22
- package/templates/immersive/filemap.json +0 -13
- package/templates/immersive/package.json +0 -13
- package/templates/immersive/phases.ts +0 -154
- package/templates/immersive/safeCanvas.tsx +0 -82
- package/templates/immersive/stage.ts +0 -5
- package/templates/immersive/useAnchor.ts +0 -13
package/package.json
CHANGED
|
@@ -1,31 +1,13 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
2
|
import { TARGET_ENVIRONMENT } from "./vars.mjs";
|
|
3
3
|
|
|
4
|
-
const TAG_BY_ENV = {
|
|
5
|
-
production: "latest",
|
|
6
|
-
staging: "staging",
|
|
7
|
-
develop: "develop",
|
|
8
|
-
};
|
|
9
|
-
|
|
10
4
|
export async function getSdkVersion() {
|
|
11
|
-
const tag = TAG_BY_ENV[TARGET_ENVIRONMENT];
|
|
12
|
-
|
|
13
|
-
if (!tag) {
|
|
14
|
-
throw new Error(
|
|
15
|
-
`[sdk-update] Unknown NEXT_PUBLIC_ENVIRONMENT "${TARGET_ENVIRONMENT}". ` +
|
|
16
|
-
`Expected one of: ${Object.keys(TAG_BY_ENV).join(", ")}`,
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
5
|
const res = await fetch("https://registry.npmjs.org/dh-remixer-sdk");
|
|
21
6
|
const data = await res.json();
|
|
22
|
-
const sdkVersion =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
`[sdk-update] No "${tag}" dist-tag published for dh-remixer-sdk on npm`,
|
|
27
|
-
);
|
|
28
|
-
}
|
|
7
|
+
const sdkVersion =
|
|
8
|
+
TARGET_ENVIRONMENT === "production"
|
|
9
|
+
? data["dist-tags"].latest
|
|
10
|
+
: data["dist-tags"].dev;
|
|
29
11
|
|
|
30
12
|
return sdkVersion;
|
|
31
13
|
}
|
|
@@ -5,19 +5,7 @@ import { SDK_ROOT } from "./vars.mjs";
|
|
|
5
5
|
import { jsonMerge } from "./type-utils.mjs";
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
function assertTemplateExists(templateType) {
|
|
9
|
-
if (templateType === "base") return;
|
|
10
|
-
const templateRoot = path.join(SDK_ROOT, "templates", templateType);
|
|
11
|
-
if (!fssync.existsSync(templateRoot)) {
|
|
12
|
-
throw new Error(
|
|
13
|
-
`[sdk-update] Template "${templateType}" not found in installed dh-remixer-sdk (${templateRoot}). ` +
|
|
14
|
-
`Run: npm install dh-remixer-sdk@latest`,
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
8
|
export async function getDeletionList(templateType) {
|
|
20
|
-
assertTemplateExists(templateType);
|
|
21
9
|
const baseRoot = path.join(SDK_ROOT, "templates", "base");
|
|
22
10
|
const templateRoot = path.join(SDK_ROOT, "templates", templateType);
|
|
23
11
|
const templateCleanupPath = path.join(templateRoot, "cleanup.json");
|
|
@@ -35,7 +23,6 @@ export async function getDeletionList(templateType) {
|
|
|
35
23
|
}
|
|
36
24
|
|
|
37
25
|
export async function getExtractionList(templateType) {
|
|
38
|
-
assertTemplateExists(templateType);
|
|
39
26
|
const baseRoot = path.join(SDK_ROOT, "templates", "base");
|
|
40
27
|
const templateRoot = path.join(SDK_ROOT, "templates", templateType);
|
|
41
28
|
const templateFilemapPath = path.join(templateRoot, "filemap.json");
|
|
@@ -6,12 +6,6 @@ const CHANGEFREQ_HOME = "daily";
|
|
|
6
6
|
const CHANGEFREQ_NORMAL = "weekly";
|
|
7
7
|
const CHANGEFREQ_TEMPLATED = "weekly";
|
|
8
8
|
|
|
9
|
-
const ensureTrailingSlash = (p) => {
|
|
10
|
-
const [base, suffix] = p.split(/([?#].*)/); // keep query/hash intact
|
|
11
|
-
const normalized = base.endsWith("/") ? base : base + "/";
|
|
12
|
-
return suffix ? normalized + suffix : normalized;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
9
|
export function buildSitemapXml(origin, routes) {
|
|
16
10
|
if (!/^https?:\/\//i.test(origin)) origin = "https://" + origin;
|
|
17
11
|
const cleanOrigin = origin.replace(/\/+$/, "");
|
|
@@ -66,7 +60,7 @@ export function buildSitemapXml(origin, routes) {
|
|
|
66
60
|
: CHANGEFREQ_NORMAL;
|
|
67
61
|
|
|
68
62
|
return ` <url>
|
|
69
|
-
<loc>${esc(abs(
|
|
63
|
+
<loc>${esc(abs(path))}</loc>
|
|
70
64
|
<lastmod>${today}</lastmod>
|
|
71
65
|
<changefreq>${changefreq}</changefreq>
|
|
72
66
|
<priority>${priority.toFixed(1)}</priority>
|
|
@@ -202,15 +202,6 @@ export class Prerenderer {
|
|
|
202
202
|
this.#client = await CDP({ port: this.#cdpPort, target: pageTarget });
|
|
203
203
|
await this.#client.Page.enable();
|
|
204
204
|
await this.#client.Runtime.enable();
|
|
205
|
-
|
|
206
|
-
// Signal to the app that we are in SSG prerender mode, BEFORE any page
|
|
207
|
-
// scripts run. Components (e.g. ScrollScene, useScrollProgress) can read
|
|
208
|
-
// window.__PRERENDER__ to skip WebGL/Lenis and render a static fallback,
|
|
209
|
-
// which keeps headless Chrome from hanging on canvas rendering and
|
|
210
|
-
// guarantees meaningful HTML for SEO.
|
|
211
|
-
await this.#client.Page.addScriptToEvaluateOnNewDocument({
|
|
212
|
-
source: "window.__PRERENDER__ = true;",
|
|
213
|
-
});
|
|
214
205
|
}
|
|
215
206
|
|
|
216
207
|
async #launchDirect() {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"index.tsx": "index.tsx",
|
|
3
|
-
"SEOHead.tsx": "SEOHead.tsx",
|
|
4
3
|
"gitignore": ".gitignore",
|
|
5
4
|
"index.html": "index.html",
|
|
6
5
|
"package.json": "package.json",
|
|
@@ -9,13 +8,5 @@
|
|
|
9
8
|
"vite.config.ts": "vite.config.ts",
|
|
10
9
|
"robots.txt": "public/robots.txt",
|
|
11
10
|
".htaccess": "public/.htaccess",
|
|
12
|
-
"supabase.ts": "lib/supabase.ts"
|
|
13
|
-
"remixer.ts": "lib/remixer.ts",
|
|
14
|
-
"remixer/actions.ts": "lib/remixer/actions.ts",
|
|
15
|
-
"remixer/auth.ts": "lib/remixer/auth.ts",
|
|
16
|
-
"remixer/core.ts": "lib/remixer/core.ts",
|
|
17
|
-
"remixer/data.ts": "lib/remixer/data.ts",
|
|
18
|
-
"remixer/ecommerce.ts": "lib/remixer/ecommerce.ts",
|
|
19
|
-
"remixer/runtime.ts": "lib/remixer/runtime.ts",
|
|
20
|
-
"remixer/storage.ts": "lib/remixer/storage.ts"
|
|
11
|
+
"supabase.ts": "lib/supabase.ts"
|
|
21
12
|
}
|
package/templates/base/index.tsx
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import ReactDOM from "react-dom/client";
|
|
3
|
-
import { HelmetProvider } from "react-helmet-async";
|
|
4
3
|
import tailwindConfig from "@/tailwind.config";
|
|
5
4
|
import App from "@/App";
|
|
6
5
|
import { GOOGLE_FONTS_URL } from "@/fonts";
|
|
@@ -28,10 +27,8 @@ if (!rootElement) {
|
|
|
28
27
|
const root = ReactDOM.createRoot(rootElement);
|
|
29
28
|
root.render(
|
|
30
29
|
<React.StrictMode>
|
|
31
|
-
<
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
</LanguageProvider>
|
|
35
|
-
</HelmetProvider>
|
|
30
|
+
<LanguageProvider>
|
|
31
|
+
<App />
|
|
32
|
+
</LanguageProvider>
|
|
36
33
|
</React.StrictMode>
|
|
37
|
-
);
|
|
34
|
+
);
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"start": "vite preview --host 0.0.0.0 --mode production --port ${PORT:-4173}",
|
|
9
9
|
"dev": "vite --host 0.0.0.0 --port ${PORT:-4173} --mode development",
|
|
10
10
|
"lint": "echo 'Linting not implemented!'",
|
|
11
|
-
"remixer-sdk:update": "
|
|
11
|
+
"remixer-sdk:update": "npm cache clean --force && npm install dh-remixer-sdk@latest && sdk-update"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@openobserve/browser-logs": "0.3.1",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"react": "19.2.0",
|
|
22
22
|
"react-aria-components": "1.11.0",
|
|
23
23
|
"react-dom": "19.2.0",
|
|
24
|
-
"react-helmet
|
|
24
|
+
"react-helmet": "6.1.0",
|
|
25
25
|
"react-router-dom": "7.9.6"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
|
|
2
2
|
import { createClient } from '@supabase/supabase-js';
|
|
3
|
-
import type { Session } from '@supabase/supabase-js';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* 1) supabase — user-scoped client
|
|
@@ -36,25 +35,6 @@ export const supabaseProject = createClient(
|
|
|
36
35
|
}
|
|
37
36
|
);
|
|
38
37
|
|
|
39
|
-
export function isValidProjectSession(session: Session | null) {
|
|
40
|
-
if (!session) return true;
|
|
41
|
-
const sessionProjectId = session?.user?.app_metadata?.project_id;
|
|
42
|
-
return sessionProjectId === import.meta.env.VITE_PROJECT_ID;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export async function getProjectSession() {
|
|
46
|
-
const {
|
|
47
|
-
data: { session },
|
|
48
|
-
} = await supabase.auth.getSession();
|
|
49
|
-
|
|
50
|
-
if (!isValidProjectSession(session)) {
|
|
51
|
-
await supabase.auth.signOut({ scope: 'local' });
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return session;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
38
|
/**
|
|
59
39
|
* authHeader() — helper for manual fetch() calls (Edge Functions/REST)
|
|
60
40
|
* • Returns `{ Authorization: 'Bearer <token>' }` where `<token>` is:
|
|
@@ -65,7 +45,16 @@ export async function getProjectSession() {
|
|
|
65
45
|
* time — no client-side updateUser() needed.
|
|
66
46
|
*/
|
|
67
47
|
export async function authHeader() {
|
|
68
|
-
const
|
|
48
|
+
const {
|
|
49
|
+
data: { session },
|
|
50
|
+
} = await supabase.auth.getSession();
|
|
51
|
+
|
|
52
|
+
if (session?.user?.app_metadata?.project_id &&
|
|
53
|
+
session.user.app_metadata.project_id !== import.meta.env.VITE_PROJECT_ID) {
|
|
54
|
+
await supabase.auth.signOut({ scope: 'local' });
|
|
55
|
+
return { Authorization: `Bearer ${import.meta.env.VITE_PROJECT_ACCESS_TOKEN}` };
|
|
56
|
+
}
|
|
57
|
+
|
|
69
58
|
const token =
|
|
70
59
|
session?.access_token ?? import.meta.env.VITE_PROJECT_ACCESS_TOKEN;
|
|
71
60
|
|
|
@@ -1,10 +1,113 @@
|
|
|
1
|
-
import { defineConfig,
|
|
1
|
+
import { defineConfig, Plugin } from "vite";
|
|
2
2
|
import react from "@vitejs/plugin-react";
|
|
3
3
|
import tailwindcss from "tailwindcss";
|
|
4
4
|
import autoprefixer from "autoprefixer";
|
|
5
5
|
import tailwindConfig from "./tailwind.config.ts";
|
|
6
6
|
import path from "path";
|
|
7
7
|
|
|
8
|
+
const REMIXER_LOGO_SVG = `
|
|
9
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
10
|
+
<path d="M18.0005 12.0025C14.6877 12.0025 12.0012 14.6889 12.0012 18.0016V24.0006H24.0024V12H18.0031L18.0005 12.0025Z" fill="url(#paint0_linear_14487_36369)"/>
|
|
11
|
+
<path d="M12.0012 5.99904V0H0V12.0006H5.99932C9.31215 12.0006 11.9986 9.31423 11.9986 6.00155L12.0012 5.99904Z" fill="url(#paint1_linear_14487_36369)"/>
|
|
12
|
+
<path d="M5.99902 11.999C9.31222 11.999 11.9988 14.6851 11.999 17.998C11.999 21.3112 9.31236 23.9971 5.99902 23.9971C2.68583 23.9969 0 21.3111 0 17.998C0.00021569 14.6852 2.68596 11.9992 5.99902 11.999ZM18 0C21.3133 0 24 2.68585 24 5.99902C24 9.3122 21.3133 11.998 18 11.998C14.6869 11.9978 12.001 9.31205 12.001 5.99902C12.001 2.68601 14.6869 0.00024737 18 0Z" fill="url(#paint2_linear_14487_36369)"/>
|
|
13
|
+
<path d="M12.0012 6H18.0005V11.999C14.6877 11.999 12.0012 9.31016 12.0012 6Z" fill="white"/>
|
|
14
|
+
<path d="M5.99927 12V6.00096H11.9986C11.9986 9.31364 9.30958 12 5.99927 12Z" fill="white"/>
|
|
15
|
+
<path d="M12.0012 18H6.0019L6.0019 12.001C9.31473 12.001 12.0012 14.6898 12.0012 18Z" fill="white"/>
|
|
16
|
+
<path d="M18.0005 12V17.999H12.0012C12.0012 14.6864 14.6902 12 18.0005 12Z" fill="white"/>
|
|
17
|
+
<defs>
|
|
18
|
+
<linearGradient id="paint0_linear_14487_36369" x1="12.0024" y1="12" x2="24.0018" y2="24" gradientUnits="userSpaceOnUse">
|
|
19
|
+
<stop stop-color="#3F3F46"/>
|
|
20
|
+
<stop offset="1" stop-color="#71717A"/>
|
|
21
|
+
</linearGradient>
|
|
22
|
+
<linearGradient id="paint1_linear_14487_36369" x1="0.001139" y1="3.18903e-07" x2="12.0005" y2="12" gradientUnits="userSpaceOnUse">
|
|
23
|
+
<stop stop-color="#71717A"/>
|
|
24
|
+
<stop offset="1" stop-color="#3F3F46"/>
|
|
25
|
+
</linearGradient>
|
|
26
|
+
<linearGradient id="paint2_linear_14487_36369" x1="-8.53364" y1="33.7017" x2="-6.30119" y2="-14.057" gradientUnits="userSpaceOnUse">
|
|
27
|
+
<stop stop-color="#BE59FF"/>
|
|
28
|
+
<stop offset="0.19" stop-color="#9D60FF"/>
|
|
29
|
+
<stop offset="0.74" stop-color="#4274FF"/>
|
|
30
|
+
<stop offset="1" stop-color="#1F7CFF"/>
|
|
31
|
+
</linearGradient>
|
|
32
|
+
</defs>
|
|
33
|
+
</svg>`
|
|
34
|
+
|
|
35
|
+
const ARROW_SVG = `
|
|
36
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
|
37
|
+
<path d="M11.1635 10.0004L7.60246 6.43958C7.48718 6.32417 7.42816 6.19646 7.42538 6.05646C7.42274 5.9166 7.48177 5.78625 7.60246 5.66542C7.72329 5.54472 7.85232 5.48438 7.98954 5.48438C8.12677 5.48438 8.25579 5.54472 8.37663 5.66542L12.2468 9.53563C12.3109 9.59979 12.3589 9.67167 12.391 9.75125C12.4231 9.83083 12.4391 9.91389 12.4391 10.0004C12.4391 10.0869 12.4231 10.17 12.391 10.2496C12.3589 10.3292 12.3109 10.401 12.2468 10.4652L8.37663 14.3354C8.26121 14.4507 8.13697 14.5063 8.00392 14.5021C7.871 14.4978 7.74413 14.4353 7.62329 14.3146C7.5026 14.1938 7.44225 14.0647 7.44225 13.9275C7.44225 13.7903 7.5026 13.6613 7.62329 13.5404L11.1635 10.0004Z" fill="#A18AFB" fill-opacity="0.7"/>
|
|
38
|
+
</svg>`
|
|
39
|
+
|
|
40
|
+
const BUILT_WITH_REMIXER_TEXT = (classes?: string) => `
|
|
41
|
+
<div class="flex gap-[12px] items-center">
|
|
42
|
+
${REMIXER_LOGO_SVG}
|
|
43
|
+
<p class="${classes} text-[#FFF] text-[14px] font-[400]">Built with <span class="font-[600]">Remixer</span></p>
|
|
44
|
+
</div>`
|
|
45
|
+
|
|
46
|
+
const CTA_LINK = (title: string, href: string, isShowArrow: boolean = false) => `
|
|
47
|
+
<a href="${href}" target="_blank" class="group text-[14px] text-[#B6A3FE] font-[600] flex gap-[6px] items-center cursor-pointer relative">
|
|
48
|
+
${title}
|
|
49
|
+
${isShowArrow ? ARROW_SVG : ''}
|
|
50
|
+
<div class="bg-[#B6A3FE] absolute left-0 bottom-0 h-[1px] right-[100%] transition-all duration-150 ${isShowArrow ? 'group-hover:right-[4px]' : 'group-hover:right-[0px]'}"></div>
|
|
51
|
+
</a>`
|
|
52
|
+
|
|
53
|
+
const BADGE_CONTAINER = (cta_links?: string) => `
|
|
54
|
+
<div class="fixed bottom-[0px] right-[0px] z-[2147483647] flex p-[8px] gap-[16px] mx-[16px] mb-[16px] bg-[#09090B] border-[#3F3F46] border-[1px] border-solid rounded-[12px] items-center shadow-[0_2px_32px_0_rgba(0,0,0,0.25)]">
|
|
55
|
+
<div class="flex gap-[12px] items-center">
|
|
56
|
+
${cta_links ?
|
|
57
|
+
[
|
|
58
|
+
BUILT_WITH_REMIXER_TEXT('hidden md:block'),
|
|
59
|
+
'<div class="h-[20px] w-[1px] bg-[#3F3F46]"></div>',
|
|
60
|
+
cta_links
|
|
61
|
+
].join('\n') :
|
|
62
|
+
BUILT_WITH_REMIXER_TEXT()
|
|
63
|
+
}
|
|
64
|
+
</div>
|
|
65
|
+
</div>`
|
|
66
|
+
|
|
67
|
+
const PREVIEW_DOMAINS = [
|
|
68
|
+
'.remixer.ai',
|
|
69
|
+
'.dreamhosters.ai',
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
function injectRemixerBadgePlugin(): Plugin {
|
|
73
|
+
return {
|
|
74
|
+
name: "vite-plugin-inject-remixer-badge",
|
|
75
|
+
apply: "build",
|
|
76
|
+
|
|
77
|
+
transformIndexHtml(html) {
|
|
78
|
+
try {
|
|
79
|
+
const IS_SHOW_REMIXER_BADGE = process.env.IS_SHOW_REMIXER_BADGE === 'true';
|
|
80
|
+
const REMIXER_BADGE_TYPE: string = process.env.REMIXER_BADGE_TYPE || 'DEFAULT';
|
|
81
|
+
|
|
82
|
+
const domain = process.env.NEXT_PUBLIC_DOMAIN || '';
|
|
83
|
+
const isPreviewService = PREVIEW_DOMAINS.some(pd => domain.endsWith(pd));
|
|
84
|
+
|
|
85
|
+
if (!IS_SHOW_REMIXER_BADGE && !isPreviewService) return html
|
|
86
|
+
|
|
87
|
+
const DICTIONARY: Record<string, string> = {
|
|
88
|
+
DEFAULT: BADGE_CONTAINER(),
|
|
89
|
+
UPGRADE_PLAN: BADGE_CONTAINER([
|
|
90
|
+
CTA_LINK(`Upgrade Plan`, 'https://www.dreamhost.com/remixer-website-builder/', true)
|
|
91
|
+
|
|
92
|
+
].join('\n')),
|
|
93
|
+
NAVBAR: BADGE_CONTAINER([
|
|
94
|
+
CTA_LINK(`Upgrade plan`, 'https://www.dreamhost.com/remixer-website-builder/'),
|
|
95
|
+
CTA_LINK(`Get Access`, 'https://www.dreamhost.com/remixer-website-builder/'),
|
|
96
|
+
CTA_LINK(`Signup`, 'https://www.dreamhost.com/remixer-website-builder/')
|
|
97
|
+
].join('\n')),
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const BADGE_CONTENT = DICTIONARY[REMIXER_BADGE_TYPE]
|
|
101
|
+
|
|
102
|
+
return html.replace(/<\/body>/, `${BADGE_CONTENT}\n</body>`);
|
|
103
|
+
} catch (e) {
|
|
104
|
+
console.warn('Remixer badge failed to inject', e);
|
|
105
|
+
return html;
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
8
111
|
// Switches from Tailwind CDN to regular Tailwind CSS with PostCSS for production builds
|
|
9
112
|
function tailwindProdPlugin(): Plugin {
|
|
10
113
|
return {
|
|
@@ -34,7 +137,7 @@ function tailwindProdPlugin(): Plugin {
|
|
|
34
137
|
|
|
35
138
|
transformIndexHtml(html) {
|
|
36
139
|
return html.replace(
|
|
37
|
-
/\s*<script\s+src=["']https:\/\/cdn\.tailwindcss\.com["']\s*><\/script>\s*/g,
|
|
140
|
+
/\s*<script\s+src=["']https:\/\/cdn\.tailwindcss\.com[^"']*["']\s*><\/script>\s*/g,
|
|
38
141
|
"\n"
|
|
39
142
|
);
|
|
40
143
|
},
|
|
@@ -56,16 +159,10 @@ const VIRTUAL_OO_ID = "virtual:openobserve";
|
|
|
56
159
|
const RESOLVED_OO_ID = "\0" + VIRTUAL_OO_ID;
|
|
57
160
|
|
|
58
161
|
function openobservePlugin(): Plugin {
|
|
59
|
-
let env: Record<string, string> = {};
|
|
60
|
-
|
|
61
162
|
return {
|
|
62
163
|
name: "vite-plugin-openobserve",
|
|
63
164
|
apply: "build",
|
|
64
165
|
|
|
65
|
-
config(_, { mode }) {
|
|
66
|
-
env = loadEnv(mode, process.cwd(), "VITE_OO_");
|
|
67
|
-
},
|
|
68
|
-
|
|
69
166
|
resolveId(id) {
|
|
70
167
|
if (id === VIRTUAL_OO_ID) return RESOLVED_OO_ID;
|
|
71
168
|
},
|
|
@@ -73,47 +170,55 @@ function openobservePlugin(): Plugin {
|
|
|
73
170
|
load(id) {
|
|
74
171
|
if (id !== RESOLVED_OO_ID) return;
|
|
75
172
|
|
|
76
|
-
const token = env.VITE_OO_CLIENT_TOKEN;
|
|
173
|
+
const token = process.env.VITE_OO_CLIENT_TOKEN;
|
|
77
174
|
if (!token) return "export default false;";
|
|
78
175
|
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
const
|
|
176
|
+
const domain = process.env.NEXT_PUBLIC_DOMAIN || "";
|
|
177
|
+
if (PREVIEW_DOMAINS.some(pd => domain.endsWith(pd))) return "export default false;";
|
|
178
|
+
|
|
179
|
+
const site = process.env.VITE_OO_SITE || "api.openobserve.ai";
|
|
180
|
+
const org = process.env.VITE_OO_ORG || "";
|
|
181
|
+
const appId = process.env.VITE_OO_APP_ID || "";
|
|
182
|
+
const service = domain;
|
|
183
|
+
const version = process.env.VITE_OO_VERSION || "0.0.0";
|
|
184
|
+
const env = process.env.NEXT_PUBLIC_ENVIRONMENT || "production";
|
|
84
185
|
|
|
85
186
|
return `
|
|
86
187
|
import { openobserveRum } from "@openobserve/browser-rum-slim";
|
|
87
188
|
import { openobserveLogs } from "@openobserve/browser-logs";
|
|
88
189
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
190
|
+
try {
|
|
191
|
+
openobserveRum.init({
|
|
192
|
+
applicationId: ${JSON.stringify(appId)},
|
|
193
|
+
clientToken: ${JSON.stringify(token)},
|
|
194
|
+
site: ${JSON.stringify(site)},
|
|
195
|
+
organizationIdentifier: ${JSON.stringify(org)},
|
|
196
|
+
service: ${JSON.stringify(service)},
|
|
197
|
+
env: ${JSON.stringify(env)},
|
|
198
|
+
version: ${JSON.stringify(version)},
|
|
199
|
+
trackResources: true,
|
|
200
|
+
trackLongTasks: true,
|
|
201
|
+
trackUserInteractions: true,
|
|
202
|
+
insecureHTTP: false,
|
|
203
|
+
apiVersion: "v1",
|
|
204
|
+
defaultPrivacyLevel: "allow",
|
|
205
|
+
sessionSampleRate: 100,
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
openobserveLogs.init({
|
|
209
|
+
clientToken: ${JSON.stringify(token)},
|
|
210
|
+
site: ${JSON.stringify(site)},
|
|
211
|
+
organizationIdentifier: ${JSON.stringify(org)},
|
|
212
|
+
service: ${JSON.stringify(service)},
|
|
213
|
+
env: ${JSON.stringify(env)},
|
|
214
|
+
version: ${JSON.stringify(version)},
|
|
215
|
+
forwardErrorsToLogs: true,
|
|
216
|
+
insecureHTTP: false,
|
|
217
|
+
apiVersion: "v1",
|
|
218
|
+
});
|
|
219
|
+
} catch (e) {
|
|
220
|
+
console.warn('RemixerObserve failed to initialize', e);
|
|
221
|
+
}
|
|
117
222
|
|
|
118
223
|
export default true;
|
|
119
224
|
`;
|
|
@@ -129,6 +234,7 @@ export default true;
|
|
|
129
234
|
|
|
130
235
|
export default defineConfig({
|
|
131
236
|
plugins: [
|
|
237
|
+
injectRemixerBadgePlugin(),
|
|
132
238
|
openobservePlugin(),
|
|
133
239
|
tailwindProdPlugin(),
|
|
134
240
|
react(),
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { RemixerShippingAddress } from "@/lib/remixer";
|
|
1
|
+
import { authHeader } from "@/lib/supabase";
|
|
3
2
|
|
|
4
|
-
export
|
|
3
|
+
export interface ShippingAddress {
|
|
4
|
+
name: string;
|
|
5
|
+
street1: string;
|
|
6
|
+
street2?: string;
|
|
7
|
+
city: string;
|
|
8
|
+
state: string;
|
|
9
|
+
zip: string;
|
|
10
|
+
country: string;
|
|
11
|
+
phone?: string;
|
|
12
|
+
email?: string;
|
|
13
|
+
}
|
|
5
14
|
|
|
6
15
|
export interface Parcel {
|
|
7
16
|
length: string;
|
|
@@ -52,17 +61,56 @@ export async function getShippingRates(
|
|
|
52
61
|
addressFrom?: ShippingAddress;
|
|
53
62
|
}
|
|
54
63
|
): Promise<ShippingRatesResponse> {
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
line_items
|
|
60
|
-
}
|
|
61
|
-
|
|
64
|
+
const headers = await authHeader();
|
|
65
|
+
const body: Record<string, unknown> = { address_to: addressTo };
|
|
66
|
+
|
|
67
|
+
if (options.lineItems && options.lineItems.length > 0) {
|
|
68
|
+
body.line_items = options.lineItems;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (options.parcel) {
|
|
72
|
+
body.parcel = options.parcel;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (options.addressFrom) {
|
|
76
|
+
body.address_from = options.addressFrom;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const res = await fetch(
|
|
80
|
+
`${import.meta.env.VITE_SUPABASE_URL}/functions/v1/shippo-rates`,
|
|
81
|
+
{
|
|
82
|
+
method: "POST",
|
|
83
|
+
headers: { ...headers, "Content-Type": "application/json" },
|
|
84
|
+
body: JSON.stringify(body),
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
if (!res.ok) {
|
|
89
|
+
const err = await res.json().catch(() => ({ error: "Failed to fetch shipping rates" }));
|
|
90
|
+
throw new Error(err.error || "Failed to fetch shipping rates");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return res.json();
|
|
62
94
|
}
|
|
63
95
|
|
|
64
96
|
export async function validateAddress(
|
|
65
97
|
address: ShippingAddress
|
|
66
98
|
): Promise<AddressValidationResponse> {
|
|
67
|
-
|
|
99
|
+
const headers = await authHeader();
|
|
100
|
+
|
|
101
|
+
const res = await fetch(
|
|
102
|
+
`${import.meta.env.VITE_SUPABASE_URL}/functions/v1/shippo-validate-address`,
|
|
103
|
+
{
|
|
104
|
+
method: "POST",
|
|
105
|
+
headers: { ...headers, "Content-Type": "application/json" },
|
|
106
|
+
body: JSON.stringify(address),
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
if (!res.ok) {
|
|
111
|
+
const err = await res.json().catch(() => ({ error: "Failed to validate address" }));
|
|
112
|
+
throw new Error(err.error || "Failed to validate address");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return res.json();
|
|
68
116
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { RemixerCheckoutParams, RemixerCheckoutSession, RemixerShippingAddress } from "@/lib/remixer";
|
|
1
|
+
import { authHeader, supabase } from "@/lib/supabase";
|
|
3
2
|
|
|
4
3
|
export interface CreateCheckoutSessionParams {
|
|
5
4
|
items: { priceId: string; quantity: number }[];
|
|
@@ -10,32 +9,70 @@ export interface CreateCheckoutSessionParams {
|
|
|
10
9
|
shippingRateId?: string;
|
|
11
10
|
shippingCost?: number;
|
|
12
11
|
shippingLabel?: string;
|
|
13
|
-
shippingAddress?:
|
|
12
|
+
shippingAddress?: {
|
|
13
|
+
name: string;
|
|
14
|
+
street1: string;
|
|
15
|
+
street2?: string;
|
|
16
|
+
city: string;
|
|
17
|
+
state: string;
|
|
18
|
+
zip: string;
|
|
19
|
+
country: string;
|
|
20
|
+
};
|
|
14
21
|
}
|
|
15
22
|
|
|
16
|
-
export type CheckoutSessionResponse =
|
|
23
|
+
export type CheckoutSessionResponse = {
|
|
24
|
+
url: string;
|
|
25
|
+
};
|
|
17
26
|
|
|
18
27
|
export const createCheckoutSession = async (
|
|
19
28
|
params: CreateCheckoutSessionParams
|
|
20
29
|
): Promise<CheckoutSessionResponse> => {
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
const headers = await authHeader();
|
|
31
|
+
|
|
32
|
+
const {
|
|
33
|
+
data: { user },
|
|
34
|
+
} = await supabase.auth.getUser();
|
|
35
|
+
const isAuthenticated = !!user;
|
|
36
|
+
const apiUrl = `${import.meta.env.VITE_SUPABASE_URL}/functions/v1/stripe-checkout`;
|
|
37
|
+
|
|
38
|
+
const payload: Record<string, unknown> = {
|
|
39
|
+
line_items: params.items.map((item) => ({
|
|
40
|
+
price_id: item.priceId,
|
|
41
|
+
quantity: item.quantity,
|
|
42
|
+
})),
|
|
24
43
|
mode: params.mode,
|
|
25
|
-
|
|
26
|
-
|
|
44
|
+
success_url: params.successUrl,
|
|
45
|
+
cancel_url: params.cancelUrl,
|
|
27
46
|
};
|
|
28
47
|
|
|
29
|
-
if (!
|
|
30
|
-
payload.
|
|
48
|
+
if (!isAuthenticated && params.guestEmail) {
|
|
49
|
+
payload.guest_email = params.guestEmail;
|
|
31
50
|
}
|
|
32
51
|
|
|
33
52
|
if (params.shippingRateId && params.mode !== 'subscription') {
|
|
34
|
-
payload.
|
|
35
|
-
payload.
|
|
36
|
-
|
|
37
|
-
|
|
53
|
+
payload.shipping_rate_id = params.shippingRateId;
|
|
54
|
+
payload.shipping_cost = params.shippingCost;
|
|
55
|
+
if (params.shippingLabel) {
|
|
56
|
+
payload.shipping_label = params.shippingLabel;
|
|
57
|
+
}
|
|
58
|
+
if (params.shippingAddress) {
|
|
59
|
+
payload.shipping_address = params.shippingAddress;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const response = await fetch(apiUrl, {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: {
|
|
66
|
+
...headers,
|
|
67
|
+
"Content-Type": "application/json",
|
|
68
|
+
},
|
|
69
|
+
body: JSON.stringify(payload),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
const error = await response.json();
|
|
74
|
+
throw new Error(error.error || "Failed to create checkout session");
|
|
38
75
|
}
|
|
39
76
|
|
|
40
|
-
return
|
|
77
|
+
return response.json();
|
|
41
78
|
};
|