js-routes 2.3.6 → 2.3.7
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/lib/js_routes/instance.rb +6 -1
- data/lib/js_routes/route.rb +1 -1
- data/lib/js_routes/version.rb +1 -1
- data/lib/routes.d.ts +21 -21
- data/lib/routes.js +18 -27
- data/lib/routes.ts +600 -615
- metadata +4 -4
data/lib/routes.ts
CHANGED
|
@@ -25,17 +25,17 @@ type RouteHelperExtras = {
|
|
|
25
25
|
type RequiredParameters<T extends number> = T extends 1
|
|
26
26
|
? [RequiredRouteParameter]
|
|
27
27
|
: T extends 2
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
28
|
+
? [RequiredRouteParameter, RequiredRouteParameter]
|
|
29
|
+
: T extends 3
|
|
30
|
+
? [RequiredRouteParameter, RequiredRouteParameter, RequiredRouteParameter]
|
|
31
|
+
: T extends 4
|
|
32
|
+
? [
|
|
33
|
+
RequiredRouteParameter,
|
|
34
|
+
RequiredRouteParameter,
|
|
35
|
+
RequiredRouteParameter,
|
|
36
|
+
RequiredRouteParameter,
|
|
37
|
+
]
|
|
38
|
+
: RequiredRouteParameter[];
|
|
39
39
|
|
|
40
40
|
type RouteHelperOptions = RouteOptions & Collection<OptionalRouteParameter>;
|
|
41
41
|
|
|
@@ -94,677 +94,662 @@ declare const define:
|
|
|
94
94
|
|
|
95
95
|
declare const module: { exports: unknown } | undefined;
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return typeof module === "object";
|
|
155
|
-
},
|
|
97
|
+
RubyVariables.WRAPPER((): RouterExposedMethods => {
|
|
98
|
+
const hasProp = (value: unknown, key: string): boolean =>
|
|
99
|
+
Object.prototype.hasOwnProperty.call(value, key);
|
|
100
|
+
enum NodeTypes {
|
|
101
|
+
GROUP = 1,
|
|
102
|
+
CAT = 2,
|
|
103
|
+
SYMBOL = 3,
|
|
104
|
+
OR = 4,
|
|
105
|
+
STAR = 5,
|
|
106
|
+
LITERAL = 6,
|
|
107
|
+
SLASH = 7,
|
|
108
|
+
DOT = 8,
|
|
109
|
+
}
|
|
110
|
+
type RouteNodes = {
|
|
111
|
+
[NodeTypes.GROUP]: { left: RouteTree; right: never };
|
|
112
|
+
[NodeTypes.STAR]: { left: RouteTree; right: never };
|
|
113
|
+
[NodeTypes.LITERAL]: { left: string; right: never };
|
|
114
|
+
[NodeTypes.SLASH]: { left: "/"; right: never };
|
|
115
|
+
[NodeTypes.DOT]: { left: "."; right: never };
|
|
116
|
+
[NodeTypes.CAT]: { left: RouteTree; right: RouteTree };
|
|
117
|
+
[NodeTypes.SYMBOL]: { left: string; right: never };
|
|
118
|
+
};
|
|
119
|
+
type RouteNode<T extends keyof RouteNodes> = [
|
|
120
|
+
T,
|
|
121
|
+
RouteNodes[T]["left"],
|
|
122
|
+
RouteNodes[T]["right"],
|
|
123
|
+
];
|
|
124
|
+
type RouteTree = {
|
|
125
|
+
[T in keyof RouteNodes]: RouteNode<T>;
|
|
126
|
+
}[keyof RouteNodes];
|
|
127
|
+
|
|
128
|
+
const isBrowser = typeof window !== "undefined";
|
|
129
|
+
type ModuleDefinition = {
|
|
130
|
+
define: (routes: RouterExposedMethods) => void;
|
|
131
|
+
isSupported: () => boolean;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const UnescapedSpecials = "-._~!$&'()*+,;=:@"
|
|
135
|
+
.split("")
|
|
136
|
+
.map((s) => s.charCodeAt(0));
|
|
137
|
+
const UnescapedRanges = [
|
|
138
|
+
["a", "z"],
|
|
139
|
+
["A", "Z"],
|
|
140
|
+
["0", "9"],
|
|
141
|
+
].map((range) => range.map((s) => s.charCodeAt(0)));
|
|
142
|
+
|
|
143
|
+
const ModuleReferences: Record<ModuleType, ModuleDefinition> = {
|
|
144
|
+
CJS: {
|
|
145
|
+
define(routes) {
|
|
146
|
+
if (module) {
|
|
147
|
+
// Some javascript processors (like vite/rolldown)
|
|
148
|
+
// warn on using module dot exports in an ESM module.
|
|
149
|
+
// This just obfuscates that assignment a little so
|
|
150
|
+
// users don't get a warning they can't fix.
|
|
151
|
+
const _mod = module;
|
|
152
|
+
_mod.exports = routes;
|
|
153
|
+
}
|
|
156
154
|
},
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (define) {
|
|
160
|
-
define([], function () {
|
|
161
|
-
return routes;
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
},
|
|
165
|
-
isSupported() {
|
|
166
|
-
return typeof define === "function" && !!define.amd;
|
|
167
|
-
},
|
|
155
|
+
isSupported() {
|
|
156
|
+
return typeof module === "object";
|
|
168
157
|
},
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
158
|
+
},
|
|
159
|
+
AMD: {
|
|
160
|
+
define(routes) {
|
|
161
|
+
if (define) {
|
|
162
|
+
define([], function () {
|
|
163
|
+
return routes;
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
isSupported() {
|
|
168
|
+
return typeof define === "function" && !!define.amd;
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
UMD: {
|
|
172
|
+
define(routes) {
|
|
173
|
+
if (ModuleReferences.AMD.isSupported()) {
|
|
174
|
+
ModuleReferences.AMD.define(routes);
|
|
175
|
+
} else {
|
|
176
|
+
if (ModuleReferences.CJS.isSupported()) {
|
|
177
|
+
try {
|
|
178
|
+
ModuleReferences.CJS.define(routes);
|
|
179
|
+
} catch (error) {
|
|
180
|
+
if ((error as Error).name !== "TypeError") throw error;
|
|
180
181
|
}
|
|
181
182
|
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
)
|
|
188
|
-
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
isSupported() {
|
|
186
|
+
return (
|
|
187
|
+
ModuleReferences.AMD.isSupported() ||
|
|
188
|
+
ModuleReferences.CJS.isSupported()
|
|
189
|
+
);
|
|
189
190
|
},
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
isSupported() {
|
|
195
|
-
// Its impossible to check if "export" keyword is supported
|
|
196
|
-
return true;
|
|
197
|
-
},
|
|
191
|
+
},
|
|
192
|
+
ESM: {
|
|
193
|
+
define() {
|
|
194
|
+
// Module can only be defined using ruby code generation
|
|
198
195
|
},
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
},
|
|
203
|
-
isSupported() {
|
|
204
|
-
return true;
|
|
205
|
-
},
|
|
196
|
+
isSupported() {
|
|
197
|
+
// Its impossible to check if "export" keyword is supported
|
|
198
|
+
return true;
|
|
206
199
|
},
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
},
|
|
212
|
-
isSupported() {
|
|
213
|
-
return ModuleReferences.ESM.isSupported();
|
|
214
|
-
},
|
|
200
|
+
},
|
|
201
|
+
NIL: {
|
|
202
|
+
define() {
|
|
203
|
+
// Defined using RubyVariables . WRAPPER
|
|
215
204
|
},
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
205
|
+
isSupported() {
|
|
206
|
+
return true;
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
DTS: {
|
|
210
|
+
// Acts the same as ESM
|
|
211
|
+
define(routes) {
|
|
212
|
+
ModuleReferences.ESM.define(routes);
|
|
213
|
+
},
|
|
214
|
+
isSupported() {
|
|
215
|
+
return ModuleReferences.ESM.isSupported();
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
class ParametersMissing extends Error {
|
|
221
|
+
readonly keys: string[];
|
|
222
|
+
constructor(...keys: string[]) {
|
|
223
|
+
super(`Route missing required keys: ${keys.join(", ")}`);
|
|
224
|
+
this.keys = keys;
|
|
225
|
+
Object.setPrototypeOf(this, Object.getPrototypeOf(this));
|
|
226
|
+
this.name = ParametersMissing.name;
|
|
226
227
|
}
|
|
228
|
+
}
|
|
227
229
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
230
|
+
const ReservedOptions = [
|
|
231
|
+
"anchor",
|
|
232
|
+
"trailing_slash",
|
|
233
|
+
"subdomain",
|
|
234
|
+
"host",
|
|
235
|
+
"port",
|
|
236
|
+
"protocol",
|
|
237
|
+
"script_name",
|
|
238
|
+
] as const;
|
|
239
|
+
|
|
240
|
+
type ReservedOption = (typeof ReservedOptions)[any];
|
|
241
|
+
|
|
242
|
+
class UtilsClass {
|
|
243
|
+
configuration: Configuration = {
|
|
244
|
+
prefix: RubyVariables.PREFIX,
|
|
245
|
+
default_url_options: RubyVariables.DEFAULT_URL_OPTIONS,
|
|
246
|
+
special_options_key: RubyVariables.SPECIAL_OPTIONS_KEY,
|
|
247
|
+
serializer:
|
|
248
|
+
RubyVariables.SERIALIZER || this.default_serializer.bind(this),
|
|
249
|
+
};
|
|
248
250
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
default_serializer(value: unknown, prefix?: string | null): string {
|
|
252
|
+
if (!prefix && !this.is_object(value)) {
|
|
253
|
+
throw new Error("Url parameters should be a javascript hash");
|
|
254
|
+
}
|
|
255
|
+
prefix = prefix || "";
|
|
256
|
+
const result: string[] = [];
|
|
257
|
+
if (this.is_array(value)) {
|
|
258
|
+
for (const element of value) {
|
|
259
|
+
result.push(this.default_serializer(element, prefix + "[]"));
|
|
252
260
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
261
|
+
} else if (this.is_object(value)) {
|
|
262
|
+
for (let key in value) {
|
|
263
|
+
if (!hasProp(value, key)) continue;
|
|
264
|
+
let prop = value[key];
|
|
265
|
+
if (prefix) {
|
|
266
|
+
key = prefix + "[" + key + "]";
|
|
258
267
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
let prop = value[key];
|
|
263
|
-
if (prefix) {
|
|
264
|
-
key = prefix + "[" + key + "]";
|
|
265
|
-
}
|
|
266
|
-
const subvalue = this.default_serializer(prop, key);
|
|
267
|
-
if (subvalue.length) {
|
|
268
|
-
result.push(subvalue);
|
|
269
|
-
}
|
|
268
|
+
const subvalue = this.default_serializer(prop, key);
|
|
269
|
+
if (subvalue.length) {
|
|
270
|
+
result.push(subvalue);
|
|
270
271
|
}
|
|
271
|
-
} else {
|
|
272
|
-
result.push(
|
|
273
|
-
this.is_not_nullable(value) ||
|
|
274
|
-
RubyVariables.DEPRECATED_NIL_QUERY_PARAMETER_BEHAVIOR
|
|
275
|
-
? encodeURIComponent(prefix) +
|
|
276
|
-
"=" +
|
|
277
|
-
encodeURIComponent("" + (value ?? ""))
|
|
278
|
-
: encodeURIComponent(prefix)
|
|
279
|
-
);
|
|
280
272
|
}
|
|
281
|
-
|
|
273
|
+
} else {
|
|
274
|
+
const key = encodeURIComponent(prefix);
|
|
275
|
+
result.push(
|
|
276
|
+
this.is_not_nullable(value) ||
|
|
277
|
+
RubyVariables.DEPRECATED_NIL_QUERY_PARAMETER_BEHAVIOR
|
|
278
|
+
? key + "=" + encodeURIComponent("" + (value ?? ""))
|
|
279
|
+
: key,
|
|
280
|
+
);
|
|
282
281
|
}
|
|
282
|
+
return result.join("&");
|
|
283
|
+
}
|
|
283
284
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
285
|
+
serialize(object: Serializable): string {
|
|
286
|
+
return this.configuration.serializer(object);
|
|
287
|
+
}
|
|
287
288
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
) {
|
|
301
|
-
|
|
302
|
-
delete last_el[this.configuration.special_options_key];
|
|
303
|
-
}
|
|
304
|
-
return {
|
|
305
|
-
args: args.slice(0, args.length - 1),
|
|
306
|
-
options: last_el as unknown as RouteOptions,
|
|
307
|
-
};
|
|
308
|
-
} else {
|
|
309
|
-
return { args, options: {} };
|
|
289
|
+
extract_options(
|
|
290
|
+
number_of_params: number,
|
|
291
|
+
args: OptionalRouteParameter[],
|
|
292
|
+
): {
|
|
293
|
+
args: OptionalRouteParameter[];
|
|
294
|
+
options: RouteOptions;
|
|
295
|
+
} {
|
|
296
|
+
const last_el = args[args.length - 1];
|
|
297
|
+
if (
|
|
298
|
+
(args.length > number_of_params && last_el === 0) ||
|
|
299
|
+
(this.is_object(last_el) && !this.looks_like_serialized_model(last_el))
|
|
300
|
+
) {
|
|
301
|
+
if (this.is_object(last_el)) {
|
|
302
|
+
delete last_el[this.configuration.special_options_key];
|
|
310
303
|
}
|
|
304
|
+
return {
|
|
305
|
+
args: args.slice(0, args.length - 1),
|
|
306
|
+
options: last_el as unknown as RouteOptions,
|
|
307
|
+
};
|
|
308
|
+
} else {
|
|
309
|
+
return { args, options: {} };
|
|
311
310
|
}
|
|
311
|
+
}
|
|
312
312
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
313
|
+
looks_like_serialized_model(
|
|
314
|
+
object: unknown,
|
|
315
|
+
): object is ModelRouteParameter {
|
|
316
|
+
return (
|
|
317
|
+
this.is_object(object) &&
|
|
318
|
+
!(this.configuration.special_options_key in object) &&
|
|
319
|
+
("id" in object || "to_param" in object || "toParam" in object)
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
322
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}
|
|
323
|
+
path_identifier(object: QueryRouteParameter): string {
|
|
324
|
+
const result = this.unwrap_path_identifier(object);
|
|
325
|
+
return this.is_nullable(result) ||
|
|
326
|
+
(RubyVariables.DEPRECATED_FALSE_PARAMETER_BEHAVIOR && result === false)
|
|
327
|
+
? ""
|
|
328
|
+
: "" + result;
|
|
329
|
+
}
|
|
331
330
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
331
|
+
unwrap_path_identifier(object: QueryRouteParameter): unknown {
|
|
332
|
+
let result: unknown = object;
|
|
333
|
+
if (!this.is_object(object)) {
|
|
334
|
+
return object;
|
|
335
|
+
}
|
|
336
|
+
if ("to_param" in object) {
|
|
337
|
+
result = object.to_param;
|
|
338
|
+
} else if ("toParam" in object) {
|
|
339
|
+
result = object.toParam;
|
|
340
|
+
} else if ("id" in object) {
|
|
341
|
+
result = object.id;
|
|
342
|
+
} else {
|
|
343
|
+
result = object;
|
|
344
|
+
}
|
|
345
|
+
return this.is_callable(result) ? result.call(object) : result;
|
|
346
|
+
}
|
|
348
347
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
parts_options[key] = value;
|
|
376
|
-
}
|
|
348
|
+
partition_parameters(
|
|
349
|
+
parts: string[],
|
|
350
|
+
required_params: string[],
|
|
351
|
+
default_options: RouteParameters,
|
|
352
|
+
call_arguments: OptionalRouteParameter[],
|
|
353
|
+
): {
|
|
354
|
+
keyword_parameters: KeywordUrlOptions;
|
|
355
|
+
query_parameters: RouteParameters;
|
|
356
|
+
} {
|
|
357
|
+
let { args, options } = this.extract_options(
|
|
358
|
+
parts.length,
|
|
359
|
+
call_arguments,
|
|
360
|
+
);
|
|
361
|
+
if (args.length > parts.length) {
|
|
362
|
+
throw new Error("Too many parameters provided for path");
|
|
363
|
+
}
|
|
364
|
+
let use_all_parts = args.length > required_params.length;
|
|
365
|
+
const parts_options: RouteParameters = {
|
|
366
|
+
...this.configuration.default_url_options,
|
|
367
|
+
};
|
|
368
|
+
for (const key in options) {
|
|
369
|
+
const value = options[key];
|
|
370
|
+
if (!hasProp(options, key)) continue;
|
|
371
|
+
use_all_parts = true;
|
|
372
|
+
if (parts.includes(key)) {
|
|
373
|
+
parts_options[key] = value;
|
|
377
374
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
375
|
+
}
|
|
376
|
+
options = {
|
|
377
|
+
...this.configuration.default_url_options,
|
|
378
|
+
...default_options,
|
|
379
|
+
...options,
|
|
380
|
+
};
|
|
383
381
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
} else {
|
|
396
|
-
throw new Error("params value should always be an object");
|
|
397
|
-
}
|
|
398
|
-
} else if (this.is_reserved_option(key)) {
|
|
399
|
-
keyword_parameters[key] = value as any;
|
|
382
|
+
const keyword_parameters: KeywordUrlOptions = {};
|
|
383
|
+
let query_parameters: RouteParameters = {};
|
|
384
|
+
for (const key in options) {
|
|
385
|
+
if (!hasProp(options, key)) continue;
|
|
386
|
+
const value = options[key];
|
|
387
|
+
if (key === "params") {
|
|
388
|
+
if (this.is_object(value)) {
|
|
389
|
+
query_parameters = {
|
|
390
|
+
...query_parameters,
|
|
391
|
+
...(value as RouteParameters),
|
|
392
|
+
};
|
|
400
393
|
} else {
|
|
401
|
-
|
|
402
|
-
!this.is_nullable(value) &&
|
|
403
|
-
(value !== default_options[key] || required_params.includes(key))
|
|
404
|
-
) {
|
|
405
|
-
query_parameters[key] = value;
|
|
406
|
-
}
|
|
394
|
+
throw new Error("params value should always be an object");
|
|
407
395
|
}
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
++i;
|
|
417
|
-
}
|
|
396
|
+
} else if (this.is_reserved_option(key)) {
|
|
397
|
+
keyword_parameters[key] = value as any;
|
|
398
|
+
} else {
|
|
399
|
+
if (
|
|
400
|
+
!this.is_nullable(value) &&
|
|
401
|
+
(value !== default_options[key] || required_params.includes(key))
|
|
402
|
+
) {
|
|
403
|
+
query_parameters[key] = value;
|
|
418
404
|
}
|
|
419
405
|
}
|
|
420
|
-
return { keyword_parameters, query_parameters };
|
|
421
406
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
): string {
|
|
431
|
-
const { keyword_parameters, query_parameters } =
|
|
432
|
-
this.partition_parameters(
|
|
433
|
-
parts,
|
|
434
|
-
required_params,
|
|
435
|
-
default_options,
|
|
436
|
-
args
|
|
437
|
-
);
|
|
438
|
-
|
|
439
|
-
let { trailing_slash, anchor, script_name } = keyword_parameters;
|
|
440
|
-
const missing_params = required_params.filter(
|
|
441
|
-
(param) =>
|
|
442
|
-
!hasProp(query_parameters, param) ||
|
|
443
|
-
this.is_nullable(query_parameters[param])
|
|
444
|
-
);
|
|
445
|
-
if (missing_params.length) {
|
|
446
|
-
throw new ParametersMissing(...missing_params);
|
|
447
|
-
}
|
|
448
|
-
let result = this.get_prefix() + this.visit(route, query_parameters);
|
|
449
|
-
if (trailing_slash) {
|
|
450
|
-
result = result.replace(/(.*?)[/]?$/, "$1/");
|
|
451
|
-
}
|
|
452
|
-
const url_params = this.serialize(query_parameters);
|
|
453
|
-
if (url_params.length) {
|
|
454
|
-
result += "?" + url_params;
|
|
455
|
-
}
|
|
456
|
-
if (anchor) {
|
|
457
|
-
result += "#" + anchor;
|
|
458
|
-
}
|
|
459
|
-
if (script_name) {
|
|
460
|
-
const last_index = script_name.length - 1;
|
|
461
|
-
if (script_name[last_index] == "/" && result[0] == "/") {
|
|
462
|
-
script_name = script_name.slice(0, last_index);
|
|
407
|
+
const route_parts = use_all_parts ? parts : required_params;
|
|
408
|
+
let i = 0;
|
|
409
|
+
for (const part of route_parts) {
|
|
410
|
+
if (i < args.length) {
|
|
411
|
+
const value = args[i];
|
|
412
|
+
if (!hasProp(parts_options, part)) {
|
|
413
|
+
query_parameters[part] = value;
|
|
414
|
+
++i;
|
|
463
415
|
}
|
|
464
|
-
result = script_name + result;
|
|
465
|
-
}
|
|
466
|
-
if (absolute) {
|
|
467
|
-
result = this.route_url(keyword_parameters) + result;
|
|
468
|
-
}
|
|
469
|
-
return result;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
visit(
|
|
473
|
-
route: RouteTree,
|
|
474
|
-
parameters: RouteParameters,
|
|
475
|
-
optional = false
|
|
476
|
-
): string {
|
|
477
|
-
switch (route[0]) {
|
|
478
|
-
case NodeTypes.GROUP:
|
|
479
|
-
return this.visit(route[1], parameters, true);
|
|
480
|
-
case NodeTypes.CAT:
|
|
481
|
-
return this.visit_cat(route, parameters, optional);
|
|
482
|
-
case NodeTypes.SYMBOL:
|
|
483
|
-
return this.visit_symbol(route, parameters, optional);
|
|
484
|
-
case NodeTypes.STAR:
|
|
485
|
-
return this.visit_globbing(route[1], parameters, true);
|
|
486
|
-
case NodeTypes.LITERAL:
|
|
487
|
-
case NodeTypes.SLASH:
|
|
488
|
-
case NodeTypes.DOT:
|
|
489
|
-
return route[1];
|
|
490
|
-
default:
|
|
491
|
-
throw new Error("Unknown Rails node type");
|
|
492
416
|
}
|
|
493
417
|
}
|
|
418
|
+
return { keyword_parameters, query_parameters };
|
|
419
|
+
}
|
|
494
420
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
421
|
+
build_route(
|
|
422
|
+
parts: string[],
|
|
423
|
+
required_params: string[],
|
|
424
|
+
default_options: RouteParameters,
|
|
425
|
+
route: RouteTree,
|
|
426
|
+
absolute: boolean,
|
|
427
|
+
args: OptionalRouteParameter[],
|
|
428
|
+
): string {
|
|
429
|
+
const { keyword_parameters, query_parameters } =
|
|
430
|
+
this.partition_parameters(
|
|
431
|
+
parts,
|
|
432
|
+
required_params,
|
|
433
|
+
default_options,
|
|
434
|
+
args,
|
|
435
|
+
);
|
|
502
436
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
)
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
437
|
+
let { trailing_slash, anchor, script_name } = keyword_parameters;
|
|
438
|
+
const missing_params = required_params.filter(
|
|
439
|
+
(param) =>
|
|
440
|
+
!hasProp(query_parameters, param) ||
|
|
441
|
+
this.is_nullable(query_parameters[param]),
|
|
442
|
+
);
|
|
443
|
+
if (missing_params.length) {
|
|
444
|
+
throw new ParametersMissing(...missing_params);
|
|
445
|
+
}
|
|
446
|
+
let result = this.get_prefix() + this.visit(route, query_parameters);
|
|
447
|
+
if (trailing_slash) {
|
|
448
|
+
result = result.replace(/(.*?)[/]?$/, "$1/");
|
|
449
|
+
}
|
|
450
|
+
const url_params = this.serialize(query_parameters);
|
|
451
|
+
if (url_params.length) {
|
|
452
|
+
result += "?" + url_params;
|
|
453
|
+
}
|
|
454
|
+
if (anchor) {
|
|
455
|
+
result += "#" + anchor;
|
|
456
|
+
}
|
|
457
|
+
if (script_name) {
|
|
458
|
+
const last_index = script_name.length - 1;
|
|
459
|
+
if (script_name[last_index] == "/" && result[0] == "/") {
|
|
460
|
+
script_name = script_name.slice(0, last_index);
|
|
517
461
|
}
|
|
518
|
-
|
|
519
|
-
if (left_part[left_part.length - 1] === "/" && right_part[0] === "/") {
|
|
520
|
-
// strip slash from right_part
|
|
521
|
-
// to prevent double slash
|
|
522
|
-
right_part = right_part.substring(1);
|
|
523
|
-
}
|
|
524
|
-
return left_part + right_part;
|
|
462
|
+
result = script_name + result;
|
|
525
463
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
529
|
-
[_type, key]: RouteNode<NodeTypes.SYMBOL>,
|
|
530
|
-
parameters: RouteParameters,
|
|
531
|
-
optional: boolean
|
|
532
|
-
): string {
|
|
533
|
-
const value = this.path_identifier(parameters[key]);
|
|
534
|
-
delete parameters[key];
|
|
535
|
-
if (value.length) {
|
|
536
|
-
return this.encode_segment(value);
|
|
537
|
-
}
|
|
538
|
-
if (optional) {
|
|
539
|
-
return "";
|
|
540
|
-
} else {
|
|
541
|
-
throw new ParametersMissing(key);
|
|
542
|
-
}
|
|
464
|
+
if (absolute) {
|
|
465
|
+
result = this.route_url(keyword_parameters) + result;
|
|
543
466
|
}
|
|
467
|
+
return result;
|
|
468
|
+
}
|
|
544
469
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
470
|
+
visit(
|
|
471
|
+
route: RouteTree,
|
|
472
|
+
parameters: RouteParameters,
|
|
473
|
+
optional = false,
|
|
474
|
+
): string {
|
|
475
|
+
switch (route[0]) {
|
|
476
|
+
case NodeTypes.GROUP:
|
|
477
|
+
return this.visit(route[1], parameters, true);
|
|
478
|
+
case NodeTypes.CAT:
|
|
479
|
+
return this.visit_cat(route, parameters, optional);
|
|
480
|
+
case NodeTypes.SYMBOL:
|
|
481
|
+
return this.visit_symbol(route, parameters, optional);
|
|
482
|
+
case NodeTypes.STAR:
|
|
483
|
+
return this.visit_globbing(route[1], parameters, true);
|
|
484
|
+
case NodeTypes.LITERAL:
|
|
485
|
+
case NodeTypes.SLASH:
|
|
486
|
+
case NodeTypes.DOT:
|
|
487
|
+
return route[1];
|
|
488
|
+
default:
|
|
489
|
+
throw new Error("Unknown Rails node type");
|
|
565
490
|
}
|
|
491
|
+
}
|
|
566
492
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
493
|
+
is_not_nullable<T>(object: T): object is NonNullable<T> {
|
|
494
|
+
return !this.is_nullable(object);
|
|
495
|
+
}
|
|
570
496
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
case NodeTypes.GROUP:
|
|
575
|
-
return `(${this.build_path_spec(route[1])})`;
|
|
576
|
-
case NodeTypes.CAT:
|
|
577
|
-
return (
|
|
578
|
-
this.build_path_spec(route[1]) + this.build_path_spec(route[2])
|
|
579
|
-
);
|
|
580
|
-
case NodeTypes.STAR:
|
|
581
|
-
return this.build_path_spec(route[1], true);
|
|
582
|
-
case NodeTypes.SYMBOL:
|
|
583
|
-
key = route[1];
|
|
584
|
-
if (wildcard) {
|
|
585
|
-
return (key.startsWith("*") ? "" : "*") + key;
|
|
586
|
-
} else {
|
|
587
|
-
return ":" + key;
|
|
588
|
-
}
|
|
589
|
-
break;
|
|
590
|
-
case NodeTypes.SLASH:
|
|
591
|
-
case NodeTypes.DOT:
|
|
592
|
-
case NodeTypes.LITERAL:
|
|
593
|
-
return route[1];
|
|
594
|
-
default:
|
|
595
|
-
throw new Error("Unknown Rails node type");
|
|
596
|
-
}
|
|
597
|
-
}
|
|
497
|
+
is_nullable(object: unknown): object is null | undefined {
|
|
498
|
+
return object === undefined || object === null;
|
|
499
|
+
}
|
|
598
500
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
501
|
+
visit_cat(
|
|
502
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
503
|
+
[_type, left, right]: RouteNode<NodeTypes.CAT>,
|
|
504
|
+
parameters: RouteParameters,
|
|
505
|
+
optional: boolean,
|
|
506
|
+
): string {
|
|
507
|
+
const left_part = this.visit(left, parameters, optional);
|
|
508
|
+
let right_part = this.visit(right, parameters, optional);
|
|
509
|
+
if (
|
|
510
|
+
optional &&
|
|
511
|
+
((this.is_optional_node(left[0]) && !left_part) ||
|
|
512
|
+
(this.is_optional_node(right[0]) && !right_part))
|
|
513
|
+
) {
|
|
514
|
+
return "";
|
|
515
|
+
}
|
|
516
|
+
// if left_part ends on '/' and right_part starts on '/'
|
|
517
|
+
if (left_part[left_part.length - 1] === "/" && right_part[0] === "/") {
|
|
518
|
+
// strip slash from right_part
|
|
519
|
+
// to prevent double slash
|
|
520
|
+
right_part = right_part.substring(1);
|
|
521
|
+
}
|
|
522
|
+
return left_part + right_part;
|
|
523
|
+
}
|
|
616
524
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
525
|
+
visit_symbol(
|
|
526
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
527
|
+
[_type, key]: RouteNode<NodeTypes.SYMBOL>,
|
|
528
|
+
parameters: RouteParameters,
|
|
529
|
+
optional: boolean,
|
|
530
|
+
): string {
|
|
531
|
+
const value = this.path_identifier(parameters[key]);
|
|
532
|
+
delete parameters[key];
|
|
533
|
+
if (value.length) {
|
|
534
|
+
return this.encode_segment(value);
|
|
535
|
+
}
|
|
536
|
+
if (optional) {
|
|
537
|
+
return "";
|
|
538
|
+
} else {
|
|
539
|
+
throw new ParametersMissing(key);
|
|
622
540
|
}
|
|
541
|
+
}
|
|
623
542
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
543
|
+
encode_segment(segment: string): string {
|
|
544
|
+
if (segment.match(/^[a-zA-Z0-9-]$/)) {
|
|
545
|
+
// Performance optimization for 99% of cases
|
|
546
|
+
return segment;
|
|
547
|
+
}
|
|
548
|
+
return (segment.match(/./gu) || [])
|
|
549
|
+
.map((ch) => {
|
|
550
|
+
const code = ch.charCodeAt(0);
|
|
551
|
+
if (
|
|
552
|
+
UnescapedRanges.find(
|
|
553
|
+
(range) => code >= range[0] && code <= range[1],
|
|
554
|
+
) ||
|
|
555
|
+
UnescapedSpecials.includes(code)
|
|
556
|
+
) {
|
|
557
|
+
return ch;
|
|
558
|
+
} else {
|
|
559
|
+
return encodeURIComponent(ch);
|
|
641
560
|
}
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
561
|
+
})
|
|
562
|
+
.join("");
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
is_optional_node(node: NodeTypes): boolean {
|
|
566
|
+
return [NodeTypes.STAR, NodeTypes.SYMBOL, NodeTypes.CAT].includes(node);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
build_path_spec(route: RouteTree, wildcard = false): string {
|
|
570
|
+
let key: string;
|
|
571
|
+
switch (route[0]) {
|
|
572
|
+
case NodeTypes.GROUP:
|
|
573
|
+
return `(${this.build_path_spec(route[1])})`;
|
|
574
|
+
case NodeTypes.CAT:
|
|
575
|
+
return (
|
|
576
|
+
this.build_path_spec(route[1]) + this.build_path_spec(route[2])
|
|
651
577
|
);
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
578
|
+
case NodeTypes.STAR:
|
|
579
|
+
return this.build_path_spec(route[1], true);
|
|
580
|
+
case NodeTypes.SYMBOL:
|
|
581
|
+
key = route[1];
|
|
582
|
+
if (wildcard) {
|
|
583
|
+
return (key.startsWith("*") ? "" : "*") + key;
|
|
584
|
+
} else {
|
|
585
|
+
return ":" + key;
|
|
586
|
+
}
|
|
587
|
+
break;
|
|
588
|
+
case NodeTypes.SLASH:
|
|
589
|
+
case NodeTypes.DOT:
|
|
590
|
+
case NodeTypes.LITERAL:
|
|
591
|
+
return route[1];
|
|
592
|
+
default:
|
|
593
|
+
throw new Error("Unknown Rails node type");
|
|
658
594
|
}
|
|
595
|
+
}
|
|
659
596
|
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
597
|
+
visit_globbing(
|
|
598
|
+
route: RouteTree,
|
|
599
|
+
parameters: RouteParameters,
|
|
600
|
+
optional: boolean,
|
|
601
|
+
): string {
|
|
602
|
+
const key = route[1] as string;
|
|
603
|
+
let value = parameters[key];
|
|
604
|
+
delete parameters[key];
|
|
605
|
+
if (this.is_nullable(value)) {
|
|
606
|
+
return this.visit(route, parameters, optional);
|
|
607
|
+
}
|
|
608
|
+
if (this.is_array(value)) {
|
|
609
|
+
value = value.join("/");
|
|
610
|
+
}
|
|
611
|
+
const result = this.path_identifier(value as any);
|
|
612
|
+
return encodeURI(result);
|
|
613
|
+
}
|
|
675
614
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
615
|
+
get_prefix(): string {
|
|
616
|
+
const prefix = this.configuration.prefix;
|
|
617
|
+
return prefix.match("/$")
|
|
618
|
+
? prefix.substring(0, prefix.length - 1)
|
|
619
|
+
: prefix;
|
|
620
|
+
}
|
|
679
621
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
622
|
+
route(
|
|
623
|
+
parts_table: PartsTable,
|
|
624
|
+
route_spec: RouteTree,
|
|
625
|
+
absolute = false,
|
|
626
|
+
): RouteHelper {
|
|
627
|
+
const required_params: string[] = [];
|
|
628
|
+
const parts: string[] = [];
|
|
629
|
+
const default_options: RouteParameters = {};
|
|
630
|
+
for (const [part, { r: required, d: value }] of Object.entries(
|
|
631
|
+
parts_table,
|
|
632
|
+
)) {
|
|
633
|
+
parts.push(part);
|
|
634
|
+
if (required) {
|
|
635
|
+
required_params.push(part);
|
|
636
|
+
}
|
|
637
|
+
if (this.is_not_nullable(value)) {
|
|
638
|
+
default_options[part] = value;
|
|
639
|
+
}
|
|
684
640
|
}
|
|
641
|
+
const result = (...args: OptionalRouteParameter[]): string => {
|
|
642
|
+
return this.build_route(
|
|
643
|
+
parts,
|
|
644
|
+
required_params,
|
|
645
|
+
default_options,
|
|
646
|
+
route_spec,
|
|
647
|
+
absolute,
|
|
648
|
+
args,
|
|
649
|
+
);
|
|
650
|
+
};
|
|
651
|
+
result.requiredParams = () => required_params;
|
|
652
|
+
result.toString = () => {
|
|
653
|
+
return this.build_path_spec(route_spec);
|
|
654
|
+
};
|
|
655
|
+
return result as any;
|
|
656
|
+
}
|
|
685
657
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
658
|
+
route_url(route_defaults: KeywordUrlOptions): string {
|
|
659
|
+
const hostname = route_defaults.host || this.current_host();
|
|
660
|
+
if (!hostname) {
|
|
661
|
+
return "";
|
|
662
|
+
}
|
|
663
|
+
const subdomain = route_defaults.subdomain
|
|
664
|
+
? route_defaults.subdomain + "."
|
|
665
|
+
: "";
|
|
666
|
+
const protocol = route_defaults.protocol || this.current_protocol();
|
|
667
|
+
let port =
|
|
668
|
+
route_defaults.port ||
|
|
669
|
+
(!route_defaults.host ? this.current_port() : undefined);
|
|
670
|
+
port = port ? ":" + port : "";
|
|
671
|
+
return protocol + "://" + subdomain + hostname + port;
|
|
672
|
+
}
|
|
689
673
|
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
Object.prototype.toString.call(value) === "[object Object]"
|
|
694
|
-
);
|
|
695
|
-
}
|
|
674
|
+
current_host(): string {
|
|
675
|
+
return (isBrowser && window?.location?.hostname) || "";
|
|
676
|
+
}
|
|
696
677
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
678
|
+
current_protocol(): string {
|
|
679
|
+
return (
|
|
680
|
+
(isBrowser && window?.location?.protocol?.replace(/:$/, "")) || "http"
|
|
681
|
+
);
|
|
682
|
+
}
|
|
700
683
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
684
|
+
current_port(): string {
|
|
685
|
+
return (isBrowser && window?.location?.port) || "";
|
|
686
|
+
}
|
|
704
687
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
688
|
+
is_object(value: unknown): value is Collection<unknown> {
|
|
689
|
+
return (
|
|
690
|
+
typeof value === "object" &&
|
|
691
|
+
Object.prototype.toString.call(value) === "[object Object]"
|
|
692
|
+
);
|
|
693
|
+
}
|
|
708
694
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
"JsRoutes configuration prefix option is deprecated in favor of default_url_options.script_name."
|
|
713
|
-
);
|
|
714
|
-
}
|
|
715
|
-
this.configuration = { ...this.configuration, ...new_config };
|
|
716
|
-
return this.configuration;
|
|
717
|
-
}
|
|
695
|
+
is_array<T>(object: unknown | T[]): object is T[] {
|
|
696
|
+
return object instanceof Array;
|
|
697
|
+
}
|
|
718
698
|
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
699
|
+
is_callable(object: unknown): object is Function {
|
|
700
|
+
return typeof object === "function" && !!object.call;
|
|
701
|
+
}
|
|
722
702
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
703
|
+
is_reserved_option(key: unknown): key is ReservedOption {
|
|
704
|
+
return ReservedOptions.includes(key as any);
|
|
705
|
+
}
|
|
726
706
|
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
707
|
+
configure(new_config: Partial<Configuration>): Configuration {
|
|
708
|
+
if (new_config.prefix) {
|
|
709
|
+
console.warn(
|
|
710
|
+
"JsRoutes configuration prefix option is deprecated in favor of default_url_options.script_name.",
|
|
711
|
+
);
|
|
731
712
|
}
|
|
713
|
+
this.configuration = { ...this.configuration, ...new_config };
|
|
714
|
+
return this.configuration;
|
|
715
|
+
}
|
|
732
716
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
module: RouterExposedMethods
|
|
736
|
-
): RouterExposedMethods {
|
|
737
|
-
this.ensure_module_supported(name);
|
|
738
|
-
ModuleReferences[name].define(module);
|
|
739
|
-
return module;
|
|
740
|
-
}
|
|
717
|
+
config(): Configuration {
|
|
718
|
+
return { ...this.configuration };
|
|
741
719
|
}
|
|
742
720
|
|
|
743
|
-
|
|
721
|
+
is_module_supported(name: ModuleType): boolean {
|
|
722
|
+
return ModuleReferences[name].isSupported();
|
|
723
|
+
}
|
|
744
724
|
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
absolute?: boolean
|
|
751
|
-
): RouteHelper {
|
|
752
|
-
return utils.route(parts_table, route_spec, absolute);
|
|
753
|
-
},
|
|
754
|
-
};
|
|
725
|
+
ensure_module_supported(name: ModuleType): void {
|
|
726
|
+
if (!this.is_module_supported(name)) {
|
|
727
|
+
throw new Error(`${name} is not supported by runtime`);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
755
730
|
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
serialize: (object: Serializable): string => {
|
|
765
|
-
return utils.serialize(object);
|
|
766
|
-
},
|
|
767
|
-
...RubyVariables.ROUTES_OBJECT,
|
|
768
|
-
});
|
|
731
|
+
define_module(
|
|
732
|
+
name: ModuleType,
|
|
733
|
+
module: RouterExposedMethods,
|
|
734
|
+
): RouterExposedMethods {
|
|
735
|
+
this.ensure_module_supported(name);
|
|
736
|
+
ModuleReferences[name].define(module);
|
|
737
|
+
return module;
|
|
738
|
+
}
|
|
769
739
|
}
|
|
770
|
-
|
|
740
|
+
|
|
741
|
+
const utils = new UtilsClass();
|
|
742
|
+
|
|
743
|
+
// We want this helper name to be short
|
|
744
|
+
const __jsr = {
|
|
745
|
+
r: utils.route.bind(utils),
|
|
746
|
+
};
|
|
747
|
+
|
|
748
|
+
return utils.define_module(RubyVariables.MODULE_TYPE, {
|
|
749
|
+
...__jsr,
|
|
750
|
+
configure: utils.configure.bind(utils),
|
|
751
|
+
config: utils.config.bind(utils),
|
|
752
|
+
serialize: utils.serialize.bind(utils),
|
|
753
|
+
...RubyVariables.ROUTES_OBJECT,
|
|
754
|
+
});
|
|
755
|
+
})();
|