truckaurbus 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/README.md ADDED
@@ -0,0 +1,18 @@
1
+ # truckaurbus (TypeScript)
2
+
3
+ ```
4
+ npm install truckaurbus
5
+ ```
6
+
7
+ ```ts
8
+ import { Truckaurbus } from "truckaurbus";
9
+
10
+ const tab = new Truckaurbus("tab_live_...");
11
+ const { hits } = await tab.variants.search({ q: "12 tyre tipper", price_max: 4_000_000, sort: "price_asc" });
12
+ const sheet = await tab.variants.get(String(hits[0].slug));
13
+ const dealers = await tab.dealers.near("442001", { km: 50, brand: "tata-motors" });
14
+ await tab.leads.create({ kind: "quote", buyer_name: "A Buyer", buyer_phone: "9876543210", vehicle_ref: String(sheet.slug), consent: true });
15
+ console.log(tab.rateLimit);
16
+ ```
17
+
18
+ Works in Node 18+ and the browser (use a server-side key; never ship a key to a browser). Prices carry a `price_kind` (maker, dealer, reported, estimate); say which when you show them. Free-tier keys must attribute the data ("Data by Truckaurbus"). Docs: https://docs.truckaurbus.com/developers/
@@ -0,0 +1,83 @@
1
+ /** Truckaurbus API v1 client. Every method returns the API's JSON. Errors throw TruckaurbusError with the status and detail.
2
+ * Free-tier keys must attribute the data ("Data by Truckaurbus") wherever it is shown. */
3
+ export declare class TruckaurbusError extends Error {
4
+ readonly status: number;
5
+ readonly detail: string;
6
+ readonly requestId?: string;
7
+ constructor(status: number, detail: string, requestId?: string);
8
+ }
9
+ export type SearchFilters = {
10
+ q?: string;
11
+ vehicle_class?: string;
12
+ manufacturer?: string;
13
+ body_type?: string;
14
+ fuel?: string;
15
+ axle_config?: string;
16
+ gvw_min?: number;
17
+ gvw_max?: number;
18
+ price_min?: number;
19
+ price_max?: number;
20
+ power_min?: number;
21
+ sort?: "price_asc" | "price_desc" | "gvw_asc" | "gvw_desc" | "power_desc" | "newest";
22
+ limit?: number;
23
+ offset?: number;
24
+ };
25
+ export type LeadInput = {
26
+ kind: "callback" | "quote" | "finance" | "insurance";
27
+ buyer_name: string;
28
+ buyer_phone: string;
29
+ buyer_pin?: string;
30
+ vehicle_ref?: string;
31
+ intent?: "now" | "soon" | "exploring";
32
+ notes?: string;
33
+ consent: true;
34
+ };
35
+ type Fetch = typeof fetch;
36
+ export declare class Truckaurbus {
37
+ readonly baseUrl: string;
38
+ lastRequestId?: string;
39
+ rateLimit: Record<string, string>;
40
+ private readonly fetchImpl;
41
+ private readonly apiKey;
42
+ constructor(apiKey: string, options?: {
43
+ baseUrl?: string;
44
+ fetch?: Fetch;
45
+ });
46
+ readonly variants: {
47
+ search: (filters?: SearchFilters) => Promise<{
48
+ hits: Record<string, unknown>[];
49
+ total: number;
50
+ facets: Record<string, Record<string, number>>;
51
+ }>;
52
+ get: (slug: string) => Promise<Record<string, unknown>>;
53
+ ratings: (slug: string) => Promise<Record<string, unknown>>;
54
+ };
55
+ readonly dealers: {
56
+ near: (pin: string, options?: {
57
+ km?: number;
58
+ kind?: string;
59
+ brand?: string;
60
+ }) => Promise<Record<string, unknown>[]>;
61
+ };
62
+ readonly pincodes: {
63
+ get: (pin: string) => Promise<Record<string, unknown>>;
64
+ };
65
+ readonly leads: {
66
+ create: (lead: LeadInput) => Promise<Record<string, unknown>>;
67
+ };
68
+ readonly webhooks: {
69
+ list: () => Promise<Record<string, unknown>[]>;
70
+ create: (url: string, events: string[]) => Promise<Record<string, unknown>>;
71
+ delete: (id: number) => Promise<{
72
+ deleted: boolean;
73
+ }>;
74
+ };
75
+ manufacturers(): Promise<Record<string, unknown>[]>;
76
+ exportVariantsCsv(): Promise<string>;
77
+ private headers;
78
+ private note;
79
+ private detail;
80
+ private get;
81
+ private request;
82
+ }
83
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,90 @@
1
+ /** Truckaurbus API v1 client. Every method returns the API's JSON. Errors throw TruckaurbusError with the status and detail.
2
+ * Free-tier keys must attribute the data ("Data by Truckaurbus") wherever it is shown. */
3
+ export class TruckaurbusError extends Error {
4
+ status;
5
+ detail;
6
+ requestId;
7
+ constructor(status, detail, requestId) {
8
+ super(`${status}: ${detail}`);
9
+ this.status = status;
10
+ this.detail = detail;
11
+ this.requestId = requestId;
12
+ }
13
+ }
14
+ export class Truckaurbus {
15
+ baseUrl;
16
+ lastRequestId;
17
+ rateLimit = {};
18
+ fetchImpl;
19
+ apiKey;
20
+ constructor(apiKey, options = {}) {
21
+ if (!apiKey)
22
+ throw new Error("an API key is required (create one on your account page at truckaurbus.com)");
23
+ this.apiKey = apiKey;
24
+ this.baseUrl = (options.baseUrl ?? "https://api.truckaurbus.com/v1").replace(/\/+$/, "");
25
+ this.fetchImpl = options.fetch ?? fetch;
26
+ }
27
+ variants = {
28
+ search: (filters = {}) => this.get("/variants", filters),
29
+ get: (slug) => this.get(`/variants/${encodeURIComponent(slug)}`),
30
+ ratings: (slug) => this.get(`/variants/${encodeURIComponent(slug)}/ratings`),
31
+ };
32
+ dealers = { near: (pin, options = {}) => this.get("/dealers", { pin, ...options }) };
33
+ pincodes = { get: (pin) => this.get(`/pincodes/${encodeURIComponent(pin)}`) };
34
+ leads = {
35
+ create: (lead) => {
36
+ if (!lead.consent)
37
+ throw new Error("consent is required before a lead is recorded");
38
+ return this.request("POST", "/leads", undefined, { ...lead, wants_finance: lead.kind === "finance", wants_insurance: lead.kind === "insurance", source: "sdk-ts" });
39
+ },
40
+ };
41
+ webhooks = {
42
+ list: () => this.get("/webhooks"),
43
+ create: (url, events) => this.request("POST", "/webhooks", undefined, { url, events }),
44
+ delete: (id) => this.request("DELETE", `/webhooks/${id}`),
45
+ };
46
+ manufacturers() {
47
+ return this.get("/manufacturers");
48
+ }
49
+ async exportVariantsCsv() {
50
+ const res = await this.fetchImpl(`${this.baseUrl}/export/variants.csv`, { headers: this.headers() });
51
+ this.note(res);
52
+ if (!res.ok)
53
+ throw new TruckaurbusError(res.status, await this.detail(res), this.lastRequestId);
54
+ return res.text();
55
+ }
56
+ headers() {
57
+ return { Authorization: `Bearer ${this.apiKey}`, "User-Agent": "truckaurbus-ts/0.1.0" };
58
+ }
59
+ note(res) {
60
+ this.lastRequestId = res.headers.get("x-request-id") ?? undefined;
61
+ this.rateLimit = {};
62
+ res.headers.forEach((v, k) => {
63
+ if (k.toLowerCase().startsWith("x-ratelimit-"))
64
+ this.rateLimit[k.toLowerCase().slice("x-ratelimit-".length)] = v;
65
+ });
66
+ }
67
+ async detail(res) {
68
+ try {
69
+ const data = (await res.json());
70
+ return data.detail ?? `${res.status}`;
71
+ }
72
+ catch {
73
+ return `${res.status}`;
74
+ }
75
+ }
76
+ get(path, params) {
77
+ return this.request("GET", path, params);
78
+ }
79
+ async request(method, path, params, body) {
80
+ const url = new URL(`${this.baseUrl}${path}`);
81
+ for (const [k, v] of Object.entries(params ?? {}))
82
+ if (v !== undefined && v !== null && v !== "")
83
+ url.searchParams.set(k, String(v));
84
+ const res = await this.fetchImpl(url.toString(), { method, headers: { ...this.headers(), ...(body ? { "content-type": "application/json" } : {}) }, body: body ? JSON.stringify(body) : undefined });
85
+ this.note(res);
86
+ if (!res.ok)
87
+ throw new TruckaurbusError(res.status, await this.detail(res), this.lastRequestId);
88
+ return (await res.json());
89
+ }
90
+ }
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "truckaurbus",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript client for the Truckaurbus API v1: Indian commercial vehicle specs, prices, ratings, dealers and leads",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc -p tsconfig.build.json",
21
+ "test": "node --experimental-strip-types --test test/*.test.ts",
22
+ "typecheck": "tsc --noEmit -p .",
23
+ "prepublishOnly": "npm run build && npm test"
24
+ },
25
+ "license": "MIT",
26
+ "devDependencies": {
27
+ "typescript": "^5.6.0",
28
+ "@types/node": "^22.0.0"
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/truckaurbus/truckaurbus-services.git",
33
+ "directory": "packages/tab-sdk-ts"
34
+ },
35
+ "homepage": "https://docs.truckaurbus.com/developers/",
36
+ "keywords": [
37
+ "truckaurbus",
38
+ "commercial vehicles",
39
+ "india",
40
+ "trucks",
41
+ "buses",
42
+ "api",
43
+ "sdk"
44
+ ],
45
+ "engines": {
46
+ "node": ">=18"
47
+ }
48
+ }