millas 0.2.11 → 0.2.12-beta-1

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.
Files changed (74) hide show
  1. package/package.json +6 -5
  2. package/src/auth/Auth.js +13 -8
  3. package/src/auth/AuthController.js +45 -134
  4. package/src/auth/AuthMiddleware.js +12 -23
  5. package/src/auth/AuthUser.js +98 -0
  6. package/src/auth/RoleMiddleware.js +7 -17
  7. package/src/cli.js +1 -1
  8. package/src/commands/migrate.js +46 -31
  9. package/src/commands/serve.js +238 -38
  10. package/src/container/AppInitializer.js +158 -0
  11. package/src/container/Application.js +288 -183
  12. package/src/container/HttpServer.js +156 -0
  13. package/src/container/MillasApp.js +23 -280
  14. package/src/container/MillasConfig.js +163 -0
  15. package/src/controller/Controller.js +79 -300
  16. package/src/core/auth.js +9 -0
  17. package/src/core/db.js +8 -0
  18. package/src/core/foundation.js +67 -0
  19. package/src/core/http.js +11 -0
  20. package/src/core/mail.js +6 -0
  21. package/src/core/queue.js +7 -0
  22. package/src/core/validation.js +29 -0
  23. package/src/errors/ErrorRenderer.js +640 -0
  24. package/src/facades/Admin.js +49 -0
  25. package/src/facades/Auth.js +29 -0
  26. package/src/facades/Cache.js +28 -0
  27. package/src/facades/Database.js +43 -0
  28. package/src/facades/Events.js +25 -0
  29. package/src/facades/Facade.js +197 -0
  30. package/src/facades/Http.js +51 -0
  31. package/src/facades/Log.js +32 -0
  32. package/src/facades/Mail.js +35 -0
  33. package/src/facades/Queue.js +30 -0
  34. package/src/facades/Storage.js +25 -0
  35. package/src/facades/Url.js +53 -0
  36. package/src/http/HttpClient.js +673 -0
  37. package/src/http/MillasRequest.js +253 -0
  38. package/src/http/MillasResponse.js +196 -0
  39. package/src/http/RequestContext.js +176 -0
  40. package/src/http/ResponseDispatcher.js +51 -0
  41. package/src/http/UrlGenerator.js +375 -0
  42. package/src/http/WelcomePage.js +273 -0
  43. package/src/http/adapters/ExpressAdapter.js +315 -0
  44. package/src/http/adapters/HttpAdapter.js +168 -0
  45. package/src/http/adapters/index.js +9 -0
  46. package/src/http/helpers.js +164 -0
  47. package/src/http/index.js +13 -0
  48. package/src/index.js +5 -91
  49. package/src/logger/formatters/PrettyFormatter.js +15 -5
  50. package/src/logger/internal.js +76 -0
  51. package/src/logger/patchConsole.js +145 -0
  52. package/src/middleware/CorsMiddleware.js +22 -30
  53. package/src/middleware/LogMiddleware.js +27 -59
  54. package/src/middleware/Middleware.js +24 -15
  55. package/src/middleware/MiddlewarePipeline.js +30 -67
  56. package/src/middleware/MiddlewareRegistry.js +106 -0
  57. package/src/middleware/ThrottleMiddleware.js +22 -26
  58. package/src/orm/fields/index.js +124 -56
  59. package/src/orm/migration/ModelInspector.js +339 -336
  60. package/src/orm/model/Model.js +96 -6
  61. package/src/orm/query/QueryBuilder.js +141 -3
  62. package/src/providers/AuthServiceProvider.js +9 -5
  63. package/src/providers/CacheStorageServiceProvider.js +3 -1
  64. package/src/providers/EventServiceProvider.js +2 -1
  65. package/src/providers/LogServiceProvider.js +88 -17
  66. package/src/providers/MailServiceProvider.js +3 -2
  67. package/src/providers/ProviderRegistry.js +14 -1
  68. package/src/providers/QueueServiceProvider.js +3 -2
  69. package/src/providers/ServiceProvider.js +40 -8
  70. package/src/router/Router.js +121 -222
  71. package/src/scaffold/maker.js +24 -59
  72. package/src/scaffold/templates.js +21 -19
  73. package/src/validation/BaseValidator.js +193 -0
  74. package/src/validation/Validator.js +680 -0
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ const { createFacade } = require('./Facade');
4
+ const { AuthUser, Hasher, JwtDriver, AuthMiddleware, RoleMiddleware, AuthController, AuthServiceProvider } = require('../core');
5
+
6
+ /**
7
+ * Auth facade.
8
+ *
9
+ * @class
10
+ * @property {function(object): Promise<object>} register
11
+ * @property {function(string, string): Promise<{user, token, refreshToken}>} login
12
+ * @property {function(string): object} verify
13
+ * @property {function(object): Promise<object|null>} user
14
+ * @property {function(object): Promise<object>} userOrFail
15
+ * @property {function(string, string): Promise<boolean>} checkPassword
16
+ * @property {function(string): Promise<string>} hashPassword
17
+ * @property {function(object, object=): string} issueToken
18
+ * @property {function(string): object} decode
19
+ * @property {function(object): string} generateResetToken
20
+ * @property {function(string): object} verifyResetToken
21
+ * @property {function(function): void} setUserModel
22
+ * @property {function(object): void} swap
23
+ * @property {function(): void} restore
24
+ *
25
+ * @see src/auth/Auth.js
26
+ */
27
+ class Auth extends createFacade('auth') {}
28
+
29
+ module.exports = { Auth, AuthUser, Hasher, JwtDriver, AuthMiddleware, RoleMiddleware, AuthController, AuthServiceProvider };
@@ -0,0 +1,28 @@
1
+ 'use strict';
2
+
3
+ const {createFacade} = require('./Facade');
4
+
5
+ /**
6
+ * Cache facade.
7
+ *
8
+ * @class
9
+ * @property {function(string, *, number=): Promise<void>} set
10
+ * @property {function(string, *=): Promise<*>} get
11
+ * @property {function(string): Promise<void>} delete
12
+ * @property {function(string): Promise<void>} deletePattern
13
+ * @property {function(): Promise<void>} flush
14
+ * @property {function(string, number, function): Promise<*>} remember
15
+ * @property {function(string, number=): Promise<number>} increment
16
+ * @property {function(string, number=): Promise<number>} decrement
17
+ * @property {function(string[]): Promise<object>} getMany
18
+ * @property {function(object, number=): Promise<void>} setMany
19
+ * @property {function(...string): TaggedCache} tags
20
+ * @property {function(object): void} swap
21
+ * @property {function(): void} restore
22
+ *
23
+ * @see src/cache/Cache.js
24
+ */
25
+ class Cache extends createFacade('cache') {
26
+ }
27
+
28
+ module.exports = Cache;
@@ -0,0 +1,43 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * millas/facades/Database
5
+ *
6
+ * ORM models, field definitions, and query builder.
7
+ *
8
+ * const { Model, fields } = require('millas/facades/Database');
9
+ *
10
+ * class Post extends Model {
11
+ * static table = 'posts';
12
+ * static fields = {
13
+ * id: fields.id(),
14
+ * title: fields.string({ max: 255 }),
15
+ * author: fields.ForeignKey('User', { relatedName: 'posts' }),
16
+ * published: fields.boolean({ default: false }),
17
+ * created_at: fields.timestamp(),
18
+ * updated_at: fields.timestamp(),
19
+ * };
20
+ * }
21
+ */
22
+
23
+ const {
24
+ Model,
25
+ fields,
26
+ QueryBuilder,
27
+ DatabaseManager,
28
+ SchemaBuilder,
29
+ MigrationRunner,
30
+ ModelInspector,
31
+ DatabaseServiceProvider,
32
+ } = require('../core');
33
+
34
+ module.exports = {
35
+ Model,
36
+ fields,
37
+ QueryBuilder,
38
+ DatabaseManager,
39
+ SchemaBuilder,
40
+ MigrationRunner,
41
+ ModelInspector,
42
+ DatabaseServiceProvider,
43
+ };
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ const { createFacade } = require('./Facade');
4
+
5
+ /**
6
+ * Events facade.
7
+ *
8
+ * @class
9
+ * @property {function(string|function, function[]|function): EventEmitter} listen
10
+ * @property {function(string|function, function): EventEmitter} on
11
+ * @property {function(string|function, function): EventEmitter} once
12
+ * @property {function(string|function, function): EventEmitter} off
13
+ * @property {function(string, function): EventEmitter} onWildcard
14
+ * @property {function(string|Event, object=): Promise<void>} emit
15
+ * @property {function(string|function): function[]} getListeners
16
+ * @property {function(string|function): EventEmitter} removeAll
17
+ * @property {function(): EventEmitter} flush
18
+ * @property {function(object): void} swap
19
+ * @property {function(): void} restore
20
+ *
21
+ * @see src/events/EventEmitter.js
22
+ */
23
+ class Events extends createFacade('events') {}
24
+
25
+ module.exports = Events;
@@ -0,0 +1,197 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Facade
5
+ *
6
+ * Base class for all Millas facades.
7
+ *
8
+ * A facade is a static proxy to a service that lives in the DI container.
9
+ * Instead of importing the service directly, developers use the facade and
10
+ * the framework resolves the correct instance transparently.
11
+ *
12
+ * ── How it works ─────────────────────────────────────────────────────────────
13
+ *
14
+ * class Cache extends Facade {
15
+ * static get facadeAccessor() { return 'cache'; }
16
+ * }
17
+ *
18
+ * Cache.get('key')
19
+ * // ↓ Facade.__get intercepts 'get'
20
+ * // ↓ container.make('cache') → the Cache singleton
21
+ * // ↓ singleton.get('key')
22
+ *
23
+ * ── Benefits over direct singleton re-export ─────────────────────────────────
24
+ *
25
+ * 1. Swappable — rebind 'cache' in the container and every call site
26
+ * automatically uses the new implementation, zero changes.
27
+ *
28
+ * 2. Testable — swap the binding to a mock/fake in tests:
29
+ * Facade.swap('cache', fakeCacheInstance);
30
+ *
31
+ * 3. Lazy — the service is only resolved from the container on first call,
32
+ * not at require() time. Safe to import facades before boot.
33
+ *
34
+ * 4. Consistent — all services have the same access pattern regardless of
35
+ * how they were registered (singleton, instance, factory).
36
+ *
37
+ * ── Usage ────────────────────────────────────────────────────────────────────
38
+ *
39
+ * const { Cache } = require('millas/facades/Cache');
40
+ *
41
+ * await Cache.get('user:1');
42
+ * await Cache.set('user:1', user, 300);
43
+ * await Cache.remember('stats', 60, () => Stats.compute());
44
+ */
45
+ class Facade {
46
+ /**
47
+ * The container key this facade resolves to.
48
+ * Every subclass must override this.
49
+ *
50
+ * @returns {string}
51
+ */
52
+ static get facadeAccessor() {
53
+ throw new Error(
54
+ `Facade "${this.name}" must define a static facadeAccessor getter.\n` +
55
+ ` static get facadeAccessor() { return 'myService'; }`
56
+ );
57
+ }
58
+
59
+ // ── Container binding ──────────────────────────────────────────────────────
60
+
61
+ /**
62
+ * The shared container instance.
63
+ * Set by AppInitialiser once the container is fully booted.
64
+ * All facades share a single reference.
65
+ */
66
+ static _container = null;
67
+
68
+ /**
69
+ * Per-facade instance overrides — used by swap() for testing.
70
+ * key: facadeAccessor string → value: override instance
71
+ */
72
+ static _overrides = new Map();
73
+
74
+ /**
75
+ * Called by AppInitialiser after the container is booted.
76
+ * Wires all facades to the live container in one call.
77
+ *
78
+ * @param {import('../container/Container')} container
79
+ */
80
+ static setContainer(container) {
81
+ Facade._container = container;
82
+ }
83
+
84
+ /**
85
+ * Resolve the underlying service instance.
86
+ * Uses the override if one has been swapped in (for testing).
87
+ *
88
+ * @returns {object}
89
+ */
90
+ static _resolveInstance() {
91
+ const accessor = this.facadeAccessor;
92
+
93
+ if (Facade._overrides.has(accessor)) {
94
+ return Facade._overrides.get(accessor);
95
+ }
96
+
97
+ if (!Facade._container) {
98
+ throw new Error(
99
+ `[Millas] Facade "${this.name}" used before the application was booted.\n` +
100
+ `The container is not yet available. ` +
101
+ `Make sure you're not calling facade methods at module load time ` +
102
+ `(outside of route handlers, controllers, or provider boot methods).`
103
+ );
104
+ }
105
+
106
+ return Facade._container.make(accessor);
107
+ }
108
+
109
+ // ── Testing helpers ────────────────────────────────────────────────────────
110
+
111
+ /**
112
+ * Swap the facade's underlying instance for testing.
113
+ * The swap is scoped to the accessor key so it only affects this facade.
114
+ *
115
+ * Cache.swap({ get: async () => 'mocked' });
116
+ * const val = await Cache.get('key'); // → 'mocked'
117
+ * Cache.restore();
118
+ *
119
+ * @param {object} instance
120
+ */
121
+ static swap(instance) {
122
+ Facade._overrides.set(this.facadeAccessor, instance);
123
+ }
124
+
125
+ /**
126
+ * Remove a test swap and return to the real container binding.
127
+ */
128
+ static restore() {
129
+ Facade._overrides.delete(this.facadeAccessor);
130
+ }
131
+
132
+ /**
133
+ * Remove all test swaps.
134
+ */
135
+ static restoreAll() {
136
+ Facade._overrides.clear();
137
+ }
138
+ }
139
+
140
+ // ── Proxy handler ─────────────────────────────────────────────────────────────
141
+ //
142
+ // Intercepts every static property access on a Facade subclass.
143
+ // If the property isn't a real static member of the class, it's assumed
144
+ // to be a method or property on the underlying service instance.
145
+ //
146
+ // This means Cache.get → resolves the 'cache' service → calls .get on it.
147
+ // It also means Cache.set, Cache.remember, Cache.tags, etc. all work
148
+ // without listing them explicitly.
149
+
150
+ const FACADE_OWN_PROPS = new Set([
151
+ 'facadeAccessor',
152
+ '_container',
153
+ '_overrides',
154
+ 'setContainer',
155
+ '_resolveInstance',
156
+ 'swap',
157
+ 'restore',
158
+ 'restoreAll',
159
+ 'name',
160
+ 'prototype',
161
+ 'length',
162
+ ]);
163
+
164
+ const FacadeProxyHandler = {
165
+ get(target, prop, receiver) {
166
+ // Let real static members through untouched
167
+ if (FACADE_OWN_PROPS.has(prop) || prop in target) {
168
+ return Reflect.get(target, prop, receiver);
169
+ }
170
+
171
+ // Symbol access (Symbol.toPrimitive, Symbol.iterator, etc.) — pass through
172
+ if (typeof prop === 'symbol') {
173
+ return Reflect.get(target, prop, receiver);
174
+ }
175
+
176
+ // Proxy the call to the resolved service instance
177
+ return (...args) => target._resolveInstance()[prop](...args);
178
+ },
179
+ };
180
+
181
+ /**
182
+ * Create a Facade subclass that is automatically wrapped in a Proxy.
183
+ * Used internally — subclasses extend this instead of Facade directly.
184
+ *
185
+ * @example
186
+ * class Cache extends createFacade('cache') {}
187
+ */
188
+ function createFacade(accessor) {
189
+ class BoundFacade extends Facade {
190
+ static get facadeAccessor() { return accessor; }
191
+ }
192
+ return new Proxy(BoundFacade, FacadeProxyHandler);
193
+ }
194
+
195
+ module.exports = Facade;
196
+ module.exports.createFacade = createFacade;
197
+ module.exports.FacadeProxyHandler = FacadeProxyHandler;
@@ -0,0 +1,51 @@
1
+ 'use strict';
2
+
3
+ const { createFacade } = require('./Facade');
4
+ // const {PendingRequest,HttpResponse} = require('../http/HttpClient');
5
+
6
+ /**
7
+ * Fluent outbound HTTP client facade.
8
+ * Resolved from the DI container — every method creates a fresh PendingRequest.
9
+ *
10
+ * @class
11
+ *
12
+ * — Verbs
13
+ * @property {function(string, object=): Promise<HttpResponse>} get
14
+ * @property {function(string, object=): Promise<HttpResponse>} post
15
+ * @property {function(string, object=): Promise<HttpResponse>} put
16
+ * @property {function(string, object=): Promise<HttpResponse>} patch
17
+ * @property {function(string, object=): Promise<HttpResponse>} delete
18
+ * @property {function(string, object=): Promise<HttpResponse>} head
19
+ * @property {function(string): Promise<HttpResponse>} options
20
+ *
21
+ * — Builder (each returns PendingRequest for chaining)
22
+ * @property {function(string): PendingRequest} baseUrl
23
+ * @property {function(object): PendingRequest} withHeaders
24
+ * @property {function(string, string=): PendingRequest} withToken
25
+ * @property {function(string, string): PendingRequest} withBasicAuth
26
+ * @property {function(object): PendingRequest} withCookies
27
+ * @property {function(string): PendingRequest} withUserAgent
28
+ * @property {function(string, string=): PendingRequest} withBody
29
+ * @property {function(string): PendingRequest} accept
30
+ * @property {function(): PendingRequest} acceptJson
31
+ * @property {function(): PendingRequest} asJson
32
+ * @property {function(): PendingRequest} asForm
33
+ * @property {function(): PendingRequest} asMultipart
34
+ * @property {function(number): PendingRequest} timeout
35
+ * @property {function(number, number=): PendingRequest} retry
36
+ * @property {function(): PendingRequest} throwOnFailure
37
+ * @property {function(function): PendingRequest} beforeSending
38
+ * @property {function(function): PendingRequest} afterReceiving
39
+ *
40
+ * — Concurrent
41
+ * @property {function(function): Promise<HttpResponse[]>} pool
42
+ *
43
+ * — Testing
44
+ * @property {function(object): void} swap
45
+ * @property {function(): void} restore
46
+ *
47
+ * @see src/http/HttpClient.js
48
+ */
49
+ class Http extends createFacade('http') {}
50
+
51
+ module.exports = Http;
@@ -0,0 +1,32 @@
1
+ 'use strict';
2
+
3
+ const {createFacade} = require('./Facade');
4
+
5
+
6
+ /**
7
+ * Log facade.
8
+ *
9
+ * @class
10
+ * @property {function(TAG:string,message:string,...*): void} v
11
+ * @property {function(TAG:string,message:string,...*): void} d
12
+ * @property {function(TAG:string,message:string,...*): void} i
13
+ * @property {function(TAG:string,message:string,...*): void} w
14
+ * @property {function(TAG:string,message:string,...*): void} e
15
+ * @property {function(TAG:string,message:string,...*): void} wtf
16
+ * @property {function(TAG:string,message:string,...*): void} verbose
17
+ * @property {function(TAG:string,message:string,...*): void} debug
18
+ * @property {function(TAG:string,message:string,...*): void} info
19
+ * @property {function(TAG:string,message:string,...*): void} warn
20
+ * @property {function(TAG:string,message:string,...*): void} error
21
+ * @property {function(string): TaggedLogger} tag
22
+ * @property {function(string): function} time
23
+ * @property {function(string, function): Promise<*>} timed
24
+ * @property {function(object): void} swap
25
+ * @property {function(): void} restore
26
+ *
27
+ * @see src/logger/Logger.js
28
+ */
29
+ class Log extends createFacade('log') {
30
+ }
31
+
32
+ module.exports = Log;
@@ -0,0 +1,35 @@
1
+ 'use strict';
2
+
3
+ const { createFacade } = require('./Facade');
4
+ const { MailMessage, TemplateEngine, SmtpDriver, SendGridDriver, MailgunDriver, LogDriver, MailServiceProvider } = require('../core');
5
+
6
+ /**
7
+ * Mail facade.
8
+ *
9
+ * @class
10
+ * @property {function(MailMessage|object): Promise<void>} send
11
+ * @property {function(MailMessage|object): Promise<void>} queue
12
+ * @property {function(string, string=): MailMessage} to
13
+ * @property {function(object): void} swap
14
+ * @property {function(): void} restore
15
+ *
16
+ * — MailMessage builder (returned by Mail.to())
17
+ * @property {function(string, string=): MailMessage} MailMessage.prototype.to
18
+ * @property {function(string, string=): MailMessage} MailMessage.prototype.cc
19
+ * @property {function(string, string=): MailMessage} MailMessage.prototype.bcc
20
+ * @property {function(string, string=): MailMessage} MailMessage.prototype.from
21
+ * @property {function(string, string=): MailMessage} MailMessage.prototype.replyTo
22
+ * @property {function(string): MailMessage} MailMessage.prototype.subject
23
+ * @property {function(string): MailMessage} MailMessage.prototype.html
24
+ * @property {function(string): MailMessage} MailMessage.prototype.text
25
+ * @property {function(string, object=): MailMessage} MailMessage.prototype.view
26
+ * @property {function(string, string=, string=): MailMessage} MailMessage.prototype.attach
27
+ * @property {function(number): MailMessage} MailMessage.prototype.priority
28
+ * @property {function(): Promise<void>} MailMessage.prototype.send
29
+ * @property {function(): Promise<void>} MailMessage.prototype.queue
30
+ *
31
+ * @see src/mail/Mail.js
32
+ */
33
+ class Mail extends createFacade('mail') {}
34
+
35
+ module.exports = Mail
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ const { createFacade } = require('./Facade');
4
+
5
+ /**
6
+ * Queue facade.
7
+ *
8
+ * @class
9
+ * @property {function(Job): Promise<void>} push
10
+ * @property {function(string=): Promise<number>} size
11
+ * @property {function(string=): Promise<void>} clear
12
+ * @property {function(function): void} register
13
+ * @property {function(object): void} swap
14
+ * @property {function(): void} restore
15
+ *
16
+ * @see src/queue/Queue.js
17
+ */
18
+ class Queue extends createFacade('queue') {}
19
+
20
+ /**
21
+ * Shorthand for Queue.push(job).
22
+ *
23
+ * @param {Job} job
24
+ * @returns {Promise<void>}
25
+ */
26
+ async function dispatch(job) {
27
+ return Queue.push(job);
28
+ }
29
+
30
+ module.exports = Queue;
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ const { createFacade } = require('./Facade');
4
+
5
+ /**
6
+ * Storage facade.
7
+ *
8
+ * @class
9
+ * @property {function(string, Buffer|string, object=): Promise<void>} put
10
+ * @property {function(string): Promise<Buffer|string>} get
11
+ * @property {function(string): Promise<boolean>} exists
12
+ * @property {function(string): Promise<void>} delete
13
+ * @property {function(string): Promise<object>} metadata
14
+ * @property {function(string): string} url
15
+ * @property {function(string): string} path
16
+ * @property {function(string, object, object=): void} stream
17
+ * @property {function(string): Storage} disk
18
+ * @property {function(object): void} swap
19
+ * @property {function(): void} restore
20
+ *
21
+ * @see src/storage/Storage.js
22
+ */
23
+ class Storage extends createFacade('storage') {}
24
+
25
+ module.exports = Storage;
@@ -0,0 +1,53 @@
1
+ 'use strict';
2
+
3
+ const {createFacade} = require('./Facade');
4
+
5
+ /**
6
+ * URL facade — Laravel-like URL generation.
7
+ *
8
+ * @class
9
+ *
10
+ * — Base
11
+ * @property {function(): string} base
12
+ *
13
+ * — URL generation
14
+ * @property {function(string, object=): string} to
15
+ * @property {function(string, object=): string} secure
16
+ * @property {function(string, object=): string} relative
17
+ *
18
+ * — Named routes
19
+ * @property {function(string, object=, object=): string} route
20
+ *
21
+ * — Assets
22
+ * @property {function(string): string} asset
23
+ * @property {function(string): string} secureAsset
24
+ *
25
+ * — Current / previous request
26
+ * @property {function(): string|null} current
27
+ * @property {function(): string|null} currentPath
28
+ * @property {function(string=): string} previous
29
+ *
30
+ * — Signed URLs
31
+ * @property {function(string, object=, number=): string} signedRoute
32
+ * @property {function(string, number=): string} signedUrl
33
+ * @property {function(object): boolean} hasValidSignature
34
+ *
35
+ * — Scheme control
36
+ * @property {function(boolean=): UrlGenerator} forceHttps
37
+ * @property {function(string): UrlGenerator} forceScheme
38
+ * @property {function(string): UrlGenerator} useAssetOrigin
39
+ *
40
+ * — Introspection
41
+ * @property {function(string): boolean} isValid
42
+ * @property {function(...string): boolean} is
43
+ *
44
+ * — Testing
45
+ * @property {function(object): void} swap
46
+ * @property {function(): void} restore
47
+ *
48
+ * @see src/http/UrlGenerator.js
49
+ */
50
+ class URL extends createFacade('url') {
51
+ }
52
+
53
+ module.exports = URL;