@solvapay/core 1.0.9 → 1.1.0

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,87 +1,37 @@
1
1
  # @solvapay/core
2
2
 
3
- Shared types, schemas, errors, and utilities used across all SolvaPay SDK packages.
3
+ [![npm version](https://img.shields.io/npm/v/@solvapay/core.svg)](https://www.npmjs.com/package/@solvapay/core)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
5
 
5
- This package is **runtime-agnostic** -- it contains no Node.js or browser globals and has `"sideEffects": false`.
6
+ Shared types, schemas, errors, and utilities used across all SolvaPay SDK packages. Runtime-agnostic no Node.js or browser globals.
7
+
8
+ **When to use this package:** rarely install directly. It is pulled in automatically by `@solvapay/server`, `@solvapay/react`, and other packages. Install only if you need shared types or `SolvaPayError` without a full SDK surface.
6
9
 
7
10
  ## Install
8
11
 
9
12
  ```bash
10
- npm install @solvapay/core
11
- # or
12
- yarn add @solvapay/core
13
- # or
14
13
  pnpm add @solvapay/core
15
14
  ```
16
15
 
17
- ## Exports
18
-
19
- ### `SolvaPayError`
20
-
21
- Base error class for all SolvaPay SDK errors. Useful for catching SDK-specific errors:
22
-
23
- ```typescript
24
- import { SolvaPayError } from '@solvapay/core'
25
-
26
- try {
27
- const config = getSolvaPayConfig()
28
- } catch (error) {
29
- if (error instanceof SolvaPayError) {
30
- console.error('SolvaPay error:', error.message)
31
- }
32
- }
33
- ```
34
-
35
- ### `SolvaPayConfig`
36
-
37
- Configuration interface for the SDK:
16
+ ## Key exports
38
17
 
39
18
  ```typescript
19
+ import { SolvaPayError, getSolvaPayConfig, Env } from '@solvapay/core'
40
20
  import type { SolvaPayConfig } from '@solvapay/core'
41
-
42
- const config: SolvaPayConfig = {
43
- apiKey: 'sk_live_...',
44
- apiBaseUrl: 'https://api.solvapay.com', // optional
45
- }
46
- ```
47
-
48
- ### `getSolvaPayConfig()`
49
-
50
- Validates and returns configuration from environment variables. Reads `SOLVAPAY_SECRET_KEY` and optional `SOLVAPAY_API_BASE_URL`:
51
-
52
- ```typescript
53
- import { getSolvaPayConfig } from '@solvapay/core'
54
-
55
- const config = getSolvaPayConfig()
56
- // config.apiKey - from SOLVAPAY_SECRET_KEY
57
- // config.apiBaseUrl - from SOLVAPAY_API_BASE_URL (optional)
58
- ```
59
-
60
- Throws `SolvaPayError` if `SOLVAPAY_SECRET_KEY` is not set.
61
-
62
- ### `Env`
63
-
64
- Zod schema for validating environment variables:
65
-
66
- ```typescript
67
- import { Env } from '@solvapay/core'
68
-
69
- const result = Env.safeParse(process.env)
70
- if (!result.success) {
71
- console.error('Invalid environment:', result.error)
72
- }
73
21
  ```
74
22
 
75
- ### `version`
76
-
77
- The current SDK version string.
23
+ - `SolvaPayError` — base error class for SDK errors
24
+ - `SolvaPayConfig` / `getSolvaPayConfig()` — config from `SOLVAPAY_SECRET_KEY` env
25
+ - `Env` Zod schema for env validation
26
+ - `version` — current SDK version string
78
27
 
79
- ## When to Use This Package
28
+ ## See also
80
29
 
81
- Most developers don't need to install `@solvapay/core` directly -- it's automatically included as a dependency of `@solvapay/server`, `@solvapay/react`, and other packages. Install it directly only if you need access to the shared types or error classes without pulling in a full SDK package.
30
+ - [`@solvapay/server`](../server) server-side paywall and API client
31
+ - [`@solvapay/react`](../react) — client-side checkout components
32
+ - [Architecture guide](../../docs/contributing/architecture.md) — package boundaries
82
33
 
83
- ## More Information
34
+ ## Support
84
35
 
85
- - [Architecture Guide](../../docs/contributing/architecture.md) - Package design and boundaries
86
- - [Server SDK](../server/README.md) - Server-side paywall protection
87
- - [React SDK](../react/README.md) - Client-side payment components
36
+ - **Issues**: [GitHub Issues](https://github.com/solvapay/solvapay-sdk/issues)
37
+ - **Docs**: [docs.solvapay.com/sdks/typescript](https://docs.solvapay.com/sdks/typescript/intro)
package/dist/index.cjs CHANGED
@@ -22,24 +22,81 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  Env: () => Env,
24
24
  SolvaPayError: () => SolvaPayError,
25
+ creditsToDisplayMinorUnits: () => creditsToDisplayMinorUnits,
25
26
  getSolvaPayConfig: () => getSolvaPayConfig,
27
+ isZeroDecimalCurrency: () => isZeroDecimalCurrency,
28
+ minorUnitsPerMajor: () => minorUnitsPerMajor,
26
29
  version: () => version
27
30
  });
28
31
  module.exports = __toCommonJS(index_exports);
29
32
  var import_zod = require("zod");
33
+
34
+ // src/credit-display.ts
35
+ var ZERO_DECIMAL = /* @__PURE__ */ new Set([
36
+ "bif",
37
+ "clp",
38
+ "djf",
39
+ "gnf",
40
+ "jpy",
41
+ "kmf",
42
+ "krw",
43
+ "mga",
44
+ "pyg",
45
+ "rwf",
46
+ "ugx",
47
+ "vnd",
48
+ "vuv",
49
+ "xaf",
50
+ "xof",
51
+ "xpf"
52
+ ]);
53
+ function minorUnitsPerMajor(currency) {
54
+ return ZERO_DECIMAL.has(currency.toLowerCase()) ? 1 : 100;
55
+ }
56
+ function isZeroDecimalCurrency(currency) {
57
+ return ZERO_DECIMAL.has(currency.toLowerCase());
58
+ }
59
+ function creditsToDisplayMinorUnits(input) {
60
+ const { credits, creditsPerMinorUnit, displayExchangeRate, displayCurrency } = input;
61
+ if (!creditsPerMinorUnit || creditsPerMinorUnit <= 0) return null;
62
+ const usdMajor = credits / creditsPerMinorUnit / 100;
63
+ return Math.round(
64
+ usdMajor * (displayExchangeRate || 1) * minorUnitsPerMajor(displayCurrency)
65
+ );
66
+ }
67
+
68
+ // src/index.ts
30
69
  var Env = import_zod.z.object({
31
70
  SOLVAPAY_SECRET_KEY: import_zod.z.string().min(1),
32
71
  SOLVAPAY_API_BASE_URL: import_zod.z.string().url().optional()
33
72
  });
34
73
  var SolvaPayError = class extends Error {
74
+ /**
75
+ * HTTP status code associated with the error, when the error
76
+ * originated from an upstream API response. Optional so existing
77
+ * `new SolvaPayError(message)` callsites stay valid.
78
+ */
79
+ status;
80
+ /**
81
+ * Optional short code for programmatic branching (e.g.
82
+ * `'missing_secret'`, `'merchant_not_found'`). Free-form by design;
83
+ * callers should not depend on an exhaustive enum.
84
+ */
85
+ code;
35
86
  /**
36
87
  * Creates a new SolvaPayError instance.
37
88
  *
38
89
  * @param message - Error message
90
+ * @param init - Optional `{ status, code }` metadata. Both fields
91
+ * are preserved on the instance so downstream consumers
92
+ * (`handleRouteError`, MCP trace wrappers) can branch on HTTP
93
+ * status without parsing the message string.
39
94
  */
40
- constructor(message) {
95
+ constructor(message, init = {}) {
41
96
  super(message);
42
97
  this.name = "SolvaPayError";
98
+ this.status = init.status;
99
+ this.code = init.code;
43
100
  }
44
101
  };
45
102
  function getSolvaPayConfig() {
@@ -60,6 +117,9 @@ var version = "0.1.0";
60
117
  0 && (module.exports = {
61
118
  Env,
62
119
  SolvaPayError,
120
+ creditsToDisplayMinorUnits,
63
121
  getSolvaPayConfig,
122
+ isZeroDecimalCurrency,
123
+ minorUnitsPerMajor,
64
124
  version
65
125
  });
package/dist/index.d.cts CHANGED
@@ -1,5 +1,21 @@
1
1
  import { z } from 'zod';
2
2
 
3
+ /**
4
+ * Shared credit → fiat conversion for MCP bootstrap narration and React
5
+ * balance surfaces. Backend contract: `credits = USD_cents × creditsPerMinorUnit`
6
+ * (mint scale; `creditsPerMinorUnit` is typically 100), and
7
+ * `displayExchangeRate` is USD → display currency (e.g. 9.46 for SEK).
8
+ */
9
+ declare function minorUnitsPerMajor(currency: string): number;
10
+ declare function isZeroDecimalCurrency(currency: string): boolean;
11
+ /** Fiat value of a credit balance, in MINOR units of `displayCurrency`. */
12
+ declare function creditsToDisplayMinorUnits(input: {
13
+ credits: number;
14
+ creditsPerMinorUnit: number;
15
+ displayExchangeRate: number;
16
+ displayCurrency: string;
17
+ }): number | null;
18
+
3
19
  declare const Env: z.ZodObject<{
4
20
  SOLVAPAY_SECRET_KEY: z.ZodString;
5
21
  SOLVAPAY_API_BASE_URL: z.ZodOptional<z.ZodString>;
@@ -31,12 +47,31 @@ type Env = z.infer<typeof Env>;
31
47
  * @since 1.0.0
32
48
  */
33
49
  declare class SolvaPayError extends Error {
50
+ /**
51
+ * HTTP status code associated with the error, when the error
52
+ * originated from an upstream API response. Optional so existing
53
+ * `new SolvaPayError(message)` callsites stay valid.
54
+ */
55
+ readonly status?: number;
56
+ /**
57
+ * Optional short code for programmatic branching (e.g.
58
+ * `'missing_secret'`, `'merchant_not_found'`). Free-form by design;
59
+ * callers should not depend on an exhaustive enum.
60
+ */
61
+ readonly code?: string;
34
62
  /**
35
63
  * Creates a new SolvaPayError instance.
36
64
  *
37
65
  * @param message - Error message
66
+ * @param init - Optional `{ status, code }` metadata. Both fields
67
+ * are preserved on the instance so downstream consumers
68
+ * (`handleRouteError`, MCP trace wrappers) can branch on HTTP
69
+ * status without parsing the message string.
38
70
  */
39
- constructor(message: string);
71
+ constructor(message: string, init?: {
72
+ status?: number;
73
+ code?: string;
74
+ });
40
75
  }
41
76
  interface SolvaPayConfig {
42
77
  apiKey: string;
@@ -68,6 +103,7 @@ interface SolvaPayConfig {
68
103
  * @since 1.0.0
69
104
  */
70
105
  declare function getSolvaPayConfig(): SolvaPayConfig;
106
+
71
107
  declare const version = "0.1.0";
72
108
 
73
- export { Env, type SolvaPayConfig, SolvaPayError, getSolvaPayConfig, version };
109
+ export { Env, type SolvaPayConfig, SolvaPayError, creditsToDisplayMinorUnits, getSolvaPayConfig, isZeroDecimalCurrency, minorUnitsPerMajor, version };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,21 @@
1
1
  import { z } from 'zod';
2
2
 
3
+ /**
4
+ * Shared credit → fiat conversion for MCP bootstrap narration and React
5
+ * balance surfaces. Backend contract: `credits = USD_cents × creditsPerMinorUnit`
6
+ * (mint scale; `creditsPerMinorUnit` is typically 100), and
7
+ * `displayExchangeRate` is USD → display currency (e.g. 9.46 for SEK).
8
+ */
9
+ declare function minorUnitsPerMajor(currency: string): number;
10
+ declare function isZeroDecimalCurrency(currency: string): boolean;
11
+ /** Fiat value of a credit balance, in MINOR units of `displayCurrency`. */
12
+ declare function creditsToDisplayMinorUnits(input: {
13
+ credits: number;
14
+ creditsPerMinorUnit: number;
15
+ displayExchangeRate: number;
16
+ displayCurrency: string;
17
+ }): number | null;
18
+
3
19
  declare const Env: z.ZodObject<{
4
20
  SOLVAPAY_SECRET_KEY: z.ZodString;
5
21
  SOLVAPAY_API_BASE_URL: z.ZodOptional<z.ZodString>;
@@ -31,12 +47,31 @@ type Env = z.infer<typeof Env>;
31
47
  * @since 1.0.0
32
48
  */
33
49
  declare class SolvaPayError extends Error {
50
+ /**
51
+ * HTTP status code associated with the error, when the error
52
+ * originated from an upstream API response. Optional so existing
53
+ * `new SolvaPayError(message)` callsites stay valid.
54
+ */
55
+ readonly status?: number;
56
+ /**
57
+ * Optional short code for programmatic branching (e.g.
58
+ * `'missing_secret'`, `'merchant_not_found'`). Free-form by design;
59
+ * callers should not depend on an exhaustive enum.
60
+ */
61
+ readonly code?: string;
34
62
  /**
35
63
  * Creates a new SolvaPayError instance.
36
64
  *
37
65
  * @param message - Error message
66
+ * @param init - Optional `{ status, code }` metadata. Both fields
67
+ * are preserved on the instance so downstream consumers
68
+ * (`handleRouteError`, MCP trace wrappers) can branch on HTTP
69
+ * status without parsing the message string.
38
70
  */
39
- constructor(message: string);
71
+ constructor(message: string, init?: {
72
+ status?: number;
73
+ code?: string;
74
+ });
40
75
  }
41
76
  interface SolvaPayConfig {
42
77
  apiKey: string;
@@ -68,6 +103,7 @@ interface SolvaPayConfig {
68
103
  * @since 1.0.0
69
104
  */
70
105
  declare function getSolvaPayConfig(): SolvaPayConfig;
106
+
71
107
  declare const version = "0.1.0";
72
108
 
73
- export { Env, type SolvaPayConfig, SolvaPayError, getSolvaPayConfig, version };
109
+ export { Env, type SolvaPayConfig, SolvaPayError, creditsToDisplayMinorUnits, getSolvaPayConfig, isZeroDecimalCurrency, minorUnitsPerMajor, version };
package/dist/index.js CHANGED
@@ -1,18 +1,72 @@
1
1
  // src/index.ts
2
2
  import { z } from "zod";
3
+
4
+ // src/credit-display.ts
5
+ var ZERO_DECIMAL = /* @__PURE__ */ new Set([
6
+ "bif",
7
+ "clp",
8
+ "djf",
9
+ "gnf",
10
+ "jpy",
11
+ "kmf",
12
+ "krw",
13
+ "mga",
14
+ "pyg",
15
+ "rwf",
16
+ "ugx",
17
+ "vnd",
18
+ "vuv",
19
+ "xaf",
20
+ "xof",
21
+ "xpf"
22
+ ]);
23
+ function minorUnitsPerMajor(currency) {
24
+ return ZERO_DECIMAL.has(currency.toLowerCase()) ? 1 : 100;
25
+ }
26
+ function isZeroDecimalCurrency(currency) {
27
+ return ZERO_DECIMAL.has(currency.toLowerCase());
28
+ }
29
+ function creditsToDisplayMinorUnits(input) {
30
+ const { credits, creditsPerMinorUnit, displayExchangeRate, displayCurrency } = input;
31
+ if (!creditsPerMinorUnit || creditsPerMinorUnit <= 0) return null;
32
+ const usdMajor = credits / creditsPerMinorUnit / 100;
33
+ return Math.round(
34
+ usdMajor * (displayExchangeRate || 1) * minorUnitsPerMajor(displayCurrency)
35
+ );
36
+ }
37
+
38
+ // src/index.ts
3
39
  var Env = z.object({
4
40
  SOLVAPAY_SECRET_KEY: z.string().min(1),
5
41
  SOLVAPAY_API_BASE_URL: z.string().url().optional()
6
42
  });
7
43
  var SolvaPayError = class extends Error {
44
+ /**
45
+ * HTTP status code associated with the error, when the error
46
+ * originated from an upstream API response. Optional so existing
47
+ * `new SolvaPayError(message)` callsites stay valid.
48
+ */
49
+ status;
50
+ /**
51
+ * Optional short code for programmatic branching (e.g.
52
+ * `'missing_secret'`, `'merchant_not_found'`). Free-form by design;
53
+ * callers should not depend on an exhaustive enum.
54
+ */
55
+ code;
8
56
  /**
9
57
  * Creates a new SolvaPayError instance.
10
58
  *
11
59
  * @param message - Error message
60
+ * @param init - Optional `{ status, code }` metadata. Both fields
61
+ * are preserved on the instance so downstream consumers
62
+ * (`handleRouteError`, MCP trace wrappers) can branch on HTTP
63
+ * status without parsing the message string.
12
64
  */
13
- constructor(message) {
65
+ constructor(message, init = {}) {
14
66
  super(message);
15
67
  this.name = "SolvaPayError";
68
+ this.status = init.status;
69
+ this.code = init.code;
16
70
  }
17
71
  };
18
72
  function getSolvaPayConfig() {
@@ -32,6 +86,9 @@ var version = "0.1.0";
32
86
  export {
33
87
  Env,
34
88
  SolvaPayError,
89
+ creditsToDisplayMinorUnits,
35
90
  getSolvaPayConfig,
91
+ isZeroDecimalCurrency,
92
+ minorUnitsPerMajor,
36
93
  version
37
94
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solvapay/core",
3
- "version": "1.0.9",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",