nuxt-feathers-zod 0.1.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.
Files changed (95) hide show
  1. package/README.md +283 -0
  2. package/dist/module.d.mts +17 -0
  3. package/dist/module.json +12 -0
  4. package/dist/module.mjs +124 -0
  5. package/dist/runtime/adapters/ofetch.d.ts +5 -0
  6. package/dist/runtime/adapters/ofetch.js +18 -0
  7. package/dist/runtime/composables/feathers.d.ts +5 -0
  8. package/dist/runtime/composables/feathers.js +9 -0
  9. package/dist/runtime/composables/pinia.d.ts +1 -0
  10. package/dist/runtime/composables/pinia.js +11 -0
  11. package/dist/runtime/errors.d.ts +3 -0
  12. package/dist/runtime/errors.js +5 -0
  13. package/dist/runtime/options/authentication/client.d.ts +13 -0
  14. package/dist/runtime/options/authentication/client.js +12 -0
  15. package/dist/runtime/options/authentication/index.d.ts +42 -0
  16. package/dist/runtime/options/authentication/index.js +71 -0
  17. package/dist/runtime/options/authentication/jwt-types.d.ts +29 -0
  18. package/dist/runtime/options/authentication/jwt-types.js +0 -0
  19. package/dist/runtime/options/authentication/jwt.d.ts +7 -0
  20. package/dist/runtime/options/authentication/jwt.js +19 -0
  21. package/dist/runtime/options/authentication/local.d.ts +8 -0
  22. package/dist/runtime/options/authentication/local.js +8 -0
  23. package/dist/runtime/options/client/index.d.ts +14 -0
  24. package/dist/runtime/options/client/index.js +33 -0
  25. package/dist/runtime/options/client/pinia.d.ts +14 -0
  26. package/dist/runtime/options/client/pinia.js +22 -0
  27. package/dist/runtime/options/database/index.d.ts +6 -0
  28. package/dist/runtime/options/database/index.js +8 -0
  29. package/dist/runtime/options/database/mongodb.d.ts +12 -0
  30. package/dist/runtime/options/database/mongodb.js +3 -0
  31. package/dist/runtime/options/index.d.ts +44 -0
  32. package/dist/runtime/options/index.js +63 -0
  33. package/dist/runtime/options/plugins.d.ts +20 -0
  34. package/dist/runtime/options/plugins.js +69 -0
  35. package/dist/runtime/options/server.d.ts +7 -0
  36. package/dist/runtime/options/server.js +11 -0
  37. package/dist/runtime/options/services.d.ts +6 -0
  38. package/dist/runtime/options/services.js +13 -0
  39. package/dist/runtime/options/transports/index.d.ts +23 -0
  40. package/dist/runtime/options/transports/index.js +14 -0
  41. package/dist/runtime/options/transports/rest.d.ts +9 -0
  42. package/dist/runtime/options/transports/rest.js +22 -0
  43. package/dist/runtime/options/transports/utils.d.ts +1 -0
  44. package/dist/runtime/options/transports/utils.js +7 -0
  45. package/dist/runtime/options/transports/websocket.d.ts +8 -0
  46. package/dist/runtime/options/transports/websocket.js +17 -0
  47. package/dist/runtime/options/utils.d.ts +11 -0
  48. package/dist/runtime/options/utils.js +22 -0
  49. package/dist/runtime/options/validator.d.ts +13 -0
  50. package/dist/runtime/options/validator.js +29 -0
  51. package/dist/runtime/plugins/feathers-auth.d.ts +11 -0
  52. package/dist/runtime/plugins/feathers-auth.js +13 -0
  53. package/dist/runtime/server/tsconfig.json +3 -0
  54. package/dist/runtime/services.d.ts +4 -0
  55. package/dist/runtime/services.js +14 -0
  56. package/dist/runtime/stores/auth.d.ts +28 -0
  57. package/dist/runtime/stores/auth.js +47 -0
  58. package/dist/runtime/templates/client/authentication.d.ts +2 -0
  59. package/dist/runtime/templates/client/authentication.js +28 -0
  60. package/dist/runtime/templates/client/client.d.ts +2 -0
  61. package/dist/runtime/templates/client/client.js +50 -0
  62. package/dist/runtime/templates/client/connection.d.ts +3 -0
  63. package/dist/runtime/templates/client/connection.js +39 -0
  64. package/dist/runtime/templates/client/index.d.ts +4 -0
  65. package/dist/runtime/templates/client/index.js +33 -0
  66. package/dist/runtime/templates/client/plugin.d.ts +2 -0
  67. package/dist/runtime/templates/client/plugin.js +81 -0
  68. package/dist/runtime/templates/server/authentication.d.ts +2 -0
  69. package/dist/runtime/templates/server/authentication.js +32 -0
  70. package/dist/runtime/templates/server/index.d.ts +3 -0
  71. package/dist/runtime/templates/server/index.js +33 -0
  72. package/dist/runtime/templates/server/mongodb.d.ts +2 -0
  73. package/dist/runtime/templates/server/mongodb.js +26 -0
  74. package/dist/runtime/templates/server/plugin.d.ts +2 -0
  75. package/dist/runtime/templates/server/plugin.js +110 -0
  76. package/dist/runtime/templates/server/server.d.ts +2 -0
  77. package/dist/runtime/templates/server/server.js +61 -0
  78. package/dist/runtime/templates/server/validators.d.ts +2 -0
  79. package/dist/runtime/templates/server/validators.js +30 -0
  80. package/dist/runtime/templates/types.d.ts +6 -0
  81. package/dist/runtime/templates/types.js +0 -0
  82. package/dist/runtime/templates/utils.d.ts +4 -0
  83. package/dist/runtime/templates/utils.js +6 -0
  84. package/dist/runtime/zod/format.d.ts +10 -0
  85. package/dist/runtime/zod/format.js +7 -0
  86. package/dist/runtime/zod/index.d.ts +4 -0
  87. package/dist/runtime/zod/index.js +4 -0
  88. package/dist/runtime/zod/objectId.d.ts +9 -0
  89. package/dist/runtime/zod/objectId.js +17 -0
  90. package/dist/runtime/zod/query.d.ts +43 -0
  91. package/dist/runtime/zod/query.js +75 -0
  92. package/dist/runtime/zod/validators.d.ts +17 -0
  93. package/dist/runtime/zod/validators.js +46 -0
  94. package/dist/types.d.mts +7 -0
  95. package/package.json +111 -0
package/README.md ADDED
@@ -0,0 +1,283 @@
1
+ # nuxt-feathers-zod
2
+
3
+ Nuxt 4 module that embeds a **FeathersJS v5 (Dove)** server into **Nitro** and generates a **typed Feathers client** for your Nuxt app, with **Zod-first validation**.
4
+ It's using and inspired from project **[https://github.com/GaborTorma/feathers-nitro-adapter.git]()**
5
+
6
+ This repository ships a ready-to-run playground (`nuxi dev playground`) and a module you can install in your own Nuxt application.
7
+
8
+ ## Features
9
+
10
+ - FeathersJS v5 server running inside Nitro (no separate server process required)
11
+ - REST transport (Koa or Express) and optional Socket.io (websocket)
12
+ - Zod schemas for data + query validation (server-side)
13
+ - Optional client integration with Pinia stores (via `feathers-pinia`)
14
+ - Generated types for services (`ServiceTypes`) and shared client service registrations (`*.shared.ts`)
15
+
16
+ ## Requirements
17
+
18
+ - Node.js 18+ (or Bun)
19
+ - Nuxt 4
20
+
21
+ ## Install
22
+
23
+ In your Nuxt application:
24
+
25
+ ```bash
26
+ # Bun
27
+ bun add nuxt-feathers-zod feathers-pinia
28
+
29
+ # npm
30
+ npm i nuxt-feathers-zod feathers-pinia
31
+ ```
32
+
33
+ Then enable the module:
34
+
35
+ ```ts
36
+ // nuxt.config.ts
37
+ export default defineNuxtConfig({
38
+ modules: ['nuxt-feathers-zod'],
39
+ })
40
+ ```
41
+
42
+ ## Minimal configuration
43
+
44
+ Below is a minimal configuration that:
45
+
46
+ - exposes Feathers REST under `/feathers` (default)
47
+ - enables websocket (`/socket.io`)
48
+ - enables authentication (local + jwt)
49
+
50
+ ```ts
51
+ // nuxt.config.ts
52
+ export default defineNuxtConfig({
53
+ modules: ['nuxt-feathers-zod'],
54
+ feathers: {
55
+ servicesDirs: ['services'],
56
+ transports: {
57
+ rest: { path: '/feathers', framework: 'koa' },
58
+ websocket: { path: '/socket.io' },
59
+ },
60
+ database: {
61
+ mongo: {
62
+ url: process.env.MONGODB_URL || 'mongodb://127.0.0.1:27017/nuxt-feathers-zod',
63
+ },
64
+ },
65
+ client: {
66
+ pinia: {
67
+ // where Pinia stores will be generated/loaded from (if you use them)
68
+ storesDirs: ['stores'],
69
+ // default id field for services
70
+ idField: 'id',
71
+ // per-service overrides
72
+ services: {
73
+ mongos: { idField: '_id' },
74
+ },
75
+ },
76
+ },
77
+ auth: {
78
+ entity: 'user',
79
+ service: 'users',
80
+ authStrategies: ['local', 'jwt'],
81
+ local: { usernameField: 'userId', passwordField: 'password' },
82
+ // IMPORTANT: always set in production via env
83
+ secret: process.env.AUTH_SECRET || 'dev-secret-change-me',
84
+ },
85
+ },
86
+ })
87
+ ```
88
+
89
+ ## Transport examples
90
+
91
+ ### REST with Koa (default)
92
+
93
+ ```ts
94
+ export default defineNuxtConfig({
95
+ modules: ['nuxt-feathers-zod'],
96
+ feathers: {
97
+ transports: { rest: { framework: 'koa' } },
98
+ },
99
+ })
100
+ ```
101
+
102
+ ### REST with Express
103
+
104
+ ```ts
105
+ export default defineNuxtConfig({
106
+ modules: ['nuxt-feathers-zod'],
107
+ feathers: {
108
+ transports: { rest: { framework: 'express' } },
109
+ },
110
+ })
111
+ ```
112
+
113
+ If you use Express REST, ensure your project includes the Express transport dependencies (Feathers server side):
114
+
115
+ ```bash
116
+ bun add @feathersjs/express express
117
+ ```
118
+
119
+ ### WebSocket with Socket.io
120
+
121
+ ```ts
122
+ export default defineNuxtConfig({
123
+ modules: ['nuxt-feathers-zod'],
124
+ feathers: {
125
+ transports: {
126
+ websocket: { path: '/socket.io', connectTimeout: 45_000 },
127
+ },
128
+ },
129
+ })
130
+ ```
131
+
132
+ When both REST and websocket are enabled, the generated client typically uses REST on SSR and websocket in the browser.
133
+
134
+ ## Service structure
135
+
136
+ Services live in `services/**` and follow this convention:
137
+
138
+ - `services/<name>/<name>.class.ts` – Feathers service class (MongoDB, memory, custom, ...)
139
+ - `services/<name>/<name>.schema.ts` – Zod schemas + Feathers resolvers
140
+ - `services/<name>/<name>.ts` – service registration + hooks
141
+ - `services/<name>/<name>.shared.ts` – client registration (used by generator)
142
+
143
+ ## Using the generated client in your app
144
+
145
+ The module injects a typed Feathers client as `nuxtApp.$api`.
146
+
147
+ ```ts
148
+ // example: in a component or composable
149
+ const { $api } = useNuxtApp()
150
+
151
+ // typed service access (if you generated types)
152
+ const users = $api.service('users')
153
+ const list = await users.find({ query: {} })
154
+ ```
155
+
156
+ ## Authentication: testing with curl
157
+
158
+ Create a user:
159
+
160
+ ```bash
161
+ curl -i -X POST "http://localhost:3000/feathers/users" \
162
+ -H "Content-Type: application/json" \
163
+ -d '{"userId":"demo","password":"demo123"}'
164
+ ```
165
+
166
+ Authenticate:
167
+
168
+ ```bash
169
+ curl -i -X POST "http://localhost:3000/feathers/authentication" \
170
+ -H "Content-Type: application/json" \
171
+ -d '{"strategy":"local","userId":"demo","password":"demo123"}'
172
+ ```
173
+
174
+ Use the JWT to call a protected endpoint:
175
+
176
+ ```bash
177
+ curl -i "http://localhost:3000/feathers/users" \
178
+ -H "Authorization: Bearer <ACCESS_TOKEN>"
179
+ ```
180
+
181
+ ## Playground
182
+
183
+ Run the playground:
184
+
185
+ ```bash
186
+ bun install
187
+ bun run dev
188
+ ```
189
+
190
+ Open:
191
+
192
+ - Nuxt app: `http://localhost:3000/`
193
+ - Feathers REST: `http://localhost:3000/feathers/*`
194
+
195
+ ### End-to-end smoke test (REST + auth)
196
+
197
+ Once the dev server is up, run the following commands in a terminal.
198
+
199
+ Create a user:
200
+
201
+ ```bash
202
+ curl -i -X POST "http://localhost:3000/feathers/users" \
203
+ -H "Content-Type: application/json" \
204
+ -d '{"userId":"demo","password":"demo123"}'
205
+ ```
206
+
207
+ Authenticate (local strategy):
208
+
209
+ ```bash
210
+ curl -i -X POST "http://localhost:3000/feathers/authentication" \
211
+ -H "Content-Type: application/json" \
212
+ -d '{"strategy":"local","userId":"demo","password":"demo123"}'
213
+ ```
214
+
215
+ Copy the `accessToken` from the JSON response, then call a protected route:
216
+
217
+ ```bash
218
+ curl -i "http://localhost:3000/feathers/users" \
219
+ -H "Authorization: Bearer <ACCESS_TOKEN>"
220
+ ```
221
+
222
+ Expected:
223
+
224
+ - `POST /feathers/users` returns `201`
225
+ - `POST /feathers/authentication` returns `201` and an `accessToken`
226
+ - `GET /feathers/users` returns `200` when `Authorization: Bearer ...` is provided
227
+
228
+ ### WebSocket smoke test (Socket.io)
229
+
230
+ If you enabled `transports.websocket`, you can test websocket connectivity with a tiny script.
231
+
232
+ ```bash
233
+ # from the repo root
234
+ bun -e "
235
+ import { io } from 'socket.io-client'
236
+ const socket = io('http://localhost:3000', { path: '/socket.io', transports: ['websocket'] })
237
+ socket.on('connect', async () => {
238
+ console.log('connected', socket.id)
239
+ socket.disconnect()
240
+ process.exit(0)
241
+ })
242
+ socket.on('connect_error', (e) => {
243
+ console.error('connect_error', e?.message || e)
244
+ process.exit(1)
245
+ })
246
+ "
247
+ ```
248
+
249
+ If you want to test authenticated websocket calls, use `@feathersjs/socketio-client` in a small script (see `playground/` for a browser-first example).
250
+
251
+ ## Publishing to npm
252
+
253
+ This repository is a Nuxt module. The published package should only contain the compiled output (see `files: ["dist"]` in `package.json`).
254
+
255
+ Recommended flow:
256
+
257
+ ```bash
258
+ # 1) install
259
+ bun install
260
+
261
+ # 2) run unit + type tests
262
+ bun run test:types
263
+ bun run test
264
+
265
+ # 3) build the module (produces ./dist)
266
+ bun run prepare
267
+
268
+ # 4) publish (from the repo root)
269
+ npm publish --access public
270
+ ```
271
+
272
+ Notes:
273
+
274
+ - Keep Feathers packages aligned (single version across the workspace). This repo uses `overrides` for that purpose.
275
+ - Do not publish `playground/` build artifacts (`playground/.nuxt`, `playground/node_modules`).
276
+
277
+ ## Notes about SSR and Pinia auth bootstrap
278
+
279
+ The runtime auth bootstrap (`src/runtime/plugins/feathers-auth.ts`) re-authenticates **client-side only** to avoid SSR startup failures when the Feathers client is not yet injected.
280
+
281
+ ## License
282
+
283
+ MIT
@@ -0,0 +1,17 @@
1
+ import * as _nuxt_schema from '@nuxt/schema';
2
+ import { ModuleConfig, FeathersRuntimeConfig, FeathersPublicRuntimeConfig, ModuleOptions } from '../dist/runtime/options/index.js';
3
+
4
+ declare module '@nuxt/schema' {
5
+ interface NuxtConfig {
6
+ feathers?: ModuleConfig;
7
+ }
8
+ interface RuntimeConfig {
9
+ _feathers: FeathersRuntimeConfig;
10
+ }
11
+ interface PublicRuntimeConfig {
12
+ _feathers: FeathersPublicRuntimeConfig;
13
+ }
14
+ }
15
+ declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
16
+
17
+ export { _default as default };
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "nuxt-feathers-zod",
3
+ "configKey": "feathers",
4
+ "compatibility": {
5
+ "nuxt": "^4.0.0"
6
+ },
7
+ "version": "0.1.0",
8
+ "builder": {
9
+ "@nuxt/module-builder": "1.0.2",
10
+ "unbuild": "3.6.1"
11
+ }
12
+ }
@@ -0,0 +1,124 @@
1
+ import { defineNuxtModule, createResolver, addImportsDir, addTemplate, addServerPlugin, addImports, addPlugin, hasNuxtModule, installModule } from '@nuxt/kit';
2
+ import { consola } from 'consola';
3
+ import defu from 'defu';
4
+ import { resolveOptions, resolveRuntimeConfig, resolvePublicRuntimeConfig } from '../dist/runtime/options/index.js';
5
+ import { serverDefaults } from '../dist/runtime/options/server.js';
6
+ import { getServicesImports, addServicesImports } from '../dist/runtime/services.js';
7
+ import { getClientTemplates } from '../dist/runtime/templates/client/index.js';
8
+ import { getServerTemplates } from '../dist/runtime/templates/server/index.js';
9
+
10
+ function setAliases(options, nuxt) {
11
+ const resolver = createResolver(import.meta.url);
12
+ const aliases = {
13
+ "nuxt-feathers-zod/server": resolver.resolve(options.templateDir, "server/server"),
14
+ "nuxt-feathers-zod/validators": resolver.resolve("runtime/zod/validators"),
15
+ "nuxt-feathers-zod/query": resolver.resolve("runtime/zod/query"),
16
+ "nuxt-feathers-zod/zod": resolver.resolve("runtime/zod/index"),
17
+ "nuxt-feathers-zod/options": resolver.resolve("runtime/options")
18
+ };
19
+ nuxt.options.alias = defu(nuxt.options.alias, aliases);
20
+ if (options.client)
21
+ nuxt.options.alias["nuxt-feathers-zod/client"] = resolver.resolve(options.templateDir, "client/client");
22
+ nuxt.hook("nitro:config", async (nitroConfig) => {
23
+ nitroConfig.alias = defu(nitroConfig.alias, aliases);
24
+ });
25
+ }
26
+ function setTsIncludes(options, nuxt) {
27
+ const resolver = createResolver(import.meta.url);
28
+ const servicesDirs = options.servicesDirs.map((dir) => resolver.resolve(dir, "**/*.ts"));
29
+ nuxt.hook("prepare:types", async ({ tsConfig }) => {
30
+ tsConfig.include?.push(...servicesDirs);
31
+ });
32
+ nuxt.hook("nitro:config", (nitroConfig) => {
33
+ nitroConfig.typescript?.tsConfig?.include?.push(...servicesDirs);
34
+ });
35
+ }
36
+ async function loadPinia(client) {
37
+ const storesDirs = client.pinia?.storesDirs;
38
+ if (storesDirs?.length) {
39
+ if (hasNuxtModule("@pinia/nuxt"))
40
+ return consola.warn("Pinia is already loaded, skipping your configuration");
41
+ await installModule("@pinia/nuxt", { storesDirs });
42
+ }
43
+ if (!hasNuxtModule("@pinia/nuxt"))
44
+ await installModule("@pinia/nuxt");
45
+ }
46
+ const module$1 = defineNuxtModule({
47
+ meta: {
48
+ name: "nuxt-feathers-zod",
49
+ configKey: "feathers",
50
+ compatibility: {
51
+ nuxt: "^4.0.0"
52
+ }
53
+ },
54
+ // Default configuration options of the Nuxt module
55
+ defaults: {
56
+ transports: {
57
+ websocket: true
58
+ },
59
+ server: serverDefaults,
60
+ client: true,
61
+ servicesDirs: [],
62
+ validator: {
63
+ formats: [],
64
+ extendDefaults: true
65
+ },
66
+ loadFeathersConfig: false,
67
+ auth: true
68
+ },
69
+ async setup(options, nuxt) {
70
+ const resolver = createResolver(import.meta.url);
71
+ const resolvedOptions = await resolveOptions(options, nuxt);
72
+ nuxt.options.runtimeConfig._feathers = resolveRuntimeConfig(resolvedOptions);
73
+ nuxt.options.runtimeConfig.public._feathers = resolvePublicRuntimeConfig(resolvedOptions);
74
+ const servicesImports = await getServicesImports(resolvedOptions.servicesDirs);
75
+ await addServicesImports(servicesImports);
76
+ setAliases(resolvedOptions, nuxt);
77
+ setTsIncludes(resolvedOptions, nuxt);
78
+ if (resolvedOptions.transports.websocket) {
79
+ nuxt.hook("nitro:config", (nitroConfig) => {
80
+ nitroConfig.experimental = defu(nitroConfig.experimental, { websocket: true });
81
+ });
82
+ }
83
+ addImportsDir(resolver.resolve("./runtime/composables"));
84
+ let serverPluginDst;
85
+ for (const serverTemplate of getServerTemplates(resolvedOptions)) {
86
+ const tpl = addTemplate({ ...serverTemplate, options: resolvedOptions });
87
+ if (serverTemplate.filename?.endsWith("server/plugin.ts") || serverTemplate.filename?.endsWith("server/plugin"))
88
+ serverPluginDst = tpl.dst;
89
+ }
90
+ addServerPlugin(serverPluginDst ?? resolver.resolve(resolvedOptions.templateDir, "server/plugin.ts"));
91
+ if (resolvedOptions.client) {
92
+ const clientOptions = resolvedOptions.client;
93
+ if (clientOptions.pinia) {
94
+ await loadPinia(clientOptions);
95
+ nuxt.hook("vite:extendConfig", (config) => {
96
+ config.optimizeDeps?.include?.push("feathers-pinia");
97
+ });
98
+ if (resolvedOptions.auth) {
99
+ addImports({ from: resolver.resolve("./runtime/stores/auth"), name: "useAuthStore" });
100
+ addPlugin({ order: 1, src: resolver.resolve("./runtime/plugins/feathers-auth") });
101
+ }
102
+ }
103
+ let clientPluginDst;
104
+ for (const clientTemplate of getClientTemplates(resolvedOptions, resolver)) {
105
+ const tpl = addTemplate({ ...clientTemplate, options: resolvedOptions });
106
+ if (clientTemplate.filename?.endsWith("client/plugin.ts") || clientTemplate.filename?.endsWith("client/plugin"))
107
+ clientPluginDst = tpl.dst;
108
+ }
109
+ addPlugin({ order: 0, src: clientPluginDst ?? resolver.resolve(resolvedOptions.templateDir, "client/plugin.ts"), mode: "client" });
110
+ }
111
+ nuxt.hook("mcp:setup", ({ mcp }) => {
112
+ mcp.tool("get-feathers-config", "Get the Feathers config", {}, async () => {
113
+ return {
114
+ content: [{
115
+ type: "text",
116
+ text: JSON.stringify(resolvedOptions, null, 2)
117
+ }]
118
+ };
119
+ });
120
+ });
121
+ }
122
+ });
123
+
124
+ export { module$1 as default };
@@ -0,0 +1,5 @@
1
+ import type { Params } from '@feathersjs/feathers';
2
+ import { FetchClient } from '@feathersjs/rest-client';
3
+ export declare class OFetch extends FetchClient {
4
+ request(options: any, params: Params): Promise<any>;
5
+ }
@@ -0,0 +1,18 @@
1
+ import { FetchClient } from "@feathersjs/rest-client";
2
+ export class OFetch extends FetchClient {
3
+ async request(options, params) {
4
+ const fetchOptions = Object.assign({}, options, params.connection);
5
+ fetchOptions.headers = Object.assign({ Accept: "application/json" }, this.options.headers, fetchOptions.headers);
6
+ if (options.body)
7
+ fetchOptions.body = options.body;
8
+ try {
9
+ const response = await this.connection.raw(options.url, fetchOptions);
10
+ const { _data, status } = response;
11
+ if (status === 204)
12
+ return null;
13
+ return _data;
14
+ } catch (error) {
15
+ throw error.data;
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,5 @@
1
+ import type { ServiceTypes } from 'nuxt-feathers-zod/client';
2
+ export declare function useFeathers(): {
3
+ api: import("feathers-pinia").FeathersPiniaClient<import("nuxt-feathers-zod/client").ClientApplication>;
4
+ };
5
+ export declare function useService<L extends keyof ServiceTypes>(path: L): import("@feathersjs/feathers").FeathersService<import("feathers-pinia").FeathersPiniaClient<import("nuxt-feathers-zod/client").ClientApplication>, import("feathers-pinia").CreatePiniaServiceTypes<import("nuxt-feathers-zod/client").ClientApplication>[L]>;
@@ -0,0 +1,9 @@
1
+ import { useNuxtApp } from "#imports";
2
+ export function useFeathers() {
3
+ const { $api: api } = useNuxtApp();
4
+ return { api };
5
+ }
6
+ export function useService(path) {
7
+ const { api } = useFeathers();
8
+ return api.service(path);
9
+ }
@@ -0,0 +1 @@
1
+ export { createPiniaClient, defineGetters, defineSetters, defineValues, useAuth, useBackup, useDataStore, useInstanceDefaults, useServiceInstance, } from 'feathers-pinia';
@@ -0,0 +1,11 @@
1
+ export {
2
+ createPiniaClient,
3
+ defineGetters,
4
+ defineSetters,
5
+ defineValues,
6
+ useAuth,
7
+ useBackup,
8
+ useDataStore,
9
+ useInstanceDefaults,
10
+ useServiceInstance
11
+ } from "feathers-pinia";
@@ -0,0 +1,3 @@
1
+ export declare class NuxtFeathersError extends Error {
2
+ constructor(message?: string);
3
+ }
@@ -0,0 +1,5 @@
1
+ export class NuxtFeathersError extends Error {
2
+ constructor(message) {
3
+ super(`[nuxt-feathers-zod]: ${message}`);
4
+ }
5
+ }
@@ -0,0 +1,13 @@
1
+ import type { AuthStrategies } from '.';
2
+ export interface AuthClientOptions {
3
+ header?: string;
4
+ scheme?: string;
5
+ storageKey?: string;
6
+ locationKey?: string;
7
+ locationErrorKey?: string;
8
+ jwtStrategy?: string;
9
+ path?: string;
10
+ }
11
+ export type ResolvedAuthClientOptions = AuthClientOptions;
12
+ export declare function getAuthClientDefaults(authStrategies: AuthStrategies): ResolvedAuthClientOptions;
13
+ export declare function resolveAuthClientOptions(authClient: AuthClientOptions | undefined, authStrategies: AuthStrategies): ResolvedAuthClientOptions;
@@ -0,0 +1,12 @@
1
+ import defu from "defu";
2
+ import { getAuthClientJwtDefaults } from "./jwt.js";
3
+ export function getAuthClientDefaults(authStrategies) {
4
+ if (!authStrategies.includes("jwt"))
5
+ return {};
6
+ return getAuthClientJwtDefaults();
7
+ }
8
+ export function resolveAuthClientOptions(authClient, authStrategies) {
9
+ const defaultAuthClient = getAuthClientDefaults(authStrategies);
10
+ const resolvedAuthClient = defu(authClient || {}, defaultAuthClient);
11
+ return resolvedAuthClient;
12
+ }
@@ -0,0 +1,42 @@
1
+ import type { Import } from 'unimport';
2
+ import type { ModuleOptions } from '..';
3
+ import type { AuthClientOptions } from './client.js';
4
+ import type { AuthJwtOptions } from './jwt.js';
5
+ import type { AuthLocalOptions } from './local.js';
6
+ export type AuthStrategy = 'jwt' | 'local';
7
+ export type AuthStrategies = [AuthStrategy] | [AuthStrategy, AuthStrategy];
8
+ export interface StaticAuthOptions {
9
+ service: string;
10
+ entity: string;
11
+ entityClass: string;
12
+ }
13
+ export interface DefaultAuthOptions extends StaticAuthOptions {
14
+ authStrategies: AuthStrategies;
15
+ secret: string;
16
+ entityImport?: Import;
17
+ }
18
+ export interface AdditionalAuthOptions {
19
+ jwtOptions?: AuthJwtOptions;
20
+ local?: AuthLocalOptions;
21
+ client?: AuthClientOptions;
22
+ }
23
+ export type AuthOptions = Partial<DefaultAuthOptions> & AdditionalAuthOptions;
24
+ export interface ResolvedAuthOptions extends DefaultAuthOptions, AdditionalAuthOptions {
25
+ entityImport: Import;
26
+ }
27
+ export type ResolvedAuthOptionsOrDisabled = ResolvedAuthOptions | false;
28
+ export type ResolvedAuthOptionsWithOutEntityImport = Omit<ResolvedAuthOptions, 'entityImport'>;
29
+ export interface PublicAuthOptions {
30
+ authStrategies: AuthStrategies;
31
+ servicePath: string;
32
+ entityKey: string;
33
+ entityClass: string;
34
+ client: AuthClientOptions;
35
+ }
36
+ export declare const authStaticDefaults: StaticAuthOptions;
37
+ export declare function getAuthStaticDefaults(): StaticAuthOptions;
38
+ export declare const defaultAuthStrategies: AuthStrategies;
39
+ export declare function getDefaultAuthStrategies(): AuthStrategies;
40
+ export declare function getAuthDefaults(appDir: string, authStrategies?: AuthStrategies): ResolvedAuthOptionsWithOutEntityImport;
41
+ export declare const authClientDefaultOptions: AuthClientOptions;
42
+ export declare function resolveAuthOptions(auth: ModuleOptions['auth'], client: boolean, servicesImports: Import[], appDir: string): ResolvedAuthOptionsOrDisabled;
@@ -0,0 +1,71 @@
1
+ import { capitalCase } from "change-case";
2
+ import defu from "defu";
3
+ import { klona } from "klona";
4
+ import { digest } from "ohash";
5
+ import { NuxtFeathersError } from "../../errors.js";
6
+ import { resolveAuthClientOptions } from "./client.js";
7
+ import { getAuthJwtDefaults } from "./jwt.js";
8
+ import { getAuthLocalDefaults } from "./local.js";
9
+ export const authStaticDefaults = {
10
+ entity: "user",
11
+ entityClass: "User",
12
+ service: "users"
13
+ };
14
+ export function getAuthStaticDefaults() {
15
+ return klona(authStaticDefaults);
16
+ }
17
+ export const defaultAuthStrategies = ["local", "jwt"];
18
+ export function getDefaultAuthStrategies() {
19
+ return klona(defaultAuthStrategies);
20
+ }
21
+ export function getAuthDefaults(appDir, authStrategies) {
22
+ authStrategies ||= getDefaultAuthStrategies();
23
+ const authOptions = {
24
+ ...getAuthStaticDefaults(),
25
+ secret: digest(appDir),
26
+ authStrategies
27
+ };
28
+ if (authStrategies.includes("jwt"))
29
+ authOptions.jwtOptions = getAuthJwtDefaults();
30
+ if (authStrategies.includes("local"))
31
+ authOptions.local = getAuthLocalDefaults();
32
+ return authOptions;
33
+ }
34
+ function getEntityClass(authOptions) {
35
+ return authOptions.entityClass || capitalCase(authOptions.entity || "") || authStaticDefaults.entityClass;
36
+ }
37
+ export const authClientDefaultOptions = {
38
+ storageKey: "feathers-jwt"
39
+ };
40
+ export function resolveAuthOptions(auth, client, servicesImports, appDir) {
41
+ if (auth === false)
42
+ return false;
43
+ let authOptions;
44
+ const authDefaults = getAuthDefaults(appDir, auth?.authStrategies);
45
+ if (auth === true) {
46
+ authOptions = authDefaults;
47
+ } else {
48
+ authOptions = defu(auth, authDefaults);
49
+ authOptions.authStrategies = authDefaults.authStrategies;
50
+ if (!authOptions.authStrategies?.includes("jwt"))
51
+ delete authOptions.jwtOptions;
52
+ if (!authOptions.authStrategies?.includes("local"))
53
+ delete authOptions.local;
54
+ }
55
+ if (client)
56
+ authOptions.client = resolveAuthClientOptions(authOptions.client, authOptions.authStrategies);
57
+ else
58
+ delete authOptions.client;
59
+ const entityClass = getEntityClass(auth);
60
+ const entityImport = servicesImports.find((i) => i.as === entityClass);
61
+ if (!entityImport)
62
+ throw new NuxtFeathersError(`Entity class ${entityClass} not found in services imports`);
63
+ entityImport.from = entityImport.from.replace(/\.ts$/, "");
64
+ const resolvedAuth = {
65
+ ...authOptions,
66
+ entityClass,
67
+ entityImport
68
+ };
69
+ console.log(resolvedAuth);
70
+ return resolvedAuth;
71
+ }
@@ -0,0 +1,29 @@
1
+ export type Algorithm = 'HS256' | 'HS384' | 'HS512' | 'RS256' | 'RS384' | 'RS512' | 'ES256' | 'ES384' | 'ES512' | 'PS256' | 'PS384' | 'PS512' | 'none';
2
+ export interface JwtHeader {
3
+ 'alg': string | Algorithm;
4
+ 'typ'?: string | undefined;
5
+ 'cty'?: string | undefined;
6
+ 'crit'?: Array<string | Exclude<keyof JwtHeader, 'crit'>> | undefined;
7
+ 'kid'?: string | undefined;
8
+ 'jku'?: string | undefined;
9
+ 'x5u'?: string | string[] | undefined;
10
+ 'x5t#S256'?: string | undefined;
11
+ 'x5t'?: string | undefined;
12
+ 'x5c'?: string | string[] | undefined;
13
+ }
14
+ export interface SignOptions {
15
+ algorithm?: Algorithm | undefined;
16
+ keyid?: string | undefined;
17
+ expiresIn?: string | number;
18
+ notBefore?: string | number | undefined;
19
+ audience?: string | string[] | undefined;
20
+ subject?: string | undefined;
21
+ issuer?: string | undefined;
22
+ jwtid?: string | undefined;
23
+ mutatePayload?: boolean | undefined;
24
+ noTimestamp?: boolean | undefined;
25
+ header?: JwtHeader | undefined;
26
+ encoding?: string | undefined;
27
+ allowInsecureKeySizes?: boolean | undefined;
28
+ allowInvalidAsymmetricKeyTypes?: boolean | undefined;
29
+ }