@arc-js/qust 0.0.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/js/index.js ADDED
@@ -0,0 +1,328 @@
1
+ const globalFunct = (function (global) {
2
+ 'use strict';
3
+ const DEFAULT_OPTIONS = {
4
+ arrayFormat: 'bracket',
5
+ arraySeparator: ',',
6
+ skipNull: true,
7
+ skipEmptyString: false,
8
+ encode: true,
9
+ decode: true,
10
+ depth: 10
11
+ };
12
+ class Qust {
13
+ options;
14
+ constructor(options = {}) {
15
+ this.options = { ...DEFAULT_OPTIONS, ...options };
16
+ }
17
+ stringify(obj) {
18
+ if (!obj || typeof obj !== 'object') {
19
+ return '';
20
+ }
21
+ const parts = [];
22
+ this.processObject('', obj, parts, 0);
23
+ return parts.length > 0 ? `?${parts.join('&')}` : '';
24
+ }
25
+ parse(queryString) {
26
+ if (!queryString || typeof queryString !== 'string') {
27
+ return {};
28
+ }
29
+ const cleanString = queryString.startsWith('?')
30
+ ? queryString.slice(1)
31
+ : queryString;
32
+ if (!cleanString) {
33
+ return {};
34
+ }
35
+ const result = {};
36
+ const pairs = cleanString.split('&');
37
+ for (const pair of pairs) {
38
+ if (!pair)
39
+ continue;
40
+ const [encodedKey, encodedValue] = pair.split('=');
41
+ if (!encodedKey)
42
+ continue;
43
+ const key = this.options.decode
44
+ ? decodeURIComponent(encodedKey)
45
+ : encodedKey;
46
+ const value = this.options.decode && encodedValue !== undefined
47
+ ? decodeURIComponent(encodedValue)
48
+ : encodedValue;
49
+ this.setValue(result, key, value);
50
+ }
51
+ return this.transformArrays(result);
52
+ }
53
+ processObject(prefix, value, parts, depth) {
54
+ if (depth > this.options.depth) {
55
+ console.warn('Qust: Profondeur maximale atteinte, arrêt de la récursion');
56
+ return;
57
+ }
58
+ if (value === null || value === undefined) {
59
+ if (!this.options.skipNull) {
60
+ parts.push(this.encodeKey(prefix));
61
+ }
62
+ return;
63
+ }
64
+ if (typeof value === 'string' && value === '' && this.options.skipEmptyString) {
65
+ return;
66
+ }
67
+ if (Array.isArray(value)) {
68
+ this.processArray(prefix, value, parts, depth + 1);
69
+ return;
70
+ }
71
+ if (typeof value === 'object' && !this.isPrimitive(value)) {
72
+ for (const [key, val] of Object.entries(value)) {
73
+ const newPrefix = prefix ? `${prefix}[${key}]` : key;
74
+ this.processObject(newPrefix, val, parts, depth + 1);
75
+ }
76
+ return;
77
+ }
78
+ const encodedKey = this.encodeKey(prefix);
79
+ const encodedValue = this.options.encode && typeof value === 'string'
80
+ ? encodeURIComponent(value)
81
+ : String(value);
82
+ parts.push(`${encodedKey}=${encodedValue}`);
83
+ }
84
+ processArray(prefix, array, parts, depth) {
85
+ if (array.length === 0)
86
+ return;
87
+ const encodedKey = this.encodeKey(prefix);
88
+ switch (this.options.arrayFormat) {
89
+ case 'comma':
90
+ const values = array
91
+ .map(item => this.options.encode && typeof item === 'string'
92
+ ? encodeURIComponent(item)
93
+ : String(item))
94
+ .join(this.options.arraySeparator);
95
+ parts.push(`${encodedKey}=${values}`);
96
+ break;
97
+ case 'index':
98
+ array.forEach((item, index) => {
99
+ const arrayPrefix = `${prefix}[${index}]`;
100
+ this.processObject(arrayPrefix, item, parts, depth);
101
+ });
102
+ break;
103
+ case 'separator':
104
+ array.forEach(item => {
105
+ const encodedValue = this.options.encode && typeof item === 'string'
106
+ ? encodeURIComponent(item)
107
+ : String(item);
108
+ parts.push(`${encodedKey}=${encodedValue}`);
109
+ });
110
+ break;
111
+ case 'none':
112
+ array.forEach(item => {
113
+ this.processObject(prefix, item, parts, depth);
114
+ });
115
+ break;
116
+ case 'bracket':
117
+ default:
118
+ array.forEach(item => {
119
+ const arrayPrefix = `${prefix}[]`;
120
+ this.processObject(arrayPrefix, item, parts, depth);
121
+ });
122
+ break;
123
+ }
124
+ }
125
+ encodeKey(key) {
126
+ if (!this.options.encode) {
127
+ return key;
128
+ }
129
+ const parts = [];
130
+ let currentPart = '';
131
+ for (let i = 0; i < key.length; i++) {
132
+ const char = key[i];
133
+ if (char === '[' || char === ']') {
134
+ if (currentPart) {
135
+ parts.push(encodeURIComponent(currentPart));
136
+ currentPart = '';
137
+ }
138
+ parts.push(char);
139
+ }
140
+ else {
141
+ currentPart += char;
142
+ }
143
+ }
144
+ if (currentPart) {
145
+ parts.push(encodeURIComponent(currentPart));
146
+ }
147
+ return parts.join('');
148
+ }
149
+ setValue(obj, key, value) {
150
+ const matches = key.match(/([^\[\]]+)|(\[\])/g);
151
+ if (!matches) {
152
+ if (value !== undefined) {
153
+ obj[key] = this.parseValue(value);
154
+ }
155
+ return;
156
+ }
157
+ let current = obj;
158
+ for (let i = 0; i < matches.length; i++) {
159
+ const match = matches[i];
160
+ const isLast = i === matches.length - 1;
161
+ if (match === '[]') {
162
+ if (!Array.isArray(current)) {
163
+ current = [];
164
+ }
165
+ if (isLast) {
166
+ if (!!value) {
167
+ current.push(this.parseValue(value));
168
+ }
169
+ }
170
+ else {
171
+ const nextMatch = matches[i + 1];
172
+ const nextIndex = parseInt(nextMatch, 10);
173
+ if (!isNaN(nextIndex)) {
174
+ if (current[nextIndex] === undefined) {
175
+ current[nextIndex] = {};
176
+ }
177
+ current = current[nextIndex];
178
+ i++;
179
+ }
180
+ else {
181
+ const newObj = {};
182
+ current.push(newObj);
183
+ current = newObj;
184
+ }
185
+ }
186
+ }
187
+ else {
188
+ if (isLast) {
189
+ if (value !== undefined) {
190
+ current[match] = this.parseValue(value);
191
+ }
192
+ }
193
+ else {
194
+ if (current[match] === undefined || typeof current[match] !== 'object') {
195
+ const nextMatch = matches[i + 1];
196
+ current[match] = nextMatch === '[]' ? [] : {};
197
+ }
198
+ current = current[match];
199
+ }
200
+ }
201
+ }
202
+ }
203
+ transformArrays(obj) {
204
+ if (Array.isArray(obj)) {
205
+ return obj.map(item => typeof item === 'object' && item !== null
206
+ ? this.transformArrays(item)
207
+ : item);
208
+ }
209
+ if (typeof obj !== 'object' || obj === null) {
210
+ return obj;
211
+ }
212
+ const result = {};
213
+ const keys = Object.keys(obj);
214
+ const isArrayLike = keys.every(key => {
215
+ const num = parseInt(key, 10);
216
+ return !isNaN(num) && num >= 0 && num.toString() === key;
217
+ });
218
+ if (isArrayLike && keys.length > 0) {
219
+ const array = [];
220
+ keys.forEach(key => {
221
+ const index = parseInt(key, 10);
222
+ array[index] = this.transformArrays(obj[key]);
223
+ });
224
+ return array;
225
+ }
226
+ keys.forEach(key => {
227
+ const value = obj[key];
228
+ result[key] =
229
+ typeof value === 'object' && value !== null
230
+ ? this.transformArrays(value)
231
+ : value;
232
+ });
233
+ return result;
234
+ }
235
+ parseValue(value) {
236
+ if (value === 'true')
237
+ return true;
238
+ if (value === 'false')
239
+ return false;
240
+ if (value === 'null')
241
+ return null;
242
+ if (value === 'undefined')
243
+ return undefined;
244
+ const num = Number(value);
245
+ if (!isNaN(num) && value.trim() !== '')
246
+ return num;
247
+ return value;
248
+ }
249
+ isPrimitive(value) {
250
+ return value === null ||
251
+ typeof value !== 'object' &&
252
+ typeof value !== 'function';
253
+ }
254
+ setOptions(newOptions) {
255
+ this.options = { ...this.options, ...newOptions };
256
+ }
257
+ getOptions() {
258
+ return { ...this.options };
259
+ }
260
+ static exposeToGlobal() {
261
+ if (typeof window !== "undefined") {
262
+ window.Qust = Qust;
263
+ }
264
+ }
265
+ }
266
+ const qust = {
267
+ stringify(obj, options) {
268
+ return new Qust(options).stringify(obj);
269
+ },
270
+ parse(queryString, options) {
271
+ return new Qust(options).parse(queryString);
272
+ }
273
+ };
274
+ if (typeof window !== "undefined") {
275
+ window.Qust = Qust;
276
+ window.qust = qust;
277
+ }
278
+ const globalFunctModule = {
279
+ default: qust,
280
+ Qust: Qust,
281
+ qust: qust,
282
+ };
283
+ globalFunctModule.default = { ...(globalFunctModule?.default || {}), Qust: Qust };
284
+ globalFunctModule.default = { ...(globalFunctModule?.default || {}), qust: qust };
285
+ const __bundledModules = globalFunctModule;
286
+ if (typeof global !== 'undefined') {
287
+ global.default = qust;
288
+ global.Qust = Qust;
289
+ global.qust = qust;
290
+ global.__bundledModules = __bundledModules;
291
+ }
292
+ if (typeof window !== "undefined") {
293
+ window.default = qust;
294
+ window.Qust = Qust;
295
+ window.qust = qust;
296
+ window.__bundledModules = __bundledModules;
297
+ }
298
+ if (typeof module !== 'undefined' && module.exports) {
299
+ module.exports = __bundledModules;
300
+ module.exports.default = qust;
301
+ module.exports.Qust = Qust;
302
+ module.exports.qust = qust;
303
+ }
304
+ if (typeof exports !== 'undefined') {
305
+ exports.default = qust;
306
+ exports.Qust = Qust;
307
+ exports.qust = qust;
308
+ }
309
+ return __bundledModules;
310
+ })(typeof global !== 'undefined' ? global :
311
+ typeof window !== 'undefined' ? window :
312
+ typeof self !== 'undefined' ? self :
313
+ typeof globalThis !== 'undefined' ? globalThis :
314
+ {});
315
+ const QustElementGF = globalFunct.Qust;
316
+ const qustElementGF = globalFunct.qust;
317
+ const defaultElementGF = globalFunct.default;
318
+ export { QustElementGF as Qust, qustElementGF as qust, };
319
+ export default defaultElementGF;
320
+ if (typeof module !== 'undefined' && module.exports) {
321
+ module.exports = {
322
+ Qust: QustElementGF,
323
+ qust: qustElementGF,
324
+ };
325
+ }
326
+ if (typeof module !== 'undefined' && module.exports) {
327
+ module.exports.default = globalFunct?.default;
328
+ }
package/package.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@arc-js/qust",
3
+ "publishConfig": {
4
+ "access": "public"
5
+ },
6
+ "version": "0.0.0",
7
+ "description": "Qust est une bibliothèque TypeScript ultra-légère et performante pour la sérialisation et désérialisation d'objets en chaînes de requête (query strings). Elle offre une API simple et puissante pour manipuler les paramètres d'URL avec support des types complexes, des tableaux, des objets imbriqués et des options avancées.",
8
+ "main": "index.js",
9
+ "keywords": [],
10
+ "author": "INICODE <contact.inicode@gmail.com>",
11
+ "license": "MIT",
12
+ "scripts": {
13
+ "init": "npm init --scope=@arc-js/qust",
14
+ "login": "npm login"
15
+ },
16
+ "devDependencies": {},
17
+ "dependencies": {}
18
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES6",
4
+ "module": "commonjs",
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable", "ESNext"],
6
+ "esModuleInterop": true,
7
+ "skipLibCheck": true,
8
+ "declaration": false,
9
+ "sourceMap": false,
10
+ "allowSyntheticDefaultImports": true,
11
+ "noEmit": false,
12
+
13
+ "strict": false,
14
+ "noImplicitAny": false,
15
+ "strictNullChecks": false,
16
+ "strictFunctionTypes": false,
17
+ "strictBindCallApply": false,
18
+ "strictPropertyInitialization": false,
19
+ "noImplicitThis": false,
20
+ "alwaysStrict": false
21
+ },
22
+ "include": [],
23
+ "exclude": [
24
+ "node_modules",
25
+ "**/*.d.ts"
26
+ ]
27
+ }
package/web/qust.js ADDED
@@ -0,0 +1,326 @@
1
+ const globalFunct = (function (global) {
2
+ 'use strict';
3
+ const DEFAULT_OPTIONS = {
4
+ arrayFormat: 'bracket',
5
+ arraySeparator: ',',
6
+ skipNull: true,
7
+ skipEmptyString: false,
8
+ encode: true,
9
+ decode: true,
10
+ depth: 10
11
+ };
12
+ class Qust {
13
+ options;
14
+ constructor(options = {}) {
15
+ this.options = { ...DEFAULT_OPTIONS, ...options };
16
+ }
17
+ stringify(obj) {
18
+ if (!obj || typeof obj !== 'object') {
19
+ return '';
20
+ }
21
+ const parts = [];
22
+ this.processObject('', obj, parts, 0);
23
+ return parts.length > 0 ? `?${parts.join('&')}` : '';
24
+ }
25
+ parse(queryString) {
26
+ if (!queryString || typeof queryString !== 'string') {
27
+ return {};
28
+ }
29
+ const cleanString = queryString.startsWith('?')
30
+ ? queryString.slice(1)
31
+ : queryString;
32
+ if (!cleanString) {
33
+ return {};
34
+ }
35
+ const result = {};
36
+ const pairs = cleanString.split('&');
37
+ for (const pair of pairs) {
38
+ if (!pair)
39
+ continue;
40
+ const [encodedKey, encodedValue] = pair.split('=');
41
+ if (!encodedKey)
42
+ continue;
43
+ const key = this.options.decode
44
+ ? decodeURIComponent(encodedKey)
45
+ : encodedKey;
46
+ const value = this.options.decode && encodedValue !== undefined
47
+ ? decodeURIComponent(encodedValue)
48
+ : encodedValue;
49
+ this.setValue(result, key, value);
50
+ }
51
+ return this.transformArrays(result);
52
+ }
53
+ processObject(prefix, value, parts, depth) {
54
+ if (depth > this.options.depth) {
55
+ console.warn('Qust: Profondeur maximale atteinte, arrêt de la récursion');
56
+ return;
57
+ }
58
+ if (value === null || value === undefined) {
59
+ if (!this.options.skipNull) {
60
+ parts.push(this.encodeKey(prefix));
61
+ }
62
+ return;
63
+ }
64
+ if (typeof value === 'string' && value === '' && this.options.skipEmptyString) {
65
+ return;
66
+ }
67
+ if (Array.isArray(value)) {
68
+ this.processArray(prefix, value, parts, depth + 1);
69
+ return;
70
+ }
71
+ if (typeof value === 'object' && !this.isPrimitive(value)) {
72
+ for (const [key, val] of Object.entries(value)) {
73
+ const newPrefix = prefix ? `${prefix}[${key}]` : key;
74
+ this.processObject(newPrefix, val, parts, depth + 1);
75
+ }
76
+ return;
77
+ }
78
+ const encodedKey = this.encodeKey(prefix);
79
+ const encodedValue = this.options.encode && typeof value === 'string'
80
+ ? encodeURIComponent(value)
81
+ : String(value);
82
+ parts.push(`${encodedKey}=${encodedValue}`);
83
+ }
84
+ processArray(prefix, array, parts, depth) {
85
+ if (array.length === 0)
86
+ return;
87
+ const encodedKey = this.encodeKey(prefix);
88
+ switch (this.options.arrayFormat) {
89
+ case 'comma':
90
+ const values = array
91
+ .map(item => this.options.encode && typeof item === 'string'
92
+ ? encodeURIComponent(item)
93
+ : String(item))
94
+ .join(this.options.arraySeparator);
95
+ parts.push(`${encodedKey}=${values}`);
96
+ break;
97
+ case 'index':
98
+ array.forEach((item, index) => {
99
+ const arrayPrefix = `${prefix}[${index}]`;
100
+ this.processObject(arrayPrefix, item, parts, depth);
101
+ });
102
+ break;
103
+ case 'separator':
104
+ array.forEach(item => {
105
+ const encodedValue = this.options.encode && typeof item === 'string'
106
+ ? encodeURIComponent(item)
107
+ : String(item);
108
+ parts.push(`${encodedKey}=${encodedValue}`);
109
+ });
110
+ break;
111
+ case 'none':
112
+ array.forEach(item => {
113
+ this.processObject(prefix, item, parts, depth);
114
+ });
115
+ break;
116
+ case 'bracket':
117
+ default:
118
+ array.forEach(item => {
119
+ const arrayPrefix = `${prefix}[]`;
120
+ this.processObject(arrayPrefix, item, parts, depth);
121
+ });
122
+ break;
123
+ }
124
+ }
125
+ encodeKey(key) {
126
+ if (!this.options.encode) {
127
+ return key;
128
+ }
129
+ const parts = [];
130
+ let currentPart = '';
131
+ for (let i = 0; i < key.length; i++) {
132
+ const char = key[i];
133
+ if (char === '[' || char === ']') {
134
+ if (currentPart) {
135
+ parts.push(encodeURIComponent(currentPart));
136
+ currentPart = '';
137
+ }
138
+ parts.push(char);
139
+ }
140
+ else {
141
+ currentPart += char;
142
+ }
143
+ }
144
+ if (currentPart) {
145
+ parts.push(encodeURIComponent(currentPart));
146
+ }
147
+ return parts.join('');
148
+ }
149
+ setValue(obj, key, value) {
150
+ const matches = key.match(/([^\[\]]+)|(\[\])/g);
151
+ if (!matches) {
152
+ if (value !== undefined) {
153
+ obj[key] = this.parseValue(value);
154
+ }
155
+ return;
156
+ }
157
+ let current = obj;
158
+ for (let i = 0; i < matches.length; i++) {
159
+ const match = matches[i];
160
+ const isLast = i === matches.length - 1;
161
+ if (match === '[]') {
162
+ if (!Array.isArray(current)) {
163
+ current = [];
164
+ }
165
+ if (isLast) {
166
+ if (!!value) {
167
+ current.push(this.parseValue(value));
168
+ }
169
+ }
170
+ else {
171
+ const nextMatch = matches[i + 1];
172
+ const nextIndex = parseInt(nextMatch, 10);
173
+ if (!isNaN(nextIndex)) {
174
+ if (current[nextIndex] === undefined) {
175
+ current[nextIndex] = {};
176
+ }
177
+ current = current[nextIndex];
178
+ i++;
179
+ }
180
+ else {
181
+ const newObj = {};
182
+ current.push(newObj);
183
+ current = newObj;
184
+ }
185
+ }
186
+ }
187
+ else {
188
+ if (isLast) {
189
+ if (value !== undefined) {
190
+ current[match] = this.parseValue(value);
191
+ }
192
+ }
193
+ else {
194
+ if (current[match] === undefined || typeof current[match] !== 'object') {
195
+ const nextMatch = matches[i + 1];
196
+ current[match] = nextMatch === '[]' ? [] : {};
197
+ }
198
+ current = current[match];
199
+ }
200
+ }
201
+ }
202
+ }
203
+ transformArrays(obj) {
204
+ if (Array.isArray(obj)) {
205
+ return obj.map(item => typeof item === 'object' && item !== null
206
+ ? this.transformArrays(item)
207
+ : item);
208
+ }
209
+ if (typeof obj !== 'object' || obj === null) {
210
+ return obj;
211
+ }
212
+ const result = {};
213
+ const keys = Object.keys(obj);
214
+ const isArrayLike = keys.every(key => {
215
+ const num = parseInt(key, 10);
216
+ return !isNaN(num) && num >= 0 && num.toString() === key;
217
+ });
218
+ if (isArrayLike && keys.length > 0) {
219
+ const array = [];
220
+ keys.forEach(key => {
221
+ const index = parseInt(key, 10);
222
+ array[index] = this.transformArrays(obj[key]);
223
+ });
224
+ return array;
225
+ }
226
+ keys.forEach(key => {
227
+ const value = obj[key];
228
+ result[key] =
229
+ typeof value === 'object' && value !== null
230
+ ? this.transformArrays(value)
231
+ : value;
232
+ });
233
+ return result;
234
+ }
235
+ parseValue(value) {
236
+ if (value === 'true')
237
+ return true;
238
+ if (value === 'false')
239
+ return false;
240
+ if (value === 'null')
241
+ return null;
242
+ if (value === 'undefined')
243
+ return undefined;
244
+ const num = Number(value);
245
+ if (!isNaN(num) && value.trim() !== '')
246
+ return num;
247
+ return value;
248
+ }
249
+ isPrimitive(value) {
250
+ return value === null ||
251
+ typeof value !== 'object' &&
252
+ typeof value !== 'function';
253
+ }
254
+ setOptions(newOptions) {
255
+ this.options = { ...this.options, ...newOptions };
256
+ }
257
+ getOptions() {
258
+ return { ...this.options };
259
+ }
260
+ static exposeToGlobal() {
261
+ if (typeof window !== "undefined") {
262
+ window.Qust = Qust;
263
+ }
264
+ }
265
+ }
266
+ const qust = {
267
+ stringify(obj, options) {
268
+ return new Qust(options).stringify(obj);
269
+ },
270
+ parse(queryString, options) {
271
+ return new Qust(options).parse(queryString);
272
+ }
273
+ };
274
+ if (typeof window !== "undefined") {
275
+ window.Qust = Qust;
276
+ window.qust = qust;
277
+ }
278
+ const globalFunctModule = {
279
+ default: qust,
280
+ Qust: Qust,
281
+ qust: qust,
282
+ };
283
+ globalFunctModule.default = { ...(globalFunctModule?.default || {}), Qust: Qust };
284
+ globalFunctModule.default = { ...(globalFunctModule?.default || {}), qust: qust };
285
+ const __bundledModules = globalFunctModule;
286
+ if (typeof global !== 'undefined') {
287
+ global.default = qust;
288
+ global.Qust = Qust;
289
+ global.qust = qust;
290
+ global.__bundledModules = __bundledModules;
291
+ }
292
+ if (typeof window !== "undefined") {
293
+ window.default = qust;
294
+ window.Qust = Qust;
295
+ window.qust = qust;
296
+ window.__bundledModules = __bundledModules;
297
+ }
298
+ if (typeof module !== 'undefined' && module.exports) {
299
+ module.exports = __bundledModules;
300
+ module.exports.default = qust;
301
+ module.exports.Qust = Qust;
302
+ module.exports.qust = qust;
303
+ }
304
+ if (typeof exports !== 'undefined') {
305
+ exports.default = qust;
306
+ exports.Qust = Qust;
307
+ exports.qust = qust;
308
+ }
309
+ return __bundledModules;
310
+ })(typeof global !== 'undefined' ? global :
311
+ typeof window !== 'undefined' ? window :
312
+ typeof self !== 'undefined' ? self :
313
+ typeof globalThis !== 'undefined' ? globalThis :
314
+ {});
315
+ const QustElementGF = globalFunct.Qust;
316
+ const qustElementGF = globalFunct.qust;
317
+ const defaultElementGF = globalFunct.default;
318
+ if (typeof module !== 'undefined' && module.exports) {
319
+ module.exports = {
320
+ Qust: QustElementGF,
321
+ qust: qustElementGF,
322
+ };
323
+ }
324
+ if (typeof module !== 'undefined' && module.exports) {
325
+ module.exports.default = globalFunct?.default;
326
+ }