@byteoniclabs/intake 1.0.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.
@@ -0,0 +1,80 @@
1
+ // src/server.ts
2
+ var ByteonicServerClient = class {
3
+ constructor(config) {
4
+ if (!config.apiKey) {
5
+ throw new Error("[Byteonic Intake] API Key is required");
6
+ }
7
+ this.apiKey = config.apiKey;
8
+ this.baseUrl = config.baseUrl || "https://intake.byteoniclabs.com/api/external";
9
+ this.origin = config.origin;
10
+ }
11
+ /**
12
+ * Submit form data to Byteonic Intake from a Node.js Server
13
+ * @param formSlug The slug of the form to submit to
14
+ * @param data The form data (Record<string, any> or FormData)
15
+ * @param options Server-specific options for tracking user IP/Agent
16
+ */
17
+ async submit(formSlug, data, options = {}) {
18
+ const url = `${this.baseUrl}/forms/${formSlug}/submit`;
19
+ const meta = {
20
+ sdk_version: "1.0.0-server",
21
+ source_url: options.sourceUrl || "server",
22
+ submission_source: "byteonic_intake_sdk_server"
23
+ };
24
+ let fetchHeaders = {
25
+ "Authorization": `Bearer ${this.apiKey}`
26
+ };
27
+ if (this.origin) {
28
+ fetchHeaders["Origin"] = this.origin;
29
+ fetchHeaders["Referer"] = this.origin;
30
+ }
31
+ if (options.userIp) {
32
+ fetchHeaders["x-forwarded-for"] = options.userIp;
33
+ }
34
+ if (options.userAgent) {
35
+ fetchHeaders["User-Agent"] = options.userAgent;
36
+ }
37
+ let fetchOptions = {
38
+ method: "POST",
39
+ headers: fetchHeaders
40
+ };
41
+ if (typeof FormData !== "undefined" && data instanceof FormData) {
42
+ data.append("_meta", JSON.stringify(meta));
43
+ fetchOptions.body = data;
44
+ } else {
45
+ const payload = data;
46
+ payload._meta = meta;
47
+ fetchOptions.headers = {
48
+ ...fetchOptions.headers,
49
+ "Content-Type": "application/json"
50
+ };
51
+ fetchOptions.body = JSON.stringify(payload);
52
+ }
53
+ try {
54
+ const response = await fetch(url, fetchOptions);
55
+ const responseData = await response.json().catch(() => ({}));
56
+ if (!response.ok) {
57
+ return {
58
+ success: false,
59
+ error: responseData.error || `Submission failed with status ${response.status}`,
60
+ status: response.status
61
+ };
62
+ }
63
+ return {
64
+ success: true,
65
+ data: responseData,
66
+ status: response.status
67
+ };
68
+ } catch (error) {
69
+ return {
70
+ success: false,
71
+ error: error.message || "Network request failed",
72
+ status: 500
73
+ };
74
+ }
75
+ }
76
+ };
77
+ export {
78
+ ByteonicServerClient
79
+ };
80
+ //# sourceMappingURL=server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.ts"],"sourcesContent":["import { SubmissionResponse } from './types';\n\nexport interface ServerConfig {\n apiKey: string;\n baseUrl?: string;\n /**\n * If your Byteonic Intake dashboard has Domain Whitelisting enabled,\n * you MUST provide a matching origin here to bypass the block.\n * Example: \"https://yourdomain.com\"\n */\n origin?: string;\n}\n\nexport interface ServerSubmitOptions {\n /**\n * The actual IP address of the end-user (e.g., from req.headers['x-forwarded-for']).\n * This ensures your Intake dashboard shows the user's location, not your server's location.\n */\n userIp?: string;\n /**\n * The actual User-Agent of the end-user browser.\n */\n userAgent?: string;\n /**\n * A custom source URL to tag this submission with.\n */\n sourceUrl?: string;\n}\n\nexport class ByteonicServerClient {\n private apiKey: string;\n private baseUrl: string;\n private origin?: string;\n\n constructor(config: ServerConfig) {\n if (!config.apiKey) {\n throw new Error('[Byteonic Intake] API Key is required');\n }\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl || 'https://intake.byteoniclabs.com/api/external';\n this.origin = config.origin;\n }\n\n /**\n * Submit form data to Byteonic Intake from a Node.js Server\n * @param formSlug The slug of the form to submit to\n * @param data The form data (Record<string, any> or FormData)\n * @param options Server-specific options for tracking user IP/Agent\n */\n async submit(formSlug: string, data: Record<string, any> | FormData, options: ServerSubmitOptions = {}): Promise<SubmissionResponse> {\n const url = `${this.baseUrl}/forms/${formSlug}/submit`;\n \n // Auto-track metadata for servers\n const meta = {\n sdk_version: '1.0.0-server',\n source_url: options.sourceUrl || 'server',\n submission_source: 'byteonic_intake_sdk_server'\n };\n\n let fetchHeaders: Record<string, string> = {\n 'Authorization': `Bearer ${this.apiKey}`\n };\n\n // Spoof origin if provided to bypass domain whitelists safely\n if (this.origin) {\n fetchHeaders['Origin'] = this.origin;\n fetchHeaders['Referer'] = this.origin;\n }\n \n // Forward user headers if provided\n if (options.userIp) {\n fetchHeaders['x-forwarded-for'] = options.userIp;\n }\n if (options.userAgent) {\n fetchHeaders['User-Agent'] = options.userAgent;\n }\n\n let fetchOptions: RequestInit = {\n method: 'POST',\n headers: fetchHeaders\n };\n\n if (typeof FormData !== 'undefined' && data instanceof FormData) {\n // Native Node 18+ FormData support\n data.append('_meta', JSON.stringify(meta));\n fetchOptions.body = data;\n } else {\n // Standard JSON payload\n const payload = data as Record<string, any>;\n payload._meta = meta;\n \n fetchOptions.headers = {\n ...fetchOptions.headers,\n 'Content-Type': 'application/json'\n };\n fetchOptions.body = JSON.stringify(payload);\n }\n\n try {\n const response = await fetch(url, fetchOptions);\n const responseData = await response.json().catch(() => ({}));\n \n if (!response.ok) {\n return {\n success: false,\n error: responseData.error || `Submission failed with status ${response.status}`,\n status: response.status\n };\n }\n\n return {\n success: true,\n data: responseData,\n status: response.status\n };\n } catch (error: any) {\n return {\n success: false,\n error: error.message || 'Network request failed',\n status: 500\n };\n }\n }\n}\n"],"mappings":";AA6BO,IAAM,uBAAN,MAA2B;AAAA,EAKhC,YAAY,QAAsB;AAChC,QAAI,CAAC,OAAO,QAAQ;AAClB,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AACA,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU,OAAO,WAAW;AACjC,SAAK,SAAS,OAAO;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAO,UAAkB,MAAsC,UAA+B,CAAC,GAAgC;AACnI,UAAM,MAAM,GAAG,KAAK,OAAO,UAAU,QAAQ;AAG7C,UAAM,OAAO;AAAA,MACX,aAAa;AAAA,MACb,YAAY,QAAQ,aAAa;AAAA,MACjC,mBAAmB;AAAA,IACrB;AAEA,QAAI,eAAuC;AAAA,MACzC,iBAAiB,UAAU,KAAK,MAAM;AAAA,IACxC;AAGA,QAAI,KAAK,QAAQ;AACf,mBAAa,QAAQ,IAAI,KAAK;AAC9B,mBAAa,SAAS,IAAI,KAAK;AAAA,IACjC;AAGA,QAAI,QAAQ,QAAQ;AAClB,mBAAa,iBAAiB,IAAI,QAAQ;AAAA,IAC5C;AACA,QAAI,QAAQ,WAAW;AACrB,mBAAa,YAAY,IAAI,QAAQ;AAAA,IACvC;AAEA,QAAI,eAA4B;AAAA,MAC9B,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAEA,QAAI,OAAO,aAAa,eAAe,gBAAgB,UAAU;AAE/D,WAAK,OAAO,SAAS,KAAK,UAAU,IAAI,CAAC;AACzC,mBAAa,OAAO;AAAA,IACtB,OAAO;AAEL,YAAM,UAAU;AAChB,cAAQ,QAAQ;AAEhB,mBAAa,UAAU;AAAA,QACrB,GAAG,aAAa;AAAA,QAChB,gBAAgB;AAAA,MAClB;AACA,mBAAa,OAAO,KAAK,UAAU,OAAO;AAAA,IAC5C;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK,YAAY;AAC9C,YAAM,eAAe,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAE3D,UAAI,CAAC,SAAS,IAAI;AAChB,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,aAAa,SAAS,iCAAiC,SAAS,MAAM;AAAA,UAC7E,QAAQ,SAAS;AAAA,QACnB;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM;AAAA,QACN,QAAQ,SAAS;AAAA,MACnB;AAAA,IACF,SAAS,OAAY;AACnB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,MAAM,WAAW;AAAA,QACxB,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,13 @@
1
+ interface ByteonicConfig {
2
+ apiKey: string;
3
+ baseUrl?: string;
4
+ }
5
+ interface SubmissionResponse {
6
+ success?: boolean;
7
+ message?: string;
8
+ error?: string;
9
+ details?: Record<string, string> | string;
10
+ [key: string]: any;
11
+ }
12
+
13
+ export type { ByteonicConfig as B, SubmissionResponse as S };
@@ -0,0 +1,13 @@
1
+ interface ByteonicConfig {
2
+ apiKey: string;
3
+ baseUrl?: string;
4
+ }
5
+ interface SubmissionResponse {
6
+ success?: boolean;
7
+ message?: string;
8
+ error?: string;
9
+ details?: Record<string, string> | string;
10
+ [key: string]: any;
11
+ }
12
+
13
+ export type { ByteonicConfig as B, SubmissionResponse as S };
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@byteoniclabs/intake",
3
+ "version": "1.0.0",
4
+ "description": "Securely submit forms to Byteonic Intake from any frontend.",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ },
14
+ "./react": {
15
+ "types": "./dist/react/index.d.ts",
16
+ "import": "./dist/react/index.mjs",
17
+ "require": "./dist/react/index.js"
18
+ },
19
+ "./server": {
20
+ "types": "./dist/server.d.ts",
21
+ "import": "./dist/server.mjs",
22
+ "require": "./dist/server.js"
23
+ }
24
+ },
25
+ "scripts": {
26
+ "build": "tsup",
27
+ "dev": "tsup --watch",
28
+ "typecheck": "tsc --noEmit"
29
+ },
30
+ "files": [
31
+ "dist"
32
+ ],
33
+ "keywords": [
34
+ "byteonic",
35
+ "intake",
36
+ "forms",
37
+ "form-builder",
38
+ "react",
39
+ "chatbot"
40
+ ],
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/Byteonic-Labs/intake.byteoniclabs.com.git"
44
+ },
45
+ "peerDependencies": {
46
+ "react": ">=16.8"
47
+ },
48
+ "peerDependenciesMeta": {
49
+ "react": {
50
+ "optional": true
51
+ }
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": "^25.9.1",
55
+ "@types/react": "^19.2.14",
56
+ "react": "^19.2.4",
57
+ "tsup": "^8.5.1",
58
+ "typescript": "^5.5.4"
59
+ },
60
+ "author": "Byteonic Labs",
61
+ "license": "ISC"
62
+ }