@findatruck/convex-client 0.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/dist/index.cjs ADDED
@@ -0,0 +1,210 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ BatchConvexUpdateSchema: () => import_shared_schemas2.BatchConvexUpdateSchema,
24
+ ConvexClient: () => ConvexClient,
25
+ ConvexClientError: () => ConvexClientError,
26
+ ConvexDriverSchema: () => import_shared_schemas2.ConvexDriverSchema,
27
+ ConvexUpdateSchema: () => import_shared_schemas2.ConvexUpdateSchema,
28
+ ScrapeStatus: () => import_shared_schemas2.ScrapeStatus,
29
+ UpdateScrapeStatusMessage: () => import_shared_schemas2.UpdateScrapeStatusMessage,
30
+ checkWorkerSecret: () => checkWorkerSecret,
31
+ parseAndValidate: () => parseAndValidate,
32
+ responses: () => responses,
33
+ routes: () => routes
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+
37
+ // src/routes.ts
38
+ var import_shared_schemas = require("@findatruck/shared-schemas");
39
+ var routes = {
40
+ ingestDriverView: {
41
+ path: "/ingest/driver-view",
42
+ method: "POST",
43
+ requestSchema: import_shared_schemas.ConvexUpdateSchema
44
+ },
45
+ ingestProviderAccountStatus: {
46
+ path: "/ingest/provider-account-status",
47
+ method: "POST",
48
+ requestSchema: import_shared_schemas.UpdateScrapeStatusMessage
49
+ }
50
+ };
51
+
52
+ // src/types.ts
53
+ var ConvexClientError = class extends Error {
54
+ constructor(message, endpoint, status, responseBody) {
55
+ super(message);
56
+ this.endpoint = endpoint;
57
+ this.status = status;
58
+ this.responseBody = responseBody;
59
+ this.name = "ConvexClientError";
60
+ }
61
+ };
62
+
63
+ // src/client.ts
64
+ var ConvexClient = class {
65
+ constructor(config) {
66
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
67
+ this.workerSecret = config.workerSecret;
68
+ }
69
+ /**
70
+ * Posts driver view data to the Convex ingestion endpoint.
71
+ */
72
+ async postDriverView(data) {
73
+ const route = routes.ingestDriverView;
74
+ const parseResult = route.requestSchema.safeParse(data);
75
+ if (!parseResult.success) {
76
+ throw new ConvexClientError(
77
+ `Invalid request: ${parseResult.error.message}`,
78
+ route.path
79
+ );
80
+ }
81
+ await this.makeRequest(route.path, route.method, data);
82
+ }
83
+ /**
84
+ * Posts provider account status updates to the Convex ingestion endpoint.
85
+ */
86
+ async postProviderAccountStatus(data) {
87
+ const route = routes.ingestProviderAccountStatus;
88
+ const parseResult = route.requestSchema.safeParse(data);
89
+ if (!parseResult.success) {
90
+ throw new ConvexClientError(
91
+ `Invalid request: ${parseResult.error.message}`,
92
+ route.path
93
+ );
94
+ }
95
+ await this.makeRequest(route.path, route.method, data);
96
+ }
97
+ async makeRequest(path, method, body) {
98
+ const url = `${this.baseUrl}${path}`;
99
+ const response = await fetch(url, {
100
+ method,
101
+ headers: {
102
+ "Content-Type": "application/json",
103
+ "Authorization": `Bearer ${this.workerSecret}`
104
+ },
105
+ body: JSON.stringify(body)
106
+ });
107
+ if (!response.ok) {
108
+ let responseBody;
109
+ try {
110
+ responseBody = await response.json();
111
+ } catch {
112
+ responseBody = await response.text();
113
+ }
114
+ throw new ConvexClientError(
115
+ `Request to ${path} failed with status ${response.status}`,
116
+ path,
117
+ response.status,
118
+ responseBody
119
+ );
120
+ }
121
+ }
122
+ };
123
+
124
+ // src/validation.ts
125
+ function checkWorkerSecret(req, expectedSecret) {
126
+ const authHeader = req.headers.get("Authorization");
127
+ if (!authHeader) {
128
+ return false;
129
+ }
130
+ const expectedValue = `Bearer ${expectedSecret}`;
131
+ if (authHeader.length !== expectedValue.length) {
132
+ return false;
133
+ }
134
+ let result = 0;
135
+ for (let i = 0; i < authHeader.length; i++) {
136
+ result |= authHeader.charCodeAt(i) ^ expectedValue.charCodeAt(i);
137
+ }
138
+ return result === 0;
139
+ }
140
+ async function parseAndValidate(schema, req) {
141
+ let body;
142
+ try {
143
+ body = await req.json();
144
+ } catch {
145
+ return { success: false, error: "Invalid JSON body" };
146
+ }
147
+ const result = schema.safeParse(body);
148
+ if (!result.success) {
149
+ return { success: false, error: result.error.message };
150
+ }
151
+ return { success: true, data: result.data };
152
+ }
153
+ var responses = {
154
+ /**
155
+ * Returns a 200 OK response with optional JSON body
156
+ */
157
+ ok(body) {
158
+ if (body === void 0) {
159
+ return new Response(null, { status: 200 });
160
+ }
161
+ return new Response(JSON.stringify(body), {
162
+ status: 200,
163
+ headers: { "Content-Type": "application/json" }
164
+ });
165
+ },
166
+ /**
167
+ * Returns a 401 Unauthorized response
168
+ */
169
+ unauthorized() {
170
+ return new Response(JSON.stringify({ error: "Unauthorized" }), {
171
+ status: 401,
172
+ headers: { "Content-Type": "application/json" }
173
+ });
174
+ },
175
+ /**
176
+ * Returns a 400 Bad Request response with error message
177
+ */
178
+ badRequest(error) {
179
+ return new Response(JSON.stringify({ error }), {
180
+ status: 400,
181
+ headers: { "Content-Type": "application/json" }
182
+ });
183
+ },
184
+ /**
185
+ * Returns a 500 Internal Server Error response with optional error message
186
+ */
187
+ serverError(error) {
188
+ return new Response(JSON.stringify({ error: error ?? "Internal server error" }), {
189
+ status: 500,
190
+ headers: { "Content-Type": "application/json" }
191
+ });
192
+ }
193
+ };
194
+
195
+ // src/index.ts
196
+ var import_shared_schemas2 = require("@findatruck/shared-schemas");
197
+ // Annotate the CommonJS export names for ESM import in node:
198
+ 0 && (module.exports = {
199
+ BatchConvexUpdateSchema,
200
+ ConvexClient,
201
+ ConvexClientError,
202
+ ConvexDriverSchema,
203
+ ConvexUpdateSchema,
204
+ ScrapeStatus,
205
+ UpdateScrapeStatusMessage,
206
+ checkWorkerSecret,
207
+ parseAndValidate,
208
+ responses,
209
+ routes
210
+ });
@@ -0,0 +1,154 @@
1
+ import * as _findatruck_shared_schemas from '@findatruck/shared-schemas';
2
+ import { ConvexUpdateData, UpdateScrapeStatusMessage } from '@findatruck/shared-schemas';
3
+ export { BatchConvexUpdateData, BatchConvexUpdateSchema, ConvexDriverData, ConvexDriverSchema, ConvexUpdateData, ConvexUpdateSchema, ScrapeStatus, UpdateScrapeStatusMessage, UpdateScrapeStatusMessage as UpdateScrapeStatusMessageType } from '@findatruck/shared-schemas';
4
+ import { z } from 'zod';
5
+
6
+ /**
7
+ * Configuration for the ConvexClient
8
+ */
9
+ interface ConvexClientConfig {
10
+ /** Base URL of the Convex HTTP endpoint (e.g., "https://your-deployment.convex.site") */
11
+ baseUrl: string;
12
+ /** Worker shared secret for authentication */
13
+ workerSecret: string;
14
+ }
15
+ /**
16
+ * Error thrown by the ConvexClient when requests fail
17
+ */
18
+ declare class ConvexClientError extends Error {
19
+ readonly endpoint: string;
20
+ readonly status?: number | undefined;
21
+ readonly responseBody?: unknown | undefined;
22
+ constructor(message: string, endpoint: string, status?: number | undefined, responseBody?: unknown | undefined);
23
+ }
24
+ /**
25
+ * Result of parsing and validating a request body
26
+ */
27
+ type ValidationResult<T> = {
28
+ success: true;
29
+ data: T;
30
+ } | {
31
+ success: false;
32
+ error: string;
33
+ };
34
+
35
+ /**
36
+ * Typed HTTP client for calling Convex HTTP endpoints from eld-aggregator.
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * const client = new ConvexClient({
41
+ * baseUrl: process.env.CONVEX_HTTP_URL,
42
+ * workerSecret: process.env.WORKER_SHARED_SECRET,
43
+ * });
44
+ *
45
+ * await client.postDriverView(convexUpdate);
46
+ * await client.postProviderAccountStatus(statusMessage);
47
+ * ```
48
+ */
49
+ declare class ConvexClient {
50
+ private readonly baseUrl;
51
+ private readonly workerSecret;
52
+ constructor(config: ConvexClientConfig);
53
+ /**
54
+ * Posts driver view data to the Convex ingestion endpoint.
55
+ */
56
+ postDriverView(data: ConvexUpdateData): Promise<void>;
57
+ /**
58
+ * Posts provider account status updates to the Convex ingestion endpoint.
59
+ */
60
+ postProviderAccountStatus(data: UpdateScrapeStatusMessage): Promise<void>;
61
+ private makeRequest;
62
+ }
63
+
64
+ /**
65
+ * Route definition with path, method, and request schema
66
+ */
67
+ interface RouteDefinition<TRequest extends z.ZodType> {
68
+ path: string;
69
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
70
+ requestSchema: TRequest;
71
+ }
72
+ /**
73
+ * Single source of truth for all Convex HTTP routes
74
+ * consumed from eld-aggregator and findatruck-next Convex backend.
75
+ */
76
+ declare const routes: {
77
+ readonly ingestDriverView: {
78
+ readonly path: "/ingest/driver-view";
79
+ readonly method: "POST";
80
+ readonly requestSchema: z.ZodObject<{
81
+ provider_url: z.ZodString;
82
+ username: z.ZodString;
83
+ drivers: z.ZodArray<z.ZodObject<{
84
+ driver_name: z.ZodOptional<z.ZodString>;
85
+ vehicle_id: z.ZodOptional<z.ZodString>;
86
+ driver_status: z.ZodString;
87
+ time_remaining_in_shift: z.ZodNumber;
88
+ time_remaining_till_break: z.ZodNumber;
89
+ time_remaining_in_week: z.ZodNumber;
90
+ time_remaining_in_drive: z.ZodNumber;
91
+ driver_current_location_latitude: z.ZodNumber;
92
+ driver_current_location_longitude: z.ZodNumber;
93
+ driver_current_location_address: z.ZodString;
94
+ license_number: z.ZodOptional<z.ZodString>;
95
+ license_state: z.ZodOptional<z.ZodString>;
96
+ speed: z.ZodOptional<z.ZodNumber>;
97
+ odometer: z.ZodOptional<z.ZodNumber>;
98
+ convex_provider_account_id: z.ZodString;
99
+ external_provider_account_id: z.ZodString;
100
+ external_driver_id: z.ZodString;
101
+ mileage_since_last_update: z.ZodOptional<z.ZodNumber>;
102
+ }, z.core.$strip>>;
103
+ version: z.ZodDefault<z.ZodString>;
104
+ }, z.core.$strip>;
105
+ };
106
+ readonly ingestProviderAccountStatus: {
107
+ readonly path: "/ingest/provider-account-status";
108
+ readonly method: "POST";
109
+ readonly requestSchema: z.ZodObject<{
110
+ status: z.ZodEnum<typeof _findatruck_shared_schemas.ScrapeStatus>;
111
+ correctPassword: z.ZodOptional<z.ZodBoolean>;
112
+ externalProviderAccountId: z.ZodString;
113
+ username: z.ZodString;
114
+ provider_url: z.ZodString;
115
+ driverCount: z.ZodOptional<z.ZodNumber>;
116
+ providerSlug: z.ZodOptional<z.ZodString>;
117
+ }, z.core.$strip>;
118
+ };
119
+ };
120
+ type RouteName = keyof typeof routes;
121
+
122
+ /**
123
+ * Constant-time string comparison to prevent timing attacks.
124
+ * Returns true if the Authorization header matches the expected Bearer token.
125
+ */
126
+ declare function checkWorkerSecret(req: Request, expectedSecret: string): boolean;
127
+ /**
128
+ * Parses the JSON body of a request and validates it against a Zod schema.
129
+ * Returns a ValidationResult with either the parsed data or an error message.
130
+ */
131
+ declare function parseAndValidate<T>(schema: z.ZodType<T>, req: Request): Promise<ValidationResult<T>>;
132
+ /**
133
+ * Standard HTTP responses for Convex httpAction handlers.
134
+ */
135
+ declare const responses: {
136
+ /**
137
+ * Returns a 200 OK response with optional JSON body
138
+ */
139
+ readonly ok: (body?: unknown) => Response;
140
+ /**
141
+ * Returns a 401 Unauthorized response
142
+ */
143
+ readonly unauthorized: () => Response;
144
+ /**
145
+ * Returns a 400 Bad Request response with error message
146
+ */
147
+ readonly badRequest: (error: string) => Response;
148
+ /**
149
+ * Returns a 500 Internal Server Error response with optional error message
150
+ */
151
+ readonly serverError: (error?: string) => Response;
152
+ };
153
+
154
+ export { ConvexClient, type ConvexClientConfig, ConvexClientError, type RouteDefinition, type RouteName, type ValidationResult, checkWorkerSecret, parseAndValidate, responses, routes };
@@ -0,0 +1,154 @@
1
+ import * as _findatruck_shared_schemas from '@findatruck/shared-schemas';
2
+ import { ConvexUpdateData, UpdateScrapeStatusMessage } from '@findatruck/shared-schemas';
3
+ export { BatchConvexUpdateData, BatchConvexUpdateSchema, ConvexDriverData, ConvexDriverSchema, ConvexUpdateData, ConvexUpdateSchema, ScrapeStatus, UpdateScrapeStatusMessage, UpdateScrapeStatusMessage as UpdateScrapeStatusMessageType } from '@findatruck/shared-schemas';
4
+ import { z } from 'zod';
5
+
6
+ /**
7
+ * Configuration for the ConvexClient
8
+ */
9
+ interface ConvexClientConfig {
10
+ /** Base URL of the Convex HTTP endpoint (e.g., "https://your-deployment.convex.site") */
11
+ baseUrl: string;
12
+ /** Worker shared secret for authentication */
13
+ workerSecret: string;
14
+ }
15
+ /**
16
+ * Error thrown by the ConvexClient when requests fail
17
+ */
18
+ declare class ConvexClientError extends Error {
19
+ readonly endpoint: string;
20
+ readonly status?: number | undefined;
21
+ readonly responseBody?: unknown | undefined;
22
+ constructor(message: string, endpoint: string, status?: number | undefined, responseBody?: unknown | undefined);
23
+ }
24
+ /**
25
+ * Result of parsing and validating a request body
26
+ */
27
+ type ValidationResult<T> = {
28
+ success: true;
29
+ data: T;
30
+ } | {
31
+ success: false;
32
+ error: string;
33
+ };
34
+
35
+ /**
36
+ * Typed HTTP client for calling Convex HTTP endpoints from eld-aggregator.
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * const client = new ConvexClient({
41
+ * baseUrl: process.env.CONVEX_HTTP_URL,
42
+ * workerSecret: process.env.WORKER_SHARED_SECRET,
43
+ * });
44
+ *
45
+ * await client.postDriverView(convexUpdate);
46
+ * await client.postProviderAccountStatus(statusMessage);
47
+ * ```
48
+ */
49
+ declare class ConvexClient {
50
+ private readonly baseUrl;
51
+ private readonly workerSecret;
52
+ constructor(config: ConvexClientConfig);
53
+ /**
54
+ * Posts driver view data to the Convex ingestion endpoint.
55
+ */
56
+ postDriverView(data: ConvexUpdateData): Promise<void>;
57
+ /**
58
+ * Posts provider account status updates to the Convex ingestion endpoint.
59
+ */
60
+ postProviderAccountStatus(data: UpdateScrapeStatusMessage): Promise<void>;
61
+ private makeRequest;
62
+ }
63
+
64
+ /**
65
+ * Route definition with path, method, and request schema
66
+ */
67
+ interface RouteDefinition<TRequest extends z.ZodType> {
68
+ path: string;
69
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
70
+ requestSchema: TRequest;
71
+ }
72
+ /**
73
+ * Single source of truth for all Convex HTTP routes
74
+ * consumed from eld-aggregator and findatruck-next Convex backend.
75
+ */
76
+ declare const routes: {
77
+ readonly ingestDriverView: {
78
+ readonly path: "/ingest/driver-view";
79
+ readonly method: "POST";
80
+ readonly requestSchema: z.ZodObject<{
81
+ provider_url: z.ZodString;
82
+ username: z.ZodString;
83
+ drivers: z.ZodArray<z.ZodObject<{
84
+ driver_name: z.ZodOptional<z.ZodString>;
85
+ vehicle_id: z.ZodOptional<z.ZodString>;
86
+ driver_status: z.ZodString;
87
+ time_remaining_in_shift: z.ZodNumber;
88
+ time_remaining_till_break: z.ZodNumber;
89
+ time_remaining_in_week: z.ZodNumber;
90
+ time_remaining_in_drive: z.ZodNumber;
91
+ driver_current_location_latitude: z.ZodNumber;
92
+ driver_current_location_longitude: z.ZodNumber;
93
+ driver_current_location_address: z.ZodString;
94
+ license_number: z.ZodOptional<z.ZodString>;
95
+ license_state: z.ZodOptional<z.ZodString>;
96
+ speed: z.ZodOptional<z.ZodNumber>;
97
+ odometer: z.ZodOptional<z.ZodNumber>;
98
+ convex_provider_account_id: z.ZodString;
99
+ external_provider_account_id: z.ZodString;
100
+ external_driver_id: z.ZodString;
101
+ mileage_since_last_update: z.ZodOptional<z.ZodNumber>;
102
+ }, z.core.$strip>>;
103
+ version: z.ZodDefault<z.ZodString>;
104
+ }, z.core.$strip>;
105
+ };
106
+ readonly ingestProviderAccountStatus: {
107
+ readonly path: "/ingest/provider-account-status";
108
+ readonly method: "POST";
109
+ readonly requestSchema: z.ZodObject<{
110
+ status: z.ZodEnum<typeof _findatruck_shared_schemas.ScrapeStatus>;
111
+ correctPassword: z.ZodOptional<z.ZodBoolean>;
112
+ externalProviderAccountId: z.ZodString;
113
+ username: z.ZodString;
114
+ provider_url: z.ZodString;
115
+ driverCount: z.ZodOptional<z.ZodNumber>;
116
+ providerSlug: z.ZodOptional<z.ZodString>;
117
+ }, z.core.$strip>;
118
+ };
119
+ };
120
+ type RouteName = keyof typeof routes;
121
+
122
+ /**
123
+ * Constant-time string comparison to prevent timing attacks.
124
+ * Returns true if the Authorization header matches the expected Bearer token.
125
+ */
126
+ declare function checkWorkerSecret(req: Request, expectedSecret: string): boolean;
127
+ /**
128
+ * Parses the JSON body of a request and validates it against a Zod schema.
129
+ * Returns a ValidationResult with either the parsed data or an error message.
130
+ */
131
+ declare function parseAndValidate<T>(schema: z.ZodType<T>, req: Request): Promise<ValidationResult<T>>;
132
+ /**
133
+ * Standard HTTP responses for Convex httpAction handlers.
134
+ */
135
+ declare const responses: {
136
+ /**
137
+ * Returns a 200 OK response with optional JSON body
138
+ */
139
+ readonly ok: (body?: unknown) => Response;
140
+ /**
141
+ * Returns a 401 Unauthorized response
142
+ */
143
+ readonly unauthorized: () => Response;
144
+ /**
145
+ * Returns a 400 Bad Request response with error message
146
+ */
147
+ readonly badRequest: (error: string) => Response;
148
+ /**
149
+ * Returns a 500 Internal Server Error response with optional error message
150
+ */
151
+ readonly serverError: (error?: string) => Response;
152
+ };
153
+
154
+ export { ConvexClient, type ConvexClientConfig, ConvexClientError, type RouteDefinition, type RouteName, type ValidationResult, checkWorkerSecret, parseAndValidate, responses, routes };
package/dist/index.js ADDED
@@ -0,0 +1,182 @@
1
+ // src/routes.ts
2
+ import {
3
+ ConvexUpdateSchema,
4
+ UpdateScrapeStatusMessage
5
+ } from "@findatruck/shared-schemas";
6
+ var routes = {
7
+ ingestDriverView: {
8
+ path: "/ingest/driver-view",
9
+ method: "POST",
10
+ requestSchema: ConvexUpdateSchema
11
+ },
12
+ ingestProviderAccountStatus: {
13
+ path: "/ingest/provider-account-status",
14
+ method: "POST",
15
+ requestSchema: UpdateScrapeStatusMessage
16
+ }
17
+ };
18
+
19
+ // src/types.ts
20
+ var ConvexClientError = class extends Error {
21
+ constructor(message, endpoint, status, responseBody) {
22
+ super(message);
23
+ this.endpoint = endpoint;
24
+ this.status = status;
25
+ this.responseBody = responseBody;
26
+ this.name = "ConvexClientError";
27
+ }
28
+ };
29
+
30
+ // src/client.ts
31
+ var ConvexClient = class {
32
+ constructor(config) {
33
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
34
+ this.workerSecret = config.workerSecret;
35
+ }
36
+ /**
37
+ * Posts driver view data to the Convex ingestion endpoint.
38
+ */
39
+ async postDriverView(data) {
40
+ const route = routes.ingestDriverView;
41
+ const parseResult = route.requestSchema.safeParse(data);
42
+ if (!parseResult.success) {
43
+ throw new ConvexClientError(
44
+ `Invalid request: ${parseResult.error.message}`,
45
+ route.path
46
+ );
47
+ }
48
+ await this.makeRequest(route.path, route.method, data);
49
+ }
50
+ /**
51
+ * Posts provider account status updates to the Convex ingestion endpoint.
52
+ */
53
+ async postProviderAccountStatus(data) {
54
+ const route = routes.ingestProviderAccountStatus;
55
+ const parseResult = route.requestSchema.safeParse(data);
56
+ if (!parseResult.success) {
57
+ throw new ConvexClientError(
58
+ `Invalid request: ${parseResult.error.message}`,
59
+ route.path
60
+ );
61
+ }
62
+ await this.makeRequest(route.path, route.method, data);
63
+ }
64
+ async makeRequest(path, method, body) {
65
+ const url = `${this.baseUrl}${path}`;
66
+ const response = await fetch(url, {
67
+ method,
68
+ headers: {
69
+ "Content-Type": "application/json",
70
+ "Authorization": `Bearer ${this.workerSecret}`
71
+ },
72
+ body: JSON.stringify(body)
73
+ });
74
+ if (!response.ok) {
75
+ let responseBody;
76
+ try {
77
+ responseBody = await response.json();
78
+ } catch {
79
+ responseBody = await response.text();
80
+ }
81
+ throw new ConvexClientError(
82
+ `Request to ${path} failed with status ${response.status}`,
83
+ path,
84
+ response.status,
85
+ responseBody
86
+ );
87
+ }
88
+ }
89
+ };
90
+
91
+ // src/validation.ts
92
+ function checkWorkerSecret(req, expectedSecret) {
93
+ const authHeader = req.headers.get("Authorization");
94
+ if (!authHeader) {
95
+ return false;
96
+ }
97
+ const expectedValue = `Bearer ${expectedSecret}`;
98
+ if (authHeader.length !== expectedValue.length) {
99
+ return false;
100
+ }
101
+ let result = 0;
102
+ for (let i = 0; i < authHeader.length; i++) {
103
+ result |= authHeader.charCodeAt(i) ^ expectedValue.charCodeAt(i);
104
+ }
105
+ return result === 0;
106
+ }
107
+ async function parseAndValidate(schema, req) {
108
+ let body;
109
+ try {
110
+ body = await req.json();
111
+ } catch {
112
+ return { success: false, error: "Invalid JSON body" };
113
+ }
114
+ const result = schema.safeParse(body);
115
+ if (!result.success) {
116
+ return { success: false, error: result.error.message };
117
+ }
118
+ return { success: true, data: result.data };
119
+ }
120
+ var responses = {
121
+ /**
122
+ * Returns a 200 OK response with optional JSON body
123
+ */
124
+ ok(body) {
125
+ if (body === void 0) {
126
+ return new Response(null, { status: 200 });
127
+ }
128
+ return new Response(JSON.stringify(body), {
129
+ status: 200,
130
+ headers: { "Content-Type": "application/json" }
131
+ });
132
+ },
133
+ /**
134
+ * Returns a 401 Unauthorized response
135
+ */
136
+ unauthorized() {
137
+ return new Response(JSON.stringify({ error: "Unauthorized" }), {
138
+ status: 401,
139
+ headers: { "Content-Type": "application/json" }
140
+ });
141
+ },
142
+ /**
143
+ * Returns a 400 Bad Request response with error message
144
+ */
145
+ badRequest(error) {
146
+ return new Response(JSON.stringify({ error }), {
147
+ status: 400,
148
+ headers: { "Content-Type": "application/json" }
149
+ });
150
+ },
151
+ /**
152
+ * Returns a 500 Internal Server Error response with optional error message
153
+ */
154
+ serverError(error) {
155
+ return new Response(JSON.stringify({ error: error ?? "Internal server error" }), {
156
+ status: 500,
157
+ headers: { "Content-Type": "application/json" }
158
+ });
159
+ }
160
+ };
161
+
162
+ // src/index.ts
163
+ import {
164
+ ConvexUpdateSchema as ConvexUpdateSchema2,
165
+ ConvexDriverSchema,
166
+ BatchConvexUpdateSchema,
167
+ UpdateScrapeStatusMessage as UpdateScrapeStatusMessage2,
168
+ ScrapeStatus
169
+ } from "@findatruck/shared-schemas";
170
+ export {
171
+ BatchConvexUpdateSchema,
172
+ ConvexClient,
173
+ ConvexClientError,
174
+ ConvexDriverSchema,
175
+ ConvexUpdateSchema2 as ConvexUpdateSchema,
176
+ ScrapeStatus,
177
+ UpdateScrapeStatusMessage2 as UpdateScrapeStatusMessage,
178
+ checkWorkerSecret,
179
+ parseAndValidate,
180
+ responses,
181
+ routes
182
+ };
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@findatruck/convex-client",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "sideEffects": false,
19
+ "scripts": {
20
+ "build": "tsup src/index.ts --dts --format esm,cjs --out-dir dist --clean",
21
+ "prepublishOnly": "npm run build",
22
+ "test": "vitest run",
23
+ "test:watch": "vitest"
24
+ },
25
+ "dependencies": {
26
+ "@findatruck/shared-schemas": "^2.9.0"
27
+ },
28
+ "peerDependencies": {
29
+ "zod": "^4.1.11"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^24.7.0",
33
+ "tsup": "^8.0.0",
34
+ "typescript": "^5.9.3",
35
+ "vitest": "^3.2.4",
36
+ "zod": "^4.1.11"
37
+ }
38
+ }