js-routes 2.3.7 → 2.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +95 -0
- data/Readme.md +51 -1
- data/lib/js_routes/configuration.rb +62 -5
- data/lib/js_routes/generators/base.rb +5 -4
- data/lib/js_routes/instance.rb +96 -25
- data/lib/js_routes/route.rb +40 -8
- data/lib/js_routes/utils.rb +6 -1
- data/lib/js_routes/version.rb +1 -1
- data/lib/js_routes.rb +11 -1
- data/lib/router.d.ts +63 -0
- data/lib/router.js +449 -0
- data/lib/router.ts +665 -0
- data/lib/routes.d.ts +1 -78
- data/lib/routes.js +103 -502
- data/lib/routes.ts +125 -703
- data/lib/templates/initializer.rb +12 -2
- metadata +7 -4
data/lib/js_routes.rb
CHANGED
|
@@ -40,10 +40,20 @@ module JsRoutes
|
|
|
40
40
|
instance = Instance.new(file: file_name, **opts)
|
|
41
41
|
instance.generate!
|
|
42
42
|
if typed && instance.configuration.modern?
|
|
43
|
-
definitions!(file_name, **opts)
|
|
43
|
+
definitions!(file_name, **opts.except(:package))
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
sig { params(opts: T.untyped).returns(String) }
|
|
48
|
+
def package(**opts)
|
|
49
|
+
Instance.new(module_type: 'PKG', **opts).package
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
sig { params(file_name: FileName, opts: T.untyped).void }
|
|
53
|
+
def package!(file_name = nil, **opts)
|
|
54
|
+
Instance.new(module_type: 'PKG', file: file_name, **opts).package!
|
|
55
|
+
end
|
|
56
|
+
|
|
47
57
|
sig { params(file_name: FileName, opts: T.untyped).void }
|
|
48
58
|
def remove!(file_name = configuration.file, **opts)
|
|
49
59
|
Instance.new(file: file_name, **opts).remove!
|
data/lib/router.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
type Optional<T> = {
|
|
2
|
+
[P in keyof T]?: T[P] | null;
|
|
3
|
+
};
|
|
4
|
+
export type Collection<T> = Record<string, T>;
|
|
5
|
+
type BaseRouteParameter = string | boolean | Date | number | bigint;
|
|
6
|
+
type MethodRouteParameter = BaseRouteParameter | (() => BaseRouteParameter);
|
|
7
|
+
type ModelRouteParameter = {
|
|
8
|
+
id: MethodRouteParameter;
|
|
9
|
+
} | {
|
|
10
|
+
to_param: MethodRouteParameter;
|
|
11
|
+
} | {
|
|
12
|
+
toParam: MethodRouteParameter;
|
|
13
|
+
};
|
|
14
|
+
type RequiredRouteParameter = BaseRouteParameter | ModelRouteParameter;
|
|
15
|
+
type OptionalRouteParameter = undefined | null | RequiredRouteParameter;
|
|
16
|
+
type QueryRouteParameter = OptionalRouteParameter | QueryRouteParameter[] | {
|
|
17
|
+
[k: string]: QueryRouteParameter;
|
|
18
|
+
};
|
|
19
|
+
export type RouteParameters = Collection<QueryRouteParameter>;
|
|
20
|
+
type Serializable = Collection<unknown>;
|
|
21
|
+
export type Serializer = (value: Serializable) => string;
|
|
22
|
+
type RouteHelperExtras = {
|
|
23
|
+
requiredParams(): string[];
|
|
24
|
+
toString(): string;
|
|
25
|
+
};
|
|
26
|
+
type RequiredParameters<T extends number> = T extends 1 ? [RequiredRouteParameter] : T extends 2 ? [RequiredRouteParameter, RequiredRouteParameter] : T extends 3 ? [RequiredRouteParameter, RequiredRouteParameter, RequiredRouteParameter] : T extends 4 ? [
|
|
27
|
+
RequiredRouteParameter,
|
|
28
|
+
RequiredRouteParameter,
|
|
29
|
+
RequiredRouteParameter,
|
|
30
|
+
RequiredRouteParameter
|
|
31
|
+
] : RequiredRouteParameter[];
|
|
32
|
+
type RouteHelperOptions = RouteOptions & Collection<OptionalRouteParameter>;
|
|
33
|
+
export type RouteHelper<T extends number = number> = ((...args: [...RequiredParameters<T>, RouteHelperOptions]) => string) & RouteHelperExtras;
|
|
34
|
+
type Configuration = {
|
|
35
|
+
prefix: string;
|
|
36
|
+
default_url_options: RouteParameters;
|
|
37
|
+
special_options_key: string;
|
|
38
|
+
serializer: Serializer;
|
|
39
|
+
deprecated_false_parameter_behavior: boolean;
|
|
40
|
+
deprecated_nil_query_parameter_behavior: boolean;
|
|
41
|
+
include_undefined_query_parameters: boolean;
|
|
42
|
+
};
|
|
43
|
+
export interface RouterExposedMethods {
|
|
44
|
+
config(): Configuration;
|
|
45
|
+
configure(arg: Partial<Configuration>): Configuration;
|
|
46
|
+
serialize: Serializer;
|
|
47
|
+
__route(...args: unknown[]): RouteHelper;
|
|
48
|
+
}
|
|
49
|
+
export interface RouterConstructor {
|
|
50
|
+
new (config?: Partial<Configuration>): RouterExposedMethods;
|
|
51
|
+
}
|
|
52
|
+
type KeywordUrlOptions = Optional<{
|
|
53
|
+
host: string;
|
|
54
|
+
protocol: string;
|
|
55
|
+
subdomain: string;
|
|
56
|
+
port: string | number;
|
|
57
|
+
anchor: string;
|
|
58
|
+
trailing_slash: boolean;
|
|
59
|
+
script_name: string;
|
|
60
|
+
params: RouteParameters;
|
|
61
|
+
}>;
|
|
62
|
+
type RouteOptions = KeywordUrlOptions & RouteParameters;
|
|
63
|
+
export {};
|
data/lib/router.js
ADDED
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2
|
+
const Router = (() => {
|
|
3
|
+
let NodeTypes;
|
|
4
|
+
(function (NodeTypes) {
|
|
5
|
+
NodeTypes[NodeTypes["GROUP"] = 1] = "GROUP";
|
|
6
|
+
NodeTypes[NodeTypes["CAT"] = 2] = "CAT";
|
|
7
|
+
NodeTypes[NodeTypes["SYMBOL"] = 3] = "SYMBOL";
|
|
8
|
+
NodeTypes[NodeTypes["OR"] = 4] = "OR";
|
|
9
|
+
NodeTypes[NodeTypes["STAR"] = 5] = "STAR";
|
|
10
|
+
NodeTypes[NodeTypes["LITERAL"] = 6] = "LITERAL";
|
|
11
|
+
NodeTypes[NodeTypes["SLASH"] = 7] = "SLASH";
|
|
12
|
+
NodeTypes[NodeTypes["DOT"] = 8] = "DOT";
|
|
13
|
+
})(NodeTypes || (NodeTypes = {}));
|
|
14
|
+
const isBrowser = typeof window !== "undefined";
|
|
15
|
+
const UnescapedSpecials = "-._~!$&'()*+,;=:@"
|
|
16
|
+
.split("")
|
|
17
|
+
.map((s) => s.charCodeAt(0));
|
|
18
|
+
const UnescapedRanges = [
|
|
19
|
+
["a", "z"],
|
|
20
|
+
["A", "Z"],
|
|
21
|
+
["0", "9"],
|
|
22
|
+
].map((range) => range.map((s) => s.charCodeAt(0)));
|
|
23
|
+
class ParametersMissing extends Error {
|
|
24
|
+
constructor(...keys) {
|
|
25
|
+
super(`Route missing required keys: ${keys.join(", ")}`);
|
|
26
|
+
this.keys = keys;
|
|
27
|
+
Object.setPrototypeOf(this, Object.getPrototypeOf(this));
|
|
28
|
+
this.name = ParametersMissing.name;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const ReservedOptions = [
|
|
32
|
+
"anchor",
|
|
33
|
+
"trailing_slash",
|
|
34
|
+
"subdomain",
|
|
35
|
+
"host",
|
|
36
|
+
"port",
|
|
37
|
+
"protocol",
|
|
38
|
+
"script_name",
|
|
39
|
+
];
|
|
40
|
+
class Router {
|
|
41
|
+
constructor(config = {}) {
|
|
42
|
+
this.configuration = {
|
|
43
|
+
prefix: "",
|
|
44
|
+
default_url_options: {},
|
|
45
|
+
special_options_key: "__options__",
|
|
46
|
+
serializer: this.default_serializer.bind(this),
|
|
47
|
+
deprecated_false_parameter_behavior: false,
|
|
48
|
+
deprecated_nil_query_parameter_behavior: false,
|
|
49
|
+
include_undefined_query_parameters: true,
|
|
50
|
+
};
|
|
51
|
+
this.configure(config);
|
|
52
|
+
}
|
|
53
|
+
configure(new_config) {
|
|
54
|
+
var _a;
|
|
55
|
+
if (new_config.prefix) {
|
|
56
|
+
console.warn("JsRoutes configuration prefix option is deprecated in favor of default_url_options.script_name.");
|
|
57
|
+
}
|
|
58
|
+
(_a = new_config.serializer) !== null && _a !== void 0 ? _a : (new_config.serializer = this.default_serializer.bind(this));
|
|
59
|
+
this.configuration = { ...this.configuration, ...new_config };
|
|
60
|
+
return this.configuration;
|
|
61
|
+
}
|
|
62
|
+
config() {
|
|
63
|
+
return { ...this.configuration };
|
|
64
|
+
}
|
|
65
|
+
serialize(object) {
|
|
66
|
+
return this.configuration.serializer(object);
|
|
67
|
+
}
|
|
68
|
+
__route(parts_table, route_spec, absolute = false) {
|
|
69
|
+
const required_params = [];
|
|
70
|
+
const parts = [];
|
|
71
|
+
const default_options = {};
|
|
72
|
+
for (const [part, { r: required, d: value }] of Object.entries(parts_table)) {
|
|
73
|
+
parts.push(part);
|
|
74
|
+
if (required) {
|
|
75
|
+
required_params.push(part);
|
|
76
|
+
}
|
|
77
|
+
if (this.is_not_nullable(value)) {
|
|
78
|
+
default_options[part] = value;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const result = (...args) => {
|
|
82
|
+
return this.build_route(parts, required_params, default_options, route_spec, absolute, args);
|
|
83
|
+
};
|
|
84
|
+
result.requiredParams = () => required_params;
|
|
85
|
+
result.toString = () => {
|
|
86
|
+
return this.build_path_spec(route_spec);
|
|
87
|
+
};
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
default_serializer(value, prefix, array_element = false) {
|
|
91
|
+
if (!prefix && !this.is_object(value)) {
|
|
92
|
+
throw new Error("URL parameters should be a javascript hash");
|
|
93
|
+
}
|
|
94
|
+
prefix = prefix || "";
|
|
95
|
+
const result = [];
|
|
96
|
+
if (this.is_array(value)) {
|
|
97
|
+
// Rails serializes an empty array nested inside another array as a nil
|
|
98
|
+
// query value, while an empty object contributes no query parameter.
|
|
99
|
+
if (value.length === 0) {
|
|
100
|
+
return array_element
|
|
101
|
+
? this.default_serializer(null, prefix + "[]")
|
|
102
|
+
: "";
|
|
103
|
+
}
|
|
104
|
+
for (const element of value) {
|
|
105
|
+
const subvalue = this.default_serializer(element, prefix + "[]", true);
|
|
106
|
+
// Skip empty object results so arrays do not produce leading,
|
|
107
|
+
// trailing, or doubled "&" separators.
|
|
108
|
+
if (subvalue.length) {
|
|
109
|
+
result.push(subvalue);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else if (this.is_object(value)) {
|
|
114
|
+
for (let key in value) {
|
|
115
|
+
if (!this.hasProp(value, key))
|
|
116
|
+
continue;
|
|
117
|
+
let prop = value[key];
|
|
118
|
+
if (!this.configuration.include_undefined_query_parameters &&
|
|
119
|
+
prop === undefined) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (prefix) {
|
|
123
|
+
key = prefix + "[" + key + "]";
|
|
124
|
+
}
|
|
125
|
+
const subvalue = this.default_serializer(prop, key);
|
|
126
|
+
if (subvalue.length) {
|
|
127
|
+
result.push(subvalue);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
const key = encodeURIComponent(prefix);
|
|
133
|
+
result.push(this.is_not_nullable(value) ||
|
|
134
|
+
this.configuration.deprecated_nil_query_parameter_behavior
|
|
135
|
+
? key + "=" + encodeURIComponent("" + (value !== null && value !== void 0 ? value : ""))
|
|
136
|
+
: key);
|
|
137
|
+
}
|
|
138
|
+
return result.join("&");
|
|
139
|
+
}
|
|
140
|
+
extract_options(number_of_params, args) {
|
|
141
|
+
const last_el = args[args.length - 1];
|
|
142
|
+
if ((args.length > number_of_params && last_el === 0) ||
|
|
143
|
+
(this.is_object(last_el) && !this.looks_like_serialized_model(last_el))) {
|
|
144
|
+
if (this.is_object(last_el)) {
|
|
145
|
+
delete last_el[this.configuration.special_options_key];
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
args: args.slice(0, args.length - 1),
|
|
149
|
+
options: last_el,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
return { args, options: {} };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
looks_like_serialized_model(object) {
|
|
157
|
+
return (this.is_object(object) &&
|
|
158
|
+
!(this.configuration.special_options_key in object) &&
|
|
159
|
+
("id" in object || "to_param" in object || "toParam" in object));
|
|
160
|
+
}
|
|
161
|
+
path_identifier(object) {
|
|
162
|
+
const result = this.unwrap_path_identifier(object);
|
|
163
|
+
return this.is_nullable(result) ||
|
|
164
|
+
(this.configuration.deprecated_false_parameter_behavior &&
|
|
165
|
+
result === false)
|
|
166
|
+
? ""
|
|
167
|
+
: "" + result;
|
|
168
|
+
}
|
|
169
|
+
unwrap_path_identifier(object) {
|
|
170
|
+
let result = object;
|
|
171
|
+
if (!this.is_object(object)) {
|
|
172
|
+
return object;
|
|
173
|
+
}
|
|
174
|
+
if ("to_param" in object) {
|
|
175
|
+
result = object.to_param;
|
|
176
|
+
}
|
|
177
|
+
else if ("toParam" in object) {
|
|
178
|
+
result = object.toParam;
|
|
179
|
+
}
|
|
180
|
+
else if ("id" in object) {
|
|
181
|
+
result = object.id;
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
result = object;
|
|
185
|
+
}
|
|
186
|
+
return this.is_callable(result) ? result.call(object) : result;
|
|
187
|
+
}
|
|
188
|
+
partition_parameters(parts, required_params, default_options, call_arguments) {
|
|
189
|
+
let { args, options } = this.extract_options(parts.length, call_arguments);
|
|
190
|
+
if (args.length > parts.length) {
|
|
191
|
+
throw new Error("Too many parameters provided for path");
|
|
192
|
+
}
|
|
193
|
+
let use_all_parts = args.length > required_params.length;
|
|
194
|
+
const parts_options = {
|
|
195
|
+
...this.configuration.default_url_options,
|
|
196
|
+
};
|
|
197
|
+
for (const key in options) {
|
|
198
|
+
const value = options[key];
|
|
199
|
+
if (!this.hasProp(options, key))
|
|
200
|
+
continue;
|
|
201
|
+
use_all_parts = true;
|
|
202
|
+
if (parts.includes(key)) {
|
|
203
|
+
parts_options[key] = value;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
options = {
|
|
207
|
+
...this.configuration.default_url_options,
|
|
208
|
+
...default_options,
|
|
209
|
+
...options,
|
|
210
|
+
};
|
|
211
|
+
const keyword_parameters = {};
|
|
212
|
+
let query_parameters = {};
|
|
213
|
+
for (const key in options) {
|
|
214
|
+
if (!this.hasProp(options, key))
|
|
215
|
+
continue;
|
|
216
|
+
const value = options[key];
|
|
217
|
+
if (key === "params") {
|
|
218
|
+
if (this.is_object(value)) {
|
|
219
|
+
query_parameters = {
|
|
220
|
+
...query_parameters,
|
|
221
|
+
...value,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
throw new Error("params value should always be an object");
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else if (this.is_reserved_option(key)) {
|
|
229
|
+
keyword_parameters[key] = value;
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
if (!this.is_nullable(value) &&
|
|
233
|
+
(value !== default_options[key] || required_params.includes(key))) {
|
|
234
|
+
query_parameters[key] = value;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
const route_parts = use_all_parts ? parts : required_params;
|
|
239
|
+
let i = 0;
|
|
240
|
+
for (const part of route_parts) {
|
|
241
|
+
if (i < args.length) {
|
|
242
|
+
const value = args[i];
|
|
243
|
+
if (!this.hasProp(parts_options, part)) {
|
|
244
|
+
query_parameters[part] = value;
|
|
245
|
+
++i;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return { keyword_parameters, query_parameters };
|
|
250
|
+
}
|
|
251
|
+
build_route(parts, required_params, default_options, route, absolute, args) {
|
|
252
|
+
const { keyword_parameters, query_parameters } = this.partition_parameters(parts, required_params, default_options, args);
|
|
253
|
+
let { trailing_slash, anchor, script_name } = keyword_parameters;
|
|
254
|
+
const missing_params = required_params.filter((param) => !this.hasProp(query_parameters, param) ||
|
|
255
|
+
this.is_nullable(query_parameters[param]));
|
|
256
|
+
if (missing_params.length) {
|
|
257
|
+
throw new ParametersMissing(...missing_params);
|
|
258
|
+
}
|
|
259
|
+
let result = this.get_prefix() + this.visit(route, query_parameters);
|
|
260
|
+
if (trailing_slash) {
|
|
261
|
+
result = result.replace(/(.*?)[/]?$/, "$1/");
|
|
262
|
+
}
|
|
263
|
+
const url_params = this.serialize(query_parameters);
|
|
264
|
+
if (url_params.length) {
|
|
265
|
+
result += "?" + url_params;
|
|
266
|
+
}
|
|
267
|
+
if (anchor) {
|
|
268
|
+
result += "#" + anchor;
|
|
269
|
+
}
|
|
270
|
+
if (script_name) {
|
|
271
|
+
const last_index = script_name.length - 1;
|
|
272
|
+
if (script_name[last_index] == "/" && result[0] == "/") {
|
|
273
|
+
script_name = script_name.slice(0, last_index);
|
|
274
|
+
}
|
|
275
|
+
result = script_name + result;
|
|
276
|
+
}
|
|
277
|
+
if (absolute) {
|
|
278
|
+
result = this.route_url(keyword_parameters) + result;
|
|
279
|
+
}
|
|
280
|
+
return result;
|
|
281
|
+
}
|
|
282
|
+
visit(route, parameters, optional = false) {
|
|
283
|
+
switch (route[0]) {
|
|
284
|
+
case NodeTypes.GROUP:
|
|
285
|
+
return this.visit(route[1], parameters, true);
|
|
286
|
+
case NodeTypes.CAT:
|
|
287
|
+
return this.visit_cat(route, parameters, optional);
|
|
288
|
+
case NodeTypes.SYMBOL:
|
|
289
|
+
return this.visit_symbol(route, parameters, optional);
|
|
290
|
+
case NodeTypes.STAR:
|
|
291
|
+
return this.visit_globbing(route[1], parameters, true);
|
|
292
|
+
case NodeTypes.LITERAL:
|
|
293
|
+
case NodeTypes.SLASH:
|
|
294
|
+
case NodeTypes.DOT:
|
|
295
|
+
return route[1];
|
|
296
|
+
default:
|
|
297
|
+
throw new Error("Unknown Rails node type");
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
is_not_nullable(object) {
|
|
301
|
+
return !this.is_nullable(object);
|
|
302
|
+
}
|
|
303
|
+
is_nullable(object) {
|
|
304
|
+
return object === undefined || object === null;
|
|
305
|
+
}
|
|
306
|
+
visit_cat(
|
|
307
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
308
|
+
[_type, left, right], parameters, optional) {
|
|
309
|
+
const left_part = this.visit(left, parameters, optional);
|
|
310
|
+
let right_part = this.visit(right, parameters, optional);
|
|
311
|
+
if (optional &&
|
|
312
|
+
((this.is_optional_node(left[0]) && !left_part) ||
|
|
313
|
+
(this.is_optional_node(right[0]) && !right_part))) {
|
|
314
|
+
return "";
|
|
315
|
+
}
|
|
316
|
+
// if left_part ends on '/' and right_part starts on '/'
|
|
317
|
+
if (left_part[left_part.length - 1] === "/" && right_part[0] === "/") {
|
|
318
|
+
// strip slash from right_part
|
|
319
|
+
// to prevent double slash
|
|
320
|
+
right_part = right_part.substring(1);
|
|
321
|
+
}
|
|
322
|
+
return left_part + right_part;
|
|
323
|
+
}
|
|
324
|
+
visit_symbol(
|
|
325
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
326
|
+
[_type, key], parameters, optional) {
|
|
327
|
+
const value = this.path_identifier(parameters[key]);
|
|
328
|
+
delete parameters[key];
|
|
329
|
+
if (value.length) {
|
|
330
|
+
return this.encode_segment(value);
|
|
331
|
+
}
|
|
332
|
+
if (optional) {
|
|
333
|
+
return "";
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
throw new ParametersMissing(key);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
encode_segment(segment) {
|
|
340
|
+
if (segment.match(/^[a-zA-Z0-9-]$/)) {
|
|
341
|
+
// Performance optimization for 99% of cases
|
|
342
|
+
return segment;
|
|
343
|
+
}
|
|
344
|
+
return (segment.match(/./gu) || [])
|
|
345
|
+
.map((ch) => {
|
|
346
|
+
const code = ch.charCodeAt(0);
|
|
347
|
+
if (UnescapedRanges.find((range) => code >= range[0] && code <= range[1]) ||
|
|
348
|
+
UnescapedSpecials.includes(code)) {
|
|
349
|
+
return ch;
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
return encodeURIComponent(ch);
|
|
353
|
+
}
|
|
354
|
+
})
|
|
355
|
+
.join("");
|
|
356
|
+
}
|
|
357
|
+
is_optional_node(node) {
|
|
358
|
+
return [NodeTypes.STAR, NodeTypes.SYMBOL, NodeTypes.CAT].includes(node);
|
|
359
|
+
}
|
|
360
|
+
build_path_spec(route, wildcard = false) {
|
|
361
|
+
let key;
|
|
362
|
+
switch (route[0]) {
|
|
363
|
+
case NodeTypes.GROUP:
|
|
364
|
+
return `(${this.build_path_spec(route[1])})`;
|
|
365
|
+
case NodeTypes.CAT:
|
|
366
|
+
return (this.build_path_spec(route[1]) + this.build_path_spec(route[2]));
|
|
367
|
+
case NodeTypes.STAR:
|
|
368
|
+
return this.build_path_spec(route[1], true);
|
|
369
|
+
case NodeTypes.SYMBOL:
|
|
370
|
+
key = route[1];
|
|
371
|
+
if (wildcard) {
|
|
372
|
+
return (key.startsWith("*") ? "" : "*") + key;
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
return ":" + key;
|
|
376
|
+
}
|
|
377
|
+
case NodeTypes.SLASH:
|
|
378
|
+
case NodeTypes.DOT:
|
|
379
|
+
case NodeTypes.LITERAL:
|
|
380
|
+
return route[1];
|
|
381
|
+
default:
|
|
382
|
+
throw new Error("Unknown Rails node type");
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
visit_globbing(route, parameters, optional) {
|
|
386
|
+
const key = route[1];
|
|
387
|
+
let value = parameters[key];
|
|
388
|
+
delete parameters[key];
|
|
389
|
+
if (this.is_nullable(value)) {
|
|
390
|
+
return this.visit(route, parameters, optional);
|
|
391
|
+
}
|
|
392
|
+
if (this.is_array(value)) {
|
|
393
|
+
value = value.join("/");
|
|
394
|
+
}
|
|
395
|
+
const result = this.path_identifier(value);
|
|
396
|
+
return encodeURI(result);
|
|
397
|
+
}
|
|
398
|
+
get_prefix() {
|
|
399
|
+
const prefix = this.configuration.prefix;
|
|
400
|
+
return prefix.match("/$")
|
|
401
|
+
? prefix.substring(0, prefix.length - 1)
|
|
402
|
+
: prefix;
|
|
403
|
+
}
|
|
404
|
+
route_url(route_defaults) {
|
|
405
|
+
const hostname = route_defaults.host || this.current_host();
|
|
406
|
+
if (!hostname) {
|
|
407
|
+
return "";
|
|
408
|
+
}
|
|
409
|
+
const subdomain = route_defaults.subdomain
|
|
410
|
+
? route_defaults.subdomain + "."
|
|
411
|
+
: "";
|
|
412
|
+
const protocol = route_defaults.protocol || this.current_protocol();
|
|
413
|
+
let port = route_defaults.port ||
|
|
414
|
+
(!route_defaults.host ? this.current_port() : undefined);
|
|
415
|
+
port = port ? ":" + port : "";
|
|
416
|
+
return protocol + "://" + subdomain + hostname + port;
|
|
417
|
+
}
|
|
418
|
+
current_host() {
|
|
419
|
+
var _a;
|
|
420
|
+
return (isBrowser && ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.hostname)) || "";
|
|
421
|
+
}
|
|
422
|
+
current_protocol() {
|
|
423
|
+
var _a, _b;
|
|
424
|
+
return ((isBrowser && ((_b = (_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.protocol) === null || _b === void 0 ? void 0 : _b.replace(/:$/, ""))) || "http");
|
|
425
|
+
}
|
|
426
|
+
current_port() {
|
|
427
|
+
var _a;
|
|
428
|
+
return (isBrowser && ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.port)) || "";
|
|
429
|
+
}
|
|
430
|
+
is_object(value) {
|
|
431
|
+
return (typeof value === "object" &&
|
|
432
|
+
Object.prototype.toString.call(value) === "[object Object]");
|
|
433
|
+
}
|
|
434
|
+
is_array(object) {
|
|
435
|
+
return object instanceof Array;
|
|
436
|
+
}
|
|
437
|
+
is_callable(object) {
|
|
438
|
+
return typeof object === "function" && !!object.call;
|
|
439
|
+
}
|
|
440
|
+
is_reserved_option(key) {
|
|
441
|
+
return ReservedOptions.includes(key);
|
|
442
|
+
}
|
|
443
|
+
hasProp(value, key) {
|
|
444
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
return Router;
|
|
448
|
+
})();
|
|
449
|
+
export {};
|