@alphawebai/hs-prism 0.1.0-rc.27

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.
Files changed (39) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +493 -0
  3. package/dist/src/alphaweb/contracts.d.ts +6 -0
  4. package/dist/src/alphaweb/contracts.js +14 -0
  5. package/dist/src/alphaweb/error.d.ts +13 -0
  6. package/dist/src/alphaweb/error.js +100 -0
  7. package/dist/src/alphaweb/index.d.ts +3 -0
  8. package/dist/src/alphaweb/index.js +22 -0
  9. package/dist/src/alphaweb/manifest.d.ts +28 -0
  10. package/dist/src/alphaweb/manifest.js +55 -0
  11. package/dist/src/alphaweb/money.d.ts +19 -0
  12. package/dist/src/alphaweb/money.js +128 -0
  13. package/dist/src/alphaweb/stripe-connector.d.ts +58 -0
  14. package/dist/src/alphaweb/stripe-connector.js +1402 -0
  15. package/dist/src/alphaweb/types.d.ts +255 -0
  16. package/dist/src/alphaweb/types.js +3 -0
  17. package/dist/src/http_client.d.ts +58 -0
  18. package/dist/src/http_client.js +179 -0
  19. package/dist/src/index.d.ts +10 -0
  20. package/dist/src/index.js +41 -0
  21. package/dist/src/payments/_generated_connector_client_flows.d.ts +112 -0
  22. package/dist/src/payments/_generated_connector_client_flows.js +215 -0
  23. package/dist/src/payments/_generated_flows.js +141 -0
  24. package/dist/src/payments/_generated_grpc_client.d.ts +194 -0
  25. package/dist/src/payments/_generated_grpc_client.js +905 -0
  26. package/dist/src/payments/_generated_uniffi_client_flows.d.ts +169 -0
  27. package/dist/src/payments/_generated_uniffi_client_flows.js +342 -0
  28. package/dist/src/payments/connector_client.d.ts +51 -0
  29. package/dist/src/payments/connector_client.js +152 -0
  30. package/dist/src/payments/errors.d.ts +27 -0
  31. package/dist/src/payments/errors.js +39 -0
  32. package/dist/src/payments/generated/libconnector_service_ffi.so +0 -0
  33. package/dist/src/payments/generated/proto.d.ts +49087 -0
  34. package/dist/src/payments/generated/proto.js +154163 -0
  35. package/dist/src/payments/grpc_client.d.ts +1 -0
  36. package/dist/src/payments/grpc_client.js +20 -0
  37. package/dist/src/payments/uniffi_client.d.ts +40 -0
  38. package/dist/src/payments/uniffi_client.js +249 -0
  39. package/package.json +79 -0
@@ -0,0 +1 @@
1
+ export * from "./_generated_grpc_client";
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ // Re-exports from the auto-generated gRPC client.
18
+ // Edit the template instead: scripts/generators/code/templates/javascript/grpc_client.ts.j2
19
+ __exportStar(require("./_generated_grpc_client"), exports);
20
+ //# sourceMappingURL=grpc_client.js.map
@@ -0,0 +1,40 @@
1
+ /**
2
+ * UniFFI client for Node.js — calls the same shared library as Python/Kotlin.
3
+ *
4
+ * Uses koffi to call the UniFFI C ABI directly, replacing NAPI entirely.
5
+ * Handles RustBuffer serialization/deserialization for the UniFFI protocol.
6
+ *
7
+ * Flow dispatch is generic: callReq(flow, ...) and callRes(flow, ...) load
8
+ * the corresponding C symbol dynamically from the flow list in _generated_flows.js.
9
+ * No flow names are hardcoded here — add new flows to flows.yaml and run `make generate`.
10
+ */
11
+ export interface RustBuffer {
12
+ capacity: bigint;
13
+ len: bigint;
14
+ data: Buffer | null;
15
+ }
16
+ export interface RustCallStatus {
17
+ code: number;
18
+ error_buf: RustBuffer;
19
+ }
20
+ export declare class UniffiClient {
21
+ private _ffi;
22
+ constructor(libPath?: string);
23
+ /**
24
+ * Build the connector HTTP request for any flow.
25
+ * Returns protobuf-encoded FfiConnectorHttpRequest bytes.
26
+ */
27
+ callReq(flow: string, requestBytes: Buffer | Uint8Array, optionsBytes: Buffer | Uint8Array): Buffer;
28
+ /**
29
+ * Parse the connector HTTP response for any flow.
30
+ * responseBytes: protobuf-encoded FfiConnectorHttpResponse.
31
+ * Returns protobuf-encoded response bytes for the flow's response type.
32
+ */
33
+ callRes(flow: string, responseBytes: Buffer | Uint8Array, requestBytes: Buffer | Uint8Array, optionsBytes: Buffer | Uint8Array): Buffer;
34
+ /**
35
+ * Execute a single-step transformer directly (no HTTP round-trip).
36
+ * Used for inbound flows like webhook processing.
37
+ * Returns protobuf-encoded response bytes.
38
+ */
39
+ callDirect(flow: string, requestBytes: Buffer | Uint8Array, optionsBytes: Buffer | Uint8Array): Buffer;
40
+ }
@@ -0,0 +1,249 @@
1
+ "use strict";
2
+ /**
3
+ * UniFFI client for Node.js — calls the same shared library as Python/Kotlin.
4
+ *
5
+ * Uses koffi to call the UniFFI C ABI directly, replacing NAPI entirely.
6
+ * Handles RustBuffer serialization/deserialization for the UniFFI protocol.
7
+ *
8
+ * Flow dispatch is generic: callReq(flow, ...) and callRes(flow, ...) load
9
+ * the corresponding C symbol dynamically from the flow list in _generated_flows.js.
10
+ * No flow names are hardcoded here — add new flows to flows.yaml and run `make generate`.
11
+ */
12
+ var __importDefault = (this && this.__importDefault) || function (mod) {
13
+ return (mod && mod.__esModule) ? mod : { "default": mod };
14
+ };
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.UniffiClient = void 0;
17
+ const koffi_1 = __importDefault(require("koffi"));
18
+ const path_1 = __importDefault(require("path"));
19
+ // @ts-ignore - generated CommonJS module
20
+ const _generated_flows_js_1 = require("./_generated_flows.js");
21
+ // @ts-ignore - generated protobuf types
22
+ const proto_js_1 = require("./generated/proto.js");
23
+ const errors_1 = require("./errors");
24
+ const _dirname = __dirname;
25
+ const FLOW_NAMES = Object.keys(_generated_flows_js_1.FLOWS);
26
+ const SINGLE_FLOW_NAMES = Object.keys((_generated_flows_js_1.SINGLE_FLOWS || {}));
27
+ const RustBufferStruct = koffi_1.default.struct("RustBuffer", {
28
+ capacity: "uint64",
29
+ len: "uint64",
30
+ data: "void *",
31
+ });
32
+ const RustCallStatusStruct = koffi_1.default.struct("RustCallStatus", {
33
+ code: "int8",
34
+ error_buf: RustBufferStruct,
35
+ });
36
+ function loadLib(libPath) {
37
+ if (!libPath) {
38
+ const ext = process.platform === "darwin" ? "dylib" : "so";
39
+ libPath = path_1.default.join(_dirname, "generated", `libconnector_service_ffi.${ext}`);
40
+ }
41
+ const lib = koffi_1.default.load(libPath);
42
+ const fns = {
43
+ alloc: lib.func("ffi_connector_service_ffi_rustbuffer_alloc", RustBufferStruct, ["uint64", koffi_1.default.out(koffi_1.default.pointer(RustCallStatusStruct))]),
44
+ free: lib.func("ffi_connector_service_ffi_rustbuffer_free", "void", [RustBufferStruct, koffi_1.default.out(koffi_1.default.pointer(RustCallStatusStruct))]),
45
+ };
46
+ // Load req and res transformer symbols for every registered flow.
47
+ for (const flow of FLOW_NAMES) {
48
+ fns[`${flow}_req`] = lib.func(`uniffi_connector_service_ffi_fn_func_${flow}_req_transformer`, RustBufferStruct, [RustBufferStruct, RustBufferStruct, koffi_1.default.out(koffi_1.default.pointer(RustCallStatusStruct))]);
49
+ fns[`${flow}_res`] = lib.func(`uniffi_connector_service_ffi_fn_func_${flow}_res_transformer`, RustBufferStruct, [RustBufferStruct, RustBufferStruct, RustBufferStruct, koffi_1.default.out(koffi_1.default.pointer(RustCallStatusStruct))]);
50
+ }
51
+ // Load single-step transformer symbols (no HTTP round-trip, e.g. webhook processing).
52
+ for (const flow of SINGLE_FLOW_NAMES) {
53
+ fns[`${flow}_direct`] = lib.func(`uniffi_connector_service_ffi_fn_func_${flow}_transformer`, RustBufferStruct, [RustBufferStruct, RustBufferStruct, koffi_1.default.out(koffi_1.default.pointer(RustCallStatusStruct))]);
54
+ }
55
+ return fns;
56
+ }
57
+ // ── Helpers ──────────────────────────────────────────────────────
58
+ function makeCallStatus() {
59
+ return { code: 0, error_buf: { capacity: 0n, len: 0n, data: null } };
60
+ }
61
+ function checkCallStatus(ffi, status) {
62
+ if (status.code === 0)
63
+ return;
64
+ // Only Rust panics should reach here now (status.code === 2)
65
+ // Normal errors are encoded as protobuf IntegrationError/ConnectorError in returned bytes
66
+ if (status.error_buf.len > 0n) {
67
+ const msg = liftString(status.error_buf);
68
+ freeRustBuffer(ffi, status.error_buf);
69
+ throw new Error(`Rust panic: ${msg}`);
70
+ }
71
+ throw new Error("Unknown Rust panic");
72
+ }
73
+ /**
74
+ * UniFFI Strings are serialized as raw UTF8 bytes when top-level in RustBuffer.
75
+ */
76
+ function liftString(buf) {
77
+ if (!buf.data || buf.len === 0n)
78
+ return "";
79
+ const raw = Buffer.from(koffi_1.default.decode(buf.data, "uint8", Number(buf.len)));
80
+ return raw.toString("utf-8");
81
+ }
82
+ /**
83
+ * UniFFI Vec<u8> (Bytes) as return values are serialized as [i32 length] + [raw bytes]
84
+ */
85
+ function liftBytes(buf) {
86
+ if (!buf.data || buf.len === 0n)
87
+ return Buffer.alloc(0);
88
+ const raw = Buffer.from(koffi_1.default.decode(buf.data, "uint8", Number(buf.len)));
89
+ // UniFFI protocol for return values: first 4 bytes are the length of the actual payload
90
+ const len = raw.readInt32BE(0);
91
+ return raw.subarray(4, 4 + len);
92
+ }
93
+ function freeRustBuffer(ffi, buf) {
94
+ if (buf.data && buf.len > 0n) {
95
+ ffi.free(buf, makeCallStatus());
96
+ }
97
+ }
98
+ function allocRustBuffer(ffi, data) {
99
+ const status = makeCallStatus();
100
+ const buf = ffi.alloc(BigInt(data.length), status);
101
+ checkCallStatus(ffi, status);
102
+ koffi_1.default.encode(buf.data, "uint8", Array.from(data), data.length);
103
+ buf.len = BigInt(data.length);
104
+ return buf;
105
+ }
106
+ /**
107
+ * Lowers raw bytes into a UniFFI-compliant buffer for top-level arguments.
108
+ * Protocol: [i32 length prefix] + [raw bytes]
109
+ */
110
+ function lowerBytes(ffi, data) {
111
+ const buf = Buffer.alloc(4 + data.length);
112
+ buf.writeInt32BE(data.length, 0);
113
+ Buffer.from(data).copy(buf, 4);
114
+ return allocRustBuffer(ffi, buf);
115
+ }
116
+ class UniffiClient {
117
+ _ffi;
118
+ constructor(libPath) {
119
+ this._ffi = loadLib(libPath);
120
+ }
121
+ /**
122
+ * Build the connector HTTP request for any flow.
123
+ * Returns protobuf-encoded FfiConnectorHttpRequest bytes.
124
+ */
125
+ callReq(flow, requestBytes, optionsBytes) {
126
+ const fn = this._ffi[`${flow}_req`];
127
+ if (!fn)
128
+ throw new Error(`Unknown flow: '${flow}'. Supported: ${FLOW_NAMES.join(", ")}`);
129
+ const rbReq = lowerBytes(this._ffi, requestBytes);
130
+ const rbOpts = lowerBytes(this._ffi, optionsBytes);
131
+ const status = makeCallStatus();
132
+ const result = fn(rbReq, rbOpts, status);
133
+ try {
134
+ checkCallStatus(this._ffi, status);
135
+ const bytes = liftBytes(result);
136
+ const resultMsg = proto_js_1.types.FfiResult.decode(bytes);
137
+ // Enum-based type checking
138
+ switch (resultMsg.type) {
139
+ case proto_js_1.types.FfiResult.Type.HTTP_REQUEST:
140
+ if (!resultMsg.httpRequest) {
141
+ throw new Error("Expected httpRequest in FfiResult, but got null/undefined");
142
+ }
143
+ return Buffer.from(proto_js_1.types.FfiConnectorHttpRequest.encode(resultMsg.httpRequest).finish());
144
+ case proto_js_1.types.FfiResult.Type.INTEGRATION_ERROR:
145
+ if (!resultMsg.integrationError) {
146
+ throw new Error("Expected integrationError in FfiResult, but got null/undefined");
147
+ }
148
+ throw new errors_1.IntegrationError(resultMsg.integrationError);
149
+ case proto_js_1.types.FfiResult.Type.CONNECTOR_ERROR:
150
+ if (!resultMsg.connectorError) {
151
+ throw new Error("Expected connectorError in FfiResult, but got null/undefined");
152
+ }
153
+ throw new errors_1.ConnectorError(resultMsg.connectorError);
154
+ default:
155
+ throw new Error(`Unknown result type: ${resultMsg.type}`);
156
+ }
157
+ }
158
+ finally {
159
+ freeRustBuffer(this._ffi, result);
160
+ }
161
+ }
162
+ /**
163
+ * Parse the connector HTTP response for any flow.
164
+ * responseBytes: protobuf-encoded FfiConnectorHttpResponse.
165
+ * Returns protobuf-encoded response bytes for the flow's response type.
166
+ */
167
+ callRes(flow, responseBytes, requestBytes, optionsBytes) {
168
+ const fn = this._ffi[`${flow}_res`];
169
+ if (!fn)
170
+ throw new Error(`Unknown flow: '${flow}'. Supported: ${FLOW_NAMES.join(", ")}`);
171
+ const rbRes = lowerBytes(this._ffi, responseBytes);
172
+ const rbReq = lowerBytes(this._ffi, requestBytes);
173
+ const rbOpts = lowerBytes(this._ffi, optionsBytes);
174
+ const status = makeCallStatus();
175
+ const result = fn(rbRes, rbReq, rbOpts, status);
176
+ try {
177
+ checkCallStatus(this._ffi, status);
178
+ const bytes = liftBytes(result);
179
+ const resultMsg = proto_js_1.types.FfiResult.decode(bytes);
180
+ // Enum-based type checking
181
+ switch (resultMsg.type) {
182
+ case proto_js_1.types.FfiResult.Type.HTTP_RESPONSE:
183
+ if (!resultMsg.httpResponse) {
184
+ throw new Error("Expected httpResponse in FfiResult, but got null/undefined");
185
+ }
186
+ return Buffer.from(proto_js_1.types.FfiConnectorHttpResponse.encode(resultMsg.httpResponse).finish());
187
+ case proto_js_1.types.FfiResult.Type.CONNECTOR_ERROR:
188
+ if (!resultMsg.connectorError) {
189
+ throw new Error("Expected connectorError in FfiResult, but got null/undefined");
190
+ }
191
+ throw new errors_1.ConnectorError(resultMsg.connectorError);
192
+ case proto_js_1.types.FfiResult.Type.INTEGRATION_ERROR:
193
+ if (!resultMsg.integrationError) {
194
+ throw new Error("Expected integrationError in FfiResult, but got null/undefined");
195
+ }
196
+ throw new errors_1.IntegrationError(resultMsg.integrationError);
197
+ default:
198
+ throw new Error(`Unknown result type: ${resultMsg.type}`);
199
+ }
200
+ }
201
+ finally {
202
+ freeRustBuffer(this._ffi, result);
203
+ }
204
+ }
205
+ /**
206
+ * Execute a single-step transformer directly (no HTTP round-trip).
207
+ * Used for inbound flows like webhook processing.
208
+ * Returns protobuf-encoded response bytes.
209
+ */
210
+ callDirect(flow, requestBytes, optionsBytes) {
211
+ const fn = this._ffi[`${flow}_direct`];
212
+ if (!fn)
213
+ throw new Error(`Unknown single-step flow: '${flow}'. Supported: ${SINGLE_FLOW_NAMES.join(", ")}`);
214
+ const rbReq = lowerBytes(this._ffi, requestBytes);
215
+ const rbOpts = lowerBytes(this._ffi, optionsBytes);
216
+ const status = makeCallStatus();
217
+ const result = fn(rbReq, rbOpts, status);
218
+ try {
219
+ checkCallStatus(this._ffi, status);
220
+ const bytes = liftBytes(result);
221
+ const resultMsg = proto_js_1.types.FfiResult.decode(bytes);
222
+ // Enum-based type checking
223
+ switch (resultMsg.type) {
224
+ case proto_js_1.types.FfiResult.Type.PROTO_RESPONSE:
225
+ if (!resultMsg.protoResponse) {
226
+ throw new Error("Expected protoResponse in FfiResult, but got null/undefined");
227
+ }
228
+ return Buffer.from(resultMsg.protoResponse);
229
+ case proto_js_1.types.FfiResult.Type.CONNECTOR_ERROR:
230
+ if (!resultMsg.connectorError) {
231
+ throw new Error("Expected connectorError in FfiResult, but got null/undefined");
232
+ }
233
+ throw new errors_1.ConnectorError(resultMsg.connectorError);
234
+ case proto_js_1.types.FfiResult.Type.INTEGRATION_ERROR:
235
+ if (!resultMsg.integrationError) {
236
+ throw new Error("Expected integrationError in FfiResult, but got null/undefined");
237
+ }
238
+ throw new errors_1.IntegrationError(resultMsg.integrationError);
239
+ default:
240
+ throw new Error(`Unknown result type: ${resultMsg.type}`);
241
+ }
242
+ }
243
+ finally {
244
+ freeRustBuffer(this._ffi, result);
245
+ }
246
+ }
247
+ }
248
+ exports.UniffiClient = UniffiClient;
249
+ //# sourceMappingURL=uniffi_client.js.map
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@alphawebai/hs-prism",
3
+ "version": "0.1.0-rc.27",
4
+ "description": "Hyperswitch Payments SDK — Node.js client for connector integrations via UniFFI FFI",
5
+ "main": "dist/src/index.js",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/src/index.d.ts",
9
+ "require": "./dist/src/index.js",
10
+ "default": "./dist/src/index.js"
11
+ },
12
+ "./alphaweb": {
13
+ "types": "./dist/src/alphaweb/index.d.ts",
14
+ "require": "./dist/src/alphaweb/index.js",
15
+ "default": "./dist/src/alphaweb/index.js"
16
+ },
17
+ "./alphaweb/contracts": {
18
+ "types": "./dist/src/alphaweb/contracts.d.ts",
19
+ "require": "./dist/src/alphaweb/contracts.js",
20
+ "default": "./dist/src/alphaweb/contracts.js"
21
+ }
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/AlphaWeb-AI/hyperswitch-prism.git",
26
+ "directory": "sdk/javascript"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/AlphaWeb-AI/hyperswitch-prism/issues"
30
+ },
31
+ "homepage": "https://github.com/AlphaWeb-AI/hyperswitch-prism#readme",
32
+ "publishConfig": {
33
+ "access": "public",
34
+ "registry": "https://registry.npmjs.org"
35
+ },
36
+ "types": "dist/src/index.d.ts",
37
+ "license": "Apache-2.0",
38
+ "keywords": [
39
+ "hyperswitch",
40
+ "prism",
41
+ "payments",
42
+ "payment-processing",
43
+ "credit-cards",
44
+ "juspay",
45
+ "payment-gateway",
46
+ "stripe",
47
+ "adyen",
48
+ "paypal",
49
+ "unified-payments"
50
+ ],
51
+ "files": [
52
+ "dist/src/**/*.js",
53
+ "dist/src/**/*.d.ts",
54
+ "dist/src/payments/generated/*",
55
+ "dist/src/alphaweb/**/*.js",
56
+ "dist/src/alphaweb/**/*.d.ts",
57
+ "README.md",
58
+ "LICENSE"
59
+ ],
60
+ "scripts": {
61
+ "build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc && cp -r src/payments/generated dist/src/payments/ && cp src/payments/_generated_flows.js dist/src/payments/",
62
+ "start": "node dist/src/index.js",
63
+ "test": "tsx --test src/alphaweb/__tests__/*.test.ts",
64
+ "test:smoke": "node test_smoke.js"
65
+ },
66
+ "dependencies": {
67
+ "koffi": "^2.15.1",
68
+ "protobufjs": "7.6.5",
69
+ "undici": "6.27.0"
70
+ },
71
+ "devDependencies": {
72
+ "@types/node": "^25.3.3",
73
+ "protobufjs-cli": "1.3.3",
74
+ "ts-node": "^10.9.2",
75
+ "tsconfig-paths": "^4.2.0",
76
+ "tsx": "4.23.1",
77
+ "typescript": "^5.9.3"
78
+ }
79
+ }