@svadmin/pocketbase 0.13.17 → 0.13.19
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 +2 -2
- package/src/data-provider.ts +82 -24
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svadmin/pocketbase",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.19",
|
|
4
4
|
"description": "PocketBase adapters — DataProvider, AuthProvider, LiveProvider for svadmin",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"@svadmin/core": "^0.
|
|
23
|
+
"@svadmin/core": "^0.71.0",
|
|
24
24
|
"pocketbase": ">=0.28.0"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
package/src/data-provider.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
// @svadmin/pocketbase — PocketBase DataProvider
|
|
2
2
|
// Maps svadmin CRUD operations to PocketBase SDK
|
|
3
3
|
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
} from '@svadmin/core';
|
|
4
|
+
import { assertFiltersExecutable } from '@svadmin/core/provider-filters';
|
|
5
|
+
import type { DataProvider, Filter } from '@svadmin/core';
|
|
7
6
|
import { definedOptions } from '@svadmin/core/options';
|
|
8
7
|
import { withValidatedResponses, type DataTransport } from '@svadmin/core/schema';
|
|
9
8
|
|
|
@@ -41,27 +40,86 @@ function buildSort(sorters?: { field: string; order: 'asc' | 'desc' }[]): string
|
|
|
41
40
|
return sorters.map(s => s.order === 'desc' ? `-${s.field}` : s.field).join(',');
|
|
42
41
|
}
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
43
|
+
const FIELD_PATH = /^(?:[A-Za-z_][A-Za-z0-9_]*)(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
|
|
44
|
+
|
|
45
|
+
function pocketBaseField(field: string): string {
|
|
46
|
+
if (!FIELD_PATH.test(field)) throw new TypeError(`Unsupported PocketBase filter field: ${field}`);
|
|
47
|
+
return field;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function quoteString(value: string): string {
|
|
51
|
+
return `'${value.replaceAll('\\', '\\\\').replaceAll("'", "\\'")}'`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function pocketBaseLiteral(value: unknown): string {
|
|
55
|
+
if (value === null) return 'null';
|
|
56
|
+
if (typeof value === 'number') {
|
|
57
|
+
if (!Number.isFinite(value)) throw new TypeError('PocketBase filters reject non-finite numbers');
|
|
58
|
+
return String(value);
|
|
59
|
+
}
|
|
60
|
+
if (typeof value === 'boolean') return value ? 'true' : 'false';
|
|
61
|
+
if (typeof value === 'string') return quoteString(value);
|
|
62
|
+
throw new TypeError('PocketBase filters reject this value');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function likeLiteral(value: unknown): string {
|
|
66
|
+
if (typeof value !== 'string') throw new TypeError('PocketBase text filters require a string');
|
|
67
|
+
return value.replaceAll('\\', '\\\\').replaceAll('%', '\\%').replaceAll('_', '\\_');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function listLiterals(value: unknown, operator: string): string[] {
|
|
71
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
72
|
+
throw new TypeError(`PocketBase ${operator} filter requires a non-empty array`);
|
|
73
|
+
}
|
|
74
|
+
return value.map(pocketBaseLiteral);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function compilePocketBaseFilter(filter: Filter): string {
|
|
78
|
+
if ('field' in filter) {
|
|
79
|
+
const field = pocketBaseField(filter.field);
|
|
80
|
+
switch (filter.operator) {
|
|
81
|
+
case 'eq': return `${field} = ${pocketBaseLiteral(filter.value)}`;
|
|
82
|
+
case 'ne': return `${field} != ${pocketBaseLiteral(filter.value)}`;
|
|
83
|
+
case 'gt': return `${field} > ${pocketBaseLiteral(filter.value)}`;
|
|
84
|
+
case 'gte': return `${field} >= ${pocketBaseLiteral(filter.value)}`;
|
|
85
|
+
case 'lt': return `${field} < ${pocketBaseLiteral(filter.value)}`;
|
|
86
|
+
case 'lte': return `${field} <= ${pocketBaseLiteral(filter.value)}`;
|
|
87
|
+
case 'contains': return `${field} ~ ${quoteString(likeLiteral(filter.value))}`;
|
|
88
|
+
case 'ncontains': return `${field} !~ ${quoteString(likeLiteral(filter.value))}`;
|
|
89
|
+
case 'startswith': return `${field} ~ ${quoteString(`${likeLiteral(filter.value)}%`)}`;
|
|
90
|
+
case 'nstartswith': return `${field} !~ ${quoteString(`${likeLiteral(filter.value)}%`)}`;
|
|
91
|
+
case 'endswith': return `${field} ~ ${quoteString(`%${likeLiteral(filter.value)}`)}`;
|
|
92
|
+
case 'nendswith': return `${field} !~ ${quoteString(`%${likeLiteral(filter.value)}`)}`;
|
|
93
|
+
case 'null': return `${field} = null`;
|
|
94
|
+
case 'nnull': return `${field} != null`;
|
|
95
|
+
case 'in': return `(${listLiterals(filter.value, 'in').map((item) => `${field} = ${item}`).join(' || ')})`;
|
|
96
|
+
case 'nin': return `(${listLiterals(filter.value, 'nin').map((item) => `${field} != ${item}`).join(' && ')})`;
|
|
97
|
+
case 'between':
|
|
98
|
+
case 'nbetween': {
|
|
99
|
+
const bounds = listLiterals(filter.value, filter.operator);
|
|
100
|
+
if (bounds.length !== 2) throw new TypeError(`PocketBase ${filter.operator} filter requires two values`);
|
|
101
|
+
const [min, max] = bounds;
|
|
102
|
+
return filter.operator === 'between'
|
|
103
|
+
? `(${field} >= ${min} && ${field} <= ${max})`
|
|
104
|
+
: `(${field} < ${min} || ${field} > ${max})`;
|
|
105
|
+
}
|
|
106
|
+
default:
|
|
107
|
+
throw new Error(`Unsupported PocketBase filter operator: ${String(filter.operator)}`);
|
|
63
108
|
}
|
|
64
|
-
}
|
|
109
|
+
}
|
|
110
|
+
if (filter.operator !== 'and' && filter.operator !== 'or') {
|
|
111
|
+
throw new Error(`Unsupported PocketBase logical operator: ${String(filter.operator)}`);
|
|
112
|
+
}
|
|
113
|
+
if (!Array.isArray(filter.value)) throw new TypeError('PocketBase logical filter requires an array');
|
|
114
|
+
if (filter.value.length === 0) return filter.operator === 'and' ? '(1=1)' : '(1=0)';
|
|
115
|
+
const joiner = filter.operator === 'and' ? ' && ' : ' || ';
|
|
116
|
+
return `(${filter.value.map(compilePocketBaseFilter).join(joiner)})`;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function buildFilter(filters?: Filter[]): string | undefined {
|
|
120
|
+
if (!filters?.length) return undefined;
|
|
121
|
+
assertFiltersExecutable('pocketbase', filters);
|
|
122
|
+
return filters.map(compilePocketBaseFilter).join(' && ');
|
|
65
123
|
}
|
|
66
124
|
|
|
67
125
|
/**
|
|
@@ -87,7 +145,7 @@ export function createPocketBaseDataProvider(options: PocketBaseProviderOptions)
|
|
|
87
145
|
const perPage = params.pagination?.pageSize ?? 10;
|
|
88
146
|
const result = await pb.collection(params.resource).getList(page, perPage, definedOptions({
|
|
89
147
|
sort: buildSort(params.sorters),
|
|
90
|
-
filter: buildFilter(
|
|
148
|
+
filter: buildFilter(params.filters),
|
|
91
149
|
}));
|
|
92
150
|
if (!isObject(result)) return result;
|
|
93
151
|
return {
|