typedapi-client-helpers 0.1.7 → 0.1.9

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  `typedapi-client-helpers` generates a typed TypeScript API client from an OpenAPI/Swagger document and adds reusable helper types and functions for API results, callbacks, filtering, sorting, request parameters, and multipart uploads.
4
4
 
5
- The package is meant for frontend projects that want a generated API client while still keeping the generated files inside their own source tree.
5
+ The package is intended for frontend projects that want a generated API client while still keeping generated files inside their own source tree.
6
6
 
7
7
  ## Installation
8
8
 
@@ -28,7 +28,13 @@ Run the generator:
28
28
  npm run generate:api
29
29
  ```
30
30
 
31
- By default the generator reads the Swagger document from `https://localhost:7000/swagger/v1/swagger.json` and writes the generated API client to `src/api`.
31
+ By default, the generator reads the Swagger document from `https://localhost:7000/swagger/v1/swagger.json` and writes the generated API client to `src/api`.
32
+
33
+ You can also run the command directly:
34
+
35
+ ```bash
36
+ npx typedapi-generate
37
+ ```
32
38
 
33
39
  ## Configuration
34
40
 
@@ -44,7 +50,7 @@ Configuration can be supplied in the `config` section of your `package.json`, wi
44
50
  "apiOutput": "src/api",
45
51
  "typedApiUseTypeOnlyImports": true,
46
52
  "typedApiUseFilterFormValues": false,
47
- "typedApiDefaultFunctionsPath": "../../defaultApiFunctions",
53
+ "typedApiDefaultFunctionsPath": "src/defaultApiFunctions",
48
54
  "typedApiDefaultSuccessHandler": "handleGoodResult",
49
55
  "typedApiDefaultErrorHandler": "handleErrors"
50
56
  }
@@ -62,19 +68,22 @@ Configuration can be supplied in the `config` section of your `package.json`, wi
62
68
  | `apiOutput` | `src/api` | Directory where the generated API files are written. |
63
69
  | `typedApiUseTypeOnlyImports` | `false` | Generates `import type` statements for imports that are only used as types. |
64
70
  | `typedApiUseFilterFormValues` | `false` | Generates paginated methods that accept `FilterFormValues[]`, page values, and sort values instead of a prebuilt query object. |
65
- | `typedApiDefaultFunctionsPath` | `../../defaultApiFunctions` | Import path used by generated method files for shared success and error handlers. |
71
+ | `typedApiDefaultFunctionsPath` | `src/defaultApiFunctions` | Import path used by generated method files for shared success and error handlers. |
66
72
  | `typedApiDefaultSuccessHandler` | `handleGoodResult` | Name of the default success handler function imported into generated methods. |
67
73
  | `typedApiDefaultErrorHandler` | `handleErrors` | Name of the default error handler function imported into generated methods. |
68
74
 
69
75
  ### Environment variables
70
76
 
71
- | Environment variable | Description |
72
- | ---------------------------------- | --------------------------------------------------------------- |
73
- | `SWAGGER_URL` | URL of the OpenAPI/Swagger document. |
74
- | `SWAGGER_FILE` | Local path to an OpenAPI/Swagger document. |
75
- | `API_OUTPUT` | Directory where generated API files are written. |
76
- | `TYPED_API_USE_TYPE_ONLY_IMPORTS` | Enables type-only imports when set to `true`. |
77
- | `TYPED_API_USE_FILTER_FORM_VALUES` | Enables filter-form based paginated methods when set to `true`. |
77
+ | Environment variable | Description |
78
+ | ----------------------------------- | -------------------------------------------------- |
79
+ | `SWAGGER_URL` | URL of the OpenAPI/Swagger document. |
80
+ | `SWAGGER_FILE` | Local path to an OpenAPI/Swagger document. |
81
+ | `API_OUTPUT` | Directory where generated API files are written. |
82
+ | `TYPED_API_USE_TYPE_ONLY_IMPORTS` | Enables type-only imports when set to `true`. |
83
+ | `TYPED_API_USE_FILTER_FORM_VALUES` | Enables filter-form based paginated methods. |
84
+ | `TYPED_API_DEFAULT_FUNCTIONS_PATH` | Path to the shared default callback handler file. |
85
+ | `TYPED_API_DEFAULT_SUCCESS_HANDLER` | Export name of the shared default success handler. |
86
+ | `TYPED_API_DEFAULT_ERROR_HANDLER` | Export name of the shared default error handler. |
78
87
 
79
88
  Example:
80
89
 
@@ -88,6 +97,7 @@ SWAGGER_URL=https://localhost:7000/swagger/v1/swagger.json npm run generate:api
88
97
  npm run generate:api --swagger-url=https://localhost:7000/swagger/v1/swagger.json
89
98
  npm run generate:api --swagger-file=swagger/openapi.json
90
99
  npm run generate:api --api-output=src/api
100
+ npm run generate:api --typed-api-use-filter-form-values=true
91
101
  ```
92
102
 
93
103
  ## Generated structure
@@ -136,6 +146,39 @@ if (result.ok) {
136
146
 
137
147
  Checking `result.ok` narrows the result automatically.
138
148
 
149
+ ## Generated method argument order
150
+
151
+ Generated wrappers preserve the original generated API arguments and then add optional wrapper-only arguments at the end.
152
+
153
+ For query methods:
154
+
155
+ ```ts
156
+ await getSuppliers(query, onSuccess, onError, params);
157
+ ```
158
+
159
+ For non-query methods:
160
+
161
+ ```ts
162
+ await updateSupplier(id, body, onSuccess, onError, params);
163
+ ```
164
+
165
+ For filter-form paginated methods when `typedApiUseFilterFormValues` is enabled:
166
+
167
+ ```ts
168
+ await getSuppliers(
169
+ filters,
170
+ page,
171
+ pageSize,
172
+ sortBy,
173
+ sortDirection,
174
+ onSuccess,
175
+ onError,
176
+ params,
177
+ );
178
+ ```
179
+
180
+ The final `params` object is forwarded to the generated HTTP client and can contain values such as headers or other request options.
181
+
139
182
  ## Success and error callbacks
140
183
 
141
184
  Callbacks receive the full result object, not just the raw response or error.
@@ -268,15 +311,16 @@ Arrays are appended as repeated fields, files keep their filename, primitives be
268
311
 
269
312
  ### Utility functions
270
313
 
271
- | Export | Description |
272
- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
273
- | `buildQuery<TQuery, TSortModel>()` | Builds a query object from filter form values, page values, and sort values. |
274
- | `extractArgsCallbacksAndParams()` | Splits wrapper arguments into original API arguments, success callback, error callback, and request params. |
275
- | `extractArgsToastsAndParams()` | Backwards-compatible alias-style extractor for wrapper arguments with success/error handlers and request params. |
276
- | `handleApiResponse()` | Executes a generated API call and converts the response or thrown error into `ApiResult<T>`. |
277
- | `getSortTypeFromSortDirection()` | Converts an API sort direction into a UI `SortType`. |
278
- | `getSortDirectionFromSortType()` | Converts a UI `SortType` into an API sort direction. |
279
- | `toFormData()` | Converts an object payload into `FormData`. |
314
+ | Export | Description |
315
+ | ---------------------------------- | ----------------------------------------------------------------------------------------------------------- |
316
+ | `buildQuery<TQuery, TSortModel>()` | Builds a query object from filter form values, page values, and sort values. |
317
+ | `extractArgsCallbacksAndParams()` | Splits wrapper arguments into original API arguments, success callback, error callback, and request params. |
318
+ | `extractArgsToastsAndParams()` | Backwards-compatible extractor for wrapper arguments with success/error handlers and request params. |
319
+ | `handleApiResponse()` | Executes a generated API call and converts the response or thrown error into `ApiResult<T>`. |
320
+ | `HandleApiResponseOptions<T>` | Options object for passing success and error callbacks to `handleApiResponse`. |
321
+ | `getSortTypeFromSortDirection()` | Converts an API sort direction into a UI `SortType`. |
322
+ | `getSortDirectionFromSortType()` | Converts a UI `SortType` into an API sort direction. |
323
+ | `toFormData()` | Converts an object payload into `FormData`. |
280
324
 
281
325
  ### Default callback functions
282
326
 
package/dist/index.d.cts CHANGED
@@ -207,6 +207,8 @@ declare function buildQuery<TQuery, TSortModel = keyof TQuery>(filters: FilterFo
207
207
  /**
208
208
  * Extracts wrapper-only arguments in this order:
209
209
  * original API arguments, onSuccess, onError, request params.
210
+ *
211
+ * Kept for backwards compatibility with generated files that used toast-oriented naming.
210
212
  */
211
213
  declare function extractArgsToastsAndParams<TArgs extends readonly unknown[], TResponse>(argsWithCallbacks: [
212
214
  ...TArgs,
package/dist/index.d.ts CHANGED
@@ -207,6 +207,8 @@ declare function buildQuery<TQuery, TSortModel = keyof TQuery>(filters: FilterFo
207
207
  /**
208
208
  * Extracts wrapper-only arguments in this order:
209
209
  * original API arguments, onSuccess, onError, request params.
210
+ *
211
+ * Kept for backwards compatibility with generated files that used toast-oriented naming.
210
212
  */
211
213
  declare function extractArgsToastsAndParams<TArgs extends readonly unknown[], TResponse>(argsWithCallbacks: [
212
214
  ...TArgs,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typedapi-client-helpers",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Reusable typed OpenAPI client helpers.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -19,7 +19,7 @@
19
19
  "homepage": "https://github.com/Stef-Buurman/TypedApi/tree/main/npm/typed-api-client#readme",
20
20
  "config": {
21
21
  "apiOutput": "src/api",
22
- "typedApiDefaultFunctionsPath": "../../defaultApiFunctions",
22
+ "typedApiDefaultFunctionsPath": "src/defaultApiFunctions",
23
23
  "typedApiDefaultSuccessHandler": "handleGoodResult",
24
24
  "typedApiDefaultErrorHandler": "handleErrors"
25
25
  },
@@ -73,15 +73,17 @@ function getStringSetting(...values) {
73
73
  return undefined;
74
74
  }
75
75
 
76
- const fallbackDefaultFunctionsPath = "../../defaultApiFunctions";
76
+ const fallbackDefaultFunctionsPath = "defaultApiFunctions";
77
77
 
78
- const defaultFunctionsPath = getStringSetting(
78
+ const defaultFunctionsPathSetting = getStringSetting(
79
79
  process.env.TYPED_API_DEFAULT_FUNCTIONS_PATH,
80
80
  process.env.npm_config_typed_api_default_functions_path,
81
81
  config.typedApiDefaultFunctionsPath,
82
82
  fallbackDefaultFunctionsPath,
83
83
  );
84
84
 
85
+ const defaultFunctionsFilePath = path.resolve(cwd, defaultFunctionsPathSetting);
86
+
85
87
  const defaultSuccessHandlerName = getStringSetting(
86
88
  process.env.TYPED_API_DEFAULT_SUCCESS_HANDLER,
87
89
  process.env.npm_config_typed_api_default_success_handler,
@@ -194,23 +196,18 @@ function resolveImportFilePath(fromDirectory, importPath) {
194
196
  return candidates.find((candidate) => fs.existsSync(candidate));
195
197
  }
196
198
 
197
- function createDefaultFunctionsFileIfMissing(fromDirectory, importPath) {
198
- if (!importPath.startsWith(".")) {
199
- return undefined;
200
- }
201
-
202
- const basePath = path.resolve(fromDirectory, importPath);
203
- const extension = path.extname(basePath);
204
- const filePath = extension ? basePath : `${basePath}.ts`;
199
+ function createDefaultFunctionsFileIfMissing(filePath) {
200
+ const extension = path.extname(filePath);
201
+ const resolvedFilePath = extension ? filePath : `${filePath}.ts`;
205
202
 
206
- if (fs.existsSync(filePath)) {
207
- return filePath;
203
+ if (fs.existsSync(resolvedFilePath)) {
204
+ return resolvedFilePath;
208
205
  }
209
206
 
210
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
207
+ fs.mkdirSync(path.dirname(resolvedFilePath), { recursive: true });
211
208
 
212
209
  fs.writeFileSync(
213
- filePath,
210
+ resolvedFilePath,
214
211
  `
215
212
  ${createImportStatement({
216
213
  names: ["ApiErrorResult", "ApiSuccessResult"],
@@ -234,10 +231,22 @@ export function ${defaultErrorHandlerName}<T>(
234
231
  );
235
232
 
236
233
  console.log(
237
- `Created default API handler file: ${path.relative(process.cwd(), filePath)}`,
234
+ `Created default API handler file: ${path.relative(process.cwd(), resolvedFilePath)}`,
238
235
  );
239
236
 
240
- return filePath;
237
+ return resolvedFilePath;
238
+ }
239
+
240
+ function toRelativeImportPath(fromDirectory, filePath) {
241
+ let relativePath = path.relative(fromDirectory, filePath);
242
+
243
+ if (!relativePath.startsWith(".")) {
244
+ relativePath = `./${relativePath}`;
245
+ }
246
+
247
+ relativePath = relativePath.replaceAll(path.sep, "/");
248
+
249
+ return relativePath.replace(/\.(ts|tsx|js|jsx)$/, "");
241
250
  }
242
251
 
243
252
  function escapeRegExp(value) {
@@ -284,19 +293,8 @@ function fileExportsName(source, exportName) {
284
293
 
285
294
  function resolveDefaultHandlers(importFromDirectory) {
286
295
  const defaultFunctionsFile =
287
- resolveImportFilePath(importFromDirectory, defaultFunctionsPath) ??
288
- createDefaultFunctionsFileIfMissing(
289
- importFromDirectory,
290
- defaultFunctionsPath,
291
- );
292
-
293
- if (!defaultFunctionsFile) {
294
- console.warn(
295
- `Default API handlers were not imported because "${defaultFunctionsPath}" is not a relative path and could not be created automatically.`,
296
- );
297
-
298
- return undefined;
299
- }
296
+ resolveImportFilePath(importFromDirectory, defaultFunctionsFilePath) ??
297
+ createDefaultFunctionsFileIfMissing(defaultFunctionsFilePath);
300
298
 
301
299
  const source = fs.readFileSync(defaultFunctionsFile, "utf8");
302
300
  const hasSuccessHandler = fileExportsName(source, defaultSuccessHandlerName);
@@ -319,7 +317,10 @@ function resolveDefaultHandlers(importFromDirectory) {
319
317
  }
320
318
 
321
319
  return {
322
- defaultFunctionsPath,
320
+ defaultFunctionsPath: toRelativeImportPath(
321
+ importFromDirectory,
322
+ defaultFunctionsFile,
323
+ ),
323
324
  defaultSuccessHandlerName,
324
325
  defaultErrorHandlerName,
325
326
  };