@caldik/client 0.0.2 → 0.0.5

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 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
@@ -1,4 +1,12 @@
1
1
  //#region src/types.d.ts
2
+ interface StorefrontMetadata {
3
+ id: string;
4
+ title: string;
5
+ description: string;
6
+ json: Record<string, unknown>;
7
+ }
8
+ type ProductMetadata = StorefrontMetadata;
9
+ type CategoryMetadata = StorefrontMetadata;
2
10
  interface Category {
3
11
  id: string;
4
12
  name: string;
@@ -7,6 +15,7 @@ interface Category {
7
15
  price: string;
8
16
  logo: string | null;
9
17
  banner: string | null;
18
+ metadata: CategoryMetadata[];
10
19
  }
11
20
  interface CategoriesResponse {
12
21
  success: boolean;
@@ -27,7 +36,11 @@ interface CategoryProduct {
27
36
  interface CategoryDetails {
28
37
  id: string;
29
38
  name: string;
39
+ slug: string;
30
40
  description: string;
41
+ logo: string | null;
42
+ banner: string | null;
43
+ metadata: CategoryMetadata[];
31
44
  products: CategoryProduct[];
32
45
  }
33
46
  interface CategoryResponse {
@@ -68,6 +81,8 @@ interface Product {
68
81
  maximumQuantity: number | null;
69
82
  variants: ProductVariant[];
70
83
  tags: ProductTag[];
84
+ customFields: ProductCustomField[];
85
+ metadata: ProductMetadata[];
71
86
  }
72
87
  interface ProductVariant {
73
88
  id: string;
@@ -79,6 +94,23 @@ interface ProductTag {
79
94
  label: string;
80
95
  color: string;
81
96
  }
97
+ type ProductCustomFieldInputType = "text" | "textarea" | "number" | "dropdown" | "checkbox";
98
+ interface ProductCustomFieldOption {
99
+ id: string;
100
+ label: string;
101
+ value: string;
102
+ position: number;
103
+ }
104
+ interface ProductCustomField {
105
+ id: string;
106
+ name: string;
107
+ inputType: ProductCustomFieldInputType;
108
+ placeholder: string | null;
109
+ position: number;
110
+ defaultValue: string | null;
111
+ requiredEnabled: boolean;
112
+ options: ProductCustomFieldOption[];
113
+ }
82
114
  interface ProductsResponse {
83
115
  success: boolean;
84
116
  products: Product[];
@@ -175,19 +207,20 @@ interface CustomerLoginVerifyResponse {
175
207
  //#region src/internal/types.d.ts
176
208
  interface RequestOptions {
177
209
  edgeCache?: boolean;
210
+ /** Internal authorization policy. Protected hosted calls are the default. */
211
+ access?: "public" | "runtime";
178
212
  }
179
213
  //#endregion
180
214
  //#region src/internal/client.d.ts
181
- type CaldikTransport = "auto" | "browser" | "worker";
182
215
  type HttpClientOptions = {
183
216
  apiKey?: string;
184
217
  apiUrl?: string;
185
- transport?: CaldikTransport;
218
+ storeId?: string;
186
219
  };
187
220
  declare class CaldikHttpClient {
188
221
  private readonly apiKey?;
189
222
  private readonly apiUrl;
190
- private readonly transport;
223
+ private readonly storeId?;
191
224
  constructor(options?: HttpClientOptions);
192
225
  private baseUrl;
193
226
  private request;
@@ -250,13 +283,11 @@ declare class SubscriptionsApi {
250
283
  //#endregion
251
284
  //#region src/index.d.ts
252
285
  interface CaldikClientOptions {
253
- /** API key for explicit external/browser integrations. */
286
+ /** Store ID for external servers. Hosted Workers receive it automatically. */
287
+ storeId?: string;
288
+ /** Private API key for external server integrations. Never use in browsers. */
254
289
  apiKey?: string;
255
- /** @deprecated Use apiKey. Retained for backwards compatibility. */
256
- publicApiKey?: string;
257
290
  apiUrl?: string;
258
- /** Override automatic browser/Cloudflare Worker transport detection. */
259
- transport?: CaldikTransport;
260
291
  }
261
292
  declare class CaldikClient {
262
293
  readonly categories: CategoriesApi;
@@ -269,4 +300,4 @@ declare class CaldikClient {
269
300
  constructor(options?: CaldikClientOptions);
270
301
  }
271
302
  //#endregion
272
- export { CaldikClient, CaldikClientOptions, type CaldikTransport, 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 };
303
+ export { CaldikClient, CaldikClientOptions, CategoriesResponse, Category, CategoryDetails, CategoryMetadata, CategoryProduct, CategoryResponse, CheckoutPayment, CommerceItem, CreateOrderInput, CreateSubscriptionInput, CustomerLoginResponse, CustomerLoginVerifyResponse, ManualCommerceItem, OrderResponse, Product, ProductCommerceItem, ProductCustomField, ProductCustomFieldInputType, ProductCustomFieldOption, ProductMetadata, ProductResponse, ProductTag, ProductVariant, ProductsResponse, Review, ReviewsResponse, Store, StoreResponse, StorefrontMetadata, StorefrontOrder, SubscriptionResponse };
package/dist/index.mjs CHANGED
@@ -2,36 +2,47 @@
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;
5
6
  function isBrowserRuntime() {
6
7
  return typeof window !== "undefined" && typeof document !== "undefined";
7
8
  }
8
- function isCloudflareWorkerRuntime() {
9
- return typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers";
9
+ function boundRuntimeStoreId() {
10
+ const storeId = globalThis.process?.env?.CALDIK_STORE_ID?.trim();
11
+ return storeId && STORE_ID_PATTERN.test(storeId) ? storeId : null;
10
12
  }
11
13
  var CaldikHttpClient = class {
12
14
  apiKey;
13
15
  apiUrl;
14
- transport;
16
+ storeId;
15
17
  constructor(options = {}) {
16
- this.apiKey = options.apiKey;
18
+ this.apiKey = options.apiKey?.trim() || void 0;
17
19
  this.apiUrl = options.apiUrl || defaultApiUrl;
18
- this.transport = options.transport || "auto";
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");
19
24
  }
20
25
  baseUrl() {
21
- if (this.apiKey) return `${this.apiUrl.replace(/\/+$/, "")}/v1/storefront`;
22
- if (this.transport === "browser" || this.transport === "auto" && isBrowserRuntime()) {
26
+ if (isBrowserRuntime()) {
23
27
  if (typeof location === "undefined") throw new Error("Caldik browser transport requires a browser origin");
24
- return new URL("/__caldik/api", location.origin).toString().replace(/\/+$/, "");
28
+ const storeReference = location.hostname.trim().toLowerCase().replace(/\.$/, "");
29
+ if (!storeReference) throw new Error("Caldik browser transport requires a storefront hostname");
30
+ return `${this.apiUrl.replace(/\/+$/, "")}/v1/stores/${encodeURIComponent(storeReference)}`;
25
31
  }
26
- if (this.transport === "worker" || this.transport === "auto" && isCloudflareWorkerRuntime()) return `${this.apiUrl.replace(/\/+$/, "")}/v1/storefront`;
27
- throw new Error("Caldik authentication is unavailable in this environment. Provide apiKey for an external integration, or set transport to \"browser\" or \"worker\" when environment detection is unavailable.");
32
+ const boundStoreId = boundRuntimeStoreId();
33
+ if (boundStoreId && this.storeId && boundStoreId !== this.storeId) throw new Error("Caldik storeId does not match the hosted runtime");
34
+ const storeId = this.storeId || boundStoreId;
35
+ if (!storeId) throw new Error("Caldik authentication is unavailable. External servers must provide storeId and a private apiKey.");
36
+ if (!boundStoreId && !this.apiKey) throw new Error("Caldik authentication is unavailable. External servers must provide a private apiKey.");
37
+ return `${this.apiUrl.replace(/\/+$/, "")}/v1/stores/${encodeURIComponent(storeId)}`;
28
38
  }
29
39
  async request(method, path, input, params, options) {
30
40
  const url = new URL(`${this.baseUrl()}${path}`);
31
41
  if (params) for (const [key, value] of Object.entries(params)) url.searchParams.set(key, String(value));
32
42
  const headers = {};
33
- if (!isBrowserRuntime()) headers["User-Agent"] = "CaldikClient/0.0.1";
43
+ if (!isBrowserRuntime()) headers["User-Agent"] = "CaldikClient/0.0.2";
34
44
  if (this.apiKey) headers.Authorization = `Bearer ${this.apiKey}`;
45
+ else if (options?.access === "public" && !isBrowserRuntime()) headers["X-Caldik-Public-Request"] = "1";
35
46
  if (input !== void 0) headers["Content-Type"] = "application/json";
36
47
  if (options?.edgeCache) headers["X-Cache-Policy"] = "public";
37
48
  const response = await fetch(url, {
@@ -63,10 +74,10 @@ var CategoriesApi = class {
63
74
  this.client = client;
64
75
  }
65
76
  list(limit) {
66
- return this.client.get("/categories", limit ? { limit } : void 0);
77
+ return this.client.get("/categories", limit ? { limit } : void 0, { access: "public" });
67
78
  }
68
79
  get(categoryId) {
69
- return this.client.get(`/categories/${categoryId}`);
80
+ return this.client.get(`/categories/${categoryId}`, void 0, { access: "public" });
70
81
  }
71
82
  };
72
83
  //#endregion
@@ -77,10 +88,10 @@ var ProductsApi = class {
77
88
  this.client = client;
78
89
  }
79
90
  list() {
80
- return this.client.get("/products");
91
+ return this.client.get("/products", void 0, { access: "public" });
81
92
  }
82
93
  get(productId) {
83
- return this.client.get(`/products/${productId}`);
94
+ return this.client.get(`/products/${productId}`, void 0, { access: "public" });
84
95
  }
85
96
  };
86
97
  //#endregion
@@ -91,7 +102,7 @@ var ReviewsApi = class {
91
102
  this.client = client;
92
103
  }
93
104
  list(limit) {
94
- return this.client.get("/reviews", limit ? { limit } : void 0);
105
+ return this.client.get("/reviews", limit ? { limit } : void 0, { access: "public" });
95
106
  }
96
107
  };
97
108
  //#endregion
@@ -102,7 +113,7 @@ var StoreApi = class {
102
113
  this.client = client;
103
114
  }
104
115
  get() {
105
- return this.client.get("");
116
+ return this.client.get("", void 0, { access: "public" });
106
117
  }
107
118
  };
108
119
  //#endregion
@@ -113,10 +124,10 @@ var CheckoutApi = class {
113
124
  this.client = client;
114
125
  }
115
126
  create(input) {
116
- return this.client.post("/checkout", input);
127
+ return this.client.post("/checkouts", input, { access: "public" });
117
128
  }
118
129
  payWithBalance(orderId) {
119
- return this.client.post(`/checkout/${encodeURIComponent(orderId)}/balance-payment`);
130
+ return this.client.post(`/checkouts/${encodeURIComponent(orderId)}/balance-payment`, void 0, { access: "public" });
120
131
  }
121
132
  };
122
133
  //#endregion
@@ -127,10 +138,10 @@ var CustomerApi = class {
127
138
  this.client = client;
128
139
  }
129
140
  requestLogin(email) {
130
- return this.client.post("/customer/login", { email });
141
+ return this.client.post("/customers/login", { email }, { access: "public" });
131
142
  }
132
143
  verifyLogin(code) {
133
- return this.client.post("/customer/login/verify", { code });
144
+ return this.client.post("/customers/login/verify", { code }, { access: "public" });
134
145
  }
135
146
  };
136
147
  //#endregion
@@ -141,7 +152,7 @@ var SubscriptionsApi = class {
141
152
  this.client = client;
142
153
  }
143
154
  create(input) {
144
- return this.client.post("/subscriptions", input);
155
+ return this.client.post("/subscriptions", input, { access: "public" });
145
156
  }
146
157
  };
147
158
  //#endregion
@@ -156,9 +167,9 @@ var CaldikClient = class {
156
167
  subscriptions;
157
168
  constructor(options = {}) {
158
169
  const client = new CaldikHttpClient({
159
- apiKey: options.apiKey ?? options.publicApiKey,
170
+ apiKey: options.apiKey,
160
171
  apiUrl: options.apiUrl,
161
- transport: options.transport
172
+ storeId: options.storeId
162
173
  });
163
174
  this.categories = new CategoriesApi(client);
164
175
  this.products = new ProductsApi(client);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caldik/client",
3
- "version": "0.0.2",
3
+ "version": "0.0.5",
4
4
  "type": "module",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.mts",
@@ -21,6 +21,7 @@
21
21
  "test": "bun test"
22
22
  },
23
23
  "devDependencies": {
24
+ "@types/bun": "latest",
24
25
  "tsdown": "^0.22.3",
25
26
  "typescript": "^6.0.3"
26
27
  }