@caldik/client 0.0.1 → 0.0.4
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 +24 -0
- package/dist/index.d.mts +165 -12
- package/dist/index.mjs +107 -20
- package/package.json +3 -2
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Caldik SDK
|
|
2
|
+
|
|
3
|
+
## Caldik-hosted storefront
|
|
4
|
+
|
|
5
|
+
No credentials or store configuration are required:
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { CaldikClient } from "@caldik/client"
|
|
9
|
+
|
|
10
|
+
const caldik = new CaldikClient()
|
|
11
|
+
const { products } = await caldik.products.list()
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## External server
|
|
15
|
+
|
|
16
|
+
External integrations explicitly provide the store ID and a private `sk_` API
|
|
17
|
+
key:
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
const caldik = new CaldikClient({
|
|
21
|
+
storeId: "STORE_...",
|
|
22
|
+
apiKey: process.env.CALDIK_PRIVATE_API_KEY,
|
|
23
|
+
})
|
|
24
|
+
```
|
package/dist/index.d.mts
CHANGED
|
@@ -5,8 +5,8 @@ interface Category {
|
|
|
5
5
|
slug: string;
|
|
6
6
|
description: string;
|
|
7
7
|
price: string;
|
|
8
|
-
logo: string;
|
|
9
|
-
banner: string;
|
|
8
|
+
logo: string | null;
|
|
9
|
+
banner: string | null;
|
|
10
10
|
}
|
|
11
11
|
interface CategoriesResponse {
|
|
12
12
|
success: boolean;
|
|
@@ -21,8 +21,8 @@ interface CategoryProduct {
|
|
|
21
21
|
color: string;
|
|
22
22
|
}[];
|
|
23
23
|
price: string;
|
|
24
|
-
logo: string;
|
|
25
|
-
banner: string;
|
|
24
|
+
logo: string | null;
|
|
25
|
+
banner: string | null;
|
|
26
26
|
}
|
|
27
27
|
interface CategoryDetails {
|
|
28
28
|
id: string;
|
|
@@ -56,20 +56,144 @@ interface ReviewsResponse {
|
|
|
56
56
|
interface Product {
|
|
57
57
|
id: string;
|
|
58
58
|
name: string;
|
|
59
|
-
|
|
59
|
+
type: string;
|
|
60
|
+
slug: string;
|
|
61
|
+
description: string;
|
|
62
|
+
price: string;
|
|
63
|
+
logo: string | null;
|
|
64
|
+
banner: string | null;
|
|
65
|
+
videoUrl: string | null;
|
|
66
|
+
deliveryType: string;
|
|
67
|
+
minimumQuantity: number | null;
|
|
68
|
+
maximumQuantity: number | null;
|
|
69
|
+
variants: ProductVariant[];
|
|
70
|
+
tags: ProductTag[];
|
|
71
|
+
}
|
|
72
|
+
interface ProductVariant {
|
|
73
|
+
id: string;
|
|
74
|
+
name: string;
|
|
75
|
+
price: string;
|
|
76
|
+
compareAtPrice: string | null;
|
|
77
|
+
}
|
|
78
|
+
interface ProductTag {
|
|
79
|
+
label: string;
|
|
80
|
+
color: string;
|
|
81
|
+
}
|
|
82
|
+
interface ProductsResponse {
|
|
83
|
+
success: boolean;
|
|
84
|
+
products: Product[];
|
|
85
|
+
}
|
|
86
|
+
interface ProductResponse {
|
|
87
|
+
success: boolean;
|
|
88
|
+
product: Product;
|
|
89
|
+
}
|
|
90
|
+
interface ManualCommerceItem {
|
|
91
|
+
name: string;
|
|
92
|
+
description?: string;
|
|
93
|
+
quantity?: number;
|
|
94
|
+
unitAmount: string | number;
|
|
95
|
+
}
|
|
96
|
+
interface ProductCommerceItem {
|
|
97
|
+
productId: string;
|
|
98
|
+
productVariantId?: string;
|
|
99
|
+
quantity?: number;
|
|
100
|
+
}
|
|
101
|
+
type CommerceItem = ManualCommerceItem | ProductCommerceItem;
|
|
102
|
+
interface CreateOrderInput {
|
|
103
|
+
customerId?: string;
|
|
104
|
+
email?: string;
|
|
105
|
+
paymentMethod: "customer_balance" | "stripe" | "ovgc";
|
|
106
|
+
items: CommerceItem[];
|
|
107
|
+
successUrl?: string;
|
|
108
|
+
cancelUrl?: string;
|
|
109
|
+
}
|
|
110
|
+
interface StorefrontOrder {
|
|
111
|
+
id: string;
|
|
112
|
+
shortId: string;
|
|
113
|
+
displayId: string;
|
|
114
|
+
customerId: string | null;
|
|
115
|
+
paymentStatus: string;
|
|
116
|
+
fulfillmentStatus: string;
|
|
117
|
+
amount: string;
|
|
118
|
+
currency: string;
|
|
119
|
+
}
|
|
120
|
+
interface CheckoutPayment {
|
|
121
|
+
type: "customer_balance" | "stripe" | "ovgc";
|
|
122
|
+
checkoutUrl?: string | null;
|
|
123
|
+
checkoutSessionId?: string | null;
|
|
124
|
+
balanceAfter?: string;
|
|
125
|
+
}
|
|
126
|
+
interface OrderResponse {
|
|
127
|
+
success: boolean;
|
|
128
|
+
order: StorefrontOrder;
|
|
129
|
+
payment: CheckoutPayment | null;
|
|
130
|
+
}
|
|
131
|
+
interface CreateSubscriptionInput {
|
|
132
|
+
customerId?: string;
|
|
133
|
+
email?: string;
|
|
134
|
+
items: CommerceItem[];
|
|
135
|
+
billingInterval: "day" | "week" | "month" | "year";
|
|
136
|
+
billingIntervalCount?: number;
|
|
137
|
+
trialDays?: number;
|
|
138
|
+
successUrl: string;
|
|
139
|
+
cancelUrl: string;
|
|
140
|
+
}
|
|
141
|
+
interface SubscriptionResponse {
|
|
142
|
+
success: boolean;
|
|
143
|
+
subscription: {
|
|
144
|
+
id: string;
|
|
145
|
+
shortId: string;
|
|
146
|
+
displayId: string;
|
|
147
|
+
customerId: string;
|
|
148
|
+
status: string;
|
|
149
|
+
billingInterval: string;
|
|
150
|
+
billingIntervalCount: number;
|
|
151
|
+
amount: string;
|
|
152
|
+
currency: string;
|
|
153
|
+
};
|
|
154
|
+
payment: {
|
|
155
|
+
type: "stripe";
|
|
156
|
+
checkoutUrl: string;
|
|
157
|
+
checkoutSessionId: string;
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
interface CustomerLoginResponse {
|
|
161
|
+
success: boolean;
|
|
162
|
+
message: string;
|
|
163
|
+
}
|
|
164
|
+
interface CustomerLoginVerifyResponse {
|
|
165
|
+
success: boolean;
|
|
166
|
+
customer: {
|
|
167
|
+
id: string;
|
|
168
|
+
shortId: string;
|
|
169
|
+
displayId: string;
|
|
170
|
+
email: string;
|
|
171
|
+
status: string;
|
|
172
|
+
};
|
|
60
173
|
}
|
|
61
174
|
//#endregion
|
|
62
175
|
//#region src/internal/types.d.ts
|
|
63
176
|
interface RequestOptions {
|
|
64
177
|
edgeCache?: boolean;
|
|
178
|
+
/** Internal authorization policy. Protected hosted calls are the default. */
|
|
179
|
+
access?: "public" | "runtime";
|
|
65
180
|
}
|
|
66
181
|
//#endregion
|
|
67
182
|
//#region src/internal/client.d.ts
|
|
183
|
+
type HttpClientOptions = {
|
|
184
|
+
apiKey?: string;
|
|
185
|
+
apiUrl?: string;
|
|
186
|
+
storeId?: string;
|
|
187
|
+
};
|
|
68
188
|
declare class CaldikHttpClient {
|
|
69
|
-
private
|
|
70
|
-
private apiUrl;
|
|
71
|
-
|
|
189
|
+
private readonly apiKey?;
|
|
190
|
+
private readonly apiUrl;
|
|
191
|
+
private readonly storeId?;
|
|
192
|
+
constructor(options?: HttpClientOptions);
|
|
193
|
+
private baseUrl;
|
|
194
|
+
private request;
|
|
72
195
|
get<T>(path: string, params?: Record<string, string | number>, options?: RequestOptions): Promise<T>;
|
|
196
|
+
post<T>(path: string, input?: unknown, options?: RequestOptions): Promise<T>;
|
|
73
197
|
}
|
|
74
198
|
//#endregion
|
|
75
199
|
//#region src/categories.d.ts
|
|
@@ -84,8 +208,8 @@ declare class CategoriesApi {
|
|
|
84
208
|
declare class ProductsApi {
|
|
85
209
|
private client;
|
|
86
210
|
constructor(client: CaldikHttpClient);
|
|
87
|
-
list(): Promise<
|
|
88
|
-
get(productId: string): Promise<
|
|
211
|
+
list(): Promise<ProductsResponse>;
|
|
212
|
+
get(productId: string): Promise<ProductResponse>;
|
|
89
213
|
}
|
|
90
214
|
//#endregion
|
|
91
215
|
//#region src/reviews.d.ts
|
|
@@ -102,9 +226,35 @@ declare class StoreApi {
|
|
|
102
226
|
get(): Promise<StoreResponse>;
|
|
103
227
|
}
|
|
104
228
|
//#endregion
|
|
229
|
+
//#region src/checkout.d.ts
|
|
230
|
+
declare class CheckoutApi {
|
|
231
|
+
private client;
|
|
232
|
+
constructor(client: CaldikHttpClient);
|
|
233
|
+
create(input: CreateOrderInput): Promise<OrderResponse>;
|
|
234
|
+
payWithBalance(orderId: string): Promise<OrderResponse>;
|
|
235
|
+
}
|
|
236
|
+
//#endregion
|
|
237
|
+
//#region src/customer.d.ts
|
|
238
|
+
declare class CustomerApi {
|
|
239
|
+
private client;
|
|
240
|
+
constructor(client: CaldikHttpClient);
|
|
241
|
+
requestLogin(email: string): Promise<CustomerLoginResponse>;
|
|
242
|
+
verifyLogin(code: string): Promise<CustomerLoginVerifyResponse>;
|
|
243
|
+
}
|
|
244
|
+
//#endregion
|
|
245
|
+
//#region src/subscriptions.d.ts
|
|
246
|
+
declare class SubscriptionsApi {
|
|
247
|
+
private client;
|
|
248
|
+
constructor(client: CaldikHttpClient);
|
|
249
|
+
create(input: CreateSubscriptionInput): Promise<SubscriptionResponse>;
|
|
250
|
+
}
|
|
251
|
+
//#endregion
|
|
105
252
|
//#region src/index.d.ts
|
|
106
253
|
interface CaldikClientOptions {
|
|
107
|
-
|
|
254
|
+
/** Store ID for external servers. Hosted Workers receive it automatically. */
|
|
255
|
+
storeId?: string;
|
|
256
|
+
/** Private API key for external server integrations. Never use in browsers. */
|
|
257
|
+
apiKey?: string;
|
|
108
258
|
apiUrl?: string;
|
|
109
259
|
}
|
|
110
260
|
declare class CaldikClient {
|
|
@@ -112,7 +262,10 @@ declare class CaldikClient {
|
|
|
112
262
|
readonly products: ProductsApi;
|
|
113
263
|
readonly reviews: ReviewsApi;
|
|
114
264
|
readonly store: StoreApi;
|
|
265
|
+
readonly checkout: CheckoutApi;
|
|
266
|
+
readonly customer: CustomerApi;
|
|
267
|
+
readonly subscriptions: SubscriptionsApi;
|
|
115
268
|
constructor(options?: CaldikClientOptions);
|
|
116
269
|
}
|
|
117
270
|
//#endregion
|
|
118
|
-
export { CaldikClient, CaldikClientOptions };
|
|
271
|
+
export { CaldikClient, CaldikClientOptions, CategoriesResponse, Category, CategoryDetails, CategoryProduct, CategoryResponse, CheckoutPayment, CommerceItem, CreateOrderInput, CreateSubscriptionInput, CustomerLoginResponse, CustomerLoginVerifyResponse, ManualCommerceItem, OrderResponse, Product, ProductCommerceItem, ProductResponse, ProductTag, ProductVariant, ProductsResponse, Review, ReviewsResponse, Store, StoreResponse, StorefrontOrder, SubscriptionResponse };
|
package/dist/index.mjs
CHANGED
|
@@ -2,29 +2,67 @@
|
|
|
2
2
|
const defaultApiUrl = typeof API_URL !== "undefined" ? API_URL : "https://api.caldik.com";
|
|
3
3
|
//#endregion
|
|
4
4
|
//#region src/internal/client.ts
|
|
5
|
+
const STORE_ID_PATTERN = /^STORE_[a-f0-9]{32}$/i;
|
|
6
|
+
function isBrowserRuntime() {
|
|
7
|
+
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
8
|
+
}
|
|
9
|
+
function boundRuntimeStoreId() {
|
|
10
|
+
const storeId = globalThis.process?.env?.CALDIK_STORE_ID?.trim();
|
|
11
|
+
return storeId && STORE_ID_PATTERN.test(storeId) ? storeId : null;
|
|
12
|
+
}
|
|
5
13
|
var CaldikHttpClient = class {
|
|
6
|
-
|
|
14
|
+
apiKey;
|
|
7
15
|
apiUrl;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
this.
|
|
16
|
+
storeId;
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.apiKey = options.apiKey?.trim() || void 0;
|
|
19
|
+
this.apiUrl = options.apiUrl || defaultApiUrl;
|
|
20
|
+
this.storeId = options.storeId?.trim() || void 0;
|
|
21
|
+
if (this.apiKey && !this.apiKey.startsWith("sk_")) throw new Error("Caldik external integrations require a private sk_ API key");
|
|
22
|
+
if (this.storeId && !STORE_ID_PATTERN.test(this.storeId)) throw new Error("Caldik storeId is invalid");
|
|
23
|
+
if (isBrowserRuntime() && this.apiKey) throw new Error("Caldik private API keys cannot be used in browser code");
|
|
24
|
+
}
|
|
25
|
+
baseUrl() {
|
|
26
|
+
if (isBrowserRuntime()) {
|
|
27
|
+
if (typeof location === "undefined") throw new Error("Caldik browser transport requires a browser origin");
|
|
28
|
+
return new URL("/__caldik/api", location.origin).toString().replace(/\/+$/, "");
|
|
29
|
+
}
|
|
30
|
+
const boundStoreId = boundRuntimeStoreId();
|
|
31
|
+
if (boundStoreId && this.storeId && boundStoreId !== this.storeId) throw new Error("Caldik storeId does not match the hosted runtime");
|
|
32
|
+
const storeId = this.storeId || boundStoreId;
|
|
33
|
+
if (!storeId) throw new Error("Caldik authentication is unavailable. External servers must provide storeId and a private apiKey.");
|
|
34
|
+
if (!boundStoreId && !this.apiKey) throw new Error("Caldik authentication is unavailable. External servers must provide a private apiKey.");
|
|
35
|
+
return `${this.apiUrl.replace(/\/+$/, "")}/v1/stores/${encodeURIComponent(storeId)}`;
|
|
11
36
|
}
|
|
12
|
-
async
|
|
13
|
-
const
|
|
14
|
-
const url = new URL(`${baseUrl}/v1${path}`);
|
|
37
|
+
async request(method, path, input, params, options) {
|
|
38
|
+
const url = new URL(`${this.baseUrl()}${path}`);
|
|
15
39
|
if (params) for (const [key, value] of Object.entries(params)) url.searchParams.set(key, String(value));
|
|
16
|
-
const headers = {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
40
|
+
const headers = {};
|
|
41
|
+
if (!isBrowserRuntime()) headers["User-Agent"] = "CaldikClient/0.0.2";
|
|
42
|
+
if (this.apiKey) headers.Authorization = `Bearer ${this.apiKey}`;
|
|
43
|
+
else if (options?.access === "public") headers["X-Caldik-Public-Request"] = "1";
|
|
44
|
+
if (input !== void 0) headers["Content-Type"] = "application/json";
|
|
20
45
|
if (options?.edgeCache) headers["X-Cache-Policy"] = "public";
|
|
21
46
|
const response = await fetch(url, {
|
|
47
|
+
method,
|
|
22
48
|
headers,
|
|
23
|
-
|
|
49
|
+
...input !== void 0 ? { body: JSON.stringify(input) } : {},
|
|
50
|
+
cache: "default",
|
|
51
|
+
credentials: "include"
|
|
24
52
|
});
|
|
25
|
-
if (!response.ok)
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
const error = await response.clone().json().catch(() => null);
|
|
55
|
+
const message = typeof error?.message === "string" && error.message ? error.message : `${response.status} ${response.statusText}`.trim();
|
|
56
|
+
throw new Error(message);
|
|
57
|
+
}
|
|
26
58
|
return response.json();
|
|
27
59
|
}
|
|
60
|
+
get(path, params, options) {
|
|
61
|
+
return this.request("GET", path, void 0, params, options);
|
|
62
|
+
}
|
|
63
|
+
post(path, input, options) {
|
|
64
|
+
return this.request("POST", path, input, void 0, options);
|
|
65
|
+
}
|
|
28
66
|
};
|
|
29
67
|
//#endregion
|
|
30
68
|
//#region src/categories.ts
|
|
@@ -34,10 +72,10 @@ var CategoriesApi = class {
|
|
|
34
72
|
this.client = client;
|
|
35
73
|
}
|
|
36
74
|
list(limit) {
|
|
37
|
-
return this.client.get("/categories", limit ? { limit } : void 0);
|
|
75
|
+
return this.client.get("/categories", limit ? { limit } : void 0, { access: "public" });
|
|
38
76
|
}
|
|
39
77
|
get(categoryId) {
|
|
40
|
-
return this.client.get(`/categories/${categoryId}
|
|
78
|
+
return this.client.get(`/categories/${categoryId}`, void 0, { access: "public" });
|
|
41
79
|
}
|
|
42
80
|
};
|
|
43
81
|
//#endregion
|
|
@@ -48,10 +86,10 @@ var ProductsApi = class {
|
|
|
48
86
|
this.client = client;
|
|
49
87
|
}
|
|
50
88
|
list() {
|
|
51
|
-
return this.client.get("/products");
|
|
89
|
+
return this.client.get("/products", void 0, { access: "public" });
|
|
52
90
|
}
|
|
53
91
|
get(productId) {
|
|
54
|
-
return this.client.get(`/products/${productId}
|
|
92
|
+
return this.client.get(`/products/${productId}`, void 0, { access: "public" });
|
|
55
93
|
}
|
|
56
94
|
};
|
|
57
95
|
//#endregion
|
|
@@ -62,7 +100,7 @@ var ReviewsApi = class {
|
|
|
62
100
|
this.client = client;
|
|
63
101
|
}
|
|
64
102
|
list(limit) {
|
|
65
|
-
return this.client.get("/reviews", limit ? { limit } : void 0);
|
|
103
|
+
return this.client.get("/reviews", limit ? { limit } : void 0, { access: "public" });
|
|
66
104
|
}
|
|
67
105
|
};
|
|
68
106
|
//#endregion
|
|
@@ -73,7 +111,46 @@ var StoreApi = class {
|
|
|
73
111
|
this.client = client;
|
|
74
112
|
}
|
|
75
113
|
get() {
|
|
76
|
-
return this.client.get("");
|
|
114
|
+
return this.client.get("", void 0, { access: "public" });
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region src/checkout.ts
|
|
119
|
+
var CheckoutApi = class {
|
|
120
|
+
client;
|
|
121
|
+
constructor(client) {
|
|
122
|
+
this.client = client;
|
|
123
|
+
}
|
|
124
|
+
create(input) {
|
|
125
|
+
return this.client.post("/checkouts", input, { access: "public" });
|
|
126
|
+
}
|
|
127
|
+
payWithBalance(orderId) {
|
|
128
|
+
return this.client.post(`/checkouts/${encodeURIComponent(orderId)}/balance-payment`, void 0, { access: "public" });
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region src/customer.ts
|
|
133
|
+
var CustomerApi = class {
|
|
134
|
+
client;
|
|
135
|
+
constructor(client) {
|
|
136
|
+
this.client = client;
|
|
137
|
+
}
|
|
138
|
+
requestLogin(email) {
|
|
139
|
+
return this.client.post("/customers/login", { email }, { access: "public" });
|
|
140
|
+
}
|
|
141
|
+
verifyLogin(code) {
|
|
142
|
+
return this.client.post("/customers/login/verify", { code }, { access: "public" });
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
//#endregion
|
|
146
|
+
//#region src/subscriptions.ts
|
|
147
|
+
var SubscriptionsApi = class {
|
|
148
|
+
client;
|
|
149
|
+
constructor(client) {
|
|
150
|
+
this.client = client;
|
|
151
|
+
}
|
|
152
|
+
create(input) {
|
|
153
|
+
return this.client.post("/subscriptions", input, { access: "public" });
|
|
77
154
|
}
|
|
78
155
|
};
|
|
79
156
|
//#endregion
|
|
@@ -83,12 +160,22 @@ var CaldikClient = class {
|
|
|
83
160
|
products;
|
|
84
161
|
reviews;
|
|
85
162
|
store;
|
|
163
|
+
checkout;
|
|
164
|
+
customer;
|
|
165
|
+
subscriptions;
|
|
86
166
|
constructor(options = {}) {
|
|
87
|
-
const client = new CaldikHttpClient(
|
|
167
|
+
const client = new CaldikHttpClient({
|
|
168
|
+
apiKey: options.apiKey,
|
|
169
|
+
apiUrl: options.apiUrl,
|
|
170
|
+
storeId: options.storeId
|
|
171
|
+
});
|
|
88
172
|
this.categories = new CategoriesApi(client);
|
|
89
173
|
this.products = new ProductsApi(client);
|
|
90
174
|
this.reviews = new ReviewsApi(client);
|
|
91
175
|
this.store = new StoreApi(client);
|
|
176
|
+
this.checkout = new CheckoutApi(client);
|
|
177
|
+
this.customer = new CustomerApi(client);
|
|
178
|
+
this.subscriptions = new SubscriptionsApi(client);
|
|
92
179
|
}
|
|
93
180
|
};
|
|
94
181
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@caldik/client",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.mjs",
|
|
6
6
|
"types": "./dist/index.d.mts",
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"access": "public"
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
|
20
|
-
"build": "tsdown"
|
|
20
|
+
"build": "tsdown",
|
|
21
|
+
"test": "bun test"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
23
24
|
"tsdown": "^0.22.3",
|