tersejson 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/LICENSE +21 -0
- package/README.md +476 -0
- package/dist/analytics.d.mts +186 -0
- package/dist/analytics.d.ts +186 -0
- package/dist/analytics.js +226 -0
- package/dist/analytics.js.map +1 -0
- package/dist/analytics.mjs +217 -0
- package/dist/analytics.mjs.map +1 -0
- package/dist/client-BQAZg7I8.d.mts +138 -0
- package/dist/client-DOOGwp_p.d.ts +138 -0
- package/dist/client.d.mts +2 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +200 -0
- package/dist/client.js.map +1 -0
- package/dist/client.mjs +188 -0
- package/dist/client.mjs.map +1 -0
- package/dist/express-BoL__Ao6.d.mts +67 -0
- package/dist/express-LSVylWpN.d.ts +67 -0
- package/dist/express.d.mts +4 -0
- package/dist/express.d.ts +4 -0
- package/dist/express.js +522 -0
- package/dist/express.js.map +1 -0
- package/dist/express.mjs +512 -0
- package/dist/express.mjs.map +1 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1001 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +985 -0
- package/dist/index.mjs.map +1 -0
- package/dist/integrations-7WeFO1Lk.d.mts +264 -0
- package/dist/integrations-7WeFO1Lk.d.ts +264 -0
- package/dist/integrations.d.mts +1 -0
- package/dist/integrations.d.ts +1 -0
- package/dist/integrations.js +381 -0
- package/dist/integrations.js.map +1 -0
- package/dist/integrations.mjs +367 -0
- package/dist/integrations.mjs.map +1 -0
- package/dist/types-CzaGQaV7.d.mts +134 -0
- package/dist/types-CzaGQaV7.d.ts +134 -0
- package/package.json +87 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TerseJSON Framework Integrations
|
|
3
|
+
*
|
|
4
|
+
* Ready-to-use integrations for popular HTTP clients and frameworks.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Axios request interceptor type
|
|
8
|
+
*/
|
|
9
|
+
interface AxiosRequestConfig {
|
|
10
|
+
headers?: Record<string, string> | {
|
|
11
|
+
set?: (key: string, value: string) => void;
|
|
12
|
+
};
|
|
13
|
+
[key: string]: unknown;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Axios response type
|
|
17
|
+
*/
|
|
18
|
+
interface AxiosResponse<T = unknown> {
|
|
19
|
+
data: T;
|
|
20
|
+
headers: Record<string, string> | {
|
|
21
|
+
get?: (key: string) => string | null;
|
|
22
|
+
};
|
|
23
|
+
status: number;
|
|
24
|
+
statusText: string;
|
|
25
|
+
config: AxiosRequestConfig;
|
|
26
|
+
[key: string]: unknown;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create Axios interceptors for TerseJSON support
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* import axios from 'axios';
|
|
34
|
+
* import { createAxiosInterceptors } from 'tersejson/integrations';
|
|
35
|
+
*
|
|
36
|
+
* const { request, response } = createAxiosInterceptors();
|
|
37
|
+
* axios.interceptors.request.use(request);
|
|
38
|
+
* axios.interceptors.response.use(response);
|
|
39
|
+
*
|
|
40
|
+
* // Now all axios requests automatically handle TerseJSON
|
|
41
|
+
* const { data } = await axios.get('/api/users');
|
|
42
|
+
* console.log(data[0].firstName); // Works transparently!
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
declare function createAxiosInterceptors(options?: {
|
|
46
|
+
useProxy?: boolean;
|
|
47
|
+
debug?: boolean;
|
|
48
|
+
}): {
|
|
49
|
+
request: <T extends AxiosRequestConfig>(config: T) => T;
|
|
50
|
+
response: <T>(response: AxiosResponse<T>) => AxiosResponse<T>;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Pre-configured Axios interceptors (convenience export)
|
|
54
|
+
*/
|
|
55
|
+
declare const axiosInterceptors: {
|
|
56
|
+
request: <T extends AxiosRequestConfig>(config: T) => T;
|
|
57
|
+
response: <T>(response: AxiosResponse<T>) => AxiosResponse<T>;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Angular HttpInterceptor interface (simplified)
|
|
61
|
+
*/
|
|
62
|
+
interface HttpRequest<T = unknown> {
|
|
63
|
+
clone: (options: {
|
|
64
|
+
setHeaders?: Record<string, string>;
|
|
65
|
+
}) => HttpRequest<T>;
|
|
66
|
+
[key: string]: unknown;
|
|
67
|
+
}
|
|
68
|
+
interface HttpEvent<T = unknown> {
|
|
69
|
+
type?: number;
|
|
70
|
+
body?: T;
|
|
71
|
+
headers?: {
|
|
72
|
+
get: (name: string) => string | null;
|
|
73
|
+
};
|
|
74
|
+
[key: string]: unknown;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Creates an Angular HTTP interceptor for TerseJSON support
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* // terse.interceptor.ts
|
|
82
|
+
* import { Injectable } from '@angular/core';
|
|
83
|
+
* import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse } from '@angular/common/http';
|
|
84
|
+
* import { Observable } from 'rxjs';
|
|
85
|
+
* import { map } from 'rxjs/operators';
|
|
86
|
+
* import { createAngularInterceptor } from 'tersejson/integrations';
|
|
87
|
+
*
|
|
88
|
+
* @Injectable()
|
|
89
|
+
* export class TerseInterceptor implements HttpInterceptor {
|
|
90
|
+
* private handler = createAngularInterceptor();
|
|
91
|
+
*
|
|
92
|
+
* intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
|
93
|
+
* return this.handler(req, next);
|
|
94
|
+
* }
|
|
95
|
+
* }
|
|
96
|
+
*
|
|
97
|
+
* // app.module.ts
|
|
98
|
+
* providers: [
|
|
99
|
+
* { provide: HTTP_INTERCEPTORS, useClass: TerseInterceptor, multi: true }
|
|
100
|
+
* ]
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
declare function createAngularInterceptor(options?: {
|
|
104
|
+
useProxy?: boolean;
|
|
105
|
+
debug?: boolean;
|
|
106
|
+
}): {
|
|
107
|
+
/**
|
|
108
|
+
* Modifies the request to include the accept-terse header
|
|
109
|
+
*/
|
|
110
|
+
modifyRequest: <T>(req: HttpRequest<T>) => HttpRequest<T>;
|
|
111
|
+
/**
|
|
112
|
+
* Processes the response to expand TerseJSON payloads
|
|
113
|
+
*/
|
|
114
|
+
processResponse: <T>(event: HttpEvent<T>) => HttpEvent<T>;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Angular interceptor code snippet for copy-paste
|
|
118
|
+
* Since Angular interceptors require decorators, we provide the implementation
|
|
119
|
+
*/
|
|
120
|
+
declare const angularInterceptorSnippet = "\n// terse.interceptor.ts\nimport { Injectable } from '@angular/core';\nimport {\n HttpInterceptor,\n HttpRequest,\n HttpHandler,\n HttpEvent,\n HttpResponse\n} from '@angular/common/http';\nimport { Observable } from 'rxjs';\nimport { map } from 'rxjs/operators';\nimport { isTersePayload, wrapWithProxy } from 'tersejson';\n\n@Injectable()\nexport class TerseInterceptor implements HttpInterceptor {\n intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {\n // Add accept-terse header\n const terseReq = req.clone({\n setHeaders: { 'accept-terse': 'true' }\n });\n\n return next.handle(terseReq).pipe(\n map(event => {\n if (event instanceof HttpResponse && event.body) {\n const isTerse = event.headers.get('x-terse-json') === 'true';\n if (isTerse && isTersePayload(event.body)) {\n return event.clone({ body: wrapWithProxy(event.body) });\n }\n }\n return event;\n })\n );\n }\n}\n\n// app.module.ts - Add to providers:\n// { provide: HTTP_INTERCEPTORS, useClass: TerseInterceptor, multi: true }\n";
|
|
121
|
+
/**
|
|
122
|
+
* AngularJS $http config type
|
|
123
|
+
*/
|
|
124
|
+
interface AngularJSHttpConfig {
|
|
125
|
+
headers?: Record<string, string>;
|
|
126
|
+
[key: string]: unknown;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* AngularJS $http response type
|
|
130
|
+
*/
|
|
131
|
+
interface AngularJSHttpResponse<T = unknown> {
|
|
132
|
+
data: T;
|
|
133
|
+
headers: (name: string) => string | null;
|
|
134
|
+
status: number;
|
|
135
|
+
statusText: string;
|
|
136
|
+
config: AngularJSHttpConfig;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Creates AngularJS $http interceptor for TerseJSON support
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```javascript
|
|
143
|
+
* // In your AngularJS app config
|
|
144
|
+
* angular.module('myApp', [])
|
|
145
|
+
* .config(['$httpProvider', function($httpProvider) {
|
|
146
|
+
* $httpProvider.interceptors.push(['$q', function($q) {
|
|
147
|
+
* return createAngularJSInterceptor();
|
|
148
|
+
* }]);
|
|
149
|
+
* }]);
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
declare function createAngularJSInterceptor(options?: {
|
|
153
|
+
useProxy?: boolean;
|
|
154
|
+
debug?: boolean;
|
|
155
|
+
}): {
|
|
156
|
+
/**
|
|
157
|
+
* Request interceptor - adds accept-terse header
|
|
158
|
+
*/
|
|
159
|
+
request: <T extends AngularJSHttpConfig>(config: T) => T;
|
|
160
|
+
/**
|
|
161
|
+
* Response interceptor - expands TerseJSON payloads
|
|
162
|
+
*/
|
|
163
|
+
response: <T>(response: AngularJSHttpResponse<T>) => AngularJSHttpResponse<T>;
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* AngularJS setup code snippet
|
|
167
|
+
*/
|
|
168
|
+
declare const angularJSInterceptorSnippet = "\n// Setup TerseJSON with AngularJS\nangular.module('myApp', [])\n .factory('terseInterceptor', ['$q', function($q) {\n return {\n request: function(config) {\n config.headers = config.headers || {};\n config.headers['accept-terse'] = 'true';\n return config;\n },\n response: function(response) {\n var isTerse = response.headers('x-terse-json') === 'true';\n if (isTerse && response.data && response.data.__terse__) {\n // Use tersejson.process() or tersejson.wrapWithProxy()\n response.data = tersejson.process(response.data);\n }\n return response;\n }\n };\n }])\n .config(['$httpProvider', function($httpProvider) {\n $httpProvider.interceptors.push('terseInterceptor');\n }]);\n";
|
|
169
|
+
/**
|
|
170
|
+
* jQuery AJAX setup for TerseJSON
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```javascript
|
|
174
|
+
* import { setupJQueryAjax } from 'tersejson/integrations';
|
|
175
|
+
* setupJQueryAjax($);
|
|
176
|
+
*
|
|
177
|
+
* // Now $.ajax, $.get, $.post all support TerseJSON
|
|
178
|
+
* $.get('/api/users', function(data) {
|
|
179
|
+
* console.log(data[0].firstName); // Works!
|
|
180
|
+
* });
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
declare function setupJQueryAjax($: {
|
|
184
|
+
ajaxSetup: (options: unknown) => void;
|
|
185
|
+
ajaxPrefilter: (callback: unknown) => void;
|
|
186
|
+
}, options?: {
|
|
187
|
+
useProxy?: boolean;
|
|
188
|
+
debug?: boolean;
|
|
189
|
+
}): void;
|
|
190
|
+
/**
|
|
191
|
+
* jQuery setup code snippet
|
|
192
|
+
*/
|
|
193
|
+
declare const jQuerySetupSnippet = "\n// Setup TerseJSON with jQuery\n$.ajaxSetup({\n headers: { 'accept-terse': 'true' },\n dataFilter: function(data, type) {\n if (type === 'json') {\n var parsed = JSON.parse(data);\n if (parsed && parsed.__terse__) {\n return tersejson.process(parsed);\n }\n return parsed;\n }\n return data;\n }\n});\n";
|
|
194
|
+
/**
|
|
195
|
+
* Creates a fetcher for SWR with TerseJSON support
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```typescript
|
|
199
|
+
* import useSWR from 'swr';
|
|
200
|
+
* import { createSWRFetcher } from 'tersejson/integrations';
|
|
201
|
+
*
|
|
202
|
+
* const fetcher = createSWRFetcher();
|
|
203
|
+
*
|
|
204
|
+
* function UserList() {
|
|
205
|
+
* const { data, error } = useSWR('/api/users', fetcher);
|
|
206
|
+
* return <div>{data?.[0].firstName}</div>;
|
|
207
|
+
* }
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
declare function createSWRFetcher(options?: {
|
|
211
|
+
useProxy?: boolean;
|
|
212
|
+
debug?: boolean;
|
|
213
|
+
}): <T>(url: string) => Promise<T>;
|
|
214
|
+
/**
|
|
215
|
+
* Creates a query function for React Query / TanStack Query
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* ```typescript
|
|
219
|
+
* import { useQuery } from '@tanstack/react-query';
|
|
220
|
+
* import { createQueryFn } from 'tersejson/integrations';
|
|
221
|
+
*
|
|
222
|
+
* const queryFn = createQueryFn();
|
|
223
|
+
*
|
|
224
|
+
* function UserList() {
|
|
225
|
+
* const { data } = useQuery({
|
|
226
|
+
* queryKey: ['users'],
|
|
227
|
+
* queryFn: () => queryFn('/api/users')
|
|
228
|
+
* });
|
|
229
|
+
* return <div>{data?.[0].firstName}</div>;
|
|
230
|
+
* }
|
|
231
|
+
* ```
|
|
232
|
+
*/
|
|
233
|
+
declare const createQueryFn: typeof createSWRFetcher;
|
|
234
|
+
declare const _default: {
|
|
235
|
+
createAxiosInterceptors: typeof createAxiosInterceptors;
|
|
236
|
+
axiosInterceptors: {
|
|
237
|
+
request: <T extends AxiosRequestConfig>(config: T) => T;
|
|
238
|
+
response: <T>(response: AxiosResponse<T>) => AxiosResponse<T>;
|
|
239
|
+
};
|
|
240
|
+
createAngularInterceptor: typeof createAngularInterceptor;
|
|
241
|
+
angularInterceptorSnippet: string;
|
|
242
|
+
createAngularJSInterceptor: typeof createAngularJSInterceptor;
|
|
243
|
+
angularJSInterceptorSnippet: string;
|
|
244
|
+
setupJQueryAjax: typeof setupJQueryAjax;
|
|
245
|
+
jQuerySetupSnippet: string;
|
|
246
|
+
createSWRFetcher: typeof createSWRFetcher;
|
|
247
|
+
createQueryFn: typeof createSWRFetcher;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
declare const integrations_angularInterceptorSnippet: typeof angularInterceptorSnippet;
|
|
251
|
+
declare const integrations_angularJSInterceptorSnippet: typeof angularJSInterceptorSnippet;
|
|
252
|
+
declare const integrations_axiosInterceptors: typeof axiosInterceptors;
|
|
253
|
+
declare const integrations_createAngularInterceptor: typeof createAngularInterceptor;
|
|
254
|
+
declare const integrations_createAngularJSInterceptor: typeof createAngularJSInterceptor;
|
|
255
|
+
declare const integrations_createAxiosInterceptors: typeof createAxiosInterceptors;
|
|
256
|
+
declare const integrations_createQueryFn: typeof createQueryFn;
|
|
257
|
+
declare const integrations_createSWRFetcher: typeof createSWRFetcher;
|
|
258
|
+
declare const integrations_jQuerySetupSnippet: typeof jQuerySetupSnippet;
|
|
259
|
+
declare const integrations_setupJQueryAjax: typeof setupJQueryAjax;
|
|
260
|
+
declare namespace integrations {
|
|
261
|
+
export { integrations_angularInterceptorSnippet as angularInterceptorSnippet, integrations_angularJSInterceptorSnippet as angularJSInterceptorSnippet, integrations_axiosInterceptors as axiosInterceptors, integrations_createAngularInterceptor as createAngularInterceptor, integrations_createAngularJSInterceptor as createAngularJSInterceptor, integrations_createAxiosInterceptors as createAxiosInterceptors, integrations_createQueryFn as createQueryFn, integrations_createSWRFetcher as createSWRFetcher, _default as default, integrations_jQuerySetupSnippet as jQuerySetupSnippet, integrations_setupJQueryAjax as setupJQueryAjax };
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export { _default as _, axiosInterceptors as a, createAngularInterceptor as b, createAxiosInterceptors as c, angularInterceptorSnippet as d, createAngularJSInterceptor as e, angularJSInterceptorSnippet as f, createSWRFetcher as g, createQueryFn as h, integrations as i, jQuerySetupSnippet as j, setupJQueryAjax as s };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { d as angularInterceptorSnippet, f as angularJSInterceptorSnippet, a as axiosInterceptors, b as createAngularInterceptor, e as createAngularJSInterceptor, c as createAxiosInterceptors, h as createQueryFn, g as createSWRFetcher, _ as default, j as jQuerySetupSnippet, s as setupJQueryAjax } from './integrations-7WeFO1Lk.mjs';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { d as angularInterceptorSnippet, f as angularJSInterceptorSnippet, a as axiosInterceptors, b as createAngularInterceptor, e as createAngularJSInterceptor, c as createAxiosInterceptors, h as createQueryFn, g as createSWRFetcher, _ as default, j as jQuerySetupSnippet, s as setupJQueryAjax } from './integrations-7WeFO1Lk.js';
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
// src/types.ts
|
|
6
|
+
function isTersePayload(value) {
|
|
7
|
+
return typeof value === "object" && value !== null && "__terse__" in value && value.__terse__ === true && "v" in value && "k" in value && "d" in value;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// src/core.ts
|
|
11
|
+
function expandObject(obj, shortToKey, maxDepth, currentDepth = 0) {
|
|
12
|
+
if (currentDepth >= maxDepth) return obj;
|
|
13
|
+
const expanded = {};
|
|
14
|
+
for (const [shortKey, value] of Object.entries(obj)) {
|
|
15
|
+
const originalKey = shortToKey.get(shortKey) ?? shortKey;
|
|
16
|
+
if (Array.isArray(value)) {
|
|
17
|
+
expanded[originalKey] = value.map((item) => {
|
|
18
|
+
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
19
|
+
return expandObject(
|
|
20
|
+
item,
|
|
21
|
+
shortToKey,
|
|
22
|
+
maxDepth,
|
|
23
|
+
currentDepth + 1
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
return item;
|
|
27
|
+
});
|
|
28
|
+
} else if (typeof value === "object" && value !== null) {
|
|
29
|
+
expanded[originalKey] = expandObject(
|
|
30
|
+
value,
|
|
31
|
+
shortToKey,
|
|
32
|
+
maxDepth,
|
|
33
|
+
currentDepth + 1
|
|
34
|
+
);
|
|
35
|
+
} else {
|
|
36
|
+
expanded[originalKey] = value;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return expanded;
|
|
40
|
+
}
|
|
41
|
+
function expand(payload) {
|
|
42
|
+
const shortToKey = new Map(
|
|
43
|
+
Object.entries(payload.k).map(([short, original]) => [short, original])
|
|
44
|
+
);
|
|
45
|
+
if (Array.isArray(payload.d)) {
|
|
46
|
+
return payload.d.map((item) => {
|
|
47
|
+
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
48
|
+
return expandObject(item, shortToKey, 10);
|
|
49
|
+
}
|
|
50
|
+
return item;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (typeof payload.d === "object" && payload.d !== null) {
|
|
54
|
+
return expandObject(payload.d, shortToKey, 10);
|
|
55
|
+
}
|
|
56
|
+
return payload.d;
|
|
57
|
+
}
|
|
58
|
+
function createTerseProxy(compressed, keyMap) {
|
|
59
|
+
const originalToShort = new Map(
|
|
60
|
+
Object.entries(keyMap).map(([short, original]) => [original, short])
|
|
61
|
+
);
|
|
62
|
+
const handler = {
|
|
63
|
+
get(target, prop) {
|
|
64
|
+
if (typeof prop === "symbol") {
|
|
65
|
+
return Reflect.get(target, prop);
|
|
66
|
+
}
|
|
67
|
+
const shortKey = originalToShort.get(prop);
|
|
68
|
+
const actualKey = shortKey ?? prop;
|
|
69
|
+
const value = target[actualKey];
|
|
70
|
+
if (Array.isArray(value)) {
|
|
71
|
+
return value.map((item) => {
|
|
72
|
+
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
73
|
+
return createTerseProxy(item, keyMap);
|
|
74
|
+
}
|
|
75
|
+
return item;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (typeof value === "object" && value !== null) {
|
|
79
|
+
return createTerseProxy(value, keyMap);
|
|
80
|
+
}
|
|
81
|
+
return value;
|
|
82
|
+
},
|
|
83
|
+
has(target, prop) {
|
|
84
|
+
if (typeof prop === "symbol") {
|
|
85
|
+
return Reflect.has(target, prop);
|
|
86
|
+
}
|
|
87
|
+
const shortKey = originalToShort.get(prop);
|
|
88
|
+
return (shortKey ?? prop) in target;
|
|
89
|
+
},
|
|
90
|
+
ownKeys(target) {
|
|
91
|
+
return Object.keys(target).map((shortKey) => keyMap[shortKey] ?? shortKey);
|
|
92
|
+
},
|
|
93
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
94
|
+
if (typeof prop === "symbol") {
|
|
95
|
+
return Reflect.getOwnPropertyDescriptor(target, prop);
|
|
96
|
+
}
|
|
97
|
+
const shortKey = originalToShort.get(prop);
|
|
98
|
+
const actualKey = shortKey ?? prop;
|
|
99
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, actualKey);
|
|
100
|
+
if (descriptor) {
|
|
101
|
+
return { ...descriptor, enumerable: true, configurable: true };
|
|
102
|
+
}
|
|
103
|
+
return void 0;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
return new Proxy(compressed, handler);
|
|
107
|
+
}
|
|
108
|
+
function wrapWithProxy(payload) {
|
|
109
|
+
if (Array.isArray(payload.d)) {
|
|
110
|
+
return payload.d.map((item) => {
|
|
111
|
+
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
112
|
+
return createTerseProxy(item, payload.k);
|
|
113
|
+
}
|
|
114
|
+
return item;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
if (typeof payload.d === "object" && payload.d !== null) {
|
|
118
|
+
return createTerseProxy(payload.d, payload.k);
|
|
119
|
+
}
|
|
120
|
+
return payload.d;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// src/integrations.ts
|
|
124
|
+
function createAxiosInterceptors(options = {}) {
|
|
125
|
+
const { useProxy = true, debug = false } = options;
|
|
126
|
+
return {
|
|
127
|
+
request: (config) => {
|
|
128
|
+
if (config.headers) {
|
|
129
|
+
if (typeof config.headers.set === "function") {
|
|
130
|
+
config.headers.set("accept-terse", "true");
|
|
131
|
+
} else {
|
|
132
|
+
config.headers["accept-terse"] = "true";
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
config.headers = { "accept-terse": "true" };
|
|
136
|
+
}
|
|
137
|
+
return config;
|
|
138
|
+
},
|
|
139
|
+
response: (response) => {
|
|
140
|
+
let isTerse = false;
|
|
141
|
+
if (response.headers) {
|
|
142
|
+
if (typeof response.headers.get === "function") {
|
|
143
|
+
isTerse = response.headers.get("x-terse-json") === "true";
|
|
144
|
+
} else {
|
|
145
|
+
isTerse = response.headers["x-terse-json"] === "true";
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (isTerse && isTersePayload(response.data)) {
|
|
149
|
+
if (debug) {
|
|
150
|
+
console.log("[tersejson] Expanding Axios response");
|
|
151
|
+
}
|
|
152
|
+
response.data = useProxy ? wrapWithProxy(response.data) : expand(response.data);
|
|
153
|
+
}
|
|
154
|
+
return response;
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
var axiosInterceptors = createAxiosInterceptors();
|
|
159
|
+
function createAngularInterceptor(options = {}) {
|
|
160
|
+
const { useProxy = true, debug = false } = options;
|
|
161
|
+
return {
|
|
162
|
+
/**
|
|
163
|
+
* Modifies the request to include the accept-terse header
|
|
164
|
+
*/
|
|
165
|
+
modifyRequest: (req) => {
|
|
166
|
+
return req.clone({
|
|
167
|
+
setHeaders: {
|
|
168
|
+
"accept-terse": "true"
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
},
|
|
172
|
+
/**
|
|
173
|
+
* Processes the response to expand TerseJSON payloads
|
|
174
|
+
*/
|
|
175
|
+
processResponse: (event) => {
|
|
176
|
+
if (event.type === 4 && event.body !== void 0) {
|
|
177
|
+
const isTerse = event.headers?.get("x-terse-json") === "true";
|
|
178
|
+
if (isTerse && isTersePayload(event.body)) {
|
|
179
|
+
if (debug) {
|
|
180
|
+
console.log("[tersejson] Expanding Angular response");
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
...event,
|
|
184
|
+
body: useProxy ? wrapWithProxy(event.body) : expand(event.body)
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return event;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
var angularInterceptorSnippet = `
|
|
193
|
+
// terse.interceptor.ts
|
|
194
|
+
import { Injectable } from '@angular/core';
|
|
195
|
+
import {
|
|
196
|
+
HttpInterceptor,
|
|
197
|
+
HttpRequest,
|
|
198
|
+
HttpHandler,
|
|
199
|
+
HttpEvent,
|
|
200
|
+
HttpResponse
|
|
201
|
+
} from '@angular/common/http';
|
|
202
|
+
import { Observable } from 'rxjs';
|
|
203
|
+
import { map } from 'rxjs/operators';
|
|
204
|
+
import { isTersePayload, wrapWithProxy } from 'tersejson';
|
|
205
|
+
|
|
206
|
+
@Injectable()
|
|
207
|
+
export class TerseInterceptor implements HttpInterceptor {
|
|
208
|
+
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
|
209
|
+
// Add accept-terse header
|
|
210
|
+
const terseReq = req.clone({
|
|
211
|
+
setHeaders: { 'accept-terse': 'true' }
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
return next.handle(terseReq).pipe(
|
|
215
|
+
map(event => {
|
|
216
|
+
if (event instanceof HttpResponse && event.body) {
|
|
217
|
+
const isTerse = event.headers.get('x-terse-json') === 'true';
|
|
218
|
+
if (isTerse && isTersePayload(event.body)) {
|
|
219
|
+
return event.clone({ body: wrapWithProxy(event.body) });
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return event;
|
|
223
|
+
})
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// app.module.ts - Add to providers:
|
|
229
|
+
// { provide: HTTP_INTERCEPTORS, useClass: TerseInterceptor, multi: true }
|
|
230
|
+
`;
|
|
231
|
+
function createAngularJSInterceptor(options = {}) {
|
|
232
|
+
const { useProxy = true, debug = false } = options;
|
|
233
|
+
return {
|
|
234
|
+
/**
|
|
235
|
+
* Request interceptor - adds accept-terse header
|
|
236
|
+
*/
|
|
237
|
+
request: (config) => {
|
|
238
|
+
config.headers = config.headers || {};
|
|
239
|
+
config.headers["accept-terse"] = "true";
|
|
240
|
+
return config;
|
|
241
|
+
},
|
|
242
|
+
/**
|
|
243
|
+
* Response interceptor - expands TerseJSON payloads
|
|
244
|
+
*/
|
|
245
|
+
response: (response) => {
|
|
246
|
+
const isTerse = response.headers("x-terse-json") === "true";
|
|
247
|
+
if (isTerse && isTersePayload(response.data)) {
|
|
248
|
+
if (debug) {
|
|
249
|
+
console.log("[tersejson] Expanding AngularJS response");
|
|
250
|
+
}
|
|
251
|
+
response.data = useProxy ? wrapWithProxy(response.data) : expand(response.data);
|
|
252
|
+
}
|
|
253
|
+
return response;
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
var angularJSInterceptorSnippet = `
|
|
258
|
+
// Setup TerseJSON with AngularJS
|
|
259
|
+
angular.module('myApp', [])
|
|
260
|
+
.factory('terseInterceptor', ['$q', function($q) {
|
|
261
|
+
return {
|
|
262
|
+
request: function(config) {
|
|
263
|
+
config.headers = config.headers || {};
|
|
264
|
+
config.headers['accept-terse'] = 'true';
|
|
265
|
+
return config;
|
|
266
|
+
},
|
|
267
|
+
response: function(response) {
|
|
268
|
+
var isTerse = response.headers('x-terse-json') === 'true';
|
|
269
|
+
if (isTerse && response.data && response.data.__terse__) {
|
|
270
|
+
// Use tersejson.process() or tersejson.wrapWithProxy()
|
|
271
|
+
response.data = tersejson.process(response.data);
|
|
272
|
+
}
|
|
273
|
+
return response;
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
}])
|
|
277
|
+
.config(['$httpProvider', function($httpProvider) {
|
|
278
|
+
$httpProvider.interceptors.push('terseInterceptor');
|
|
279
|
+
}]);
|
|
280
|
+
`;
|
|
281
|
+
function setupJQueryAjax($, options = {}) {
|
|
282
|
+
const { useProxy = true, debug = false } = options;
|
|
283
|
+
$.ajaxSetup({
|
|
284
|
+
headers: {
|
|
285
|
+
"accept-terse": "true"
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
$.ajaxPrefilter((ajaxOptions) => {
|
|
289
|
+
const originalDataFilter = ajaxOptions.dataFilter;
|
|
290
|
+
ajaxOptions.dataFilter = function(data, type) {
|
|
291
|
+
let processed = data;
|
|
292
|
+
if (originalDataFilter) {
|
|
293
|
+
processed = originalDataFilter(data, type);
|
|
294
|
+
}
|
|
295
|
+
if (type === "json" || type === void 0) {
|
|
296
|
+
try {
|
|
297
|
+
const parsed = typeof processed === "string" ? JSON.parse(processed) : processed;
|
|
298
|
+
if (isTersePayload(parsed)) {
|
|
299
|
+
if (debug) {
|
|
300
|
+
console.log("[tersejson] Expanding jQuery response");
|
|
301
|
+
}
|
|
302
|
+
return useProxy ? wrapWithProxy(parsed) : expand(parsed);
|
|
303
|
+
}
|
|
304
|
+
return parsed;
|
|
305
|
+
} catch {
|
|
306
|
+
return processed;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return processed;
|
|
310
|
+
};
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
var jQuerySetupSnippet = `
|
|
314
|
+
// Setup TerseJSON with jQuery
|
|
315
|
+
$.ajaxSetup({
|
|
316
|
+
headers: { 'accept-terse': 'true' },
|
|
317
|
+
dataFilter: function(data, type) {
|
|
318
|
+
if (type === 'json') {
|
|
319
|
+
var parsed = JSON.parse(data);
|
|
320
|
+
if (parsed && parsed.__terse__) {
|
|
321
|
+
return tersejson.process(parsed);
|
|
322
|
+
}
|
|
323
|
+
return parsed;
|
|
324
|
+
}
|
|
325
|
+
return data;
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
`;
|
|
329
|
+
function createSWRFetcher(options = {}) {
|
|
330
|
+
const { useProxy = true, debug = false } = options;
|
|
331
|
+
return async (url) => {
|
|
332
|
+
const response = await globalThis.fetch(url, {
|
|
333
|
+
headers: {
|
|
334
|
+
"accept-terse": "true"
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
if (!response.ok) {
|
|
338
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
339
|
+
}
|
|
340
|
+
const data = await response.json();
|
|
341
|
+
if (isTersePayload(data)) {
|
|
342
|
+
if (debug) {
|
|
343
|
+
console.log("[tersejson] Expanding SWR response");
|
|
344
|
+
}
|
|
345
|
+
return useProxy ? wrapWithProxy(data) : expand(data);
|
|
346
|
+
}
|
|
347
|
+
return data;
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
var createQueryFn = createSWRFetcher;
|
|
351
|
+
var integrations_default = {
|
|
352
|
+
// Axios
|
|
353
|
+
createAxiosInterceptors,
|
|
354
|
+
axiosInterceptors,
|
|
355
|
+
// Angular
|
|
356
|
+
createAngularInterceptor,
|
|
357
|
+
angularInterceptorSnippet,
|
|
358
|
+
// AngularJS
|
|
359
|
+
createAngularJSInterceptor,
|
|
360
|
+
angularJSInterceptorSnippet,
|
|
361
|
+
// jQuery
|
|
362
|
+
setupJQueryAjax,
|
|
363
|
+
jQuerySetupSnippet,
|
|
364
|
+
// SWR / React Query
|
|
365
|
+
createSWRFetcher,
|
|
366
|
+
createQueryFn
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
exports.angularInterceptorSnippet = angularInterceptorSnippet;
|
|
370
|
+
exports.angularJSInterceptorSnippet = angularJSInterceptorSnippet;
|
|
371
|
+
exports.axiosInterceptors = axiosInterceptors;
|
|
372
|
+
exports.createAngularInterceptor = createAngularInterceptor;
|
|
373
|
+
exports.createAngularJSInterceptor = createAngularJSInterceptor;
|
|
374
|
+
exports.createAxiosInterceptors = createAxiosInterceptors;
|
|
375
|
+
exports.createQueryFn = createQueryFn;
|
|
376
|
+
exports.createSWRFetcher = createSWRFetcher;
|
|
377
|
+
exports.default = integrations_default;
|
|
378
|
+
exports.jQuerySetupSnippet = jQuerySetupSnippet;
|
|
379
|
+
exports.setupJQueryAjax = setupJQueryAjax;
|
|
380
|
+
//# sourceMappingURL=integrations.js.map
|
|
381
|
+
//# sourceMappingURL=integrations.js.map
|