@h3ravel/url 1.29.0-alpha.16 → 2.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/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /// <reference path="./app.globals.d.ts" />
2
- import { ExtractClassMethods, IApplication, IUrlHelpers, RouteParams } from "@h3ravel/contracts";
3
2
  import { ServiceProvider } from "@h3ravel/support";
3
+ import { ExtractClassMethods, IApplication, IUrlHelpers, RouteParams } from "@h3ravel/contracts";
4
4
 
5
5
  //#region src/RequestAwareHelpers.d.ts
6
6
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h3ravel/url",
3
- "version": "1.29.0-alpha.16",
3
+ "version": "2.0.0",
4
4
  "description": "Request-aware URI builder and URL manipulation utilities for H3ravel.",
5
5
  "h3ravel": {
6
6
  "providers": [
@@ -8,9 +8,7 @@
8
8
  ]
9
9
  },
10
10
  "type": "module",
11
- "main": "./dist/index.cjs",
12
11
  "types": "./dist/index.d.ts",
13
- "module": "./dist/index.js",
14
12
  "exports": {
15
13
  ".": {
16
14
  "import": "./dist/index.js",
@@ -44,17 +42,17 @@
44
42
  "builder"
45
43
  ],
46
44
  "dependencies": {
47
- "@h3ravel/support": "^1.29.0-alpha.16",
48
- "@h3ravel/contracts": "^1.29.0-alpha.16",
49
- "@h3ravel/foundation": "^1.29.0-alpha.16",
50
- "@h3ravel/shared": "^1.29.0-alpha.16"
45
+ "@h3ravel/support": "^2.0.0",
46
+ "@h3ravel/contracts": "^2.0.0",
47
+ "@h3ravel/foundation": "^2.0.0",
48
+ "@h3ravel/shared": "^2.0.0"
51
49
  },
52
50
  "devDependencies": {
53
51
  "typescript": "^6.0.0"
54
52
  },
55
53
  "scripts": {
56
54
  "build": "tsdown --config-loader unrun",
57
- "dev": "tsx watch src/index.ts",
55
+ "dev": "tsdown --watch --config-loader unrun",
58
56
  "start": "node dist/index.js",
59
57
  "lint": "eslint . --ext .ts",
60
58
  "test": "jest --passWithNoTests",
package/dist/index.cjs DELETED
@@ -1,459 +0,0 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- //#region \0rolldown/runtime.js
3
- var __create = Object.create;
4
- var __defProp = Object.defineProperty;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getProtoOf = Object.getPrototypeOf;
8
- var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
- key = keys[i];
12
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
- get: ((k) => from[k]).bind(null, key),
14
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
- });
16
- }
17
- return to;
18
- };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
- value: mod,
21
- enumerable: true
22
- }) : target, mod));
23
- //#endregion
24
- let _h3ravel_foundation = require("@h3ravel/foundation");
25
- let _h3ravel_support = require("@h3ravel/support");
26
- let node_path = require("node:path");
27
- node_path = __toESM(node_path, 1);
28
- //#region src/RequestAwareHelpers.ts
29
- /**
30
- * Request-aware URL helper class
31
- */
32
- var RequestAwareHelpers = class {
33
- app;
34
- baseUrl = "";
35
- constructor(app) {
36
- this.app = app;
37
- try {
38
- this.baseUrl = config("app.url", "http://localhost:3000");
39
- } catch {}
40
- }
41
- /**
42
- * Get the current request instance
43
- */
44
- getCurrentRequest() {
45
- const request = this.app.make("http.request");
46
- if (!request) throw new Error("Request instance not available in current context");
47
- return request;
48
- }
49
- /**
50
- * Get the current request URL (path only, no query string)
51
- */
52
- current() {
53
- const raw = this.getCurrentRequest().getEvent().req.url ?? "/";
54
- return new URL(raw, "http://localhost").pathname;
55
- }
56
- /**
57
- * Get the full current URL with query string
58
- */
59
- full() {
60
- const requestUrl = this.getCurrentRequest().getEvent().req.url ?? "/";
61
- if (requestUrl.startsWith("http")) return requestUrl;
62
- return new URL(requestUrl, this.baseUrl).toString();
63
- }
64
- /**
65
- * Get the previous request URL from session or referrer
66
- */
67
- previous() {
68
- const headers = this.getCurrentRequest().getEvent()?.node?.req?.headers;
69
- let referrer = headers?.referer ?? headers?.referrer;
70
- if (Array.isArray(referrer)) referrer = referrer[0];
71
- if (referrer) return referrer;
72
- return this.current();
73
- }
74
- /**
75
- * Get the previous request path (without query string)
76
- */
77
- previousPath() {
78
- const previousUrl = this.previous();
79
- try {
80
- return new URL(previousUrl).pathname;
81
- } catch {
82
- return previousUrl;
83
- }
84
- }
85
- /**
86
- * Get the current query parameters
87
- */
88
- query() {
89
- return this.getCurrentRequest()._query || {};
90
- }
91
- };
92
- /**
93
- * Global helper function factory
94
- */
95
- function createUrlHelper(app) {
96
- return () => new RequestAwareHelpers(app);
97
- }
98
- //#endregion
99
- //#region src/Url.ts
100
- /**
101
- * URL builder class with fluent API and request-aware helpers
102
- */
103
- var Url = class Url {
104
- _scheme;
105
- _host;
106
- _port;
107
- _path;
108
- _query;
109
- _fragment;
110
- app;
111
- constructor(app, scheme, host, port, path = "/", query = {}, fragment) {
112
- this.app = app;
113
- this._scheme = scheme;
114
- this._host = host;
115
- this._port = port;
116
- this._path = path.startsWith("/") ? path : `/${path}`;
117
- this._query = { ...query };
118
- this._fragment = fragment;
119
- }
120
- /**
121
- * Create a URL from a full URL string
122
- */
123
- static of(url, app) {
124
- try {
125
- const parsed = new URL(url);
126
- const query = {};
127
- parsed.searchParams.forEach((value, key) => {
128
- query[key] = value;
129
- });
130
- return new Url(app, parsed.protocol.replace(":", ""), parsed.hostname, parsed.port ? parseInt(parsed.port) : void 0, parsed.pathname || "/", query, parsed.hash ? parsed.hash.substring(1) : void 0);
131
- } catch {
132
- throw new Error(`Invalid URL: ${url}`);
133
- }
134
- }
135
- /**
136
- * Create a URL from a path relative to the app URL
137
- */
138
- static to(path, app) {
139
- let baseUrl = "";
140
- try {
141
- baseUrl = config("app.url", "http://localhost:3000");
142
- } catch {}
143
- const fullUrl = new URL(path, baseUrl).toString();
144
- return Url.of(fullUrl, app);
145
- }
146
- /**
147
- * Create a URL from a named route
148
- */
149
- static route(name, params = {}, app) {
150
- if (!app) throw new Error("Application instance required for route generation");
151
- const routeUrl = app.make("url").route(name, params);
152
- if (!routeUrl) throw new Error(`Route "${name}" not found`);
153
- return Url.to(routeUrl, app);
154
- }
155
- /**
156
- * Create a signed URL from a named route
157
- */
158
- static signedRoute(name, params = {}, app) {
159
- return Url.route(name, params, app).withSignature(app);
160
- }
161
- /**
162
- * Create a temporary signed URL from a named route
163
- */
164
- static temporarySignedRoute(name, params = {}, expiration, app) {
165
- return Url.route(name, params, app).withSignature(app, expiration);
166
- }
167
- /**
168
- * Create a URL from a controller action
169
- */
170
- static action(controller, params, app) {
171
- if (!app) throw new Error("Application instance required for action URL generation");
172
- const [controllerName, methodName = "index"] = typeof controller === "string" ? controller.split("@") : controller;
173
- const cname = typeof controllerName === "string" ? controllerName : controllerName.name;
174
- let routes;
175
- try {
176
- const legacyRoutes = app.make("app.routes");
177
- routes = Array.isArray(legacyRoutes) ? legacyRoutes : [];
178
- } catch {
179
- routes = app.make("router").getRoutes().getRoutes().map((route) => {
180
- const action = route.getAction();
181
- const controller = action.controller;
182
- const signature = typeof controller === "function" ? [controller.name, action.uses?.[1] ?? "index"] : typeof controller === "string" ? controller.replace(/^\\/, "").split("@") : void 0;
183
- return {
184
- path: route.uri(),
185
- signature
186
- };
187
- });
188
- }
189
- if (routes.length < 1) throw new Error(`No routes available to resolve action: ${controller}`);
190
- const found = routes.find((route) => {
191
- return route.signature?.[0] === cname && (route.signature?.[1] || "index") === methodName;
192
- });
193
- if (!found) throw new Error(`No route found for ${cname}`);
194
- const _params = Object.values(params ?? {}).join("/");
195
- if (_params) return Url.to(node_path.default.join(found.path, _params));
196
- return Url.to(found.path, app);
197
- }
198
- /**
199
- * Set the scheme (protocol) of the URL
200
- */
201
- withScheme(scheme) {
202
- return new Url(this.app, scheme, this._host, this._port, this._path, this._query, this._fragment);
203
- }
204
- /**
205
- * Set the host of the URL
206
- */
207
- withHost(host) {
208
- return new Url(this.app, this._scheme, host, this._port, this._path, this._query, this._fragment);
209
- }
210
- /**
211
- * Set the port of the URL
212
- */
213
- withPort(port) {
214
- return new Url(this.app, this._scheme, this._host, port, this._path, this._query, this._fragment);
215
- }
216
- /**
217
- * Set the path of the URL
218
- */
219
- withPath(path) {
220
- return new Url(this.app, this._scheme, this._host, this._port, path, this._query, this._fragment);
221
- }
222
- /**
223
- * Set the query parameters of the URL
224
- */
225
- withQuery(query) {
226
- return new Url(this.app, this._scheme, this._host, this._port, this._path, { ...query }, this._fragment);
227
- }
228
- /**
229
- * Merge additional query parameters
230
- */
231
- withQueryParams(params) {
232
- return new Url(this.app, this._scheme, this._host, this._port, this._path, {
233
- ...this._query,
234
- ...params
235
- }, this._fragment);
236
- }
237
- /**
238
- * Set the fragment (hash) of the URL
239
- */
240
- withFragment(fragment) {
241
- return new Url(this.app, this._scheme, this._host, this._port, this._path, this._query, fragment);
242
- }
243
- /**
244
- * Add a signature to the URL for security
245
- */
246
- withSignature(app, expiration) {
247
- if (!(app || this.app)) throw new Error("Application instance required for URL signing");
248
- let key = "";
249
- try {
250
- key = config("app.key");
251
- } catch {}
252
- if (!key) throw new _h3ravel_foundation.ConfigException("APP_KEY and app.key", "any", this);
253
- const url = this.toString();
254
- const queryParams = { ...this._query };
255
- if (expiration) queryParams.expires = Math.floor(expiration / 1e3);
256
- queryParams.signature = (0, _h3ravel_support.hmac)(expiration ? `${url}?expires=${queryParams.expires}` : url, key);
257
- return this.withQuery(queryParams);
258
- }
259
- /**
260
- * Verify if a URL signature is valid
261
- */
262
- hasValidSignature(app) {
263
- if (!(app || this.app)) return false;
264
- const signature = this._query.signature;
265
- if (!signature) return false;
266
- if (this._query.expires !== void 0 && this._query.expires !== null) {
267
- const expiresStr = String(this._query.expires);
268
- const expirationTime = parseInt(expiresStr, 10) * 1e3;
269
- if (isNaN(expirationTime) || Date.now() > expirationTime) return false;
270
- }
271
- const queryWithoutSignature = { ...this._query };
272
- delete queryWithoutSignature.signature;
273
- const urlWithoutSignature = new Url(this.app, this._scheme, this._host, this._port, this._path, queryWithoutSignature, this._fragment).toString();
274
- const payload = this._query.expires ? `${urlWithoutSignature}?expires=${this._query.expires}` : urlWithoutSignature;
275
- let key = "";
276
- try {
277
- key = config("app.key", "default-key");
278
- } catch {}
279
- return signature === (0, _h3ravel_support.hmac)(payload, key);
280
- }
281
- /**
282
- * Convert the URL to its string representation
283
- */
284
- toString() {
285
- let url = "";
286
- if (this._scheme && this._host) {
287
- url += `${this._scheme}://${this._host}`;
288
- if (this._port && !(this._scheme === "http" && this._port === 80 || this._scheme === "https" && this._port === 443)) url += `:${this._port}`;
289
- }
290
- if (this._path) {
291
- if (!this._path.startsWith("/")) url += "/";
292
- url += this._path;
293
- }
294
- const queryEntries = Object.entries(this._query);
295
- if (queryEntries.length > 0) {
296
- const queryString = queryEntries.map(([key, value]) => {
297
- if (Array.isArray(value)) return value.map((v) => `${encodeURIComponent(key)}%5B%5D=${encodeURIComponent(v)}`).join("&");
298
- return `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`;
299
- }).join("&");
300
- url += `?${queryString}`;
301
- }
302
- if (this._fragment) url += `#${this._fragment}`;
303
- return url;
304
- }
305
- /**
306
- * Get the scheme
307
- */
308
- getScheme() {
309
- return this._scheme;
310
- }
311
- /**
312
- * Get the host
313
- */
314
- getHost() {
315
- return this._host;
316
- }
317
- /**
318
- * Get the port
319
- */
320
- getPort() {
321
- return this._port;
322
- }
323
- /**
324
- * Get the path
325
- */
326
- getPath() {
327
- return this._path;
328
- }
329
- /**
330
- * Get the query parameters
331
- */
332
- getQuery() {
333
- return { ...this._query };
334
- }
335
- /**
336
- * Get the fragment
337
- */
338
- getFragment() {
339
- return this._fragment;
340
- }
341
- };
342
- //#endregion
343
- //#region src/Helpers.ts
344
- /**
345
- * Global helper functions for URL manipulation
346
- */
347
- /**
348
- * Create a URL from a path relative to the app URL
349
- */
350
- function to(path, app) {
351
- return Url.to(path, app);
352
- }
353
- /**
354
- * Create a URL from a named route
355
- */
356
- function route(name, params = {}, app) {
357
- return Url.route(name, params, app);
358
- }
359
- /**
360
- * Create a signed URL from a named route
361
- */
362
- function signedRoute(name, params = {}, app) {
363
- return Url.signedRoute(name, params, app);
364
- }
365
- /**
366
- * Create a temporary signed URL from a named route
367
- */
368
- function temporarySignedRoute(name, params = {}, expiration, app) {
369
- return Url.temporarySignedRoute(name, params, expiration, app);
370
- }
371
- /**
372
- * Create a URL from a controller action
373
- */
374
- function action(controller, app) {
375
- return Url.action(controller, app);
376
- }
377
- /**
378
- * Get request-aware URL helpers
379
- */
380
- function url(app) {
381
- if (!app) throw new Error("Application instance required for request-aware URL helpers");
382
- return new RequestAwareHelpers(app);
383
- }
384
- /**
385
- * Create URL helpers that are bound to an application instance
386
- */
387
- function createUrlHelpers(app) {
388
- return {
389
- /**
390
- * Create a URL from a path relative to the app URL
391
- */
392
- to: (path) => Url.to(path, app),
393
- /**
394
- * Create a URL from a named route
395
- */
396
- route: (name, params = {}) => Url.route(name, params, app).toString(),
397
- /**
398
- * Create a signed URL from a named route
399
- */
400
- signedRoute: (name, params = {}) => Url.signedRoute(name, params, app),
401
- /**
402
- * Create a temporary signed URL from a named route
403
- */
404
- temporarySignedRoute: (name, params = {}, expiration) => Url.temporarySignedRoute(name, params, expiration, app),
405
- /**
406
- * Create a URL from a controller action
407
- */
408
- action: (controller, params) => Url.action(controller, params, app).toString(),
409
- /**
410
- * Get request-aware URL helpers
411
- */
412
- url: (path) => {
413
- if (path) return Url.to(path).toString();
414
- return new RequestAwareHelpers(app);
415
- }
416
- };
417
- }
418
- //#endregion
419
- //#region src/Providers/UrlServiceProvider.ts
420
- /**
421
- * Service provider for URL utilities
422
- */
423
- var UrlServiceProvider = class extends _h3ravel_support.ServiceProvider {
424
- static priority = 897;
425
- /**
426
- * Register URL services in the container
427
- */
428
- register() {
429
- this.app.setUriResolver(() => Url);
430
- }
431
- /**
432
- * Boot URL services
433
- */
434
- boot() {
435
- this.app.singleton("app.url", () => Url);
436
- this.app.singleton("app.url.helper", () => createUrlHelper(this.app));
437
- this.app.singleton("app.url.helpers", () => createUrlHelpers(this.app));
438
- if (typeof globalThis !== "undefined") {
439
- const helpers = createUrlHelpers(this.app);
440
- Object.assign(globalThis, {
441
- url: helpers.url,
442
- route: helpers.route,
443
- action: helpers.action
444
- });
445
- }
446
- }
447
- };
448
- //#endregion
449
- exports.RequestAwareHelpers = RequestAwareHelpers;
450
- exports.Url = Url;
451
- exports.UrlServiceProvider = UrlServiceProvider;
452
- exports.action = action;
453
- exports.createUrlHelper = createUrlHelper;
454
- exports.createUrlHelpers = createUrlHelpers;
455
- exports.route = route;
456
- exports.signedRoute = signedRoute;
457
- exports.temporarySignedRoute = temporarySignedRoute;
458
- exports.to = to;
459
- exports.url = url;