@slyxup/core 1.2.0 → 2.0.1

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
@@ -56,6 +56,18 @@ await client.accounts.unlink(accountId, 'google');
56
56
  const me = await client.users.me(); // full profile (includes username, twoFactorEnabled)
57
57
  await client.users.update({ firstName: 'Ada', username: 'ada' });
58
58
  await client.users.delete(); // GDPR delete
59
+
60
+ // ── Billing ── (import { createBillingClient } from '@slyxup/core')
61
+ import { createBillingClient } from '@slyxup/core';
62
+ const billing = createBillingClient({ publishableKey: 'pk_live_xxx' });
63
+ const plans = await billing.listPlans(projectId);
64
+ const { transactionId, checkoutUrl } = await billing.checkout(planId, {
65
+ origin: 'https://your-app.com/billing/done', // return target after payment
66
+ openIn: '_blank', // or '_self' / manualOpen: true
67
+ });
68
+ // After payment, verify server-side before gating features:
69
+ const { paid, status } = await billing.getTransaction(transactionId);
70
+ const sub = await billing.getSubscription(projectId); // null when none
59
71
  ```
60
72
 
61
73
  The client keeps an internal cookie jar, so sign-in state persists across calls in **Node/SSR too** (browsers manage cookies natively).
@@ -109,11 +121,16 @@ try {
109
121
  | `users.me()` | GET | `/v1/user` |
110
122
  | `users.update(patch)` | PATCH | `/v1/user` |
111
123
  | `users.delete()` | DELETE | `/v1/user` |
124
+ | `billing.listPlans(projectId)` | GET | `/v1/billing/plans` |
125
+ | `billing.checkout(planId, { origin })` | POST | `/v1/billing/checkout` |
126
+ | `billing.getTransaction(txnId)` | GET | `/v1/billing/transactions/:id` |
127
+ | `billing.getSubscription(projectId?)` | GET | `/v1/billing/subscription` |
128
+ | `billing.getEntitlements(projectId)` | GET | `/v1/billing/entitlements` |
129
+ | `billing.cancelSubscription(projectId?)` | POST | `/v1/billing/subscription/cancel` |
130
+ | `billing.listInvoices()` | GET | `/v1/billing/invoices` |
112
131
 
113
132
  ## Framework wrappers
114
133
 
115
- - React hooks/components: [`@slyxup/react`](../react)
116
- - Next.js server helpers + middleware: [`@slyxup/nextjs`](../nextjs)
117
134
  - Prebuilt UI cards: [`@slyxup/ui`](../ui)
118
135
 
119
136
  ## License
@@ -0,0 +1,84 @@
1
+ export interface Plan {
2
+ id: string;
3
+ name: string;
4
+ paddlePriceId: string;
5
+ amount: number;
6
+ currency: string;
7
+ interval: 'month' | 'year';
8
+ trialDays: number | null;
9
+ features: string[];
10
+ isPopular: boolean;
11
+ }
12
+ export interface Subscription {
13
+ id: string;
14
+ projectId: string;
15
+ userId: string;
16
+ planId: string;
17
+ status: 'active' | 'trialing' | 'past_due' | 'paused' | 'canceled';
18
+ currentPeriodStart: string | null;
19
+ currentPeriodEnd: string | null;
20
+ cancelAtPeriodEnd: boolean;
21
+ }
22
+ export interface Invoice {
23
+ id: string;
24
+ amount: number;
25
+ currency: string;
26
+ status: 'paid' | 'pending' | 'overdue' | 'refunded';
27
+ invoiceNumber: string | null;
28
+ billedAt: string | null;
29
+ }
30
+ export interface CheckoutResult {
31
+ transactionId: string;
32
+ checkoutUrl: string;
33
+ }
34
+ export interface CheckoutOptions {
35
+ /** Return target carried through payment → success page (e.g. your app URL).
36
+ * Without it the buyer lands on the SlyxUp dashboard after paying. */
37
+ origin?: string;
38
+ /** Open the payment page in a new tab (default) or the same tab. */
39
+ openIn?: '_blank' | '_self';
40
+ /** Skip auto-opening the payment page (you open checkoutUrl yourself,
41
+ * or use the transactionId with Paddle.js overlay). */
42
+ manualOpen?: boolean;
43
+ }
44
+ export interface TransactionStatus {
45
+ id: string;
46
+ status: string;
47
+ paid: boolean;
48
+ checkoutUrl: string | null;
49
+ }
50
+ export interface BillingClientOptions {
51
+ apiUrl?: string;
52
+ publishableKey?: string;
53
+ }
54
+ export declare class BillingClient {
55
+ readonly apiUrl: string;
56
+ readonly publishableKey?: string;
57
+ constructor(options?: BillingClientOptions);
58
+ private req;
59
+ listPlans(projectId: string): Promise<Plan[]>;
60
+ getSubscription(projectId?: string): Promise<Subscription | null>;
61
+ getEntitlements(projectId: string): Promise<{
62
+ planId: string | null;
63
+ status: string;
64
+ features: string[];
65
+ }>;
66
+ /**
67
+ * Create a checkout transaction and open the real Paddle payment page.
68
+ * Returns the transaction id + payment URL. The buyer pays on the opened
69
+ * page; the subscription activates via webhook — never trust a redirect
70
+ * URL alone, verify with getTransaction() before gating features.
71
+ */
72
+ checkout(planId: string, opts?: CheckoutOptions & {
73
+ successUrl?: string;
74
+ }): Promise<CheckoutResult>;
75
+ /**
76
+ * Verify a checkout transaction with Paddle (public, capability-token).
77
+ * `paid === true` only when Paddle reports the transaction `completed`.
78
+ */
79
+ getTransaction(transactionId: string): Promise<TransactionStatus>;
80
+ cancelSubscription(projectId?: string): Promise<void>;
81
+ listInvoices(): Promise<Invoice[]>;
82
+ }
83
+ export declare function createBillingClient(options?: Partial<BillingClientOptions>): BillingClient;
84
+ //# sourceMappingURL=billing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing.d.ts","sourceRoot":"","sources":["../src/billing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ // Billing client — import from '@slyxup/core'.
2
+ function getEnvApiUrl() {
3
+ try {
4
+ const billingUrl = typeof process !== 'undefined'
5
+ ? process?.env?.NEXT_PUBLIC_SLYXUP_BILLING_URL
6
+ : undefined;
7
+ if (billingUrl)
8
+ return billingUrl;
9
+ }
10
+ catch { }
11
+ try {
12
+ const viteEnv = import.meta?.env;
13
+ if (viteEnv?.VITE_SLYXUP_BILLING_URL)
14
+ return viteEnv.VITE_SLYXUP_BILLING_URL;
15
+ }
16
+ catch { }
17
+ try {
18
+ const authUrl = typeof process !== 'undefined'
19
+ ? process?.env?.NEXT_PUBLIC_SLYXUP_API_URL
20
+ : undefined;
21
+ if (authUrl)
22
+ return authUrl.replace('auth.slyxup.online', 'billing.slyxup.online');
23
+ }
24
+ catch { }
25
+ return undefined;
26
+ }
27
+ function getStoredToken() {
28
+ try {
29
+ if (typeof window !== 'undefined' && window.localStorage) {
30
+ return window.localStorage.getItem('slyxup_session_token') ?? undefined;
31
+ }
32
+ }
33
+ catch { }
34
+ return undefined;
35
+ }
36
+ export class BillingClient {
37
+ apiUrl;
38
+ publishableKey;
39
+ constructor(options = {}) {
40
+ const raw = (options.apiUrl ??
41
+ getEnvApiUrl() ??
42
+ 'https://billing.slyxup.online').replace(/\/$/, '');
43
+ if (/^https?:\/\/localhost:\d+$/.test(raw) && raw.includes(':8787')) {
44
+ this.apiUrl = raw.replace(/:8787$/, ':8788');
45
+ }
46
+ else {
47
+ this.apiUrl = raw;
48
+ }
49
+ this.publishableKey = options.publishableKey;
50
+ }
51
+ async req(path, init) {
52
+ const token = getStoredToken();
53
+ const authHeaders = {};
54
+ if (token)
55
+ authHeaders.Authorization = `Bearer ${token}`;
56
+ if (this.publishableKey && this.publishableKey !== 'pk_test_missing')
57
+ authHeaders['X-Publishable-Key'] = this.publishableKey;
58
+ const res = await fetch(`${this.apiUrl}${path}`, {
59
+ ...init,
60
+ headers: {
61
+ 'Content-Type': 'application/json',
62
+ ...authHeaders,
63
+ ...init?.headers,
64
+ },
65
+ credentials: 'include',
66
+ });
67
+ if (!res.ok) {
68
+ const data = (await res.json().catch(() => ({})));
69
+ throw new Error(typeof data.error === 'string'
70
+ ? data.error
71
+ : `Request failed (${res.status})`);
72
+ }
73
+ return res.json();
74
+ }
75
+ async listPlans(projectId) {
76
+ const res = await this.req(`/v1/billing/plans?projectId=${projectId}`);
77
+ return res.plans;
78
+ }
79
+ async getSubscription(projectId) {
80
+ const qs = projectId ? `?projectId=${projectId}` : '';
81
+ const res = await this.req(`/v1/billing/subscription${qs}`);
82
+ return res.subscription;
83
+ }
84
+ async getEntitlements(projectId) {
85
+ const res = await this.req(`/v1/billing/entitlements?projectId=${projectId}`);
86
+ return { planId: res.planId, status: res.status, features: res.features };
87
+ }
88
+ /**
89
+ * Create a checkout transaction and open the real Paddle payment page.
90
+ * Returns the transaction id + payment URL. The buyer pays on the opened
91
+ * page; the subscription activates via webhook — never trust a redirect
92
+ * URL alone, verify with getTransaction() before gating features.
93
+ */
94
+ async checkout(planId, opts) {
95
+ const res = await this.req('/v1/billing/checkout', {
96
+ method: 'POST',
97
+ body: JSON.stringify({
98
+ planId,
99
+ ...(opts?.origin ? { origin: opts.origin } : {}),
100
+ // successUrl is legacy/ignored by the server for link building.
101
+ ...(opts?.successUrl ? { successUrl: opts.successUrl } : {}),
102
+ }),
103
+ });
104
+ if (!opts?.manualOpen && res.checkoutUrl && typeof window !== 'undefined') {
105
+ const target = opts?.openIn ?? '_blank';
106
+ if (target === '_blank') {
107
+ window.open(res.checkoutUrl, '_blank', 'noopener,noreferrer');
108
+ }
109
+ else {
110
+ window.location.assign(res.checkoutUrl);
111
+ }
112
+ }
113
+ return res;
114
+ }
115
+ /**
116
+ * Verify a checkout transaction with Paddle (public, capability-token).
117
+ * `paid === true` only when Paddle reports the transaction `completed`.
118
+ */
119
+ async getTransaction(transactionId) {
120
+ return this.req(`/v1/billing/transactions/${encodeURIComponent(transactionId)}`);
121
+ }
122
+ async cancelSubscription(projectId) {
123
+ const qs = projectId ? `?projectId=${projectId}` : '';
124
+ await this.req(`/v1/billing/subscription/cancel${qs}`, { method: 'POST' });
125
+ }
126
+ async listInvoices() {
127
+ const res = await this.req('/v1/billing/invoices');
128
+ return res.invoices;
129
+ }
130
+ }
131
+ export function createBillingClient(options) {
132
+ return new BillingClient(options);
133
+ }
134
+ //# sourceMappingURL=billing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing.js","sourceRoot":"","sources":["../src/billing.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  export { SlyxupClient } from './client.js';
2
2
  export * from './types.js';
3
3
  export * from './errors.js';
4
+ export * from './billing.js';
5
+ export * from './manage.js';
6
+ export * from './next.js';
4
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,7 @@
1
1
  export { SlyxupClient } from './client.js';
2
2
  export * from './types.js';
3
3
  export * from './errors.js';
4
+ export * from './billing.js';
5
+ export * from './manage.js';
6
+ export * from './next.js';
4
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC"}
@@ -0,0 +1,70 @@
1
+ export interface ManagedProject {
2
+ id: string;
3
+ name: string;
4
+ slug: string;
5
+ description: string | null;
6
+ }
7
+ export interface ManagedKey {
8
+ id: string;
9
+ name: string;
10
+ prefix: string;
11
+ environment: 'test' | 'live';
12
+ type: 'publishable' | 'secret';
13
+ }
14
+ export declare function manageApi(apiUrl: string, token: string): {
15
+ listProjects: () => Promise<{
16
+ ok: true;
17
+ projects: ManagedProject[];
18
+ }>;
19
+ createProject: (input: {
20
+ name: string;
21
+ slug: string;
22
+ description?: string;
23
+ }) => Promise<{
24
+ ok: true;
25
+ project: ManagedProject;
26
+ }>;
27
+ deleteProject: (id: string) => Promise<{
28
+ ok: true;
29
+ }>;
30
+ listKeys: (projectId: string) => Promise<{
31
+ ok: true;
32
+ keys: ManagedKey[];
33
+ }>;
34
+ createKey: (input: {
35
+ projectId: string;
36
+ name: string;
37
+ type: "publishable" | "secret";
38
+ environment: "test" | "live";
39
+ }) => Promise<{
40
+ ok: true;
41
+ id: string;
42
+ key: string;
43
+ prefix: string;
44
+ }>;
45
+ revokeKey: (id: string) => Promise<{
46
+ ok: true;
47
+ }>;
48
+ listDomains: (projectId: string) => Promise<{
49
+ ok: true;
50
+ environment: string;
51
+ domains: string[];
52
+ }>;
53
+ addDomain: (projectId: string, domain: string) => Promise<{
54
+ ok: true;
55
+ domains: string[];
56
+ }>;
57
+ removeDomain: (projectId: string, domain: string) => Promise<{
58
+ ok: true;
59
+ domains: string[];
60
+ }>;
61
+ goLive: (projectId: string) => Promise<{
62
+ ok: true;
63
+ environment: string;
64
+ }>;
65
+ doctor: () => Promise<{
66
+ ok: boolean;
67
+ apiUrl: string;
68
+ }>;
69
+ };
70
+ //# sourceMappingURL=manage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manage.d.ts","sourceRoot":"","sources":["../src/manage.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,IAAI,EAAE,aAAa,GAAG,QAAQ,CAAC;CAChC;AA2BD,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;YAIvC,IAAI;kBAAY,cAAc,EAAE;;2BAMrB;QACrB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB;YACW,IAAI;iBAAW,cAAc;;wBAOrB,MAAM;YACd,IAAI;;0BACM,MAAM;YAChB,IAAI;cAAQ,UAAU,EAAE;;uBAMjB;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,aAAa,GAAG,QAAQ,CAAC;QAC/B,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;KAC9B;YACW,IAAI;YAAM,MAAM;aAAO,MAAM;gBAAU,MAAM;;oBAOzC,MAAM;YACV,IAAI;;6BACS,MAAM;YACnB,IAAI;qBAAe,MAAM;iBAAW,MAAM,EAAE;;2BAMjC,MAAM,UAAU,MAAM;YACjC,IAAI;iBAAW,MAAM,EAAE;;8BAOT,MAAM,UAAU,MAAM;YACpC,IAAI;iBAAW,MAAM,EAAE;;wBAOf,MAAM;YACd,IAAI;qBAAe,MAAM;;;;;;EAexC"}
package/dist/manage.js ADDED
@@ -0,0 +1,42 @@
1
+ // Project/keys/domains management API — callable from web UI or any client.
2
+ async function req(apiUrl, token, method, path, body) {
3
+ const res = await fetch(`${apiUrl}${path}`, {
4
+ method,
5
+ headers: {
6
+ 'Content-Type': 'application/json',
7
+ Authorization: `Bearer ${token}`,
8
+ },
9
+ body: body === undefined ? undefined : JSON.stringify(body),
10
+ });
11
+ const data = (await res.json().catch(() => ({})));
12
+ if (!res.ok)
13
+ throw new Error(typeof data.error === 'string'
14
+ ? data.error
15
+ : `Request failed (${res.status})`);
16
+ return data;
17
+ }
18
+ export function manageApi(apiUrl, token) {
19
+ const base = apiUrl.replace(/\/$/, '');
20
+ return {
21
+ listProjects: () => req(base, token, 'GET', '/v1/projects'),
22
+ createProject: (input) => req(base, token, 'POST', '/v1/projects', input),
23
+ deleteProject: (id) => req(base, token, 'DELETE', `/v1/projects/${id}`),
24
+ listKeys: (projectId) => req(base, token, 'GET', `/v1/keys?projectId=${projectId}`),
25
+ createKey: (input) => req(base, token, 'POST', '/v1/keys', input),
26
+ revokeKey: (id) => req(base, token, 'DELETE', `/v1/keys/${id}`),
27
+ listDomains: (projectId) => req(base, token, 'GET', `/v1/projects/${projectId}/domains`),
28
+ addDomain: (projectId, domain) => req(base, token, 'PATCH', `/v1/projects/${projectId}/domains`, { action: 'add', domain }),
29
+ removeDomain: (projectId, domain) => req(base, token, 'PATCH', `/v1/projects/${projectId}/domains`, { action: 'remove', domain }),
30
+ goLive: (projectId) => req(base, token, 'POST', `/v1/projects/${projectId}/go-live`),
31
+ doctor: async () => {
32
+ try {
33
+ const r = await fetch(`${base}/v1/health`);
34
+ return { ok: r.ok, apiUrl: base };
35
+ }
36
+ catch {
37
+ return { ok: false, apiUrl: base };
38
+ }
39
+ },
40
+ };
41
+ }
42
+ //# sourceMappingURL=manage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manage.js","sourceRoot":"","sources":["../src/manage.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAiB5E,KAAK,UAAU,GAAG,CAChB,MAAc,EACd,KAAa,EACb,MAAc,EACd,IAAY,EACZ,IAAc;IAEd,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,GAAG,IAAI,EAAE,EAAE;QAC1C,MAAM;QACN,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,KAAK,EAAE;SACjC;QACD,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC5D,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAA4B,CAAC;IAC7E,IAAI,CAAC,GAAG,CAAC,EAAE;QACT,MAAM,IAAI,KAAK,CACb,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;YAC5B,CAAC,CAAC,IAAI,CAAC,KAAK;YACZ,CAAC,CAAC,mBAAmB,GAAG,CAAC,MAAM,GAAG,CACrC,CAAC;IACJ,OAAO,IAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAc,EAAE,KAAa;IACrD,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACvC,OAAO;QACL,YAAY,EAAE,GAAG,EAAE,CACjB,GAAG,CACD,IAAI,EACJ,KAAK,EACL,KAAK,EACL,cAAc,CACf;QACH,aAAa,EAAE,CAAC,KAIf,EAAE,EAAE,CACH,GAAG,CACD,IAAI,EACJ,KAAK,EACL,MAAM,EACN,cAAc,EACd,KAAK,CACN;QACH,aAAa,EAAE,CAAC,EAAU,EAAE,EAAE,CAC5B,GAAG,CAAe,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,EAAE,CAAC;QAChE,QAAQ,EAAE,CAAC,SAAiB,EAAE,EAAE,CAC9B,GAAG,CACD,IAAI,EACJ,KAAK,EACL,KAAK,EACL,sBAAsB,SAAS,EAAE,CAClC;QACH,SAAS,EAAE,CAAC,KAKX,EAAE,EAAE,CACH,GAAG,CACD,IAAI,EACJ,KAAK,EACL,MAAM,EACN,UAAU,EACV,KAAK,CACN;QACH,SAAS,EAAE,CAAC,EAAU,EAAE,EAAE,CACxB,GAAG,CAAe,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,CAAC;QAC5D,WAAW,EAAE,CAAC,SAAiB,EAAE,EAAE,CACjC,GAAG,CACD,IAAI,EACJ,KAAK,EACL,KAAK,EACL,gBAAgB,SAAS,UAAU,CACpC;QACH,SAAS,EAAE,CAAC,SAAiB,EAAE,MAAc,EAAE,EAAE,CAC/C,GAAG,CACD,IAAI,EACJ,KAAK,EACL,OAAO,EACP,gBAAgB,SAAS,UAAU,EACnC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAC1B;QACH,YAAY,EAAE,CAAC,SAAiB,EAAE,MAAc,EAAE,EAAE,CAClD,GAAG,CACD,IAAI,EACJ,KAAK,EACL,OAAO,EACP,gBAAgB,SAAS,UAAU,EACnC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAC7B;QACH,MAAM,EAAE,CAAC,SAAiB,EAAE,EAAE,CAC5B,GAAG,CACD,IAAI,EACJ,KAAK,EACL,MAAM,EACN,gBAAgB,SAAS,UAAU,CACpC;QACH,MAAM,EAAE,KAAK,IAAI,EAAE;YACjB,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,YAAY,CAAC,CAAC;gBAC3C,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YACrC,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
package/dist/next.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ export declare const SESSION_COOKIE_NAME = "slyxup_session";
2
+ export interface SlyxupNextOptions {
3
+ apiUrl?: string;
4
+ publishableKey?: string;
5
+ }
6
+ export declare function createSessionCookie(token: string, maxAge?: number): string;
7
+ export declare function clearSessionCookie(): string;
8
+ export interface SlyxupMiddlewareOptions extends SlyxupNextOptions {
9
+ publicRoutes?: string[];
10
+ }
11
+ export declare function slyxupMiddleware(options?: SlyxupMiddlewareOptions): (req: {
12
+ cookies?: Record<string, string>;
13
+ url: string;
14
+ }) => {
15
+ redirect: "/sign-in";
16
+ next?: undefined;
17
+ } | {
18
+ next: true;
19
+ redirect?: undefined;
20
+ };
21
+ //# sourceMappingURL=next.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AAEpD,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAMD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,SAAmB,GACxB,MAAM,CAER;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,uBAAuB,IACrC,KAAK;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,GAAG,EAAE,MAAM,CAAC;CACb;;;;;;EAQF"}
package/dist/next.js ADDED
@@ -0,0 +1,21 @@
1
+ // Server helpers + middleware + cookies — import from '@slyxup/core/next'.
2
+ export const SESSION_COOKIE_NAME = 'slyxup_session';
3
+ function baseApiUrl(_options) {
4
+ return 'https://auth.slyxup.online';
5
+ }
6
+ export function createSessionCookie(token, maxAge = 7 * 24 * 60 * 60) {
7
+ return `${SESSION_COOKIE_NAME}=${token}; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=${maxAge}`;
8
+ }
9
+ export function clearSessionCookie() {
10
+ return `${SESSION_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`;
11
+ }
12
+ export function slyxupMiddleware(options) {
13
+ return function middleware(req) {
14
+ const token = req.cookies?.[SESSION_COOKIE_NAME];
15
+ const isPublic = (options?.publicRoutes ?? ['/sign-in', '/']).some((r) => req.url.includes(r));
16
+ if (!token && !isPublic)
17
+ return { redirect: '/sign-in' };
18
+ return { next: true };
19
+ };
20
+ }
21
+ //# sourceMappingURL=next.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next.js","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAE3E,MAAM,CAAC,MAAM,mBAAmB,GAAG,gBAAgB,CAAC;AAOpD,SAAS,UAAU,CAAC,QAA4B;IAC9C,OAAO,4BAA4B,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,KAAa,EACb,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;IAEzB,OAAO,GAAG,mBAAmB,IAAI,KAAK,qDAAqD,MAAM,EAAE,CAAC;AACtG,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,GAAG,mBAAmB,sDAAsD,CAAC;AACtF,CAAC;AAMD,MAAM,UAAU,gBAAgB,CAAC,OAAiC;IAChE,OAAO,SAAS,UAAU,CAAC,GAG1B;QACC,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,mBAAmB,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,YAAY,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACvE,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CACpB,CAAC;QACF,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ;YAAE,OAAO,EAAE,QAAQ,EAAE,UAAmB,EAAE,CAAC;QAClE,OAAO,EAAE,IAAI,EAAE,IAAa,EAAE,CAAC;IACjC,CAAC,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slyxup/core",
3
- "version": "1.2.0",
3
+ "version": "2.0.1",
4
4
  "description": "@slyxup/core — SlyxUp SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",