dh-remixer-sdk 0.0.4 → 0.0.6
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/postinstall.mjs +25 -5
- package/templates/base/filemap.json +5 -5
- package/templates/base/gitignore +4 -0
- package/templates/ecommerce/cleanup.json +4 -0
- package/templates/ecommerce/filemap.json +4 -0
- package/templates/ecommerce/stripe-checkout.ts +55 -0
- package/templates/ecommerce/supabase.ts +73 -0
package/package.json
CHANGED
package/scripts/postinstall.mjs
CHANGED
|
@@ -8,6 +8,10 @@ function isObj(x) {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
function jsonMerge(low, high) {
|
|
11
|
+
if (Array.isArray(low) && Array.isArray(high)) {
|
|
12
|
+
return [...low, ...high];
|
|
13
|
+
}
|
|
14
|
+
|
|
11
15
|
if (!isObj(low) || !isObj(high)) {
|
|
12
16
|
return high === undefined ? low : high;
|
|
13
17
|
}
|
|
@@ -18,9 +22,9 @@ function jsonMerge(low, high) {
|
|
|
18
22
|
const hv = high[key];
|
|
19
23
|
|
|
20
24
|
if (hv === undefined) return [key, lv];
|
|
25
|
+
if (Array.isArray(lv) && Array.isArray(hv)) return [key, [...lv, ...hv]];
|
|
21
26
|
if (Array.isArray(lv) || Array.isArray(hv)) return [key, hv];
|
|
22
27
|
if (isObj(lv) && isObj(hv)) return [key, jsonMerge(lv, hv)];
|
|
23
|
-
|
|
24
28
|
return [key, hv];
|
|
25
29
|
}),
|
|
26
30
|
);
|
|
@@ -105,10 +109,26 @@ async function main() {
|
|
|
105
109
|
const sdkVersion = JSON.parse(await fs.readFile(sdkPkgPath, "utf8")).version;
|
|
106
110
|
const templateRoot = path.join(sdkRoot, "templates", templateType);
|
|
107
111
|
const baseRoot = path.join(sdkRoot, "templates", "base");
|
|
108
|
-
const
|
|
109
|
-
const
|
|
110
|
-
const
|
|
111
|
-
const
|
|
112
|
+
const baseCleanupPath = path.join(baseRoot, "cleanup.json");
|
|
113
|
+
const baseFilemapPath = path.join(baseRoot, "filemap.json");
|
|
114
|
+
const templateCleanupPath = path.join(templateRoot, "cleanup.json");
|
|
115
|
+
const templateFilemapPath = path.join(templateRoot, "filemap.json");
|
|
116
|
+
let cleanup = JSON.parse(await fs.readFile(baseCleanupPath, "utf8"));
|
|
117
|
+
let filemap = JSON.parse(await fs.readFile(baseFilemapPath, "utf8"));
|
|
118
|
+
|
|
119
|
+
if (fssync.existsSync(templateCleanupPath)) {
|
|
120
|
+
cleanup = jsonMerge(
|
|
121
|
+
cleanup,
|
|
122
|
+
JSON.parse(await fs.readFile(templateCleanupPath, "utf8")),
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (fssync.existsSync(templateFilemapPath)) {
|
|
127
|
+
filemap = jsonMerge(
|
|
128
|
+
cleanup,
|
|
129
|
+
JSON.parse(await fs.readFile(templateFilemapPath, "utf8")),
|
|
130
|
+
);
|
|
131
|
+
}
|
|
112
132
|
|
|
113
133
|
// Delete old files
|
|
114
134
|
await Promise.all(
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"index.html": "index.html",
|
|
3
2
|
"index.tsx": "index.tsx",
|
|
3
|
+
"gitignore": ".gitignore",
|
|
4
|
+
"index.html": "index.html",
|
|
4
5
|
"package.json": "package.json",
|
|
5
6
|
"filemap.json": "filemap.json",
|
|
6
|
-
".htaccess": "public/.htaccess",
|
|
7
|
-
"robots.txt": "public/robots.txt",
|
|
8
|
-
".gitignore": ".gitignore",
|
|
9
7
|
"tsconfig.json": "tsconfig.json",
|
|
10
|
-
"vite.config.ts": "vite.config.ts"
|
|
8
|
+
"vite.config.ts": "vite.config.ts",
|
|
9
|
+
"robots.txt": "public/robots.txt",
|
|
10
|
+
".htaccess": "public/.htaccess"
|
|
11
11
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { authHeader, supabase } from "@/lib/supabase";
|
|
2
|
+
|
|
3
|
+
export interface CreateCheckoutSessionParams {
|
|
4
|
+
items: { priceId: string; quantity: number }[];
|
|
5
|
+
mode: "payment" | "subscription";
|
|
6
|
+
successUrl: string;
|
|
7
|
+
cancelUrl: string;
|
|
8
|
+
guestEmail?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type CheckoutSessionResponse = {
|
|
12
|
+
url: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const createCheckoutSession = async (
|
|
16
|
+
params: CreateCheckoutSessionParams
|
|
17
|
+
): Promise<CheckoutSessionResponse> => {
|
|
18
|
+
const headers = await authHeader();
|
|
19
|
+
|
|
20
|
+
const {
|
|
21
|
+
data: { user },
|
|
22
|
+
} = await supabase.auth.getUser();
|
|
23
|
+
const isAuthenticated = !!user;
|
|
24
|
+
const apiUrl = `${import.meta.env.VITE_SUPABASE_URL}/functions/v1/stripe-checkout`;
|
|
25
|
+
|
|
26
|
+
const payload: Record<string, unknown> = {
|
|
27
|
+
line_items: params.items.map((item) => ({
|
|
28
|
+
price_id: item.priceId,
|
|
29
|
+
quantity: item.quantity,
|
|
30
|
+
})),
|
|
31
|
+
mode: params.mode,
|
|
32
|
+
success_url: params.successUrl,
|
|
33
|
+
cancel_url: params.cancelUrl,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
if (!isAuthenticated && params.guestEmail) {
|
|
37
|
+
(payload as any).guest_email = params.guestEmail;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const response = await fetch(apiUrl, {
|
|
41
|
+
method: "POST",
|
|
42
|
+
headers: {
|
|
43
|
+
...headers,
|
|
44
|
+
"Content-Type": "application/json",
|
|
45
|
+
},
|
|
46
|
+
body: JSON.stringify(payload),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
if (!response.ok) {
|
|
50
|
+
const error = await response.json();
|
|
51
|
+
throw new Error(error.error || "Failed to create checkout session");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return response.json();
|
|
55
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
|
|
2
|
+
import { createClient } from '@supabase/supabase-js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 1) supabase — user-scoped client
|
|
6
|
+
* • Before login: uses the project access token
|
|
7
|
+
* • After login: automatically swaps to the user's JWT
|
|
8
|
+
*/
|
|
9
|
+
export const supabase = createClient(
|
|
10
|
+
import.meta.env.VITE_SUPABASE_URL!,
|
|
11
|
+
import.meta.env.VITE_SUPABASE_ANON_KEY!,
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 2) supabaseProject — tenant-wide client
|
|
16
|
+
* • Always uses the project access token
|
|
17
|
+
* • For public or calendar-style views where you want every project's data
|
|
18
|
+
*/
|
|
19
|
+
export const supabaseProject = createClient(
|
|
20
|
+
import.meta.env.VITE_SUPABASE_URL!,
|
|
21
|
+
import.meta.env.VITE_SUPABASE_ANON_KEY!,
|
|
22
|
+
{
|
|
23
|
+
global: {
|
|
24
|
+
headers: {
|
|
25
|
+
Authorization: `Bearer ${import.meta.env.VITE_PROJECT_ACCESS_TOKEN}`,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
auth: {
|
|
29
|
+
// disable session persistence so it never picks up a user JWT
|
|
30
|
+
detectSessionInUrl: false,
|
|
31
|
+
persistSession: false,
|
|
32
|
+
autoRefreshToken: false,
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* authHeader() — helper for manual fetch() calls (Edge Functions/REST)
|
|
39
|
+
* • Ensures project_id is set in user_metadata and session is refreshed
|
|
40
|
+
* • Returns `{ Authorization: 'Bearer <token>' }` where `<token>` is:
|
|
41
|
+
* - the logged-in user's JWT (if session exists), or
|
|
42
|
+
* - the project access token (anonymous)
|
|
43
|
+
*/
|
|
44
|
+
export async function authHeader() {
|
|
45
|
+
let {
|
|
46
|
+
data: { session },
|
|
47
|
+
} = await supabase.auth.getSession();
|
|
48
|
+
|
|
49
|
+
if (session?.user) {
|
|
50
|
+
const currentProjectId = import.meta.env.VITE_PROJECT_ID;
|
|
51
|
+
const userProjectId = session.user.user_metadata?.project_id;
|
|
52
|
+
|
|
53
|
+
if (userProjectId !== currentProjectId) {
|
|
54
|
+
const { error } = await supabase.auth.updateUser({
|
|
55
|
+
data: {
|
|
56
|
+
...session.user.user_metadata,
|
|
57
|
+
project_id: currentProjectId,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
if (error) throw error;
|
|
61
|
+
|
|
62
|
+
// Force session refresh to get new JWT with updated project_id
|
|
63
|
+
const { data: refreshData, error: refreshError } = await supabase.auth.refreshSession();
|
|
64
|
+
if (refreshError) throw refreshError;
|
|
65
|
+
session = refreshData.session;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const token =
|
|
70
|
+
session?.access_token ?? import.meta.env.VITE_PROJECT_ACCESS_TOKEN;
|
|
71
|
+
|
|
72
|
+
return { Authorization: `Bearer ${token}` };
|
|
73
|
+
}
|