@tuyau/core 1.0.0-beta.8 → 1.0.0-next.17

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/README.md CHANGED
@@ -1,2 +1,11 @@
1
1
  # @tuyau/core
2
2
 
3
+ Core package for Tuyau. Includes the backend integration and the E2E typesafe client to consume your AdonisJS APIs.
4
+
5
+ ## Documentation
6
+
7
+ Available soon.
8
+
9
+ ## License
10
+
11
+ MIT
@@ -1,7 +1,190 @@
1
+ /**
2
+ * Extending the HTTP response interface to include status and response
3
+ * in the return type.
4
+ *
5
+ * This is ONLY type information and the properties will not be available
6
+ * at runtime. This is needed to infer the correct response type
7
+ */
8
+
9
+ declare module '@adonisjs/core/http' {
10
+ interface HttpResponse {
11
+ continue(): {
12
+ __status: 100;
13
+ };
14
+ switchingProtocols(etag?: boolean): {
15
+ __status: 101;
16
+ };
17
+ ok<T>(body: T, etag?: boolean): {
18
+ __response: T;
19
+ __status: 200;
20
+ };
21
+ created<T>(body?: T, etag?: boolean): {
22
+ __response: T;
23
+ __status: 201;
24
+ };
25
+ accepted<T>(body: T, etag?: boolean): {
26
+ __response: T;
27
+ __status: 202;
28
+ };
29
+ nonAuthoritativeInformation<T>(body?: T, etag?: boolean): {
30
+ __response: T;
31
+ __status: 203;
32
+ };
33
+ noContent<T>(body?: T, etag?: boolean): {
34
+ __response: T;
35
+ __status: 204;
36
+ };
37
+ resetContent<T>(body?: T, etag?: boolean): {
38
+ __response: T;
39
+ __status: 205;
40
+ };
41
+ partialContent<T>(body: T, etag?: boolean): {
42
+ __response: T;
43
+ __status: 206;
44
+ };
45
+ multipleChoices<T>(body?: T, etag?: boolean): {
46
+ __response: T;
47
+ __status: 300;
48
+ };
49
+ movedPermanently<T>(body?: T, etag?: boolean): {
50
+ __response: T;
51
+ __status: 301;
52
+ };
53
+ movedTemporarily<T>(body?: T, etag?: boolean): {
54
+ __response: T;
55
+ __status: 302;
56
+ };
57
+ seeOther<T>(body?: T, etag?: boolean): {
58
+ __response: T;
59
+ __status: 303;
60
+ };
61
+ notModified<T>(body?: T, etag?: boolean): {
62
+ __response: T;
63
+ __status: 304;
64
+ };
65
+ useProxy<T>(body?: T, etag?: boolean): {
66
+ __response: T;
67
+ __status: 305;
68
+ };
69
+ temporaryRedirect<T>(body?: T, etag?: boolean): {
70
+ __response: T;
71
+ __status: 307;
72
+ };
73
+ badRequest<T>(body?: T, etag?: boolean): {
74
+ __response: T;
75
+ __status: 400;
76
+ };
77
+ unauthorized<T>(body?: T, etag?: boolean): {
78
+ __response: T;
79
+ __status: 401;
80
+ };
81
+ paymentRequired<T>(body?: T, etag?: boolean): {
82
+ __response: T;
83
+ __status: 402;
84
+ };
85
+ forbidden<T>(body?: T, etag?: boolean): {
86
+ __response: T;
87
+ __status: 403;
88
+ };
89
+ notFound<T>(body?: T, etag?: boolean): {
90
+ __response: T;
91
+ __status: 404;
92
+ };
93
+ methodNotAllowed<T>(body?: T, etag?: boolean): {
94
+ __response: T;
95
+ __status: 405;
96
+ };
97
+ notAcceptable<T>(body?: T, etag?: boolean): {
98
+ __response: T;
99
+ __status: 406;
100
+ };
101
+ proxyAuthenticationRequired<T>(body?: T, etag?: boolean): {
102
+ __response: T;
103
+ __status: 407;
104
+ };
105
+ requestTimeout<T>(body?: T, etag?: boolean): {
106
+ __response: T;
107
+ __status: 408;
108
+ };
109
+ conflict<T>(body?: T, etag?: boolean): {
110
+ __response: T;
111
+ __status: 409;
112
+ };
113
+ gone<T>(body?: T, etag?: boolean): {
114
+ __response: T;
115
+ __status: 410;
116
+ };
117
+ lengthRequired<T>(body?: T, etag?: boolean): {
118
+ __response: T;
119
+ __status: 411;
120
+ };
121
+ preconditionFailed<T>(body?: T, etag?: boolean): {
122
+ __response: T;
123
+ __status: 412;
124
+ };
125
+ requestEntityTooLarge<T>(body?: T, etag?: boolean): {
126
+ __response: T;
127
+ __status: 413;
128
+ };
129
+ requestUriTooLong<T>(body?: T, etag?: boolean): {
130
+ __response: T;
131
+ __status: 414;
132
+ };
133
+ unsupportedMediaType<T>(body?: T, etag?: boolean): {
134
+ __response: T;
135
+ __status: 415;
136
+ };
137
+ requestedRangeNotSatisfiable<T>(body?: T, etag?: boolean): {
138
+ __response: T;
139
+ __status: 416;
140
+ };
141
+ expectationFailed<T>(body?: T, etag?: boolean): {
142
+ __response: T;
143
+ __status: 417;
144
+ };
145
+ unprocessableEntity<T>(body?: T, etag?: boolean): {
146
+ __response: T;
147
+ __status: 422;
148
+ };
149
+ tooManyRequests<T>(body?: T, etag?: boolean): {
150
+ __response: T;
151
+ __status: 429;
152
+ };
153
+ internalServerError<T>(body?: T, etag?: boolean): {
154
+ __response: T;
155
+ __status: 500;
156
+ };
157
+ notImplemented<T>(body?: T, etag?: boolean): {
158
+ __response: T;
159
+ __status: 501;
160
+ };
161
+ badGateway<T>(body?: T, etag?: boolean): {
162
+ __response: T;
163
+ __status: 502;
164
+ };
165
+ serviceUnavailable<T>(body?: T, etag?: boolean): {
166
+ __response: T;
167
+ __status: 503;
168
+ };
169
+ gatewayTimeout<T>(body?: T, etag?: boolean): {
170
+ __response: T;
171
+ __status: 504;
172
+ };
173
+ httpVersionNotSupported<T>(body?: T, etag?: boolean): {
174
+ __response: T;
175
+ __status: 505;
176
+ };
177
+ json<T>(body: T, generateEtag?: boolean): {
178
+ __response: T;
179
+ __status: 200;
180
+ };
181
+ }
182
+ }
183
+
1
184
  interface GenerateRegistryConfig {
2
185
  /**
3
- * Path to write the generated registry file
4
- * @default ./.adonisjs/client/registry.ts
186
+ * Path to write the generated registry directory
187
+ * @default ./.adonisjs/client/registry
5
188
  */
6
189
  output?: string;
7
190
  /**
@@ -1,6 +1,10 @@
1
+ // src/backend/types.ts
2
+ import "@adonisjs/core/http";
3
+
1
4
  // src/backend/generate_registry.ts
2
5
  import { dirname } from "path";
3
6
  import { writeFile, mkdir } from "fs/promises";
7
+ import stringHelpers from "@adonisjs/core/helpers/string";
4
8
  async function writeOutputFile(filePath, content) {
5
9
  const dir = dirname(filePath);
6
10
  await mkdir(dir, { recursive: true });
@@ -29,26 +33,34 @@ function filterRoute(route, filters) {
29
33
  }
30
34
  function generateRouteParams(route) {
31
35
  const dynamicParams = route.tokens.filter((token) => token.type === 1);
32
- const paramsType = dynamicParams.map((token) => `${token.val}: string`).join("; ");
33
- const paramsTuple = dynamicParams.map(() => "string").join(", ");
36
+ const paramsType = dynamicParams.map((token) => `${token.val}: ParamValue`).join("; ");
37
+ const paramsTuple = dynamicParams.map(() => "ParamValue").join(", ");
34
38
  return { paramsType, paramsTuple };
35
39
  }
36
- function toCamelCase(str) {
37
- return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
38
- }
39
40
  function buildTreeStructure(routes) {
40
41
  const tree = /* @__PURE__ */ new Map();
41
42
  for (const route of routes) {
42
43
  const segments = route.name.split(".");
43
44
  let current = tree;
44
45
  for (let i = 0; i < segments.length; i++) {
45
- const segment = toCamelCase(segments[i]);
46
+ const segment = stringHelpers.camelCase(segments[i]);
46
47
  const isLast = i === segments.length - 1;
47
48
  if (isLast) {
48
- current.set(segment, { routeName: route.name, route });
49
+ if (current.has(segment) && current.get(segment) instanceof Map) {
50
+ current.get(segment).set("$self", { routeName: route.name, route });
51
+ } else {
52
+ current.set(segment, { routeName: route.name, route });
53
+ }
49
54
  } else {
50
55
  if (!current.has(segment)) {
51
56
  current.set(segment, /* @__PURE__ */ new Map());
57
+ } else {
58
+ const existing = current.get(segment);
59
+ if (!(existing instanceof Map)) {
60
+ const newMap = /* @__PURE__ */ new Map();
61
+ newMap.set("$self", existing);
62
+ current.set(segment, newMap);
63
+ }
52
64
  }
53
65
  current = current.get(segment);
54
66
  }
@@ -60,10 +72,18 @@ function generateTreeInterface(tree, indent = 2) {
60
72
  const spaces = " ".repeat(indent);
61
73
  const lines = [];
62
74
  for (const [key, value] of tree) {
75
+ if (key === "$self") continue;
63
76
  if (value instanceof Map) {
64
- lines.push(`${spaces}${key}: {`);
65
- lines.push(generateTreeInterface(value, indent + 2));
66
- lines.push(`${spaces}}`);
77
+ const selfRoute = value.get("$self");
78
+ if (selfRoute) {
79
+ lines.push(`${spaces}${key}: typeof routes['${selfRoute.routeName}'] & {`);
80
+ lines.push(generateTreeInterface(value, indent + 2));
81
+ lines.push(`${spaces}}`);
82
+ } else {
83
+ lines.push(`${spaces}${key}: {`);
84
+ lines.push(generateTreeInterface(value, indent + 2));
85
+ lines.push(`${spaces}}`);
86
+ }
67
87
  } else {
68
88
  lines.push(`${spaces}${key}: typeof routes['${value.routeName}']`);
69
89
  }
@@ -73,21 +93,25 @@ function generateTreeInterface(tree, indent = 2) {
73
93
  function normalizeImportPaths(typeString) {
74
94
  return typeString.replace(/import\('app\//g, "import('#app/").replace(/\.ts'\)/g, "')");
75
95
  }
96
+ function sanitizeTokens(tokens) {
97
+ return tokens.map(({ old, type, val, end }) => ({ old, type, val, end }));
98
+ }
76
99
  function generateRuntimeRegistryEntry(route) {
77
100
  const routeName = route.name;
101
+ const sanitizedTokens = sanitizeTokens(route.tokens);
78
102
  return ` '${routeName}': {
79
103
  methods: ${JSON.stringify(route.methods)},
80
104
  pattern: '${route.pattern}',
81
- tokens: ${JSON.stringify(route.tokens)},
105
+ tokens: ${JSON.stringify(sanitizedTokens)},
82
106
  types: placeholder as Registry['${routeName}']['types'],
83
107
  }`;
84
108
  }
85
109
  function wrapResponseType(responseType) {
86
110
  if (responseType === "unknown" || responseType === "{}") return responseType;
87
111
  if (responseType.startsWith("ReturnType<")) {
88
- return `Awaited<${responseType}>`;
112
+ return `ExtractResponse<Awaited<${responseType}>>`;
89
113
  }
90
- return responseType;
114
+ return `ExtractResponse<${responseType}>`;
91
115
  }
92
116
  function determineBodyAndQueryTypes(options) {
93
117
  const { methods, requestType } = options;
@@ -98,7 +122,7 @@ function determineBodyAndQueryTypes(options) {
98
122
  return { bodyType: "{}", queryType: "{}" };
99
123
  }
100
124
  if (isGetLike) {
101
- return { bodyType: "{}", queryType: requestType };
125
+ return { bodyType: "{}", queryType: `ExtractQueryForGet<${requestType}>` };
102
126
  }
103
127
  return {
104
128
  bodyType: `ExtractBody<${requestType}>`,
@@ -130,8 +154,8 @@ function generateRuntimeContent(routes) {
130
154
  const registryEntries = routes.map(generateRuntimeRegistryEntry).join(",\n");
131
155
  return `/* eslint-disable prettier/prettier */
132
156
  import type { AdonisEndpoint } from '@tuyau/core/types'
133
- import type { Registry } from './registry.schema.d.ts'
134
- import type { ApiDefinition } from './registry.schema.tree.d.ts'
157
+ import type { Registry } from './schema.d.ts'
158
+ import type { ApiDefinition } from './tree.d.ts'
135
159
 
136
160
  const placeholder: any = {}
137
161
 
@@ -158,7 +182,7 @@ function generateTreeContent(routes) {
158
182
  const tree = buildTreeStructure(routes);
159
183
  const treeInterface = generateTreeInterface(tree);
160
184
  return `/* eslint-disable prettier/prettier */
161
- import type { routes } from './registry.ts'
185
+ import type { routes } from './index.ts'
162
186
 
163
187
  export interface ApiDefinition {
164
188
  ${treeInterface}
@@ -168,11 +192,13 @@ ${treeInterface}
168
192
  function generateTypesContent(routes) {
169
193
  const registryEntries = routes.map(generateTypesRegistryEntry).join("\n");
170
194
  return `/* eslint-disable prettier/prettier */
171
- /// <reference path="../../adonisrc.ts" />
195
+ /// <reference path="../manifest.d.ts" />
172
196
 
173
- import type { ExtractBody, ExtractQuery } from '@tuyau/core/types'
197
+ import type { ExtractBody, ExtractQuery, ExtractQueryForGet, ExtractResponse } from '@tuyau/core/types'
174
198
  import type { InferInput } from '@vinejs/vine/types'
175
199
 
200
+ export type ParamValue = string | number | bigint | boolean
201
+
176
202
  export interface Registry {
177
203
  ${registryEntries}
178
204
  }
@@ -180,7 +206,7 @@ ${registryEntries}
180
206
  }
181
207
  function generateRegistry(options) {
182
208
  const config = {
183
- output: "./.adonisjs/client/registry.ts",
209
+ output: "./.adonisjs/client/registry",
184
210
  ...options
185
211
  };
186
212
  return {
@@ -196,18 +222,18 @@ function generateRegistry(options) {
196
222
  const runtimeContent = generateRuntimeContent(scannedRoutes);
197
223
  const typesContent = generateTypesContent(scannedRoutes);
198
224
  const treeContent = generateTreeContent(scannedRoutes);
199
- const basePath = config.output.replace(/\.(ts|js)$/, "");
200
- const runtimePath = `${basePath}.ts`;
201
- const typesPath = `${basePath}.schema.d.ts`;
202
- const treePath = `${basePath}.schema.tree.d.ts`;
225
+ const registryDir = config.output.replace(/\/$/, "");
226
+ const runtimePath = `${registryDir}/index.ts`;
227
+ const typesPath = `${registryDir}/schema.d.ts`;
228
+ const treePath = `${registryDir}/tree.d.ts`;
203
229
  await Promise.all([
204
230
  writeOutputFile(runtimePath, runtimeContent),
205
231
  writeOutputFile(typesPath, typesContent),
206
232
  writeOutputFile(treePath, treeContent)
207
233
  ]);
208
- devServer.ui.logger.info(`created ${runtimePath}`, { startTime });
209
- devServer.ui.logger.info(`created ${typesPath}`, { startTime });
210
- devServer.ui.logger.info(`created ${treePath}`, { startTime });
234
+ devServer.ui.logger.info(`tuyau: created api client registry (${registryDir})`, {
235
+ startTime
236
+ });
211
237
  });
212
238
  }
213
239
  };
@@ -26,7 +26,7 @@ function buildSearchParams(query) {
26
26
  }
27
27
  }
28
28
  serialize2(query);
29
- return parts.length ? `?${parts.join("&")}` : "";
29
+ return parts.length ? parts.join("&") : "";
30
30
  }
31
31
 
32
32
  // src/client/errors.ts
@@ -78,6 +78,9 @@ function isObject(value) {
78
78
  var isServer = typeof FileList === "undefined";
79
79
  var isReactNative = typeof navigator !== "undefined" && navigator.product === "ReactNative";
80
80
  function segmentsToRouteName(segments) {
81
+ return segments.map((segment) => segment.replace(/[A-Z]/g, (g) => `_${g.toLowerCase()}`)).join(".");
82
+ }
83
+ function segmentsToKebabRouteName(segments) {
81
84
  return segments.map((segment) => segment.replace(/[A-Z]/g, (g) => `-${g.toLowerCase()}`)).join(".");
82
85
  }
83
86
 
@@ -284,8 +287,12 @@ var Tuyau = class {
284
287
  * Creates a proxy-based fluent API for accessing endpoints by name
285
288
  */
286
289
  #makeNamed(segments) {
287
- const routeName = segmentsToRouteName(segments);
288
- const def = this.#config.registry.routes[routeName];
290
+ let routeName = segmentsToRouteName(segments);
291
+ let def = this.#config.registry.routes[routeName];
292
+ if (!def) {
293
+ routeName = segmentsToKebabRouteName(segments);
294
+ def = this.#config.registry.routes[routeName];
295
+ }
289
296
  if (def) {
290
297
  const fn = (args) => this.#doFetch(routeName, def.methods[0], args);
291
298
  return new Proxy(fn, {
@@ -34,16 +34,38 @@ interface AdonisEndpoint extends SchemaEndpoint {
34
34
  /**
35
35
  * Extract query params from a validator type if it has a 'query' property.
36
36
  * Used in generated registry to separate query params from body for POST/PUT/PATCH/DELETE.
37
- * For GET/HEAD, the validator type is used directly as query.
37
+ * For GET/HEAD, use ExtractQueryForGet instead.
38
38
  */
39
39
  type ExtractQuery<T> = T extends {
40
40
  query?: infer Q;
41
41
  } ? Q : {};
42
42
  /**
43
- * Extract body from a validator type, excluding 'query' and 'params' properties.
44
- * Used in generated registry to separate body from query/params for POST/PUT/PATCH/DELETE.
43
+ * Extract query params for GET/HEAD requests.
44
+ * Excludes headers, cookies, and params from the validator type since these are not query params.
45
45
  */
46
- type ExtractBody<T> = Omit<T, 'query' | 'params'>;
46
+ type ExtractQueryForGet<T> = Omit<T, 'headers' | 'cookies' | 'params'>;
47
+ /**
48
+ * Extract body from a validator type, excluding reserved properties.
49
+ * Excludes 'query', 'params', 'headers', and 'cookies' as these are handled separately by AdonisJS.
50
+ */
51
+ type ExtractBody<T> = Omit<T, 'query' | 'params' | 'headers' | 'cookies'>;
52
+ /**
53
+ * Success status codes (2xx)
54
+ */
55
+ type SuccessStatus = 200 | 201 | 202 | 203 | 204 | 205 | 206;
56
+ /**
57
+ * Extract the actual response type from a controller return type.
58
+ * - Success responses (2xx): extracts `__response`
59
+ * - Error responses (non-2xx with __response/__status): returns `never` to filter from unions
60
+ * - Plain types (no __status): returns as-is
61
+ */
62
+ type ExtractResponse<T> = T extends {
63
+ __response: infer R;
64
+ __status: SuccessStatus;
65
+ } ? R : T extends {
66
+ __response: unknown;
67
+ __status: number;
68
+ } ? never : T;
47
69
  /**
48
70
  * Registry mapping endpoint names to their definitions
49
71
  */
@@ -114,13 +136,17 @@ type ResponseOf<E extends SchemaEndpoint> = E['types']['response'];
114
136
  * Function type for calling an endpoint
115
137
  */
116
138
  type EndpointFn<E extends SchemaEndpoint> = (args: RequestArgs<E>) => Promise<E['types']['response']>;
139
+ /**
140
+ * Function type for an endpoint with inlined args
141
+ */
142
+ type EndpointFnInline<E extends AdonisEndpoint> = (args: ParamsArg<E['types']['params']> & QueryArg<E['types']['query']> & BodyArg<E['types']['body']> & BaseRequestOptions) => Promise<E['types']['response']>;
117
143
  /**
118
144
  * Transforms a pre-computed ApiDefinition tree into callable endpoint functions
119
145
  * This recursively converts each endpoint in the tree to a callable function
120
- * Fully inlined for maximum performance
146
+ * Handles intersection types where a node is both an endpoint AND has children
121
147
  */
122
148
  type TransformApiDefinition<T> = {
123
- [K in keyof T]: T[K] extends AdonisEndpoint ? (args: ParamsArg<T[K]['types']['params']> & QueryArg<T[K]['types']['query']> & BodyArg<T[K]['types']['body']> & BaseRequestOptions) => Promise<T[K]['types']['response']> : TransformApiDefinition<T[K]>;
149
+ [K in keyof T]: T[K] extends AdonisEndpoint ? EndpointFnInline<T[K]> & TransformApiDefinition<Omit<T[K], keyof AdonisEndpoint>> : TransformApiDefinition<T[K]>;
124
150
  };
125
151
  /**
126
152
  * Filters endpoints by HTTP method
@@ -236,4 +262,4 @@ type RegistryGroupedByMethod<R extends Record<string, AdonisEndpoint>, M extends
236
262
  };
237
263
  };
238
264
 
239
- export { type AdonisEndpoint, type AdonisRegistry, type EndpointByMethodPattern, type EndpointByName, type EndpointFn, type EndpointTypes, type Endpoints, type EndpointsByMethod, type ExtractBody, type ExtractQuery, type InferRoutes, type InferTree, type MaybeArray, type Method, Path, PathWithRegistry, type PatternsByMethod, type QueryParameters, type RawRequestArgs, type RegValues, type RegistryGroupedByMethod, type RequestArgs, type ResponseOf, Route, RouteWithRegistry, type SchemaEndpoint, type Split, type StrKeys, type TransformApiDefinition, type TuyauConfiguration, type TuyauPlugin, type TuyauRegistry, type UnionToIntersection, type UserRegistry, type ValueOf };
265
+ export { type AdonisEndpoint, type AdonisRegistry, type BaseRequestOptions, type EndpointByMethodPattern, type EndpointByName, type EndpointFn, type EndpointTypes, type Endpoints, type EndpointsByMethod, type ExtractBody, type ExtractQuery, type ExtractQueryForGet, type ExtractResponse, type InferRoutes, type InferTree, type MaybeArray, type Method, Path, PathWithRegistry, type PatternsByMethod, type QueryParameters, type RawRequestArgs, type RegValues, type RegistryGroupedByMethod, type RequestArgs, type ResponseOf, Route, RouteWithRegistry, type SchemaEndpoint, type Split, type StrKeys, type TransformApiDefinition, type TuyauConfiguration, type TuyauPlugin, type TuyauRegistry, type UnionToIntersection, type UserRegistry, type ValueOf };
package/package.json CHANGED
@@ -1,14 +1,27 @@
1
1
  {
2
2
  "name": "@tuyau/core",
3
3
  "type": "module",
4
- "version": "1.0.0-beta.8",
5
- "description": "e2e client for AdonisJS",
4
+ "version": "1.0.0-next.17",
5
+ "description": "E2E typesafe client for AdonisJS",
6
6
  "author": "Julien Ripouteau <julien@ripouteau.com>",
7
7
  "license": "MIT",
8
+ "homepage": "https://github.com/Julien-R44/tuyau#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/Julien-R44/tuyau.git",
12
+ "directory": "packages/core"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/Julien-R44/tuyau/issues"
16
+ },
8
17
  "keywords": [
9
18
  "adonisjs",
10
- "e2e",
11
- "client"
19
+ "typescript",
20
+ "typesafe",
21
+ "api",
22
+ "rpc",
23
+ "client",
24
+ "e2e"
12
25
  ],
13
26
  "exports": {
14
27
  "./client": "./build/client/index.js",
@@ -23,22 +36,30 @@
23
36
  "node": ">=24.0.0"
24
37
  },
25
38
  "peerDependencies": {
26
- "@adonisjs/assembler": "^8.0.0-next.26",
27
- "@adonisjs/core": "^7.0.0-next.14"
39
+ "@adonisjs/assembler": "^8.0.0-next.27",
40
+ "@adonisjs/core": "^7.0.0-next.16"
41
+ },
42
+ "peerDependenciesMeta": {
43
+ "@adonisjs/assembler": {
44
+ "optional": true
45
+ },
46
+ "@adonisjs/core": {
47
+ "optional": true
48
+ }
28
49
  },
29
50
  "dependencies": {
30
- "ky": "^1.14.0",
51
+ "ky": "^1.14.2",
31
52
  "object-to-formdata": "^4.5.1"
32
53
  },
33
54
  "devDependencies": {
34
- "@adonisjs/assembler": "^8.0.0-next.26",
35
- "@adonisjs/core": "^7.0.0-next.14",
55
+ "@adonisjs/assembler": "^8.0.0-next.27",
56
+ "@adonisjs/core": "^7.0.0-next.16",
36
57
  "@adonisjs/http-server": "^8.0.0-next.16",
37
58
  "@faker-js/faker": "^10.1.0",
38
59
  "@poppinss/ts-exec": "^1.4.1",
39
- "@types/node": "^24.10.1",
60
+ "@types/node": "^25.0.3",
40
61
  "@typescript/analyze-trace": "^0.10.1",
41
- "@vinejs/vine": "^4.1.0"
62
+ "@vinejs/vine": "^4.2.0"
42
63
  },
43
64
  "publishConfig": {
44
65
  "access": "public",