@jsontech/sdk-js 0.0.5 → 0.0.7

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,130 @@
1
+ # @jsontech/sdk-js
2
+
3
+ JavaScript/TypeScript SDK for ShipIt feature flags.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @jsontech/sdk-js
9
+ # or
10
+ pnpm add @jsontech/sdk-js
11
+ # or
12
+ yarn add @jsontech/sdk-js
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### Basic Example
18
+
19
+ ```typescript
20
+ import { ShipItClient } from '@jsontech/sdk-js';
21
+
22
+ // SDK automatically uses production API URL
23
+ // Set SHIPIT_CLIENT_KEY or SHIPIT_SERVER_KEY env var, or pass sdkKey explicitly
24
+ const shipit = new ShipItClient({
25
+ sdkKey: 'shipit_srv_...' // or shipit_cli_...
26
+ });
27
+
28
+ const enabled = await shipit.bool('new-nav', { id: 'user-123' }, false);
29
+ console.log(enabled);
30
+ ```
31
+
32
+ ### Environment Variables
33
+
34
+ The SDK automatically reads from environment variables if `sdkKey` is not provided:
35
+
36
+ - `SHIPIT_CLIENT_KEY` - Client SDK key (for browser/mobile)
37
+ - `SHIPIT_SERVER_KEY` - Server SDK key (for backend)
38
+
39
+ ```typescript
40
+ // In Node.js, this will use SHIPIT_CLIENT_KEY or SHIPIT_SERVER_KEY from env
41
+ const shipit = new ShipItClient();
42
+ ```
43
+
44
+ ### API Base URL
45
+
46
+ The SDK automatically determines the API base URL:
47
+
48
+ - **Browser**: Uses `window.location.origin` (assumes API is on same origin)
49
+ - **Node.js**: Uses `https://shipit-api-246728836834.us-central1.run.app`
50
+
51
+ The API URL cannot be overridden.
52
+
53
+ ### User Payload
54
+
55
+ ```typescript
56
+ import { ShipItClient, type ShipItUserPayload } from '@jsontech/sdk-js';
57
+
58
+ const user: ShipItUserPayload = {
59
+ id: 'user-123', // Required: unique user identifier
60
+ email: 'user@example.com',
61
+ name: 'John Doe',
62
+ country: 'US',
63
+ meta: { // Custom attributes for targeting
64
+ companyId: 'acme',
65
+ plan: 'pro'
66
+ }
67
+ };
68
+
69
+ const enabled = await shipit.bool('feature-flag', user, false);
70
+ ```
71
+
72
+ ## API Reference
73
+
74
+ ### `ShipItClient`
75
+
76
+ #### Constructor
77
+
78
+ ```typescript
79
+ new ShipItClient(options?: ShipItClientOptions)
80
+ ```
81
+
82
+ **Options:**
83
+
84
+ - `sdkKey?: string` - SDK key (client or server). If not provided, reads from `SHIPIT_CLIENT_KEY` or `SHIPIT_SERVER_KEY` env vars.
85
+ - `projectKey?: string` - Legacy: project key (requires `envKey`). Not recommended.
86
+ - `envKey?: string` - Environment key (default: `'production'`). Only used with `projectKey`.
87
+
88
+ #### Methods
89
+
90
+ ##### `bool(flagKey: string, user: ShipItUserPayload, defaultValue?: boolean): Promise<boolean>`
91
+
92
+ Evaluates a boolean feature flag for a user.
93
+
94
+ - `flagKey`: The flag key to evaluate
95
+ - `user`: User payload with `id` or `key` (required)
96
+ - `defaultValue`: Default value if evaluation fails (default: `false`)
97
+
98
+ Returns `Promise<boolean>` - The flag value for the user.
99
+
100
+ **Example:**
101
+
102
+ ```typescript
103
+ const enabled = await shipit.bool('new-nav', { id: 'user-123' }, false);
104
+ ```
105
+
106
+ ## Error Handling
107
+
108
+ If the API request fails (network error, non-2xx status), the SDK returns the `defaultValue`. Network errors (DNS, timeout, connection refused) will throw; wrap calls in `try/catch` if you want to handle them.
109
+
110
+ ```typescript
111
+ try {
112
+ const enabled = await shipit.bool('flag', user, false);
113
+ } catch (error) {
114
+ // Handle network errors
115
+ console.error('Failed to evaluate flag:', error);
116
+ }
117
+ ```
118
+
119
+ ## SDK Keys
120
+
121
+ Each environment has two SDK keys:
122
+
123
+ - **Server key** (`shipit_srv_...`): Secret. Use only in trusted server environments.
124
+ - **Client key** (`shipit_cli_...`): Not a secret. Intended for browser/mobile SDKs.
125
+
126
+ Get your SDK keys from the ShipIt Console → Environments.
127
+
128
+ ## License
129
+
130
+ MIT
package/dist/index.cjs CHANGED
@@ -1,18 +1,30 @@
1
1
  'use strict';
2
2
 
3
3
  // src/index.ts
4
+ function getApiBaseUrl() {
5
+ if (typeof window !== "undefined" && typeof window.location !== "undefined") {
6
+ return window.location.origin;
7
+ }
8
+ return "https://shipit-api-246728836834.us-central1.run.app";
9
+ }
10
+ function getSdkKeyFromEnv() {
11
+ if (typeof process !== "undefined" && process.env) {
12
+ return process.env.SHIPIT_CLIENT_KEY?.trim() || process.env.SHIPIT_SERVER_KEY?.trim() || null;
13
+ }
14
+ return null;
15
+ }
4
16
  var ShipItClient = class {
5
17
  apiBaseUrl;
6
18
  sdkKey;
7
19
  projectKey;
8
20
  envKey;
9
- constructor(options) {
10
- this.apiBaseUrl = options.apiBaseUrl.replace(/\/$/, "");
11
- this.sdkKey = options.sdkKey?.trim() ? options.sdkKey.trim() : null;
21
+ constructor(options = {}) {
22
+ this.apiBaseUrl = getApiBaseUrl().replace(/\/$/, "");
23
+ this.sdkKey = options.sdkKey?.trim() || getSdkKeyFromEnv();
12
24
  this.projectKey = options.projectKey?.trim() ? options.projectKey.trim() : null;
13
25
  this.envKey = options.envKey ?? "production";
14
26
  if (!this.sdkKey && !this.projectKey) {
15
- throw new Error("ShipItClient requires either sdkKey (recommended) or projectKey (legacy).");
27
+ throw new Error("ShipItClient requires either sdkKey (recommended) or projectKey (legacy). Set SHIPIT_CLIENT_KEY or SHIPIT_SERVER_KEY env var, or pass sdkKey in options.");
16
28
  }
17
29
  }
18
30
  normalizeUser(input) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;AA6BO,IAAM,eAAN,MAAmB;AAAA,EACP,UAAA;AAAA,EACA,MAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EAEjB,YAAY,OAAA,EAA8B;AACxC,IAAA,IAAA,CAAK,UAAA,GAAa,OAAA,CAAQ,UAAA,CAAW,OAAA,CAAQ,OAAO,EAAE,CAAA;AACtD,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,MAAA,EAAQ,IAAA,KAAS,OAAA,CAAQ,MAAA,CAAO,MAAK,GAAI,IAAA;AAC/D,IAAA,IAAA,CAAK,UAAA,GAAa,QAAQ,UAAA,EAAY,IAAA,KAAS,OAAA,CAAQ,UAAA,CAAW,MAAK,GAAI,IAAA;AAC3E,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,MAAA,IAAU,YAAA;AAEhC,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,IAAU,CAAC,KAAK,UAAA,EAAY;AACpC,MAAA,MAAM,IAAI,MAAM,2EAA2E,CAAA;AAAA,IAC7F;AAAA,EACF;AAAA,EAEQ,cAAc,KAAA,EAAsC;AAC1D,IAAA,MAAM,OAAO,KAAA,CAAM,EAAA,IAAM,KAAA,CAAM,GAAA,IAAO,IAAI,IAAA,EAAK;AAC/C,IAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,qDAAqD,CAAA;AAC/E,IAAA,OAAO;AAAA,MACL,GAAA;AAAA,MACA,OAAO,KAAA,CAAM,KAAA;AAAA,MACb,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,MAAA,EAAQ,KAAA,CAAM,IAAA,IAAQ,KAAA,CAAM;AAAA,KAC9B;AAAA,EACF;AAAA,EAEA,MAAM,IAAA,CAAK,OAAA,EAAiB,IAAA,EAAyB,eAAe,KAAA,EAAyB;AAC3F,IAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,aAAA,CAAc,IAAI,CAAA;AAC9C,IAAA,MAAM,GAAA,GAAM,KAAK,MAAA,GACb,MAAM,MAAM,CAAA,EAAG,IAAA,CAAK,UAAU,CAAA,gBAAA,CAAA,EAAoB;AAAA,MAChD,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,kBAAA;AAAA,QAChB,oBAAoB,IAAA,CAAK;AAAA,OAC3B;AAAA,MACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,OAAA;AAAA,QACA,IAAA,EAAM,cAAA;AAAA,QACN;AAAA,OACD;AAAA,KACF,CAAA,GACD,MAAM,MAAM,CAAA,EAAG,IAAA,CAAK,UAAU,CAAA,YAAA,CAAA,EAAgB;AAAA,MAC5C,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,MAC9C,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,YAAY,IAAA,CAAK,UAAA;AAAA,QACjB,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,OAAA;AAAA,QACA,IAAA,EAAM,cAAA;AAAA,QACN;AAAA,OACD;AAAA,KACF,CAAA;AAEL,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,OAAO,YAAA;AACpB,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd;AACF","file":"index.cjs","sourcesContent":["export type ShipItUserPayload = {\n /** Unique user identifier (preferred). */\n id?: string;\n /** Legacy alias for id. */\n key?: string;\n email?: string;\n name?: string;\n country?: string;\n /** Queryable attributes. */\n meta?: Record<string, string | number | boolean | null>;\n /** Legacy alias for meta. */\n custom?: Record<string, string | number | boolean | null>;\n};\n\ntype ShipItUser = {\n key: string;\n email?: string;\n name?: string;\n country?: string;\n custom?: Record<string, string | number | boolean | null>;\n};\n\nexport type ShipItClientOptions = {\n apiBaseUrl: string;\n sdkKey?: string;\n projectKey?: string;\n envKey?: string;\n};\n\nexport class ShipItClient {\n private readonly apiBaseUrl: string;\n private readonly sdkKey: string | null;\n private readonly projectKey: string | null;\n private readonly envKey: string;\n\n constructor(options: ShipItClientOptions) {\n this.apiBaseUrl = options.apiBaseUrl.replace(/\\/$/, '');\n this.sdkKey = options.sdkKey?.trim() ? options.sdkKey.trim() : null;\n this.projectKey = options.projectKey?.trim() ? options.projectKey.trim() : null;\n this.envKey = options.envKey ?? 'production';\n\n if (!this.sdkKey && !this.projectKey) {\n throw new Error('ShipItClient requires either sdkKey (recommended) or projectKey (legacy).');\n }\n }\n\n private normalizeUser(input: ShipItUserPayload): ShipItUser {\n const key = (input.id ?? input.key ?? '').trim();\n if (!key) throw new Error('ShipItClient requires user.id (or legacy user.key).');\n return {\n key,\n email: input.email,\n name: input.name,\n country: input.country,\n custom: input.meta ?? input.custom\n };\n }\n\n async bool(flagKey: string, user: ShipItUserPayload, defaultValue = false): Promise<boolean> {\n const normalizedUser = this.normalizeUser(user);\n const res = this.sdkKey\n ? await fetch(`${this.apiBaseUrl}/api/v1/sdk/eval`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-shipit-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n })\n : await fetch(`${this.apiBaseUrl}/api/v1/eval`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n projectKey: this.projectKey,\n envKey: this.envKey,\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n });\n\n if (!res.ok) return defaultValue;\n const json = (await res.json()) as { value: boolean };\n return json.value;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export type ShipItUserPayload = {\n /** Unique user identifier (preferred). */\n id?: string;\n /** Legacy alias for id. */\n key?: string;\n email?: string;\n name?: string;\n country?: string;\n /** Queryable attributes. */\n meta?: Record<string, string | number | boolean | null>;\n /** Legacy alias for meta. */\n custom?: Record<string, string | number | boolean | null>;\n};\n\ntype ShipItUser = {\n key: string;\n email?: string;\n name?: string;\n country?: string;\n custom?: Record<string, string | number | boolean | null>;\n};\n\nfunction getApiBaseUrl(): string {\n // Browser: use current origin (assumes API is on same origin)\n if (typeof window !== 'undefined' && typeof (window as any).location !== 'undefined') {\n return (window as any).location.origin;\n }\n // Node.js: always use production API\n return 'https://shipit-api-246728836834.us-central1.run.app';\n}\n\nexport type ShipItClientOptions = {\n sdkKey?: string;\n projectKey?: string;\n envKey?: string;\n};\n\nfunction getSdkKeyFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return process.env.SHIPIT_CLIENT_KEY?.trim() || process.env.SHIPIT_SERVER_KEY?.trim() || null;\n }\n return null;\n}\n\nexport class ShipItClient {\n private readonly apiBaseUrl: string;\n private readonly sdkKey: string | null;\n private readonly projectKey: string | null;\n private readonly envKey: string;\n\n constructor(options: ShipItClientOptions = {}) {\n this.apiBaseUrl = getApiBaseUrl().replace(/\\/$/, '');\n this.sdkKey = options.sdkKey?.trim() || getSdkKeyFromEnv();\n this.projectKey = options.projectKey?.trim() ? options.projectKey.trim() : null;\n this.envKey = options.envKey ?? 'production';\n\n if (!this.sdkKey && !this.projectKey) {\n throw new Error('ShipItClient requires either sdkKey (recommended) or projectKey (legacy). Set SHIPIT_CLIENT_KEY or SHIPIT_SERVER_KEY env var, or pass sdkKey in options.');\n }\n }\n\n private normalizeUser(input: ShipItUserPayload): ShipItUser {\n const key = (input.id ?? input.key ?? '').trim();\n if (!key) throw new Error('ShipItClient requires user.id (or legacy user.key).');\n return {\n key,\n email: input.email,\n name: input.name,\n country: input.country,\n custom: input.meta ?? input.custom\n };\n }\n\n async bool(flagKey: string, user: ShipItUserPayload, defaultValue = false): Promise<boolean> {\n const normalizedUser = this.normalizeUser(user);\n const res = this.sdkKey\n ? await fetch(`${this.apiBaseUrl}/api/v1/sdk/eval`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-shipit-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n })\n : await fetch(`${this.apiBaseUrl}/api/v1/eval`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n projectKey: this.projectKey,\n envKey: this.envKey,\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n });\n\n if (!res.ok) return defaultValue;\n const json = (await res.json()) as { value: boolean };\n return json.value;\n }\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -12,7 +12,6 @@ type ShipItUserPayload = {
12
12
  custom?: Record<string, string | number | boolean | null>;
13
13
  };
14
14
  type ShipItClientOptions = {
15
- apiBaseUrl: string;
16
15
  sdkKey?: string;
17
16
  projectKey?: string;
18
17
  envKey?: string;
@@ -22,7 +21,7 @@ declare class ShipItClient {
22
21
  private readonly sdkKey;
23
22
  private readonly projectKey;
24
23
  private readonly envKey;
25
- constructor(options: ShipItClientOptions);
24
+ constructor(options?: ShipItClientOptions);
26
25
  private normalizeUser;
27
26
  bool(flagKey: string, user: ShipItUserPayload, defaultValue?: boolean): Promise<boolean>;
28
27
  }
package/dist/index.d.ts CHANGED
@@ -12,7 +12,6 @@ type ShipItUserPayload = {
12
12
  custom?: Record<string, string | number | boolean | null>;
13
13
  };
14
14
  type ShipItClientOptions = {
15
- apiBaseUrl: string;
16
15
  sdkKey?: string;
17
16
  projectKey?: string;
18
17
  envKey?: string;
@@ -22,7 +21,7 @@ declare class ShipItClient {
22
21
  private readonly sdkKey;
23
22
  private readonly projectKey;
24
23
  private readonly envKey;
25
- constructor(options: ShipItClientOptions);
24
+ constructor(options?: ShipItClientOptions);
26
25
  private normalizeUser;
27
26
  bool(flagKey: string, user: ShipItUserPayload, defaultValue?: boolean): Promise<boolean>;
28
27
  }
package/dist/index.js CHANGED
@@ -1,16 +1,28 @@
1
1
  // src/index.ts
2
+ function getApiBaseUrl() {
3
+ if (typeof window !== "undefined" && typeof window.location !== "undefined") {
4
+ return window.location.origin;
5
+ }
6
+ return "https://shipit-api-246728836834.us-central1.run.app";
7
+ }
8
+ function getSdkKeyFromEnv() {
9
+ if (typeof process !== "undefined" && process.env) {
10
+ return process.env.SHIPIT_CLIENT_KEY?.trim() || process.env.SHIPIT_SERVER_KEY?.trim() || null;
11
+ }
12
+ return null;
13
+ }
2
14
  var ShipItClient = class {
3
15
  apiBaseUrl;
4
16
  sdkKey;
5
17
  projectKey;
6
18
  envKey;
7
- constructor(options) {
8
- this.apiBaseUrl = options.apiBaseUrl.replace(/\/$/, "");
9
- this.sdkKey = options.sdkKey?.trim() ? options.sdkKey.trim() : null;
19
+ constructor(options = {}) {
20
+ this.apiBaseUrl = getApiBaseUrl().replace(/\/$/, "");
21
+ this.sdkKey = options.sdkKey?.trim() || getSdkKeyFromEnv();
10
22
  this.projectKey = options.projectKey?.trim() ? options.projectKey.trim() : null;
11
23
  this.envKey = options.envKey ?? "production";
12
24
  if (!this.sdkKey && !this.projectKey) {
13
- throw new Error("ShipItClient requires either sdkKey (recommended) or projectKey (legacy).");
25
+ throw new Error("ShipItClient requires either sdkKey (recommended) or projectKey (legacy). Set SHIPIT_CLIENT_KEY or SHIPIT_SERVER_KEY env var, or pass sdkKey in options.");
14
26
  }
15
27
  }
16
28
  normalizeUser(input) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";AA6BO,IAAM,eAAN,MAAmB;AAAA,EACP,UAAA;AAAA,EACA,MAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EAEjB,YAAY,OAAA,EAA8B;AACxC,IAAA,IAAA,CAAK,UAAA,GAAa,OAAA,CAAQ,UAAA,CAAW,OAAA,CAAQ,OAAO,EAAE,CAAA;AACtD,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,MAAA,EAAQ,IAAA,KAAS,OAAA,CAAQ,MAAA,CAAO,MAAK,GAAI,IAAA;AAC/D,IAAA,IAAA,CAAK,UAAA,GAAa,QAAQ,UAAA,EAAY,IAAA,KAAS,OAAA,CAAQ,UAAA,CAAW,MAAK,GAAI,IAAA;AAC3E,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,MAAA,IAAU,YAAA;AAEhC,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,IAAU,CAAC,KAAK,UAAA,EAAY;AACpC,MAAA,MAAM,IAAI,MAAM,2EAA2E,CAAA;AAAA,IAC7F;AAAA,EACF;AAAA,EAEQ,cAAc,KAAA,EAAsC;AAC1D,IAAA,MAAM,OAAO,KAAA,CAAM,EAAA,IAAM,KAAA,CAAM,GAAA,IAAO,IAAI,IAAA,EAAK;AAC/C,IAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,qDAAqD,CAAA;AAC/E,IAAA,OAAO;AAAA,MACL,GAAA;AAAA,MACA,OAAO,KAAA,CAAM,KAAA;AAAA,MACb,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,MAAA,EAAQ,KAAA,CAAM,IAAA,IAAQ,KAAA,CAAM;AAAA,KAC9B;AAAA,EACF;AAAA,EAEA,MAAM,IAAA,CAAK,OAAA,EAAiB,IAAA,EAAyB,eAAe,KAAA,EAAyB;AAC3F,IAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,aAAA,CAAc,IAAI,CAAA;AAC9C,IAAA,MAAM,GAAA,GAAM,KAAK,MAAA,GACb,MAAM,MAAM,CAAA,EAAG,IAAA,CAAK,UAAU,CAAA,gBAAA,CAAA,EAAoB;AAAA,MAChD,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,kBAAA;AAAA,QAChB,oBAAoB,IAAA,CAAK;AAAA,OAC3B;AAAA,MACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,OAAA;AAAA,QACA,IAAA,EAAM,cAAA;AAAA,QACN;AAAA,OACD;AAAA,KACF,CAAA,GACD,MAAM,MAAM,CAAA,EAAG,IAAA,CAAK,UAAU,CAAA,YAAA,CAAA,EAAgB;AAAA,MAC5C,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,MAC9C,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,YAAY,IAAA,CAAK,UAAA;AAAA,QACjB,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,OAAA;AAAA,QACA,IAAA,EAAM,cAAA;AAAA,QACN;AAAA,OACD;AAAA,KACF,CAAA;AAEL,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,OAAO,YAAA;AACpB,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd;AACF","file":"index.js","sourcesContent":["export type ShipItUserPayload = {\n /** Unique user identifier (preferred). */\n id?: string;\n /** Legacy alias for id. */\n key?: string;\n email?: string;\n name?: string;\n country?: string;\n /** Queryable attributes. */\n meta?: Record<string, string | number | boolean | null>;\n /** Legacy alias for meta. */\n custom?: Record<string, string | number | boolean | null>;\n};\n\ntype ShipItUser = {\n key: string;\n email?: string;\n name?: string;\n country?: string;\n custom?: Record<string, string | number | boolean | null>;\n};\n\nexport type ShipItClientOptions = {\n apiBaseUrl: string;\n sdkKey?: string;\n projectKey?: string;\n envKey?: string;\n};\n\nexport class ShipItClient {\n private readonly apiBaseUrl: string;\n private readonly sdkKey: string | null;\n private readonly projectKey: string | null;\n private readonly envKey: string;\n\n constructor(options: ShipItClientOptions) {\n this.apiBaseUrl = options.apiBaseUrl.replace(/\\/$/, '');\n this.sdkKey = options.sdkKey?.trim() ? options.sdkKey.trim() : null;\n this.projectKey = options.projectKey?.trim() ? options.projectKey.trim() : null;\n this.envKey = options.envKey ?? 'production';\n\n if (!this.sdkKey && !this.projectKey) {\n throw new Error('ShipItClient requires either sdkKey (recommended) or projectKey (legacy).');\n }\n }\n\n private normalizeUser(input: ShipItUserPayload): ShipItUser {\n const key = (input.id ?? input.key ?? '').trim();\n if (!key) throw new Error('ShipItClient requires user.id (or legacy user.key).');\n return {\n key,\n email: input.email,\n name: input.name,\n country: input.country,\n custom: input.meta ?? input.custom\n };\n }\n\n async bool(flagKey: string, user: ShipItUserPayload, defaultValue = false): Promise<boolean> {\n const normalizedUser = this.normalizeUser(user);\n const res = this.sdkKey\n ? await fetch(`${this.apiBaseUrl}/api/v1/sdk/eval`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-shipit-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n })\n : await fetch(`${this.apiBaseUrl}/api/v1/eval`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n projectKey: this.projectKey,\n envKey: this.envKey,\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n });\n\n if (!res.ok) return defaultValue;\n const json = (await res.json()) as { value: boolean };\n return json.value;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export type ShipItUserPayload = {\n /** Unique user identifier (preferred). */\n id?: string;\n /** Legacy alias for id. */\n key?: string;\n email?: string;\n name?: string;\n country?: string;\n /** Queryable attributes. */\n meta?: Record<string, string | number | boolean | null>;\n /** Legacy alias for meta. */\n custom?: Record<string, string | number | boolean | null>;\n};\n\ntype ShipItUser = {\n key: string;\n email?: string;\n name?: string;\n country?: string;\n custom?: Record<string, string | number | boolean | null>;\n};\n\nfunction getApiBaseUrl(): string {\n // Browser: use current origin (assumes API is on same origin)\n if (typeof window !== 'undefined' && typeof (window as any).location !== 'undefined') {\n return (window as any).location.origin;\n }\n // Node.js: always use production API\n return 'https://shipit-api-246728836834.us-central1.run.app';\n}\n\nexport type ShipItClientOptions = {\n sdkKey?: string;\n projectKey?: string;\n envKey?: string;\n};\n\nfunction getSdkKeyFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return process.env.SHIPIT_CLIENT_KEY?.trim() || process.env.SHIPIT_SERVER_KEY?.trim() || null;\n }\n return null;\n}\n\nexport class ShipItClient {\n private readonly apiBaseUrl: string;\n private readonly sdkKey: string | null;\n private readonly projectKey: string | null;\n private readonly envKey: string;\n\n constructor(options: ShipItClientOptions = {}) {\n this.apiBaseUrl = getApiBaseUrl().replace(/\\/$/, '');\n this.sdkKey = options.sdkKey?.trim() || getSdkKeyFromEnv();\n this.projectKey = options.projectKey?.trim() ? options.projectKey.trim() : null;\n this.envKey = options.envKey ?? 'production';\n\n if (!this.sdkKey && !this.projectKey) {\n throw new Error('ShipItClient requires either sdkKey (recommended) or projectKey (legacy). Set SHIPIT_CLIENT_KEY or SHIPIT_SERVER_KEY env var, or pass sdkKey in options.');\n }\n }\n\n private normalizeUser(input: ShipItUserPayload): ShipItUser {\n const key = (input.id ?? input.key ?? '').trim();\n if (!key) throw new Error('ShipItClient requires user.id (or legacy user.key).');\n return {\n key,\n email: input.email,\n name: input.name,\n country: input.country,\n custom: input.meta ?? input.custom\n };\n }\n\n async bool(flagKey: string, user: ShipItUserPayload, defaultValue = false): Promise<boolean> {\n const normalizedUser = this.normalizeUser(user);\n const res = this.sdkKey\n ? await fetch(`${this.apiBaseUrl}/api/v1/sdk/eval`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-shipit-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n })\n : await fetch(`${this.apiBaseUrl}/api/v1/eval`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n projectKey: this.projectKey,\n envKey: this.envKey,\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n });\n\n if (!res.ok) return defaultValue;\n const json = (await res.json()) as { value: boolean };\n return json.value;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsontech/sdk-js",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -17,7 +17,8 @@
17
17
  }
18
18
  },
19
19
  "files": [
20
- "dist"
20
+ "dist",
21
+ "README.md"
21
22
  ],
22
23
  "sideEffects": false,
23
24
  "scripts": {