@sfutureapps/db-sdk 0.3.14 → 0.3.15

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/package.json CHANGED
@@ -1,25 +1,16 @@
1
1
  {
2
2
  "name": "@sfutureapps/db-sdk",
3
- "version": "0.3.14",
3
+ "version": "0.3.15",
4
4
  "description": "SfutureApps JS SDK for ThinkPHP DB Gateway (MySQL)",
5
5
  "license": "MIT",
6
- "main": "dist/index.cjs",
7
- "module": "dist/index.mjs",
8
- "types": "dist/index.d.ts",
6
+ "type": "module",
7
+ "main": "./src/index.js",
9
8
  "exports": {
10
- ".": {
11
- "types": "./dist/index.d.ts",
12
- "import": "./dist/index.mjs",
13
- "require": "./dist/index.cjs"
14
- }
9
+ ".": "./src/index.js"
15
10
  },
16
11
  "files": [
17
- "dist"
12
+ "src"
18
13
  ],
19
- "scripts": {
20
- "build": "tsup src/index.ts --format cjs,esm --dts",
21
- "dev": "tsup src/index.ts --format cjs,esm --dts --watch"
22
- },
23
14
  "devDependencies": {
24
15
  "tsup": "^8.0.0",
25
16
  "typescript": "^5.4.0"
package/src/client.js ADDED
@@ -0,0 +1,53 @@
1
+ import axios from "axios";
2
+
3
+ export class HttpClient {
4
+ constructor(baseUrl, opts = {}) {
5
+ this.baseUrl = String(baseUrl).replace(/\/+$/, "");
6
+ this.apiKey = opts.apiKey;
7
+ this.accessToken = opts.accessToken;
8
+ this.extraHeaders = opts.headers || {};
9
+
10
+ this.ax = axios.create({
11
+ baseURL: this.baseUrl,
12
+ timeout: opts.timeoutMs || 15000,
13
+ headers: {
14
+ "Content-Type": "application/json",
15
+ ...this.extraHeaders,
16
+ },
17
+ });
18
+ }
19
+
20
+ async post(path, body, config = {}) {
21
+ const headers = {
22
+ ...this.extraHeaders,
23
+ ...(config.headers || {}),
24
+ };
25
+
26
+ if (this.apiKey) headers["x-api-key"] = this.apiKey;
27
+
28
+ const token = this.accessToken?.();
29
+ if (token) headers["Authorization"] = `Bearer ${token}`;
30
+
31
+ try {
32
+ const res = await this.ax.post(path, body, { ...config, headers });
33
+ const payload = res.data || {};
34
+ return {
35
+ data: payload.data ?? null,
36
+ count: payload.count ?? null,
37
+ meta: payload.meta ?? null,
38
+ error: payload.error ?? null,
39
+ };
40
+ } catch (e) {
41
+ const status = e?.response?.status ?? 0;
42
+ const payload = e?.response?.data ?? null;
43
+ return {
44
+ data: null,
45
+ error: {
46
+ status,
47
+ message: payload?.error?.message ?? e?.message ?? "Network error",
48
+ details: payload ?? e,
49
+ },
50
+ };
51
+ }
52
+ }
53
+ }
package/src/index.js ADDED
@@ -0,0 +1,11 @@
1
+ import { HttpClient } from "./client.js";
2
+ import { QueryBuilder } from "./query-builder.js";
3
+
4
+ export function createClient(baseUrl, opts = {}) {
5
+ const http = new HttpClient(baseUrl, opts);
6
+ return {
7
+ from(table) {
8
+ return new QueryBuilder(http, table);
9
+ },
10
+ };
11
+ }
@@ -0,0 +1,172 @@
1
+ export class QueryBuilder {
2
+ constructor(client, table) {
3
+ this.client = client;
4
+ this.tableName = table;
5
+
6
+ this._select = ["*"];
7
+ this._filters = [];
8
+ this._order = [];
9
+ this._limit = null;
10
+
11
+ this._page = null;
12
+ this._offset = null;
13
+
14
+ this._withCount = false;
15
+ this._single = false;
16
+
17
+ this._distinct = false;
18
+ this._group = [];
19
+ this._having = [];
20
+ }
21
+
22
+ // ---- select ----
23
+ select(columns = "*") {
24
+ const cols = String(columns).trim();
25
+ this._select = cols === "*" || cols === "" ? ["*"] : cols.split(",").map(s => s.trim()).filter(Boolean);
26
+ return this;
27
+ }
28
+
29
+ // ---- filters ----
30
+ _addFilter(col, op, val) {
31
+ this._filters.push({ col, op, val });
32
+ return this;
33
+ }
34
+ eq(col, val) { return this._addFilter(col, "eq", val); }
35
+ neq(col, val) { return this._addFilter(col, "neq", val); }
36
+ gt(col, val) { return this._addFilter(col, "gt", val); }
37
+ gte(col, val) { return this._addFilter(col, "gte", val); }
38
+ lt(col, val) { return this._addFilter(col, "lt", val); }
39
+ lte(col, val) { return this._addFilter(col, "lte", val); }
40
+
41
+ like(col, val) { return this._addFilter(col, "like", val); }
42
+ notLike(col, val) { return this._addFilter(col, "notLike", val); }
43
+
44
+ between(col, range) { return this._addFilter(col, "between", range); }
45
+ notBetween(col, range) { return this._addFilter(col, "notBetween", range); }
46
+
47
+ in(col, vals) { return this._addFilter(col, "in", vals); }
48
+ notIn(col, vals) { return this._addFilter(col, "notIn", vals); }
49
+
50
+ isNull(col) { return this._addFilter(col, "isNull", null); }
51
+ notNull(col) { return this._addFilter(col, "notNull", null); }
52
+
53
+ regexp(col, pattern) { return this._addFilter(col, "regexp", pattern); }
54
+ notRegexp(col, pattern) { return this._addFilter(col, "notRegexp", pattern); }
55
+
56
+ whereTime(col, op, time) { return this._addFilter(col, "time", { op, val: time }); }
57
+ betweenTime(col, range) { return this._addFilter(col, "time", { op: "between", val: range }); }
58
+
59
+ findInSet(col, val) { return this._addFilter(col, "findInSet", val); }
60
+
61
+ // ---- order ----
62
+ order(col, opts = {}) {
63
+ const dir = opts.ascending === false ? "desc" : "asc";
64
+ this._order.push({ col, dir });
65
+ return this;
66
+ }
67
+
68
+ // ---- pagination ----
69
+ limit(n) {
70
+ this._limit = Math.max(1, Number(n) | 0);
71
+ return this;
72
+ }
73
+
74
+ page(page, limit) {
75
+ this._page = Math.max(1, Number(page) | 0);
76
+ this._limit = Math.max(1, Number(limit) | 0);
77
+ this._offset = null;
78
+ return this;
79
+ }
80
+
81
+ range(from, to) {
82
+ const f = Math.max(0, Number(from) | 0);
83
+ const t = Math.max(f, Number(to) | 0);
84
+ this._offset = f;
85
+ this._limit = t - f + 1;
86
+ this._page = null;
87
+ return this;
88
+ }
89
+
90
+ // pagination total rows
91
+ withCount() { this._withCount = true; return this; }
92
+
93
+ single() { this._single = true; this.limit(1); return this; }
94
+
95
+ // ---- group/having/distinct ----
96
+ distinct() { this._distinct = true; return this; }
97
+
98
+ group(cols) {
99
+ this._group = String(cols).split(",").map(s => s.trim()).filter(Boolean);
100
+ return this;
101
+ }
102
+
103
+ havingEq(col, val) { this._having.push({ col, op: "eq", val }); return this; }
104
+ havingGte(col, val) { this._having.push({ col, op: "gte", val }); return this; }
105
+ havingLte(col, val) { this._having.push({ col, op: "lte", val }); return this; }
106
+ havingGt(col, val) { this._having.push({ col, op: "gt", val }); return this; }
107
+ havingLt(col, val) { this._having.push({ col, op: "lt", val }); return this; }
108
+ havingNeq(col, val) { this._having.push({ col, op: "neq", val }); return this; }
109
+
110
+ // ---- execute ----
111
+ async execute() {
112
+ const payload = {
113
+ table: this.tableName,
114
+ select: this._select,
115
+ filters: this._filters,
116
+ order: this._order,
117
+ limit: this._limit ?? 20,
118
+ count: this._withCount,
119
+ distinct: this._distinct,
120
+ group: this._group,
121
+ having: this._having,
122
+ };
123
+
124
+ if (this._page !== null) payload.page = this._page;
125
+ if (this._offset !== null) payload.offset = this._offset;
126
+
127
+ const res = await this.client.post("/db/v1/query", payload);
128
+
129
+ if (res.error) return res;
130
+
131
+ if (this._single) {
132
+ const first = Array.isArray(res.data) ? (res.data[0] ?? null) : null;
133
+ return { data: first, error: null, count: res.count ?? null, meta: res.meta ?? null };
134
+ }
135
+
136
+ return res;
137
+ }
138
+
139
+ // ---- aggregates ----
140
+ _agg(fn, field = "*") {
141
+ return this.client.post("/db/v1/query", {
142
+ table: this.tableName,
143
+ aggregate: { fn, field },
144
+ filters: this._filters,
145
+ });
146
+ }
147
+
148
+ count(field = "*") { return this._agg("count", field); }
149
+ sum(field) { return this._agg("sum", field); }
150
+ avg(field) { return this._agg("avg", field); }
151
+ min(field) { return this._agg("min", field); }
152
+ max(field) { return this._agg("max", field); }
153
+
154
+ // ---- write ----
155
+ insert(values) {
156
+ return this.client.post("/db/v1/insert", { table: this.tableName, values });
157
+ }
158
+
159
+ update(values) {
160
+ if (this._filters.length === 0) {
161
+ return Promise.resolve({ data: null, error: { message: "Update requires filters (e.g. .eq('id', 1))" } });
162
+ }
163
+ return this.client.post("/db/v1/update", { table: this.tableName, values, filters: this._filters });
164
+ }
165
+
166
+ delete() {
167
+ if (this._filters.length === 0) {
168
+ return Promise.resolve({ data: null, error: { message: "Delete requires filters (e.g. .eq('id', 1))" } });
169
+ }
170
+ return this.client.post("/db/v1/delete", { table: this.tableName, filters: this._filters });
171
+ }
172
+ }
package/dist/index.d.mts DELETED
@@ -1,120 +0,0 @@
1
- import { AxiosRequestConfig } from 'axios';
2
-
3
- type FilterOp = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "like" | "notLike" | "between" | "notBetween" | "in" | "notIn" | "isNull" | "notNull" | "regexp" | "notRegexp" | "time" | "findInSet";
4
- type Filter = {
5
- col: string;
6
- op: FilterOp;
7
- val: any;
8
- };
9
- type Order = {
10
- col: string;
11
- dir: "asc" | "desc";
12
- };
13
- type DbError = {
14
- status?: number;
15
- message: string;
16
- details?: any;
17
- };
18
- type DbResponse<T> = {
19
- data: T | null;
20
- error: DbError | null;
21
- count?: number | null;
22
- meta?: any;
23
- };
24
- type ClientOptions = {
25
- apiKey?: string;
26
- accessToken?: () => string | null;
27
- headers?: Record<string, string>;
28
- };
29
-
30
- declare class HttpClient {
31
- private baseUrl;
32
- private apiKey?;
33
- private extraHeaders;
34
- private ax;
35
- constructor(baseUrl: string, opts?: ClientOptions);
36
- post<T>(path: string, body: any, config?: AxiosRequestConfig): Promise<DbResponse<T>>;
37
- }
38
-
39
- type OrderOpts = {
40
- ascending?: boolean;
41
- };
42
- declare class QueryBuilder<Row = any> {
43
- private tableName;
44
- private client;
45
- private _select;
46
- private _filters;
47
- private _order;
48
- private _limit;
49
- private _page;
50
- private _offset;
51
- private _withCount;
52
- private _single;
53
- private _distinct;
54
- private _group;
55
- private _having;
56
- constructor(client: HttpClient, table: string);
57
- select(columns?: string): this;
58
- private addFilter;
59
- eq(col: string, val: any): this;
60
- neq(col: string, val: any): this;
61
- gt(col: string, val: any): this;
62
- gte(col: string, val: any): this;
63
- lt(col: string, val: any): this;
64
- lte(col: string, val: any): this;
65
- like(col: string, val: string): this;
66
- notLike(col: string, val: string): this;
67
- between(col: string, range: [any, any]): this;
68
- notBetween(col: string, range: [any, any]): this;
69
- in(col: string, vals: any[]): this;
70
- notIn(col: string, vals: any[]): this;
71
- isNull(col: string): this;
72
- notNull(col: string): this;
73
- regexp(col: string, pattern: string): this;
74
- notRegexp(col: string, pattern: string): this;
75
- whereTime(col: string, op: ">" | ">=" | "<" | "<=", time: string): this;
76
- betweenTime(col: string, range: [string, string]): this;
77
- findInSet(col: string, val: string | number): this;
78
- order(col: string, opts?: OrderOpts): this;
79
- limit(n: number): this;
80
- page(page: number, limit: number): this;
81
- range(from: number, to: number): this;
82
- /** Pagination total rows (not aggregate). */
83
- withCount(): this;
84
- single(): this;
85
- distinct(): this;
86
- group(cols: string): this;
87
- havingEq(col: string, val: any): this;
88
- havingGte(col: string, val: any): this;
89
- havingLte(col: string, val: any): this;
90
- havingGt(col: string, val: any): this;
91
- havingLt(col: string, val: any): this;
92
- havingNeq(col: string, val: any): this;
93
- execute(): Promise<DbResponse<Row[] | Row>>;
94
- private agg;
95
- /** Aggregate count value (COUNT(*)) */
96
- count(field?: string): Promise<DbResponse<number>>;
97
- sum(field: string): Promise<DbResponse<number>>;
98
- avg(field: string): Promise<DbResponse<number>>;
99
- min(field: string): Promise<DbResponse<number>>;
100
- max(field: string): Promise<DbResponse<number>>;
101
- insert(values: Partial<Row> | Array<Partial<Row>>): Promise<DbResponse<unknown>>;
102
- update(values: Partial<Row>): Promise<DbResponse<unknown>> | Promise<{
103
- data: null;
104
- error: {
105
- message: string;
106
- };
107
- }>;
108
- delete(): Promise<DbResponse<unknown>> | Promise<{
109
- data: null;
110
- error: {
111
- message: string;
112
- };
113
- }>;
114
- }
115
-
116
- declare function createClient(baseUrl: string, opts?: ClientOptions): {
117
- from<Row = any>(table: string): QueryBuilder<Row>;
118
- };
119
-
120
- export { type ClientOptions, type DbError, type DbResponse, type Filter, type Order, createClient };
package/dist/index.d.ts DELETED
@@ -1,120 +0,0 @@
1
- import { AxiosRequestConfig } from 'axios';
2
-
3
- type FilterOp = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "like" | "notLike" | "between" | "notBetween" | "in" | "notIn" | "isNull" | "notNull" | "regexp" | "notRegexp" | "time" | "findInSet";
4
- type Filter = {
5
- col: string;
6
- op: FilterOp;
7
- val: any;
8
- };
9
- type Order = {
10
- col: string;
11
- dir: "asc" | "desc";
12
- };
13
- type DbError = {
14
- status?: number;
15
- message: string;
16
- details?: any;
17
- };
18
- type DbResponse<T> = {
19
- data: T | null;
20
- error: DbError | null;
21
- count?: number | null;
22
- meta?: any;
23
- };
24
- type ClientOptions = {
25
- apiKey?: string;
26
- accessToken?: () => string | null;
27
- headers?: Record<string, string>;
28
- };
29
-
30
- declare class HttpClient {
31
- private baseUrl;
32
- private apiKey?;
33
- private extraHeaders;
34
- private ax;
35
- constructor(baseUrl: string, opts?: ClientOptions);
36
- post<T>(path: string, body: any, config?: AxiosRequestConfig): Promise<DbResponse<T>>;
37
- }
38
-
39
- type OrderOpts = {
40
- ascending?: boolean;
41
- };
42
- declare class QueryBuilder<Row = any> {
43
- private tableName;
44
- private client;
45
- private _select;
46
- private _filters;
47
- private _order;
48
- private _limit;
49
- private _page;
50
- private _offset;
51
- private _withCount;
52
- private _single;
53
- private _distinct;
54
- private _group;
55
- private _having;
56
- constructor(client: HttpClient, table: string);
57
- select(columns?: string): this;
58
- private addFilter;
59
- eq(col: string, val: any): this;
60
- neq(col: string, val: any): this;
61
- gt(col: string, val: any): this;
62
- gte(col: string, val: any): this;
63
- lt(col: string, val: any): this;
64
- lte(col: string, val: any): this;
65
- like(col: string, val: string): this;
66
- notLike(col: string, val: string): this;
67
- between(col: string, range: [any, any]): this;
68
- notBetween(col: string, range: [any, any]): this;
69
- in(col: string, vals: any[]): this;
70
- notIn(col: string, vals: any[]): this;
71
- isNull(col: string): this;
72
- notNull(col: string): this;
73
- regexp(col: string, pattern: string): this;
74
- notRegexp(col: string, pattern: string): this;
75
- whereTime(col: string, op: ">" | ">=" | "<" | "<=", time: string): this;
76
- betweenTime(col: string, range: [string, string]): this;
77
- findInSet(col: string, val: string | number): this;
78
- order(col: string, opts?: OrderOpts): this;
79
- limit(n: number): this;
80
- page(page: number, limit: number): this;
81
- range(from: number, to: number): this;
82
- /** Pagination total rows (not aggregate). */
83
- withCount(): this;
84
- single(): this;
85
- distinct(): this;
86
- group(cols: string): this;
87
- havingEq(col: string, val: any): this;
88
- havingGte(col: string, val: any): this;
89
- havingLte(col: string, val: any): this;
90
- havingGt(col: string, val: any): this;
91
- havingLt(col: string, val: any): this;
92
- havingNeq(col: string, val: any): this;
93
- execute(): Promise<DbResponse<Row[] | Row>>;
94
- private agg;
95
- /** Aggregate count value (COUNT(*)) */
96
- count(field?: string): Promise<DbResponse<number>>;
97
- sum(field: string): Promise<DbResponse<number>>;
98
- avg(field: string): Promise<DbResponse<number>>;
99
- min(field: string): Promise<DbResponse<number>>;
100
- max(field: string): Promise<DbResponse<number>>;
101
- insert(values: Partial<Row> | Array<Partial<Row>>): Promise<DbResponse<unknown>>;
102
- update(values: Partial<Row>): Promise<DbResponse<unknown>> | Promise<{
103
- data: null;
104
- error: {
105
- message: string;
106
- };
107
- }>;
108
- delete(): Promise<DbResponse<unknown>> | Promise<{
109
- data: null;
110
- error: {
111
- message: string;
112
- };
113
- }>;
114
- }
115
-
116
- declare function createClient(baseUrl: string, opts?: ClientOptions): {
117
- from<Row = any>(table: string): QueryBuilder<Row>;
118
- };
119
-
120
- export { type ClientOptions, type DbError, type DbResponse, type Filter, type Order, createClient };
package/dist/index.js DELETED
@@ -1,317 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
- createClient: () => createClient
34
- });
35
- module.exports = __toCommonJS(index_exports);
36
-
37
- // src/client.ts
38
- var import_axios = __toESM(require("axios"));
39
- var HttpClient = class {
40
- constructor(baseUrl, opts = {}) {
41
- this.baseUrl = baseUrl.replace(/\/+$/, "");
42
- this.apiKey = opts.apiKey;
43
- this.extraHeaders = opts.headers ?? {};
44
- this.ax = import_axios.default.create({
45
- baseURL: this.baseUrl,
46
- timeout: 15e3,
47
- headers: {
48
- "Content-Type": "application/json",
49
- ...this.extraHeaders
50
- }
51
- });
52
- }
53
- async post(path, body, config = {}) {
54
- const headers = {
55
- ...this.extraHeaders,
56
- ...config.headers
57
- };
58
- if (this.apiKey) headers["x-api-key"] = this.apiKey;
59
- try {
60
- const res = await this.ax.post(path, body, {
61
- ...config,
62
- headers
63
- });
64
- const payload = res.data;
65
- return {
66
- data: payload?.data ?? null,
67
- count: payload?.count ?? null,
68
- meta: payload?.meta ?? null,
69
- error: payload?.error ?? null
70
- };
71
- } catch (e) {
72
- const status = e?.response?.status ?? 0;
73
- const payload = e?.response?.data ?? null;
74
- return {
75
- data: null,
76
- error: {
77
- status,
78
- message: payload?.error?.message ?? e?.message ?? "Network error",
79
- details: payload ?? e
80
- }
81
- };
82
- }
83
- }
84
- };
85
-
86
- // src/query-builder.ts
87
- var QueryBuilder = class {
88
- constructor(client, table) {
89
- this._select = ["*"];
90
- this._filters = [];
91
- this._order = [];
92
- this._limit = null;
93
- this._page = null;
94
- // ThinkPHP style
95
- this._offset = null;
96
- // offset style
97
- this._withCount = false;
98
- this._single = false;
99
- this._distinct = false;
100
- this._group = [];
101
- this._having = [];
102
- this.client = client;
103
- this.tableName = table;
104
- }
105
- // ---- select ----
106
- select(columns = "*") {
107
- const cols = columns.trim();
108
- this._select = cols === "*" || cols === "" ? ["*"] : cols.split(",").map((s) => s.trim()).filter(Boolean);
109
- return this;
110
- }
111
- // ---- filters ----
112
- addFilter(col, op, val) {
113
- this._filters.push({ col, op, val });
114
- return this;
115
- }
116
- eq(col, val) {
117
- return this.addFilter(col, "eq", val);
118
- }
119
- neq(col, val) {
120
- return this.addFilter(col, "neq", val);
121
- }
122
- gt(col, val) {
123
- return this.addFilter(col, "gt", val);
124
- }
125
- gte(col, val) {
126
- return this.addFilter(col, "gte", val);
127
- }
128
- lt(col, val) {
129
- return this.addFilter(col, "lt", val);
130
- }
131
- lte(col, val) {
132
- return this.addFilter(col, "lte", val);
133
- }
134
- like(col, val) {
135
- return this.addFilter(col, "like", val);
136
- }
137
- notLike(col, val) {
138
- return this.addFilter(col, "notLike", val);
139
- }
140
- between(col, range) {
141
- return this.addFilter(col, "between", range);
142
- }
143
- notBetween(col, range) {
144
- return this.addFilter(col, "notBetween", range);
145
- }
146
- in(col, vals) {
147
- return this.addFilter(col, "in", vals);
148
- }
149
- notIn(col, vals) {
150
- return this.addFilter(col, "notIn", vals);
151
- }
152
- isNull(col) {
153
- return this.addFilter(col, "isNull", null);
154
- }
155
- notNull(col) {
156
- return this.addFilter(col, "notNull", null);
157
- }
158
- regexp(col, pattern) {
159
- return this.addFilter(col, "regexp", pattern);
160
- }
161
- notRegexp(col, pattern) {
162
- return this.addFilter(col, "notRegexp", pattern);
163
- }
164
- whereTime(col, op, time) {
165
- return this.addFilter(col, "time", { op, val: time });
166
- }
167
- betweenTime(col, range) {
168
- return this.addFilter(col, "time", { op: "between", val: range });
169
- }
170
- findInSet(col, val) {
171
- return this.addFilter(col, "findInSet", val);
172
- }
173
- // ---- order ----
174
- order(col, opts = {}) {
175
- this._order.push({ col, dir: opts.ascending === false ? "desc" : "asc" });
176
- return this;
177
- }
178
- // ---- pagination ----
179
- limit(n) {
180
- this._limit = Math.max(1, n | 0);
181
- return this;
182
- }
183
- page(page, limit) {
184
- this._page = Math.max(1, page | 0);
185
- this._limit = Math.max(1, limit | 0);
186
- this._offset = null;
187
- return this;
188
- }
189
- range(from, to) {
190
- const f = Math.max(0, from | 0);
191
- const t = Math.max(f, to | 0);
192
- this._offset = f;
193
- this._limit = t - f + 1;
194
- this._page = null;
195
- return this;
196
- }
197
- /** Pagination total rows (not aggregate). */
198
- withCount() {
199
- this._withCount = true;
200
- return this;
201
- }
202
- single() {
203
- this._single = true;
204
- this.limit(1);
205
- return this;
206
- }
207
- // ---- group/having/distinct ----
208
- distinct() {
209
- this._distinct = true;
210
- return this;
211
- }
212
- group(cols) {
213
- this._group = cols.split(",").map((s) => s.trim()).filter(Boolean);
214
- return this;
215
- }
216
- havingEq(col, val) {
217
- this._having.push({ col, op: "eq", val });
218
- return this;
219
- }
220
- havingGte(col, val) {
221
- this._having.push({ col, op: "gte", val });
222
- return this;
223
- }
224
- havingLte(col, val) {
225
- this._having.push({ col, op: "lte", val });
226
- return this;
227
- }
228
- havingGt(col, val) {
229
- this._having.push({ col, op: "gt", val });
230
- return this;
231
- }
232
- havingLt(col, val) {
233
- this._having.push({ col, op: "lt", val });
234
- return this;
235
- }
236
- havingNeq(col, val) {
237
- this._having.push({ col, op: "neq", val });
238
- return this;
239
- }
240
- // ---- execute ----
241
- async execute() {
242
- const payload = {
243
- table: this.tableName,
244
- select: this._select,
245
- filters: this._filters,
246
- order: this._order,
247
- limit: this._limit ?? 20,
248
- count: this._withCount,
249
- distinct: this._distinct,
250
- group: this._group,
251
- having: this._having
252
- };
253
- if (this._page !== null) payload.page = this._page;
254
- if (this._offset !== null) payload.offset = this._offset;
255
- const res = await this.client.post("/db/v1/query", payload);
256
- if (res.error) return res;
257
- if (this._single) {
258
- const first = Array.isArray(res.data) ? res.data[0] ?? null : null;
259
- return { data: first, error: null, count: res.count ?? null, meta: res.meta ?? null };
260
- }
261
- return res;
262
- }
263
- // ---- aggregates ----
264
- agg(fn, field = "*") {
265
- return this.client.post("/db/v1/query", {
266
- table: this.tableName,
267
- aggregate: { fn, field },
268
- filters: this._filters
269
- });
270
- }
271
- /** Aggregate count value (COUNT(*)) */
272
- count(field = "*") {
273
- return this.agg("count", field);
274
- }
275
- sum(field) {
276
- return this.agg("sum", field);
277
- }
278
- avg(field) {
279
- return this.agg("avg", field);
280
- }
281
- min(field) {
282
- return this.agg("min", field);
283
- }
284
- max(field) {
285
- return this.agg("max", field);
286
- }
287
- // ---- write ----
288
- insert(values) {
289
- return this.client.post("/db/v1/insert", { table: this.tableName, values });
290
- }
291
- update(values) {
292
- if (this._filters.length === 0) {
293
- return Promise.resolve({ data: null, error: { message: "Update requires filters (e.g. .eq('id', 1))" } });
294
- }
295
- return this.client.post("/db/v1/update", { table: this.tableName, values, filters: this._filters });
296
- }
297
- delete() {
298
- if (this._filters.length === 0) {
299
- return Promise.resolve({ data: null, error: { message: "Delete requires filters (e.g. .eq('id', 1))" } });
300
- }
301
- return this.client.post("/db/v1/delete", { table: this.tableName, filters: this._filters });
302
- }
303
- };
304
-
305
- // src/main.ts
306
- function createClient(baseUrl, opts = {}) {
307
- const http = new HttpClient(baseUrl, opts);
308
- return {
309
- from(table) {
310
- return new QueryBuilder(http, table);
311
- }
312
- };
313
- }
314
- // Annotate the CommonJS export names for ESM import in node:
315
- 0 && (module.exports = {
316
- createClient
317
- });
package/dist/index.mjs DELETED
@@ -1,280 +0,0 @@
1
- // src/client.ts
2
- import axios from "axios";
3
- var HttpClient = class {
4
- constructor(baseUrl, opts = {}) {
5
- this.baseUrl = baseUrl.replace(/\/+$/, "");
6
- this.apiKey = opts.apiKey;
7
- this.extraHeaders = opts.headers ?? {};
8
- this.ax = axios.create({
9
- baseURL: this.baseUrl,
10
- timeout: 15e3,
11
- headers: {
12
- "Content-Type": "application/json",
13
- ...this.extraHeaders
14
- }
15
- });
16
- }
17
- async post(path, body, config = {}) {
18
- const headers = {
19
- ...this.extraHeaders,
20
- ...config.headers
21
- };
22
- if (this.apiKey) headers["x-api-key"] = this.apiKey;
23
- try {
24
- const res = await this.ax.post(path, body, {
25
- ...config,
26
- headers
27
- });
28
- const payload = res.data;
29
- return {
30
- data: payload?.data ?? null,
31
- count: payload?.count ?? null,
32
- meta: payload?.meta ?? null,
33
- error: payload?.error ?? null
34
- };
35
- } catch (e) {
36
- const status = e?.response?.status ?? 0;
37
- const payload = e?.response?.data ?? null;
38
- return {
39
- data: null,
40
- error: {
41
- status,
42
- message: payload?.error?.message ?? e?.message ?? "Network error",
43
- details: payload ?? e
44
- }
45
- };
46
- }
47
- }
48
- };
49
-
50
- // src/query-builder.ts
51
- var QueryBuilder = class {
52
- constructor(client, table) {
53
- this._select = ["*"];
54
- this._filters = [];
55
- this._order = [];
56
- this._limit = null;
57
- this._page = null;
58
- // ThinkPHP style
59
- this._offset = null;
60
- // offset style
61
- this._withCount = false;
62
- this._single = false;
63
- this._distinct = false;
64
- this._group = [];
65
- this._having = [];
66
- this.client = client;
67
- this.tableName = table;
68
- }
69
- // ---- select ----
70
- select(columns = "*") {
71
- const cols = columns.trim();
72
- this._select = cols === "*" || cols === "" ? ["*"] : cols.split(",").map((s) => s.trim()).filter(Boolean);
73
- return this;
74
- }
75
- // ---- filters ----
76
- addFilter(col, op, val) {
77
- this._filters.push({ col, op, val });
78
- return this;
79
- }
80
- eq(col, val) {
81
- return this.addFilter(col, "eq", val);
82
- }
83
- neq(col, val) {
84
- return this.addFilter(col, "neq", val);
85
- }
86
- gt(col, val) {
87
- return this.addFilter(col, "gt", val);
88
- }
89
- gte(col, val) {
90
- return this.addFilter(col, "gte", val);
91
- }
92
- lt(col, val) {
93
- return this.addFilter(col, "lt", val);
94
- }
95
- lte(col, val) {
96
- return this.addFilter(col, "lte", val);
97
- }
98
- like(col, val) {
99
- return this.addFilter(col, "like", val);
100
- }
101
- notLike(col, val) {
102
- return this.addFilter(col, "notLike", val);
103
- }
104
- between(col, range) {
105
- return this.addFilter(col, "between", range);
106
- }
107
- notBetween(col, range) {
108
- return this.addFilter(col, "notBetween", range);
109
- }
110
- in(col, vals) {
111
- return this.addFilter(col, "in", vals);
112
- }
113
- notIn(col, vals) {
114
- return this.addFilter(col, "notIn", vals);
115
- }
116
- isNull(col) {
117
- return this.addFilter(col, "isNull", null);
118
- }
119
- notNull(col) {
120
- return this.addFilter(col, "notNull", null);
121
- }
122
- regexp(col, pattern) {
123
- return this.addFilter(col, "regexp", pattern);
124
- }
125
- notRegexp(col, pattern) {
126
- return this.addFilter(col, "notRegexp", pattern);
127
- }
128
- whereTime(col, op, time) {
129
- return this.addFilter(col, "time", { op, val: time });
130
- }
131
- betweenTime(col, range) {
132
- return this.addFilter(col, "time", { op: "between", val: range });
133
- }
134
- findInSet(col, val) {
135
- return this.addFilter(col, "findInSet", val);
136
- }
137
- // ---- order ----
138
- order(col, opts = {}) {
139
- this._order.push({ col, dir: opts.ascending === false ? "desc" : "asc" });
140
- return this;
141
- }
142
- // ---- pagination ----
143
- limit(n) {
144
- this._limit = Math.max(1, n | 0);
145
- return this;
146
- }
147
- page(page, limit) {
148
- this._page = Math.max(1, page | 0);
149
- this._limit = Math.max(1, limit | 0);
150
- this._offset = null;
151
- return this;
152
- }
153
- range(from, to) {
154
- const f = Math.max(0, from | 0);
155
- const t = Math.max(f, to | 0);
156
- this._offset = f;
157
- this._limit = t - f + 1;
158
- this._page = null;
159
- return this;
160
- }
161
- /** Pagination total rows (not aggregate). */
162
- withCount() {
163
- this._withCount = true;
164
- return this;
165
- }
166
- single() {
167
- this._single = true;
168
- this.limit(1);
169
- return this;
170
- }
171
- // ---- group/having/distinct ----
172
- distinct() {
173
- this._distinct = true;
174
- return this;
175
- }
176
- group(cols) {
177
- this._group = cols.split(",").map((s) => s.trim()).filter(Boolean);
178
- return this;
179
- }
180
- havingEq(col, val) {
181
- this._having.push({ col, op: "eq", val });
182
- return this;
183
- }
184
- havingGte(col, val) {
185
- this._having.push({ col, op: "gte", val });
186
- return this;
187
- }
188
- havingLte(col, val) {
189
- this._having.push({ col, op: "lte", val });
190
- return this;
191
- }
192
- havingGt(col, val) {
193
- this._having.push({ col, op: "gt", val });
194
- return this;
195
- }
196
- havingLt(col, val) {
197
- this._having.push({ col, op: "lt", val });
198
- return this;
199
- }
200
- havingNeq(col, val) {
201
- this._having.push({ col, op: "neq", val });
202
- return this;
203
- }
204
- // ---- execute ----
205
- async execute() {
206
- const payload = {
207
- table: this.tableName,
208
- select: this._select,
209
- filters: this._filters,
210
- order: this._order,
211
- limit: this._limit ?? 20,
212
- count: this._withCount,
213
- distinct: this._distinct,
214
- group: this._group,
215
- having: this._having
216
- };
217
- if (this._page !== null) payload.page = this._page;
218
- if (this._offset !== null) payload.offset = this._offset;
219
- const res = await this.client.post("/db/v1/query", payload);
220
- if (res.error) return res;
221
- if (this._single) {
222
- const first = Array.isArray(res.data) ? res.data[0] ?? null : null;
223
- return { data: first, error: null, count: res.count ?? null, meta: res.meta ?? null };
224
- }
225
- return res;
226
- }
227
- // ---- aggregates ----
228
- agg(fn, field = "*") {
229
- return this.client.post("/db/v1/query", {
230
- table: this.tableName,
231
- aggregate: { fn, field },
232
- filters: this._filters
233
- });
234
- }
235
- /** Aggregate count value (COUNT(*)) */
236
- count(field = "*") {
237
- return this.agg("count", field);
238
- }
239
- sum(field) {
240
- return this.agg("sum", field);
241
- }
242
- avg(field) {
243
- return this.agg("avg", field);
244
- }
245
- min(field) {
246
- return this.agg("min", field);
247
- }
248
- max(field) {
249
- return this.agg("max", field);
250
- }
251
- // ---- write ----
252
- insert(values) {
253
- return this.client.post("/db/v1/insert", { table: this.tableName, values });
254
- }
255
- update(values) {
256
- if (this._filters.length === 0) {
257
- return Promise.resolve({ data: null, error: { message: "Update requires filters (e.g. .eq('id', 1))" } });
258
- }
259
- return this.client.post("/db/v1/update", { table: this.tableName, values, filters: this._filters });
260
- }
261
- delete() {
262
- if (this._filters.length === 0) {
263
- return Promise.resolve({ data: null, error: { message: "Delete requires filters (e.g. .eq('id', 1))" } });
264
- }
265
- return this.client.post("/db/v1/delete", { table: this.tableName, filters: this._filters });
266
- }
267
- };
268
-
269
- // src/main.ts
270
- function createClient(baseUrl, opts = {}) {
271
- const http = new HttpClient(baseUrl, opts);
272
- return {
273
- from(table) {
274
- return new QueryBuilder(http, table);
275
- }
276
- };
277
- }
278
- export {
279
- createClient
280
- };