zone4code-sdk 1.0.7 → 1.0.9
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 +79 -0
- package/dist/index.cjs +104 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +69 -10
- package/dist/index.d.ts +69 -10
- package/dist/index.js +104 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -42,7 +42,17 @@ interface Zone4CodeConfig {
|
|
|
42
42
|
* Callback invoked when a user session expires (e.g. refresh token expired or invalid).
|
|
43
43
|
*/
|
|
44
44
|
onSessionExpired?: () => void;
|
|
45
|
+
/**
|
|
46
|
+
* Default language locale for API requests (e.g. 'en', 'fr', 'ar').
|
|
47
|
+
* Can be overridden per query with `.lang(locale)` or set to '*' for raw translations.
|
|
48
|
+
*/
|
|
49
|
+
defaultLanguage?: string;
|
|
45
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Represents either a plain localized string or a dictionary of multilingual values:
|
|
53
|
+
* e.g. "Beach Villa" or { en: "Beach Villa", fr: "Villa Plage", ar: "فيلا الشاطئ" }
|
|
54
|
+
*/
|
|
55
|
+
type Translatable<T = string> = T | Record<string, T>;
|
|
46
56
|
interface AuthUser {
|
|
47
57
|
id: string;
|
|
48
58
|
email?: string;
|
|
@@ -77,6 +87,12 @@ interface EntityListResponse<T = Record<string, any>> {
|
|
|
77
87
|
limit?: number;
|
|
78
88
|
cursor?: string;
|
|
79
89
|
}
|
|
90
|
+
interface GetEntityOptions {
|
|
91
|
+
flat?: boolean;
|
|
92
|
+
include?: string[];
|
|
93
|
+
lang?: string;
|
|
94
|
+
rawTranslations?: boolean;
|
|
95
|
+
}
|
|
80
96
|
interface SchemaProperty {
|
|
81
97
|
type: 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array';
|
|
82
98
|
description?: string;
|
|
@@ -85,6 +101,11 @@ interface SchemaProperty {
|
|
|
85
101
|
items?: SchemaProperty;
|
|
86
102
|
properties?: Record<string, SchemaProperty>;
|
|
87
103
|
required?: string[];
|
|
104
|
+
/**
|
|
105
|
+
* If true, this field accepts multilingual JSONB dictionaries ({ en: "...", fr: "..." })
|
|
106
|
+
* and automatically flattens to the active language during queries.
|
|
107
|
+
*/
|
|
108
|
+
translatable?: boolean;
|
|
88
109
|
}
|
|
89
110
|
interface EntitySchemaDefinition {
|
|
90
111
|
typeName: string;
|
|
@@ -159,6 +180,7 @@ declare class AuthClient {
|
|
|
159
180
|
private sessionExpiredListeners;
|
|
160
181
|
private activeRefreshPromise;
|
|
161
182
|
private storageLoadedPromise;
|
|
183
|
+
private getLanguage?;
|
|
162
184
|
private static TOKEN_KEY_PREFIX;
|
|
163
185
|
constructor(options: {
|
|
164
186
|
gatewayUrl: string;
|
|
@@ -170,6 +192,7 @@ declare class AuthClient {
|
|
|
170
192
|
autoRefresh?: boolean;
|
|
171
193
|
tokenExpiryBuffer?: number;
|
|
172
194
|
onSessionExpired?: () => void;
|
|
195
|
+
getLanguage?: () => string | null;
|
|
173
196
|
});
|
|
174
197
|
getToken(): string | null;
|
|
175
198
|
getRefreshToken(): string | null;
|
|
@@ -287,15 +310,30 @@ declare class EntityQueryBuilder<T = Record<string, any>> {
|
|
|
287
310
|
getToken?: () => string | null;
|
|
288
311
|
fetchFn?: typeof fetch;
|
|
289
312
|
fetchWithAuth?: (url: string, init?: RequestInit) => Promise<Response>;
|
|
313
|
+
defaultLanguage?: string | null | (() => string | null);
|
|
290
314
|
});
|
|
291
315
|
private getHeaders;
|
|
292
316
|
private executeRequest;
|
|
293
317
|
eq(field: string, value: string | number | boolean): this;
|
|
294
318
|
ne(field: string, value: string | number | boolean): this;
|
|
295
|
-
gt(field: string, value: number): this;
|
|
296
|
-
gte(field: string, value: number): this;
|
|
297
|
-
lt(field: string, value: number): this;
|
|
298
|
-
lte(field: string, value: number): this;
|
|
319
|
+
gt(field: string, value: string | number | Date): this;
|
|
320
|
+
gte(field: string, value: string | number | Date): this;
|
|
321
|
+
lt(field: string, value: string | number | Date): this;
|
|
322
|
+
lte(field: string, value: string | number | Date): this;
|
|
323
|
+
/**
|
|
324
|
+
* Filter records within a numeric or date range (inclusive)
|
|
325
|
+
* Example: .between('price', 100, 500) or .between('check_in', '2026-10-01', '2026-10-15')
|
|
326
|
+
*/
|
|
327
|
+
between(field: string, from: string | number | Date, to: string | number | Date): this;
|
|
328
|
+
/**
|
|
329
|
+
* Alias for .between(...)
|
|
330
|
+
*/
|
|
331
|
+
range(field: string, min: string | number | Date, max: string | number | Date): this;
|
|
332
|
+
/**
|
|
333
|
+
* Helper specifically for date/timestamp range filtering
|
|
334
|
+
* Example: .dateRange('created_at', '2026-09-01', '2026-09-30')
|
|
335
|
+
*/
|
|
336
|
+
dateRange(field: string, startDate: string | Date, endDate: string | Date): this;
|
|
299
337
|
/**
|
|
300
338
|
* Case-insensitive substring search (ILIKE %substring%)
|
|
301
339
|
*/
|
|
@@ -321,17 +359,29 @@ declare class EntityQueryBuilder<T = Record<string, any>> {
|
|
|
321
359
|
offset(offset: number): this;
|
|
322
360
|
cursor(token: string): this;
|
|
323
361
|
flat(enabled?: boolean): this;
|
|
362
|
+
/**
|
|
363
|
+
* Set target language for automatic JSONB translation flattening.
|
|
364
|
+
* Example: .lang('fr') returns French fields, falling back to 'en'.
|
|
365
|
+
* Set to '*' or call .rawTranslations() to get raw multilingual dictionaries.
|
|
366
|
+
*/
|
|
367
|
+
lang(locale: string): this;
|
|
368
|
+
/**
|
|
369
|
+
* Alias for .lang(locale)
|
|
370
|
+
*/
|
|
371
|
+
language(locale: string): this;
|
|
372
|
+
/**
|
|
373
|
+
* Request raw, unflattened multilingual dictionaries ({ en: "...", fr: "..." })
|
|
374
|
+
* Essential for Admin/CMS forms to avoid overwriting other language translations on update.
|
|
375
|
+
*/
|
|
376
|
+
rawTranslations(enabled?: boolean): this;
|
|
324
377
|
/**
|
|
325
378
|
* Execute query and list matching records with pagination metadata
|
|
326
379
|
*/
|
|
327
380
|
list(): Promise<EntityListResponse<T>>;
|
|
328
381
|
/**
|
|
329
|
-
* Fetch a single entity by ID with optional expansion and flattening
|
|
382
|
+
* Fetch a single entity by ID with optional expansion, translation locale, and flattening
|
|
330
383
|
*/
|
|
331
|
-
get(id: string, options?:
|
|
332
|
-
flat?: boolean;
|
|
333
|
-
include?: string[];
|
|
334
|
-
}): Promise<EntityRecord<T>>;
|
|
384
|
+
get(id: string, options?: GetEntityOptions): Promise<EntityRecord<T>>;
|
|
335
385
|
/**
|
|
336
386
|
* Create a new entity record matching schema
|
|
337
387
|
*/
|
|
@@ -420,7 +470,16 @@ declare class Zone4CodeClient {
|
|
|
420
470
|
readonly schema: SchemaClient;
|
|
421
471
|
private storage;
|
|
422
472
|
private fetchFn;
|
|
473
|
+
private currentLanguage;
|
|
423
474
|
constructor(config: Zone4CodeConfig);
|
|
475
|
+
/**
|
|
476
|
+
* Set the active default language for API requests (e.g., 'en', 'fr', 'ar', or '*' for raw)
|
|
477
|
+
*/
|
|
478
|
+
setLanguage(lang: string | null): this;
|
|
479
|
+
/**
|
|
480
|
+
* Get the active default language
|
|
481
|
+
*/
|
|
482
|
+
getLanguage(): string | null;
|
|
424
483
|
/**
|
|
425
484
|
* Access an entity collection with chainable query builder (like Supabase .from('orders'))
|
|
426
485
|
*/
|
|
@@ -458,4 +517,4 @@ declare class MemoryStorage implements StorageAdapter {
|
|
|
458
517
|
}
|
|
459
518
|
declare function getDefaultStorage(): StorageAdapter;
|
|
460
519
|
|
|
461
|
-
export { AuthClient, type AuthResponse, type AuthUser, type EntityListResponse, EntityQueryBuilder, type EntityRecord, type EntityRelationPayload, type EntityRelationRecord, type EntityReplaceRelationsPayload, type EntityRevision, type EntitySchemaDefinition, type FilterOperator, MemoryStorage, SchemaClient, type SchemaProperty, type StorageAdapter, type UserProfileWithWallet, Zone4CodeClient, type Zone4CodeConfig, createClient, createClient as default, getDefaultStorage };
|
|
520
|
+
export { AuthClient, type AuthResponse, type AuthUser, type EntityListResponse, EntityQueryBuilder, type EntityRecord, type EntityRelationPayload, type EntityRelationRecord, type EntityReplaceRelationsPayload, type EntityRevision, type EntitySchemaDefinition, type FilterOperator, type GetEntityOptions, MemoryStorage, SchemaClient, type SchemaProperty, type StorageAdapter, type Translatable, type UserProfileWithWallet, Zone4CodeClient, type Zone4CodeConfig, createClient, createClient as default, getDefaultStorage };
|
package/dist/index.d.ts
CHANGED
|
@@ -42,7 +42,17 @@ interface Zone4CodeConfig {
|
|
|
42
42
|
* Callback invoked when a user session expires (e.g. refresh token expired or invalid).
|
|
43
43
|
*/
|
|
44
44
|
onSessionExpired?: () => void;
|
|
45
|
+
/**
|
|
46
|
+
* Default language locale for API requests (e.g. 'en', 'fr', 'ar').
|
|
47
|
+
* Can be overridden per query with `.lang(locale)` or set to '*' for raw translations.
|
|
48
|
+
*/
|
|
49
|
+
defaultLanguage?: string;
|
|
45
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Represents either a plain localized string or a dictionary of multilingual values:
|
|
53
|
+
* e.g. "Beach Villa" or { en: "Beach Villa", fr: "Villa Plage", ar: "فيلا الشاطئ" }
|
|
54
|
+
*/
|
|
55
|
+
type Translatable<T = string> = T | Record<string, T>;
|
|
46
56
|
interface AuthUser {
|
|
47
57
|
id: string;
|
|
48
58
|
email?: string;
|
|
@@ -77,6 +87,12 @@ interface EntityListResponse<T = Record<string, any>> {
|
|
|
77
87
|
limit?: number;
|
|
78
88
|
cursor?: string;
|
|
79
89
|
}
|
|
90
|
+
interface GetEntityOptions {
|
|
91
|
+
flat?: boolean;
|
|
92
|
+
include?: string[];
|
|
93
|
+
lang?: string;
|
|
94
|
+
rawTranslations?: boolean;
|
|
95
|
+
}
|
|
80
96
|
interface SchemaProperty {
|
|
81
97
|
type: 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array';
|
|
82
98
|
description?: string;
|
|
@@ -85,6 +101,11 @@ interface SchemaProperty {
|
|
|
85
101
|
items?: SchemaProperty;
|
|
86
102
|
properties?: Record<string, SchemaProperty>;
|
|
87
103
|
required?: string[];
|
|
104
|
+
/**
|
|
105
|
+
* If true, this field accepts multilingual JSONB dictionaries ({ en: "...", fr: "..." })
|
|
106
|
+
* and automatically flattens to the active language during queries.
|
|
107
|
+
*/
|
|
108
|
+
translatable?: boolean;
|
|
88
109
|
}
|
|
89
110
|
interface EntitySchemaDefinition {
|
|
90
111
|
typeName: string;
|
|
@@ -159,6 +180,7 @@ declare class AuthClient {
|
|
|
159
180
|
private sessionExpiredListeners;
|
|
160
181
|
private activeRefreshPromise;
|
|
161
182
|
private storageLoadedPromise;
|
|
183
|
+
private getLanguage?;
|
|
162
184
|
private static TOKEN_KEY_PREFIX;
|
|
163
185
|
constructor(options: {
|
|
164
186
|
gatewayUrl: string;
|
|
@@ -170,6 +192,7 @@ declare class AuthClient {
|
|
|
170
192
|
autoRefresh?: boolean;
|
|
171
193
|
tokenExpiryBuffer?: number;
|
|
172
194
|
onSessionExpired?: () => void;
|
|
195
|
+
getLanguage?: () => string | null;
|
|
173
196
|
});
|
|
174
197
|
getToken(): string | null;
|
|
175
198
|
getRefreshToken(): string | null;
|
|
@@ -287,15 +310,30 @@ declare class EntityQueryBuilder<T = Record<string, any>> {
|
|
|
287
310
|
getToken?: () => string | null;
|
|
288
311
|
fetchFn?: typeof fetch;
|
|
289
312
|
fetchWithAuth?: (url: string, init?: RequestInit) => Promise<Response>;
|
|
313
|
+
defaultLanguage?: string | null | (() => string | null);
|
|
290
314
|
});
|
|
291
315
|
private getHeaders;
|
|
292
316
|
private executeRequest;
|
|
293
317
|
eq(field: string, value: string | number | boolean): this;
|
|
294
318
|
ne(field: string, value: string | number | boolean): this;
|
|
295
|
-
gt(field: string, value: number): this;
|
|
296
|
-
gte(field: string, value: number): this;
|
|
297
|
-
lt(field: string, value: number): this;
|
|
298
|
-
lte(field: string, value: number): this;
|
|
319
|
+
gt(field: string, value: string | number | Date): this;
|
|
320
|
+
gte(field: string, value: string | number | Date): this;
|
|
321
|
+
lt(field: string, value: string | number | Date): this;
|
|
322
|
+
lte(field: string, value: string | number | Date): this;
|
|
323
|
+
/**
|
|
324
|
+
* Filter records within a numeric or date range (inclusive)
|
|
325
|
+
* Example: .between('price', 100, 500) or .between('check_in', '2026-10-01', '2026-10-15')
|
|
326
|
+
*/
|
|
327
|
+
between(field: string, from: string | number | Date, to: string | number | Date): this;
|
|
328
|
+
/**
|
|
329
|
+
* Alias for .between(...)
|
|
330
|
+
*/
|
|
331
|
+
range(field: string, min: string | number | Date, max: string | number | Date): this;
|
|
332
|
+
/**
|
|
333
|
+
* Helper specifically for date/timestamp range filtering
|
|
334
|
+
* Example: .dateRange('created_at', '2026-09-01', '2026-09-30')
|
|
335
|
+
*/
|
|
336
|
+
dateRange(field: string, startDate: string | Date, endDate: string | Date): this;
|
|
299
337
|
/**
|
|
300
338
|
* Case-insensitive substring search (ILIKE %substring%)
|
|
301
339
|
*/
|
|
@@ -321,17 +359,29 @@ declare class EntityQueryBuilder<T = Record<string, any>> {
|
|
|
321
359
|
offset(offset: number): this;
|
|
322
360
|
cursor(token: string): this;
|
|
323
361
|
flat(enabled?: boolean): this;
|
|
362
|
+
/**
|
|
363
|
+
* Set target language for automatic JSONB translation flattening.
|
|
364
|
+
* Example: .lang('fr') returns French fields, falling back to 'en'.
|
|
365
|
+
* Set to '*' or call .rawTranslations() to get raw multilingual dictionaries.
|
|
366
|
+
*/
|
|
367
|
+
lang(locale: string): this;
|
|
368
|
+
/**
|
|
369
|
+
* Alias for .lang(locale)
|
|
370
|
+
*/
|
|
371
|
+
language(locale: string): this;
|
|
372
|
+
/**
|
|
373
|
+
* Request raw, unflattened multilingual dictionaries ({ en: "...", fr: "..." })
|
|
374
|
+
* Essential for Admin/CMS forms to avoid overwriting other language translations on update.
|
|
375
|
+
*/
|
|
376
|
+
rawTranslations(enabled?: boolean): this;
|
|
324
377
|
/**
|
|
325
378
|
* Execute query and list matching records with pagination metadata
|
|
326
379
|
*/
|
|
327
380
|
list(): Promise<EntityListResponse<T>>;
|
|
328
381
|
/**
|
|
329
|
-
* Fetch a single entity by ID with optional expansion and flattening
|
|
382
|
+
* Fetch a single entity by ID with optional expansion, translation locale, and flattening
|
|
330
383
|
*/
|
|
331
|
-
get(id: string, options?:
|
|
332
|
-
flat?: boolean;
|
|
333
|
-
include?: string[];
|
|
334
|
-
}): Promise<EntityRecord<T>>;
|
|
384
|
+
get(id: string, options?: GetEntityOptions): Promise<EntityRecord<T>>;
|
|
335
385
|
/**
|
|
336
386
|
* Create a new entity record matching schema
|
|
337
387
|
*/
|
|
@@ -420,7 +470,16 @@ declare class Zone4CodeClient {
|
|
|
420
470
|
readonly schema: SchemaClient;
|
|
421
471
|
private storage;
|
|
422
472
|
private fetchFn;
|
|
473
|
+
private currentLanguage;
|
|
423
474
|
constructor(config: Zone4CodeConfig);
|
|
475
|
+
/**
|
|
476
|
+
* Set the active default language for API requests (e.g., 'en', 'fr', 'ar', or '*' for raw)
|
|
477
|
+
*/
|
|
478
|
+
setLanguage(lang: string | null): this;
|
|
479
|
+
/**
|
|
480
|
+
* Get the active default language
|
|
481
|
+
*/
|
|
482
|
+
getLanguage(): string | null;
|
|
424
483
|
/**
|
|
425
484
|
* Access an entity collection with chainable query builder (like Supabase .from('orders'))
|
|
426
485
|
*/
|
|
@@ -458,4 +517,4 @@ declare class MemoryStorage implements StorageAdapter {
|
|
|
458
517
|
}
|
|
459
518
|
declare function getDefaultStorage(): StorageAdapter;
|
|
460
519
|
|
|
461
|
-
export { AuthClient, type AuthResponse, type AuthUser, type EntityListResponse, EntityQueryBuilder, type EntityRecord, type EntityRelationPayload, type EntityRelationRecord, type EntityReplaceRelationsPayload, type EntityRevision, type EntitySchemaDefinition, type FilterOperator, MemoryStorage, SchemaClient, type SchemaProperty, type StorageAdapter, type UserProfileWithWallet, Zone4CodeClient, type Zone4CodeConfig, createClient, createClient as default, getDefaultStorage };
|
|
520
|
+
export { AuthClient, type AuthResponse, type AuthUser, type EntityListResponse, EntityQueryBuilder, type EntityRecord, type EntityRelationPayload, type EntityRelationRecord, type EntityReplaceRelationsPayload, type EntityRevision, type EntitySchemaDefinition, type FilterOperator, type GetEntityOptions, MemoryStorage, SchemaClient, type SchemaProperty, type StorageAdapter, type Translatable, type UserProfileWithWallet, Zone4CodeClient, type Zone4CodeConfig, createClient, createClient as default, getDefaultStorage };
|
package/dist/index.js
CHANGED
|
@@ -48,6 +48,7 @@ var AuthClient = class _AuthClient {
|
|
|
48
48
|
sessionExpiredListeners = [];
|
|
49
49
|
activeRefreshPromise = null;
|
|
50
50
|
storageLoadedPromise;
|
|
51
|
+
getLanguage;
|
|
51
52
|
static TOKEN_KEY_PREFIX = "z4c_token_";
|
|
52
53
|
constructor(options) {
|
|
53
54
|
const storage = options.storage;
|
|
@@ -59,9 +60,10 @@ var AuthClient = class _AuthClient {
|
|
|
59
60
|
this.storageKey = storageKey;
|
|
60
61
|
this.refreshStorageKey = refreshStorageKey;
|
|
61
62
|
this.fetchFn = options.fetchFn || (typeof fetch !== "undefined" ? fetch : globalThis.fetch);
|
|
62
|
-
this.autoRefresh = options.autoRefresh
|
|
63
|
-
this.tokenExpiryBuffer = options.tokenExpiryBuffer
|
|
63
|
+
this.autoRefresh = options.autoRefresh !== void 0 ? options.autoRefresh : true;
|
|
64
|
+
this.tokenExpiryBuffer = options.tokenExpiryBuffer !== void 0 ? options.tokenExpiryBuffer : 30;
|
|
64
65
|
this.onSessionExpiredCallback = options.onSessionExpired;
|
|
66
|
+
this.getLanguage = options.getLanguage;
|
|
65
67
|
this.storageLoadedPromise = (async () => {
|
|
66
68
|
if (options.initialToken) {
|
|
67
69
|
this.setToken(options.initialToken);
|
|
@@ -176,6 +178,10 @@ var AuthClient = class _AuthClient {
|
|
|
176
178
|
if (token && !headers["Authorization"] && !headers["authorization"]) {
|
|
177
179
|
headers["Authorization"] = `Bearer ${token}`;
|
|
178
180
|
}
|
|
181
|
+
const currentLang = this.getLanguage ? this.getLanguage() : null;
|
|
182
|
+
if (currentLang && !headers["Accept-Language"] && !headers["accept-language"]) {
|
|
183
|
+
headers["Accept-Language"] = currentLang;
|
|
184
|
+
}
|
|
179
185
|
let res = await this.fetchFn(url, { ...init, headers });
|
|
180
186
|
if (res.status === 401 && this.autoRefresh && this.getRefreshToken()) {
|
|
181
187
|
try {
|
|
@@ -523,6 +529,12 @@ var EntityQueryBuilder = class {
|
|
|
523
529
|
this.getToken = options.getToken || (() => null);
|
|
524
530
|
this.fetchFn = options.fetchFn || (typeof fetch !== "undefined" ? fetch : globalThis.fetch);
|
|
525
531
|
this.fetchWithAuth = options.fetchWithAuth;
|
|
532
|
+
if (options.defaultLanguage) {
|
|
533
|
+
const langVal = typeof options.defaultLanguage === "function" ? options.defaultLanguage() : options.defaultLanguage;
|
|
534
|
+
if (langVal) {
|
|
535
|
+
this.queryParams.set("lang", langVal);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
526
538
|
}
|
|
527
539
|
getHeaders() {
|
|
528
540
|
const headers = {
|
|
@@ -554,21 +566,47 @@ var EntityQueryBuilder = class {
|
|
|
554
566
|
return this;
|
|
555
567
|
}
|
|
556
568
|
gt(field, value) {
|
|
557
|
-
|
|
569
|
+
const val = value instanceof Date ? value.toISOString() : String(value);
|
|
570
|
+
this.queryParams.append(`${field}[gt]`, val);
|
|
558
571
|
return this;
|
|
559
572
|
}
|
|
560
573
|
gte(field, value) {
|
|
561
|
-
|
|
574
|
+
const val = value instanceof Date ? value.toISOString() : String(value);
|
|
575
|
+
this.queryParams.append(`${field}[gte]`, val);
|
|
562
576
|
return this;
|
|
563
577
|
}
|
|
564
578
|
lt(field, value) {
|
|
565
|
-
|
|
579
|
+
const val = value instanceof Date ? value.toISOString() : String(value);
|
|
580
|
+
this.queryParams.append(`${field}[lt]`, val);
|
|
566
581
|
return this;
|
|
567
582
|
}
|
|
568
583
|
lte(field, value) {
|
|
569
|
-
|
|
584
|
+
const val = value instanceof Date ? value.toISOString() : String(value);
|
|
585
|
+
this.queryParams.append(`${field}[lte]`, val);
|
|
586
|
+
return this;
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Filter records within a numeric or date range (inclusive)
|
|
590
|
+
* Example: .between('price', 100, 500) or .between('check_in', '2026-10-01', '2026-10-15')
|
|
591
|
+
*/
|
|
592
|
+
between(field, from, to) {
|
|
593
|
+
this.gte(field, from);
|
|
594
|
+
this.lte(field, to);
|
|
570
595
|
return this;
|
|
571
596
|
}
|
|
597
|
+
/**
|
|
598
|
+
* Alias for .between(...)
|
|
599
|
+
*/
|
|
600
|
+
range(field, min, max) {
|
|
601
|
+
return this.between(field, min, max);
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Helper specifically for date/timestamp range filtering
|
|
605
|
+
* Example: .dateRange('created_at', '2026-09-01', '2026-09-30')
|
|
606
|
+
*/
|
|
607
|
+
dateRange(field, startDate, endDate) {
|
|
608
|
+
return this.between(field, startDate, endDate);
|
|
609
|
+
}
|
|
572
610
|
/**
|
|
573
611
|
* Case-insensitive substring search (ILIKE %substring%)
|
|
574
612
|
*/
|
|
@@ -641,6 +679,37 @@ var EntityQueryBuilder = class {
|
|
|
641
679
|
this.queryParams.set("flat", enabled ? "true" : "false");
|
|
642
680
|
return this;
|
|
643
681
|
}
|
|
682
|
+
/**
|
|
683
|
+
* Set target language for automatic JSONB translation flattening.
|
|
684
|
+
* Example: .lang('fr') returns French fields, falling back to 'en'.
|
|
685
|
+
* Set to '*' or call .rawTranslations() to get raw multilingual dictionaries.
|
|
686
|
+
*/
|
|
687
|
+
lang(locale) {
|
|
688
|
+
this.queryParams.set("lang", locale);
|
|
689
|
+
return this;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Alias for .lang(locale)
|
|
693
|
+
*/
|
|
694
|
+
language(locale) {
|
|
695
|
+
return this.lang(locale);
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Request raw, unflattened multilingual dictionaries ({ en: "...", fr: "..." })
|
|
699
|
+
* Essential for Admin/CMS forms to avoid overwriting other language translations on update.
|
|
700
|
+
*/
|
|
701
|
+
rawTranslations(enabled = true) {
|
|
702
|
+
if (enabled) {
|
|
703
|
+
this.queryParams.set("lang", "*");
|
|
704
|
+
this.queryParams.set("rawTranslations", "true");
|
|
705
|
+
} else {
|
|
706
|
+
this.queryParams.delete("rawTranslations");
|
|
707
|
+
if (this.queryParams.get("lang") === "*") {
|
|
708
|
+
this.queryParams.delete("lang");
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
return this;
|
|
712
|
+
}
|
|
644
713
|
// ----------------------------------------------------
|
|
645
714
|
// Execution Methods
|
|
646
715
|
// ----------------------------------------------------
|
|
@@ -658,13 +727,20 @@ var EntityQueryBuilder = class {
|
|
|
658
727
|
return res.json();
|
|
659
728
|
}
|
|
660
729
|
/**
|
|
661
|
-
* Fetch a single entity by ID with optional expansion and flattening
|
|
730
|
+
* Fetch a single entity by ID with optional expansion, translation locale, and flattening
|
|
662
731
|
*/
|
|
663
732
|
async get(id, options) {
|
|
664
733
|
const params = new URLSearchParams(this.queryParams);
|
|
665
734
|
if (options?.flat !== void 0) {
|
|
666
735
|
params.set("flat", options.flat ? "true" : "false");
|
|
667
736
|
}
|
|
737
|
+
if (options?.lang) {
|
|
738
|
+
params.set("lang", options.lang);
|
|
739
|
+
}
|
|
740
|
+
if (options?.rawTranslations) {
|
|
741
|
+
params.set("lang", "*");
|
|
742
|
+
params.set("rawTranslations", "true");
|
|
743
|
+
}
|
|
668
744
|
if (options?.include && options.include.length > 0) {
|
|
669
745
|
const existing = params.get("include");
|
|
670
746
|
const existingList = existing ? existing.split(",").map((s) => s.trim()) : [];
|
|
@@ -740,7 +816,8 @@ var EntityQueryBuilder = class {
|
|
|
740
816
|
* Fetch all graph relations for this entity record
|
|
741
817
|
*/
|
|
742
818
|
async getRelations(id, lang) {
|
|
743
|
-
const
|
|
819
|
+
const activeLang = lang || this.queryParams.get("lang");
|
|
820
|
+
const qs = activeLang ? `?lang=${encodeURIComponent(activeLang)}` : "";
|
|
744
821
|
const url = `${this.gatewayUrl}/generic/${this.tenantId}/${this.typeName}/${id}/relations${qs}`;
|
|
745
822
|
const res = await this.executeRequest(url);
|
|
746
823
|
if (!res.ok) {
|
|
@@ -939,6 +1016,7 @@ var Zone4CodeClient = class {
|
|
|
939
1016
|
schema;
|
|
940
1017
|
storage;
|
|
941
1018
|
fetchFn;
|
|
1019
|
+
currentLanguage = null;
|
|
942
1020
|
constructor(config) {
|
|
943
1021
|
if (!config.gatewayUrl) {
|
|
944
1022
|
throw new Error("Zone4CodeClient requires a `gatewayUrl` (e.g., http://localhost:8080)");
|
|
@@ -950,6 +1028,7 @@ var Zone4CodeClient = class {
|
|
|
950
1028
|
this.tenantId = config.tenantId;
|
|
951
1029
|
this.storage = config.storage || getDefaultStorage();
|
|
952
1030
|
this.fetchFn = config.fetch || (typeof fetch !== "undefined" ? fetch : globalThis.fetch);
|
|
1031
|
+
this.currentLanguage = config.defaultLanguage || null;
|
|
953
1032
|
this.auth = new AuthClient({
|
|
954
1033
|
gatewayUrl: this.gatewayUrl,
|
|
955
1034
|
tenantId: this.tenantId,
|
|
@@ -959,7 +1038,8 @@ var Zone4CodeClient = class {
|
|
|
959
1038
|
fetchFn: this.fetchFn,
|
|
960
1039
|
autoRefresh: config.autoRefresh,
|
|
961
1040
|
tokenExpiryBuffer: config.tokenExpiryBuffer,
|
|
962
|
-
onSessionExpired: config.onSessionExpired
|
|
1041
|
+
onSessionExpired: config.onSessionExpired,
|
|
1042
|
+
getLanguage: () => this.getLanguage()
|
|
963
1043
|
});
|
|
964
1044
|
this.schema = new SchemaClient({
|
|
965
1045
|
gatewayUrl: this.gatewayUrl,
|
|
@@ -969,6 +1049,19 @@ var Zone4CodeClient = class {
|
|
|
969
1049
|
fetchWithAuth: (url, init) => this.auth.fetchWithAuth(url, init)
|
|
970
1050
|
});
|
|
971
1051
|
}
|
|
1052
|
+
/**
|
|
1053
|
+
* Set the active default language for API requests (e.g., 'en', 'fr', 'ar', or '*' for raw)
|
|
1054
|
+
*/
|
|
1055
|
+
setLanguage(lang) {
|
|
1056
|
+
this.currentLanguage = lang;
|
|
1057
|
+
return this;
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Get the active default language
|
|
1061
|
+
*/
|
|
1062
|
+
getLanguage() {
|
|
1063
|
+
return this.currentLanguage;
|
|
1064
|
+
}
|
|
972
1065
|
/**
|
|
973
1066
|
* Access an entity collection with chainable query builder (like Supabase .from('orders'))
|
|
974
1067
|
*/
|
|
@@ -979,7 +1072,8 @@ var Zone4CodeClient = class {
|
|
|
979
1072
|
typeName,
|
|
980
1073
|
getToken: () => this.auth.getToken(),
|
|
981
1074
|
fetchFn: this.fetchFn,
|
|
982
|
-
fetchWithAuth: (url, init) => this.auth.fetchWithAuth(url, init)
|
|
1075
|
+
fetchWithAuth: (url, init) => this.auth.fetchWithAuth(url, init),
|
|
1076
|
+
defaultLanguage: () => this.getLanguage()
|
|
983
1077
|
});
|
|
984
1078
|
}
|
|
985
1079
|
/**
|