@caldik/client 0.1.0 → 0.1.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
@@ -1,81 +1,206 @@
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
- ```
25
-
26
- ## Cart and discounts
27
-
28
-
29
- ```ts
30
- const cart = caldik.cart.add({
31
- productId: "PRODUCT_...",
32
- productVariantId: "PRODUCT_VARIANT_...",
33
- quantity: 1,
34
- })
35
-
36
- caldik.cart.updateQuantity(cart.items[0].id, 3)
37
- caldik.cart.remove(cart.items[0].id)
38
- ```
39
-
40
- ```ts
41
- await caldik.cart.applyDiscount("SAVE10")
42
-
43
- const result = await caldik.cart.checkout({
44
- paymentMethod: "stripe",
45
- items: [{ productId, productVariantId, quantity: 1 }],
46
- termsAccepted: acceptedTermsCheckbox,
47
- successUrl: "https://shop.example/success",
48
- cancelUrl: "https://shop.example/cart",
49
- })
50
- ```
51
-
52
- Use `caldik.discounts.check({ code, items })` when a cart should be managed by
53
- the application instead of the SDK.
54
-
55
-
56
- ## Customer Logins
57
-
58
- Magic Code
59
- ```ts
60
- await caldik.customer.requestLogin("customer@example.com")
61
- await caldik.customer.verifyLogin(code)
62
- ```
63
-
64
- Username / Email Password ( if password login is enabled )
65
- ```ts
66
- await caldik.customer.login({ username: "customer", password })
67
- ```
68
-
69
- if you are logged in using magic code you can just do
70
- - this to enroll the customers account into username / email password login ( password login needs to be enabled in the dashboard )
71
- ```ts
72
- await caldik.customer.setPassword({ username: "customer", password })
73
- ```
74
-
75
- ## Payment methods and Settings
76
-
77
- ```ts
78
- const { settings: loginSettings } = await caldik.customer.settings.get()
79
- const { settings: checkoutSettings } = await caldik.checkout.settings.get()
80
- const { paymentMethods } = await caldik.checkout.paymentmethods.list()
1
+ # Caldik SDK
2
+
3
+ The official Caldik SDK for interacting with Caldik storefronts, products, carts, checkouts, and customer accounts.
4
+
5
+ ## Caldik-hosted Storefront
6
+
7
+ No credentials or store configuration are required when running inside a Caldik-hosted storefront.
8
+
9
+ ```ts
10
+ import { CaldikClient } from "@caldik/client"
11
+
12
+ const caldik = new CaldikClient()
13
+
14
+ const { products } = await caldik.products.list()
15
+ ```
16
+
17
+ ## External Server
18
+
19
+ External integrations must explicitly provide a store ID and a private `sk_` API key.
20
+
21
+ ```ts
22
+ import { CaldikClient } from "@caldik/client"
23
+
24
+ const caldik = new CaldikClient({
25
+ storeId: "STORE_...",
26
+ apiKey: process.env.CALDIK_PRIVATE_API_KEY,
27
+ })
28
+ ```
29
+
30
+ ## Cart and Discounts
31
+
32
+ ### Cart Management
33
+
34
+ Add products to the cart, update quantities, or remove items.
35
+
36
+ ```ts
37
+ const cart = caldik.cart.add({
38
+ productId: "PRODUCT_...",
39
+ productVariantId: "PRODUCT_VARIANT_...",
40
+ quantity: 1,
41
+ })
42
+
43
+ // Update item quantity
44
+ caldik.cart.updateQuantity(cart.items[0].id, 3)
45
+
46
+ // Remove an item
47
+ caldik.cart.remove(cart.items[0].id)
48
+ ```
49
+
50
+ ### Apply Discounts
51
+
52
+ Apply a discount code to the current cart.
53
+
54
+ ```ts
55
+ await caldik.cart.applyDiscount("SAVE10")
56
+ ```
57
+
58
+ ### Checkout
59
+
60
+ Create a checkout session using the current cart or explicitly provided items.
61
+
62
+ ```ts
63
+ const result = await caldik.cart.checkout({
64
+ paymentMethod: "stripe",
65
+ items: [
66
+ {
67
+ productId,
68
+ productVariantId,
69
+ quantity: 1,
70
+ },
71
+ ],
72
+ termsAccepted: acceptedTermsCheckbox,
73
+ successUrl: "https://shop.example/success",
74
+ cancelUrl: "https://shop.example/cart",
75
+ })
76
+ ```
77
+
78
+ ### Validate Discounts
79
+
80
+ If your application manages its own cart instead of using the SDK's built-in cart management, validate discount codes directly.
81
+
82
+ ```ts
83
+ const result = await caldik.discounts.check({
84
+ code,
85
+ items,
86
+ })
87
+ ```
88
+
89
+ ## Customer Authentication
90
+
91
+ Caldik supports email-based magic code authentication and optional password authentication.
92
+
93
+ Username authentication is available through the **Customer Usernames** plugin.
94
+
95
+ ### Magic Code Login
96
+
97
+ Customers can log in using a six-digit verification code sent to their email address.
98
+
99
+ ```ts
100
+ // Send a six-digit verification code
101
+ await caldik.customer.login("customer@example.com")
102
+
103
+ // Verify the code
104
+ await caldik.customer.login.verify(code)
105
+ ```
106
+
107
+ ### Email and Password Login
108
+
109
+ Email and password authentication requires password login to be enabled in the store dashboard.
110
+
111
+ ```ts
112
+ await caldik.customer.login({
113
+ email: "customer@example.com",
114
+ password,
115
+ })
116
+ ```
117
+
118
+ ### Username and Password Login
119
+
120
+ Username authentication requires the **Customer Usernames** plugin to be installed and enabled.
121
+
122
+ Once installed, customers can authenticate using their username instead of their email address.
123
+
124
+ ```ts
125
+ await caldik.customer.login({
126
+ username: "customer",
127
+ password,
128
+ })
129
+ ```
130
+
131
+ > **Note:** Username authentication requires both the Customer Usernames plugin and password authentication to be enabled.
132
+
133
+ ## Customer Registration
134
+
135
+ Customers can register using their email address, with optional password and username support.
136
+
137
+ All registrations require email verification before the account is activated.
138
+
139
+ Password registration must be enabled in the store dashboard.
140
+
141
+ ### Email Registration
142
+
143
+ Register a customer using their email address and password.
144
+
145
+ ```ts
146
+ // Register a new customer
147
+ await caldik.customer.register({
148
+ email: "customer@example.com",
149
+ password,
150
+ })
151
+
152
+ // Verify the email using the six-digit code
153
+ await caldik.customer.register.verify(code)
154
+ ```
155
+
156
+ ### Email and Username Registration
157
+
158
+ To register customers with a username, install and enable the **Customer Usernames** plugin.
159
+
160
+ Once installed, the registration endpoint accepts an additional `username` field.
161
+
162
+ ```ts
163
+ // Register a new customer with a username
164
+ await caldik.customer.register({
165
+ email: "customer@example.com",
166
+ password,
167
+ username: "customer",
168
+ })
169
+
170
+ // Verify the email using the six-digit code
171
+ await caldik.customer.register.verify(code)
172
+ ```
173
+
174
+ > **Note:** The `username` field is provided by the Customer Usernames plugin. Omit this field when the plugin is not installed.
175
+
176
+ ## Payment Methods and Settings
177
+
178
+ Retrieve customer authentication settings, checkout configuration, and available payment methods.
179
+
180
+ ### Customer Settings
181
+
182
+ ```ts
183
+ const { settings: loginSettings } = await caldik.customer.settings.get()
184
+ ```
185
+
186
+ ### Checkout Settings
187
+
188
+ ```ts
189
+ const { settings: checkoutSettings } = await caldik.checkout.settings.get()
190
+ ```
191
+
192
+ ### Available Payment Methods
193
+
194
+ ```ts
195
+ const { paymentMethods } = await caldik.checkout.paymentmethods.list()
196
+ ```
197
+
198
+ ### Combined Example
199
+
200
+ ```ts
201
+ const { settings: loginSettings } = await caldik.customer.settings.get()
202
+
203
+ const { settings: checkoutSettings } = await caldik.checkout.settings.get()
204
+
205
+ const { paymentMethods } = await caldik.checkout.paymentmethods.list()
81
206
  ```
package/dist/index.d.mts CHANGED
@@ -139,16 +139,19 @@ interface ManualCommerceItem {
139
139
  unitAmount: string | number;
140
140
  }
141
141
  interface ProductCommerceItem {
142
+ customFields?: Record<string, string | number | boolean>;
142
143
  productId: string;
143
144
  productVariantId?: string;
144
145
  quantity?: number;
145
146
  }
146
147
  type CommerceItem = ManualCommerceItem | ProductCommerceItem;
147
148
  interface CreateOrderInput {
149
+ uiMode?: "hosted" | "elements";
150
+ returnUrl?: string;
148
151
  customerId?: string;
149
152
  email?: string;
150
153
  termsAccepted?: boolean;
151
- paymentMethod: CheckoutPaymentProviderId;
154
+ paymentMethod?: CheckoutPaymentProviderId;
152
155
  items: CommerceItem[];
153
156
  discountCode?: string;
154
157
  successUrl?: string;
@@ -157,10 +160,8 @@ interface CreateOrderInput {
157
160
  interface StorefrontOrder {
158
161
  id: string;
159
162
  shortId: string;
160
- displayId: string;
161
163
  customerId: string | null;
162
164
  paymentStatus: string;
163
- fulfillmentStatus: string;
164
165
  subtotal: string;
165
166
  amount: string;
166
167
  discount: {
@@ -171,6 +172,8 @@ interface StorefrontOrder {
171
172
  currency: string;
172
173
  }
173
174
  interface CheckoutPayment {
175
+ clientSecret?: string;
176
+ publishableKey?: string;
174
177
  type: CheckoutPaymentProviderId;
175
178
  checkoutUrl?: string | null;
176
179
  checkoutSessionId?: string | null;
@@ -223,22 +226,52 @@ interface StoreWebhookEvent<TObject extends Record<string, unknown> = Record<str
223
226
  }
224
227
  interface CustomerLoginResponse {
225
228
  success: boolean;
226
- message: string;
229
+ challengeId: string;
227
230
  }
228
231
  interface CustomerLoginVerifyResponse {
232
+ session?: {
233
+ token: string;
234
+ expiresAt: number;
235
+ };
229
236
  success: boolean;
237
+ }
238
+ interface CustomerPasswordResponse extends CustomerLoginVerifyResponse {
230
239
  customer: {
231
240
  id: string;
232
241
  shortId: string;
233
242
  displayId: string;
234
243
  email: string | null;
235
244
  status: string;
245
+ extensions?: Record<string, Record<string, string | number | boolean>>;
236
246
  };
237
247
  }
238
248
  interface CustomerPasswordInput {
249
+ /** A username from an installed identity plugin, or the customer's email. */
239
250
  username: string;
240
251
  password: string;
241
252
  }
253
+ interface CustomerRegistrationInput {
254
+ email: string;
255
+ password?: string;
256
+ /** Available when the store installs Customer Usernames. */
257
+ username?: string;
258
+ [pluginField: string]: string | number | boolean | undefined;
259
+ }
260
+ interface CustomerRegistrationResponse extends CustomerLoginResponse {
261
+ expiresAt: number;
262
+ }
263
+ interface CustomerProfileResponse {
264
+ success: boolean;
265
+ customer: {
266
+ id: string;
267
+ email: string | null;
268
+ extensions?: Record<string, Record<string, string | number | boolean>>;
269
+ };
270
+ balances: Array<{
271
+ currency: string;
272
+ amount: string;
273
+ }>;
274
+ }
242
275
  interface CustomerLoginSettings {
243
276
  passwordEnabled: boolean;
244
277
  }
@@ -247,6 +280,9 @@ interface CustomerLoginSettingsResponse {
247
280
  settings: CustomerLoginSettings;
248
281
  }
249
282
  interface CheckoutSettings {
283
+ termsUrl?: string | null;
284
+ refundPolicyUrl?: string | null;
285
+ embedStripeMode: "elements" | "hosted" | "popup";
250
286
  requireEmail: boolean;
251
287
  requireTermsAcceptance: boolean;
252
288
  }
@@ -344,12 +380,21 @@ declare class CustomerApi {
344
380
  readonly settings: {
345
381
  get: () => Promise<CustomerLoginSettingsResponse>;
346
382
  };
383
+ readonly login: {
384
+ (email: string): Promise<CustomerLoginResponse>;
385
+ (input: CustomerPasswordInput): Promise<CustomerPasswordResponse>;
386
+ } & {
387
+ /** Pass challengeId to resume a code request after reloading the page. */verify: (code: string, challengeId?: string | undefined) => Promise<CustomerLoginVerifyResponse>;
388
+ };
389
+ readonly register: {
390
+ (email: string): Promise<CustomerRegistrationResponse>;
391
+ (input: CustomerRegistrationInput): Promise<CustomerRegistrationResponse>;
392
+ } & {
393
+ /** Verify the email and atomically activate the account. Supports resuming after a reload. */verify: (code: string, challengeId?: string | undefined) => Promise<CustomerPasswordResponse>;
394
+ };
347
395
  constructor(client: CaldikHttpClient);
348
- login(input: CustomerPasswordInput): Promise<CustomerLoginVerifyResponse>;
349
- /** Set or reset credentials after signing in with an email code. Requires a customer session. */
350
- setPassword(input: CustomerPasswordInput): Promise<CustomerLoginVerifyResponse>;
351
- requestLogin(email: string): Promise<CustomerLoginResponse>;
352
- verifyLogin(code: string): Promise<CustomerLoginVerifyResponse>;
396
+ /** Read the signed-in customer and their balances. */
397
+ me(): Promise<CustomerProfileResponse>;
353
398
  }
354
399
  //#endregion
355
400
  //#region src/subscriptions.d.ts
@@ -442,4 +487,4 @@ declare class CaldikClient {
442
487
  constructor(options?: CaldikClientOptions);
443
488
  }
444
489
  //#endregion
445
- export { AppliedDiscount, CaldikClient, CaldikClientOptions, CartApi, CartCheckoutInput, CartDiscount, CartItem, CartSnapshot, CategoriesResponse, Category, CategoryDetails, CategoryMetadata, CategoryProduct, CategoryResponse, CheckDiscountInput, CheckoutPayment, CheckoutPaymentMethod, CheckoutPaymentMethodsResponse, CheckoutPaymentProviderId, CheckoutSettings, CheckoutSettingsResponse, CommerceItem, CreateOrderInput, CreateSubscriptionInput, CustomerLoginResponse, CustomerLoginSettings, CustomerLoginSettingsResponse, CustomerLoginVerifyResponse, CustomerPasswordInput, DiscountQuoteResponse, DiscountsApi, ManualCommerceItem, OrderResponse, PaymentProviderId, Product, ProductCommerceItem, ProductCustomField, ProductCustomFieldInputType, ProductCustomFieldOption, ProductMetadata, ProductResponse, ProductTag, ProductVariant, ProductsResponse, Review, ReviewsResponse, Store, StoreResponse, StoreWebhookEvent, StoreWebhookEventName, StorefrontMetadata, StorefrontOrder, SubscriptionPaymentProviderId, SubscriptionResponse, checkoutPaymentProviderIds, paymentProviderIds, storeWebhookEventNames, subscriptionPaymentProviderIds };
490
+ export { AppliedDiscount, CaldikClient, CaldikClientOptions, CartApi, CartCheckoutInput, CartDiscount, CartItem, CartSnapshot, CategoriesResponse, Category, CategoryDetails, CategoryMetadata, CategoryProduct, CategoryResponse, CheckDiscountInput, CheckoutPayment, CheckoutPaymentMethod, CheckoutPaymentMethodsResponse, CheckoutPaymentProviderId, CheckoutSettings, CheckoutSettingsResponse, CommerceItem, CreateOrderInput, CreateSubscriptionInput, CustomerLoginResponse, CustomerLoginSettings, CustomerLoginSettingsResponse, CustomerLoginVerifyResponse, CustomerPasswordInput, CustomerPasswordResponse, CustomerProfileResponse, CustomerRegistrationInput, CustomerRegistrationResponse, DiscountQuoteResponse, DiscountsApi, ManualCommerceItem, OrderResponse, PaymentProviderId, Product, ProductCommerceItem, ProductCustomField, ProductCustomFieldInputType, ProductCustomFieldOption, ProductMetadata, ProductResponse, ProductTag, ProductVariant, ProductsResponse, Review, ReviewsResponse, Store, StoreResponse, StoreWebhookEvent, StoreWebhookEventName, StorefrontMetadata, StorefrontOrder, SubscriptionPaymentProviderId, SubscriptionResponse, checkoutPaymentProviderIds, paymentProviderIds, storeWebhookEventNames, subscriptionPaymentProviderIds };
package/dist/index.mjs CHANGED
@@ -176,22 +176,52 @@ var CheckoutApi = class {
176
176
  var CustomerApi = class {
177
177
  client;
178
178
  settings;
179
+ login;
180
+ register;
179
181
  constructor(client) {
180
182
  this.client = client;
181
183
  this.settings = { get: () => this.client.get("/customers/settings", void 0, { access: "public" }) };
182
- }
183
- login(input) {
184
- return this.client.post("/customers/login/password", input, { access: "public" });
185
- }
186
- /** Set or reset credentials after signing in with an email code. Requires a customer session. */
187
- setPassword(input) {
188
- return this.client.post("/customers/password", input, { access: "public" });
189
- }
190
- requestLogin(email) {
191
- return this.client.post("/customers/login", { email }, { access: "public" });
192
- }
193
- verifyLogin(code) {
194
- return this.client.post("/customers/login/verify", { code }, { access: "public" });
184
+ let pendingChallengeId;
185
+ async function login(input) {
186
+ if (typeof input !== "string") return client.post("/customers/login/password", input, { access: "public" });
187
+ const response = await client.post("/customers/login", { email: input }, { access: "public" });
188
+ pendingChallengeId = response.challengeId;
189
+ return response;
190
+ }
191
+ this.login = Object.assign(login, {
192
+ /** Pass challengeId to resume a code request after reloading the page. */
193
+ verify: async (code, challengeId = pendingChallengeId) => {
194
+ if (!/^\d{6}$/.test(code)) throw new Error("A six-digit login code is required");
195
+ if (!challengeId) throw new Error("Request a login code first or provide its challengeId");
196
+ const response = await client.post("/customers/login/verify", {
197
+ code,
198
+ challengeId
199
+ }, { access: "public" });
200
+ if (pendingChallengeId === challengeId) pendingChallengeId = void 0;
201
+ return response;
202
+ } });
203
+ let pendingRegistrationId;
204
+ async function register(input) {
205
+ const response = await client.post("/customers/register", typeof input === "string" ? { email: input } : input, { access: "public" });
206
+ pendingRegistrationId = response.challengeId;
207
+ return response;
208
+ }
209
+ this.register = Object.assign(register, {
210
+ /** Verify the email and atomically activate the account. Supports resuming after a reload. */
211
+ verify: async (code, challengeId = pendingRegistrationId) => {
212
+ if (!/^\d{6}$/.test(code)) throw new Error("A six-digit registration code is required");
213
+ if (!challengeId) throw new Error("Request a registration code first or provide its challengeId");
214
+ const response = await client.post("/customers/register/verify", {
215
+ code,
216
+ challengeId
217
+ }, { access: "public" });
218
+ if (pendingRegistrationId === challengeId) pendingRegistrationId = void 0;
219
+ return response;
220
+ } });
221
+ }
222
+ /** Read the signed-in customer and their balances. */
223
+ me() {
224
+ return this.client.get("/customers/me", void 0, { access: "public" });
195
225
  }
196
226
  };
197
227
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caldik/client",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.mts",