@hulla/api-nuxt 0.0.0-stage → 2.0.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.
- package/dist/client.d.ts +15 -0
- package/dist/client.js +72 -0
- package/dist/server.d.ts +25 -0
- package/dist/server.js +41 -0
- package/package.json +52 -4
- package/README.md +0 -3
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ClientTransport } from "@hulla/api/client";
|
|
2
|
+
import { $Fetch } from "ofetch";
|
|
3
|
+
//#region src/client.d.ts
|
|
4
|
+
type NuxtRequestFetch = Pick<$Fetch, 'raw'> | {
|
|
5
|
+
/** Nitro's request-scoped event.fetch preserves local dispatch and native response metadata. */
|
|
6
|
+
readonly fetch: (url: string, options: RequestInit) => Promise<Response>;
|
|
7
|
+
};
|
|
8
|
+
type NuxtFetchTransportOptions = {
|
|
9
|
+
/** URL prefix placed before the contract base path. Relative paths retain Nitro's local SSR dispatch. */
|
|
10
|
+
readonly baseUrl?: string | URL;
|
|
11
|
+
};
|
|
12
|
+
/** Preserves response metadata over browser $fetch.raw or Nitro's request-scoped event.fetch. */
|
|
13
|
+
declare function nuxtFetchTransport(fetcher: NuxtRequestFetch, options?: NuxtFetchTransportOptions): ClientTransport;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { NuxtFetchTransportOptions, NuxtRequestFetch, nuxtFetchTransport };
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { fetchTransportResponse } from "@hulla/api/fetch";
|
|
2
|
+
|
|
3
|
+
//#region src/client.ts
|
|
4
|
+
function normalizedBaseUrl(baseUrl) {
|
|
5
|
+
return baseUrl === void 0 ? "" : String(baseUrl).replace(/\/+$/, "");
|
|
6
|
+
}
|
|
7
|
+
function assertBaseUrl(baseUrl) {
|
|
8
|
+
if (baseUrl === void 0) return;
|
|
9
|
+
const value = String(baseUrl);
|
|
10
|
+
if (value.includes("?")) throw new TypeError(`Nuxt fetch base URL "${value}" cannot contain a query string`);
|
|
11
|
+
if (value.includes("#")) throw new TypeError(`Nuxt fetch base URL "${value}" cannot contain a hash fragment`);
|
|
12
|
+
}
|
|
13
|
+
function appendBaseUrl(prefix, path) {
|
|
14
|
+
if (prefix === "") return path;
|
|
15
|
+
return path === "/" ? prefix || "/" : `${prefix}${path}`;
|
|
16
|
+
}
|
|
17
|
+
function requestUrl(request, baseUrl) {
|
|
18
|
+
const url = appendBaseUrl(baseUrl, request.path);
|
|
19
|
+
if (request.query === void 0) return url;
|
|
20
|
+
const parameters = new URLSearchParams();
|
|
21
|
+
for (const [key, field] of Object.entries(request.query)) {
|
|
22
|
+
if (field === void 0) continue;
|
|
23
|
+
if (typeof field === "string") parameters.append(key, field);
|
|
24
|
+
else for (const value of field) parameters.append(key, value);
|
|
25
|
+
}
|
|
26
|
+
const encoded = parameters.toString();
|
|
27
|
+
return encoded === "" ? url : `${url}?${encoded}`;
|
|
28
|
+
}
|
|
29
|
+
function requestBody(request) {
|
|
30
|
+
const body = request.body;
|
|
31
|
+
if (body === void 0) return void 0;
|
|
32
|
+
switch (body.kind) {
|
|
33
|
+
case "json": {
|
|
34
|
+
const encoded = JSON.stringify(body.value);
|
|
35
|
+
if (encoded === void 0) throw new TypeError("JSON request body cannot encode to undefined");
|
|
36
|
+
return encoded;
|
|
37
|
+
}
|
|
38
|
+
case "text": return body.value;
|
|
39
|
+
case "bytes": return body.value;
|
|
40
|
+
case "form-data":
|
|
41
|
+
if (!(body.value instanceof FormData)) throw new TypeError("Form data request body must be FormData");
|
|
42
|
+
return body.value;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Preserves response metadata over browser $fetch.raw or Nitro's request-scoped event.fetch. */
|
|
46
|
+
function nuxtFetchTransport(fetcher, options = {}) {
|
|
47
|
+
assertBaseUrl(options.baseUrl);
|
|
48
|
+
const baseUrl = normalizedBaseUrl(options.baseUrl);
|
|
49
|
+
const nativeFetch = "fetch" in fetcher ? fetcher.fetch : void 0;
|
|
50
|
+
const rawFetch = "raw" in fetcher ? fetcher.raw : void 0;
|
|
51
|
+
if (typeof nativeFetch !== "function" && typeof rawFetch !== "function") throw new TypeError("Nuxt transport requires $fetch.raw or { fetch: event.fetch }; useRequestFetch() can return a parsed-only fetcher on the server");
|
|
52
|
+
const send = typeof nativeFetch === "function" ? (url, init) => nativeFetch(url, init) : (url, init) => rawFetch(url, {
|
|
53
|
+
...init,
|
|
54
|
+
ignoreResponseError: true,
|
|
55
|
+
responseType: "stream",
|
|
56
|
+
retry: false
|
|
57
|
+
});
|
|
58
|
+
return async (request) => {
|
|
59
|
+
request.signal?.throwIfAborted();
|
|
60
|
+
const body = requestBody(request);
|
|
61
|
+
const response = await send(requestUrl(request, baseUrl), {
|
|
62
|
+
...body === void 0 ? {} : { body },
|
|
63
|
+
headers: request.headers,
|
|
64
|
+
method: request.method,
|
|
65
|
+
...request.signal === void 0 ? {} : { signal: request.signal }
|
|
66
|
+
});
|
|
67
|
+
return fetchTransportResponse(response);
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
export { nuxtFetchTransport };
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { FetchServerErrorInput } from "@hulla/api/fetch";
|
|
2
|
+
import { Awaitable, ServerAdapter, ServerContextInput, ServerExecutableFor } from "@hulla/api/server";
|
|
3
|
+
import { H3Event } from "h3";
|
|
4
|
+
import { Contract } from "@hulla/api";
|
|
5
|
+
//#region src/server.d.ts
|
|
6
|
+
type NuxtRequestEvent = H3Event;
|
|
7
|
+
type NuxtRouteHandler = (event: NuxtRequestEvent) => Promise<Response>;
|
|
8
|
+
type NuxtAdapterContext = {
|
|
9
|
+
readonly request: Request;
|
|
10
|
+
readonly nuxtEvent: NuxtRequestEvent;
|
|
11
|
+
};
|
|
12
|
+
type NuxtServerErrorInput = Omit<FetchServerErrorInput<NuxtRequestEvent>, 'handlerContext'> & {
|
|
13
|
+
readonly nuxtEvent: NuxtRequestEvent;
|
|
14
|
+
};
|
|
15
|
+
type NuxtServerOptions = {
|
|
16
|
+
readonly onError?: ((input: NuxtServerErrorInput) => Awaitable<Response | undefined | void>) | undefined;
|
|
17
|
+
};
|
|
18
|
+
type NuxtContextInput<ContractType extends Contract = Contract> = ServerContextInput<ContractType> & NuxtAdapterContext;
|
|
19
|
+
type NuxtAdapter = ServerAdapter<'nuxt', NuxtAdapterContext> & {
|
|
20
|
+
readonly mount: <const ContractType extends Contract, const Context extends object>(implementation: ServerExecutableFor<ContractType, Context, 'nuxt', NuxtAdapterContext>, options?: NuxtServerOptions) => NuxtRouteHandler;
|
|
21
|
+
};
|
|
22
|
+
/** Creates a Nuxt adapter with native Nitro request-event context and mounting operations. */
|
|
23
|
+
declare function nuxtAdapter(options?: NuxtServerOptions): NuxtAdapter;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { NuxtAdapter, NuxtAdapterContext, NuxtContextInput, NuxtRequestEvent, NuxtRouteHandler, NuxtServerErrorInput, NuxtServerOptions, nuxtAdapter };
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createFetchHandler } from "@hulla/api/fetch";
|
|
2
|
+
import { createAdapterRuntime } from "@hulla/api/adapters";
|
|
3
|
+
import { createServerAdapter } from "@hulla/api/server";
|
|
4
|
+
import { toWebRequest } from "h3";
|
|
5
|
+
|
|
6
|
+
//#region src/server.ts
|
|
7
|
+
/** Creates a Nitro event handler backed by an @hulla/api server implementation. */
|
|
8
|
+
function createRouteHandler(implementation, options = {}) {
|
|
9
|
+
const unsupported = createAdapterRuntime(implementation).routes.filter((route) => route.method === "QUERY");
|
|
10
|
+
if (unsupported.length > 0) throw new TypeError(`Nuxt server routes do not support QUERY routes: ${unsupported.map((route) => route.key.join(".")).join(", ")}`);
|
|
11
|
+
const handler = createFetchHandler(implementation, {
|
|
12
|
+
contextAdapter: "nuxt",
|
|
13
|
+
contextInput: (_request, nuxtEvent) => ({ nuxtEvent }),
|
|
14
|
+
...options.onError === void 0 ? {} : { onError: ({ handlerContext, ...input }) => options.onError?.({
|
|
15
|
+
...input,
|
|
16
|
+
nuxtEvent: handlerContext
|
|
17
|
+
}) }
|
|
18
|
+
});
|
|
19
|
+
return async (nuxtEvent) => {
|
|
20
|
+
const request = toWebRequest(nuxtEvent);
|
|
21
|
+
if (request.method !== "HEAD") return handler(request, nuxtEvent);
|
|
22
|
+
const response = await handler(new Request(request, { method: "GET" }), nuxtEvent);
|
|
23
|
+
return new Response(null, response);
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
let nuxtAdapterValue;
|
|
27
|
+
function createNuxtAdapter(defaults) {
|
|
28
|
+
return createServerAdapter("nuxt", { mount: (implementation, options) => createRouteHandler(implementation, options === void 0 ? defaults : {
|
|
29
|
+
...defaults,
|
|
30
|
+
...options
|
|
31
|
+
}) });
|
|
32
|
+
}
|
|
33
|
+
/** Creates a Nuxt adapter with native Nitro request-event context and mounting operations. */
|
|
34
|
+
function nuxtAdapter(options) {
|
|
35
|
+
if (options !== void 0) return createNuxtAdapter({ ...options });
|
|
36
|
+
nuxtAdapterValue ??= createNuxtAdapter({});
|
|
37
|
+
return nuxtAdapterValue;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { nuxtAdapter };
|
package/package.json
CHANGED
|
@@ -1,6 +1,54 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hulla/api-nuxt",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"description": "Nuxt and Nitro integration for @hulla/api",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/hulladev/api.git",
|
|
9
|
+
"directory": "packages/nuxt"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"type": "module",
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"exports": {
|
|
17
|
+
"./client": {
|
|
18
|
+
"types": "./dist/client.d.ts",
|
|
19
|
+
"import": "./dist/client.js"
|
|
20
|
+
},
|
|
21
|
+
"./server": {
|
|
22
|
+
"types": "./dist/server.d.ts",
|
|
23
|
+
"import": "./dist/server.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public",
|
|
28
|
+
"registry": "https://registry.npmjs.org/"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsdown",
|
|
32
|
+
"clean": "rm -rf dist coverage .nuxt .output",
|
|
33
|
+
"test": "bun run build && vitest run",
|
|
34
|
+
"test:coverage": "bun run build && vitest run --coverage",
|
|
35
|
+
"test:watch": "vitest",
|
|
36
|
+
"typecheck": "tsc --noEmit"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"h3": "^1.15.4",
|
|
40
|
+
"ofetch": "^1.5.1"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@hulla/api": "2.0.1",
|
|
44
|
+
"nuxt": "^4.5.2",
|
|
45
|
+
"zod": "^4.4.3"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"@hulla/api": "^2.0.1",
|
|
49
|
+
"nuxt": "^3.0.0 || ^4.0.0"
|
|
50
|
+
},
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=22"
|
|
53
|
+
}
|
|
54
|
+
}
|
package/README.md
DELETED