@nextplus/js-sdk 0.0.4 → 0.0.6
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/chunk-YEF23TVP.js +222 -0
- package/dist/index-DnDzRLml.d.cts +5156 -0
- package/dist/index-_9HQhd2P.d.ts +5156 -0
- package/dist/index.cjs +21668 -0
- package/dist/index.d.cts +45 -0
- package/dist/index.d.ts +14 -3
- package/dist/index.js +66 -221
- package/dist/sdk/client/index.cjs +750 -0
- package/dist/sdk/client/index.d.cts +39 -0
- package/dist/sdk/index.cjs +21543 -0
- package/dist/sdk/index.d.cts +2 -0
- package/dist/sdk/index.d.ts +2 -0
- package/dist/sdk/index.js +214 -0
- package/dist/sdk/sdk.gen.cjs +21543 -0
- package/dist/sdk/sdk.gen.d.cts +2 -0
- package/dist/sdk/sdk.gen.d.ts +2 -34568
- package/dist/sdk.gen-CPR3KdM-.d.cts +39508 -0
- package/dist/sdk.gen-D3Q8YKqz.d.ts +39508 -0
- package/dist/types.gen-vDP9AbtO.d.cts +258 -0
- package/package.json +21 -4
- package/src/index.ts +98 -11
- package/src/sdk/types.gen.ts +1 -0
- package/src/smoke.ts +27 -18
- package/openapi-ts.config.ts +0 -36
- package/prettier.config.js +0 -5
- package/tsconfig.json +0 -23
- package/tsconfig.node.json +0 -11
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
type AuthToken = string | undefined;
|
|
2
|
+
interface Auth {
|
|
3
|
+
/**
|
|
4
|
+
* Which part of the request do we use to send the auth?
|
|
5
|
+
*
|
|
6
|
+
* @default 'header'
|
|
7
|
+
*/
|
|
8
|
+
in?: 'header' | 'query' | 'cookie';
|
|
9
|
+
/**
|
|
10
|
+
* Header or query parameter name.
|
|
11
|
+
*
|
|
12
|
+
* @default 'Authorization'
|
|
13
|
+
*/
|
|
14
|
+
name?: string;
|
|
15
|
+
scheme?: 'basic' | 'bearer';
|
|
16
|
+
type: 'apiKey' | 'http';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface SerializerOptions<T> {
|
|
20
|
+
/**
|
|
21
|
+
* @default true
|
|
22
|
+
*/
|
|
23
|
+
explode: boolean;
|
|
24
|
+
style: T;
|
|
25
|
+
}
|
|
26
|
+
type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited';
|
|
27
|
+
type ObjectStyle = 'form' | 'deepObject';
|
|
28
|
+
|
|
29
|
+
type QuerySerializer = (query: Record<string, unknown>) => string;
|
|
30
|
+
type BodySerializer = (body: any) => any;
|
|
31
|
+
interface QuerySerializerOptions {
|
|
32
|
+
allowReserved?: boolean;
|
|
33
|
+
array?: SerializerOptions<ArrayStyle>;
|
|
34
|
+
object?: SerializerOptions<ObjectStyle>;
|
|
35
|
+
}
|
|
36
|
+
declare const formDataBodySerializer: {
|
|
37
|
+
bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(body: T) => FormData;
|
|
38
|
+
};
|
|
39
|
+
declare const jsonBodySerializer: {
|
|
40
|
+
bodySerializer: <T>(body: T) => string;
|
|
41
|
+
};
|
|
42
|
+
declare const urlSearchParamsBodySerializer: {
|
|
43
|
+
bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(body: T) => string;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
interface Client$1<RequestFn = never, Config = unknown, MethodFn = never, BuildUrlFn = never> {
|
|
47
|
+
/**
|
|
48
|
+
* Returns the final request URL.
|
|
49
|
+
*/
|
|
50
|
+
buildUrl: BuildUrlFn;
|
|
51
|
+
connect: MethodFn;
|
|
52
|
+
delete: MethodFn;
|
|
53
|
+
get: MethodFn;
|
|
54
|
+
getConfig: () => Config;
|
|
55
|
+
head: MethodFn;
|
|
56
|
+
options: MethodFn;
|
|
57
|
+
patch: MethodFn;
|
|
58
|
+
post: MethodFn;
|
|
59
|
+
put: MethodFn;
|
|
60
|
+
request: RequestFn;
|
|
61
|
+
setConfig: (config: Config) => Config;
|
|
62
|
+
trace: MethodFn;
|
|
63
|
+
}
|
|
64
|
+
interface Config$1 {
|
|
65
|
+
/**
|
|
66
|
+
* Auth token or a function returning auth token. The resolved value will be
|
|
67
|
+
* added to the request payload as defined by its `security` array.
|
|
68
|
+
*/
|
|
69
|
+
auth?: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken;
|
|
70
|
+
/**
|
|
71
|
+
* A function for serializing request body parameter. By default,
|
|
72
|
+
* {@link JSON.stringify()} will be used.
|
|
73
|
+
*/
|
|
74
|
+
bodySerializer?: BodySerializer | null;
|
|
75
|
+
/**
|
|
76
|
+
* An object containing any HTTP headers that you want to pre-populate your
|
|
77
|
+
* `Headers` object with.
|
|
78
|
+
*
|
|
79
|
+
* {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more}
|
|
80
|
+
*/
|
|
81
|
+
headers?: RequestInit['headers'] | Record<string, string | number | boolean | (string | number | boolean)[] | null | undefined | unknown>;
|
|
82
|
+
/**
|
|
83
|
+
* The request method.
|
|
84
|
+
*
|
|
85
|
+
* {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more}
|
|
86
|
+
*/
|
|
87
|
+
method?: 'CONNECT' | 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'TRACE';
|
|
88
|
+
/**
|
|
89
|
+
* A function for serializing request query parameters. By default, arrays
|
|
90
|
+
* will be exploded in form style, objects will be exploded in deepObject
|
|
91
|
+
* style, and reserved characters are percent-encoded.
|
|
92
|
+
*
|
|
93
|
+
* This method will have no effect if the native `paramsSerializer()` Axios
|
|
94
|
+
* API function is used.
|
|
95
|
+
*
|
|
96
|
+
* {@link https://swagger.io/docs/specification/serialization/#query View examples}
|
|
97
|
+
*/
|
|
98
|
+
querySerializer?: QuerySerializer | QuerySerializerOptions;
|
|
99
|
+
/**
|
|
100
|
+
* A function validating request data. This is useful if you want to ensure
|
|
101
|
+
* the request conforms to the desired shape, so it can be safely sent to
|
|
102
|
+
* the server.
|
|
103
|
+
*/
|
|
104
|
+
requestValidator?: (data: unknown) => Promise<unknown>;
|
|
105
|
+
/**
|
|
106
|
+
* A function transforming response data before it's returned. This is useful
|
|
107
|
+
* for post-processing data, e.g. converting ISO strings into Date objects.
|
|
108
|
+
*/
|
|
109
|
+
responseTransformer?: (data: unknown) => Promise<unknown>;
|
|
110
|
+
/**
|
|
111
|
+
* A function validating response data. This is useful if you want to ensure
|
|
112
|
+
* the response conforms to the desired shape, so it can be safely passed to
|
|
113
|
+
* the transformers and returned to the user.
|
|
114
|
+
*/
|
|
115
|
+
responseValidator?: (data: unknown) => Promise<unknown>;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
declare const mergeHeaders: (...headers: Array<Required<Config>["headers"] | undefined>) => Headers;
|
|
119
|
+
type ErrInterceptor<Err, Res, Req, Options> = (error: Err, response: Res, request: Req, options: Options) => Err | Promise<Err>;
|
|
120
|
+
type ReqInterceptor<Req, Options> = (request: Req, options: Options) => Req | Promise<Req>;
|
|
121
|
+
type ResInterceptor<Res, Req, Options> = (response: Res, request: Req, options: Options) => Res | Promise<Res>;
|
|
122
|
+
declare class Interceptors<Interceptor> {
|
|
123
|
+
_fns: (Interceptor | null)[];
|
|
124
|
+
constructor();
|
|
125
|
+
clear(): void;
|
|
126
|
+
getInterceptorIndex(id: number | Interceptor): number;
|
|
127
|
+
exists(id: number | Interceptor): boolean;
|
|
128
|
+
eject(id: number | Interceptor): void;
|
|
129
|
+
update(id: number | Interceptor, fn: Interceptor): number | false | Interceptor;
|
|
130
|
+
use(fn: Interceptor): number;
|
|
131
|
+
}
|
|
132
|
+
interface Middleware<Req, Res, Err, Options> {
|
|
133
|
+
error: Pick<Interceptors<ErrInterceptor<Err, Res, Req, Options>>, 'eject' | 'use'>;
|
|
134
|
+
request: Pick<Interceptors<ReqInterceptor<Req, Options>>, 'eject' | 'use'>;
|
|
135
|
+
response: Pick<Interceptors<ResInterceptor<Res, Req, Options>>, 'eject' | 'use'>;
|
|
136
|
+
}
|
|
137
|
+
declare const createConfig: <T extends ClientOptions = ClientOptions>(override?: Config<Omit<ClientOptions, keyof T> & T>) => Config<Omit<ClientOptions, keyof T> & T>;
|
|
138
|
+
|
|
139
|
+
type ResponseStyle = 'data' | 'fields';
|
|
140
|
+
interface Config<T extends ClientOptions = ClientOptions> extends Omit<RequestInit, 'body' | 'headers' | 'method'>, Config$1 {
|
|
141
|
+
/**
|
|
142
|
+
* Base URL for all requests made by this client.
|
|
143
|
+
*/
|
|
144
|
+
baseUrl?: T['baseUrl'];
|
|
145
|
+
/**
|
|
146
|
+
* Fetch API implementation. You can use this option to provide a custom
|
|
147
|
+
* fetch instance.
|
|
148
|
+
*
|
|
149
|
+
* @default globalThis.fetch
|
|
150
|
+
*/
|
|
151
|
+
fetch?: (request: Request) => ReturnType<typeof fetch>;
|
|
152
|
+
/**
|
|
153
|
+
* Please don't use the Fetch client for Next.js applications. The `next`
|
|
154
|
+
* options won't have any effect.
|
|
155
|
+
*
|
|
156
|
+
* Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead.
|
|
157
|
+
*/
|
|
158
|
+
next?: never;
|
|
159
|
+
/**
|
|
160
|
+
* Return the response data parsed in a specified format. By default, `auto`
|
|
161
|
+
* will infer the appropriate method from the `Content-Type` response header.
|
|
162
|
+
* You can override this behavior with any of the {@link Body} methods.
|
|
163
|
+
* Select `stream` if you don't want to parse response data at all.
|
|
164
|
+
*
|
|
165
|
+
* @default 'auto'
|
|
166
|
+
*/
|
|
167
|
+
parseAs?: 'arrayBuffer' | 'auto' | 'blob' | 'formData' | 'json' | 'stream' | 'text';
|
|
168
|
+
/**
|
|
169
|
+
* Should we return only data or multiple fields (data, error, response, etc.)?
|
|
170
|
+
*
|
|
171
|
+
* @default 'fields'
|
|
172
|
+
*/
|
|
173
|
+
responseStyle?: ResponseStyle;
|
|
174
|
+
/**
|
|
175
|
+
* Throw an error instead of returning it in the response?
|
|
176
|
+
*
|
|
177
|
+
* @default false
|
|
178
|
+
*/
|
|
179
|
+
throwOnError?: T['throwOnError'];
|
|
180
|
+
}
|
|
181
|
+
interface RequestOptions<TResponseStyle extends ResponseStyle = 'fields', ThrowOnError extends boolean = boolean, Url extends string = string> extends Config<{
|
|
182
|
+
responseStyle: TResponseStyle;
|
|
183
|
+
throwOnError: ThrowOnError;
|
|
184
|
+
}> {
|
|
185
|
+
/**
|
|
186
|
+
* Any body that you want to add to your request.
|
|
187
|
+
*
|
|
188
|
+
* {@link https://developer.mozilla.org/docs/Web/API/fetch#body}
|
|
189
|
+
*/
|
|
190
|
+
body?: unknown;
|
|
191
|
+
path?: Record<string, unknown>;
|
|
192
|
+
query?: Record<string, unknown>;
|
|
193
|
+
/**
|
|
194
|
+
* Security mechanism(s) to use for the request.
|
|
195
|
+
*/
|
|
196
|
+
security?: ReadonlyArray<Auth>;
|
|
197
|
+
url: Url;
|
|
198
|
+
}
|
|
199
|
+
interface ResolvedRequestOptions<TResponseStyle extends ResponseStyle = 'fields', ThrowOnError extends boolean = boolean, Url extends string = string> extends RequestOptions<TResponseStyle, ThrowOnError, Url> {
|
|
200
|
+
serializedBody?: string;
|
|
201
|
+
}
|
|
202
|
+
type RequestResult<TData = unknown, TError = unknown, ThrowOnError extends boolean = boolean, TResponseStyle extends ResponseStyle = 'fields'> = ThrowOnError extends true ? Promise<TResponseStyle extends 'data' ? TData extends Record<string, unknown> ? TData[keyof TData] : TData : {
|
|
203
|
+
data: TData extends Record<string, unknown> ? TData[keyof TData] : TData;
|
|
204
|
+
request: Request;
|
|
205
|
+
response: Response;
|
|
206
|
+
}> : Promise<TResponseStyle extends 'data' ? (TData extends Record<string, unknown> ? TData[keyof TData] : TData) | undefined : ({
|
|
207
|
+
data: TData extends Record<string, unknown> ? TData[keyof TData] : TData;
|
|
208
|
+
error: undefined;
|
|
209
|
+
} | {
|
|
210
|
+
data: undefined;
|
|
211
|
+
error: TError extends Record<string, unknown> ? TError[keyof TError] : TError;
|
|
212
|
+
}) & {
|
|
213
|
+
request: Request;
|
|
214
|
+
response: Response;
|
|
215
|
+
}>;
|
|
216
|
+
interface ClientOptions {
|
|
217
|
+
baseUrl?: string;
|
|
218
|
+
responseStyle?: ResponseStyle;
|
|
219
|
+
throwOnError?: boolean;
|
|
220
|
+
}
|
|
221
|
+
type MethodFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean = false, TResponseStyle extends ResponseStyle = 'fields'>(options: Omit<RequestOptions<TResponseStyle, ThrowOnError>, 'method'>) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
|
|
222
|
+
type RequestFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean = false, TResponseStyle extends ResponseStyle = 'fields'>(options: Omit<RequestOptions<TResponseStyle, ThrowOnError>, 'method'> & Pick<Required<RequestOptions<TResponseStyle, ThrowOnError>>, 'method'>) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
|
|
223
|
+
type BuildUrlFn = <TData extends {
|
|
224
|
+
body?: unknown;
|
|
225
|
+
path?: Record<string, unknown>;
|
|
226
|
+
query?: Record<string, unknown>;
|
|
227
|
+
url: string;
|
|
228
|
+
}>(options: Pick<TData, 'url'> & Options<TData>) => string;
|
|
229
|
+
type Client = Client$1<RequestFn, Config, MethodFn, BuildUrlFn> & {
|
|
230
|
+
interceptors: Middleware<Request, Response, unknown, ResolvedRequestOptions>;
|
|
231
|
+
};
|
|
232
|
+
/**
|
|
233
|
+
* The `createClientConfig()` function will be called on client initialization
|
|
234
|
+
* and the returned object will become the client's initial configuration.
|
|
235
|
+
*
|
|
236
|
+
* You may want to initialize your client this way instead of calling
|
|
237
|
+
* `setConfig()`. This is useful for example if you're using Next.js
|
|
238
|
+
* to ensure your client always has the correct values.
|
|
239
|
+
*/
|
|
240
|
+
type CreateClientConfig<T extends ClientOptions = ClientOptions> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T>;
|
|
241
|
+
interface TDataShape {
|
|
242
|
+
body?: unknown;
|
|
243
|
+
headers?: unknown;
|
|
244
|
+
path?: unknown;
|
|
245
|
+
query?: unknown;
|
|
246
|
+
url: string;
|
|
247
|
+
}
|
|
248
|
+
type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>>;
|
|
249
|
+
type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean, TResponseStyle extends ResponseStyle = 'fields'> = OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'body' | 'path' | 'query' | 'url'> & Omit<TData, 'url'>;
|
|
250
|
+
type OptionsLegacyParser<TData = unknown, ThrowOnError extends boolean = boolean, TResponseStyle extends ResponseStyle = 'fields'> = TData extends {
|
|
251
|
+
body?: any;
|
|
252
|
+
} ? TData extends {
|
|
253
|
+
headers?: any;
|
|
254
|
+
} ? OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'body' | 'headers' | 'url'> & TData : OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'body' | 'url'> & TData & Pick<RequestOptions<TResponseStyle, ThrowOnError>, 'headers'> : TData extends {
|
|
255
|
+
headers?: any;
|
|
256
|
+
} ? OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'headers' | 'url'> & TData & Pick<RequestOptions<TResponseStyle, ThrowOnError>, 'body'> : OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'url'> & TData;
|
|
257
|
+
|
|
258
|
+
export { type Auth as A, type Client as C, type Options as O, type QuerySerializerOptions as Q, type RequestResult as R, type TDataShape as T, type Config as a, type ClientOptions as b, type CreateClientConfig as c, type OptionsLegacyParser as d, type RequestOptions as e, formDataBodySerializer as f, type ResolvedRequestOptions as g, type ResponseStyle as h, createConfig as i, jsonBodySerializer as j, mergeHeaders as m, urlSearchParamsBodySerializer as u };
|
package/package.json
CHANGED
|
@@ -1,20 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextplus/js-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"generate": "npm run clean && npm run openapi-ts && npm run build",
|
|
7
|
-
"build": "tsup src/index.ts src/sdk/client/index.ts src/sdk/sdk.gen.ts src/smoke.ts --dts --format esm --outDir dist --clean",
|
|
7
|
+
"build": "tsup src/index.ts src/sdk/index.ts src/sdk/client/index.ts src/sdk/sdk.gen.ts src/smoke.ts --dts --format esm,cjs --outDir dist --clean",
|
|
8
8
|
"clean": "rm -rf dist",
|
|
9
|
-
"prepublishOnly": "npm run clean && tsup src/index.ts src/sdk/client/index.ts src/sdk/sdk.gen.ts --dts --format esm --outDir dist --clean",
|
|
9
|
+
"prepublishOnly": "npm run clean && tsup src/index.ts src/sdk/index.ts src/sdk/client/index.ts src/sdk/sdk.gen.ts --dts --format esm,cjs --outDir dist --clean",
|
|
10
10
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
11
11
|
"openapi-ts": "openapi-ts",
|
|
12
12
|
"test": "npm run build && node dist/smoke.js"
|
|
13
13
|
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"src",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
14
20
|
"exports": {
|
|
15
21
|
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
16
23
|
"import": "./dist/index.js",
|
|
17
|
-
"
|
|
24
|
+
"require": "./dist/index.cjs"
|
|
25
|
+
},
|
|
26
|
+
"./sdk": {
|
|
27
|
+
"types": "./dist/sdk/index.d.ts",
|
|
28
|
+
"import": "./dist/sdk/index.js",
|
|
29
|
+
"require": "./dist/sdk/index.cjs"
|
|
30
|
+
},
|
|
31
|
+
"./sdk/client": {
|
|
32
|
+
"types": "./dist/sdk/client/index.d.ts",
|
|
33
|
+
"import": "./dist/sdk/client/index.js",
|
|
34
|
+
"require": "./dist/sdk/client/index.cjs"
|
|
18
35
|
}
|
|
19
36
|
},
|
|
20
37
|
"main": "dist/index.js",
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ import debug from 'debug';
|
|
|
2
2
|
import { createClient } from './sdk/client';
|
|
3
3
|
import { UserModelService } from './sdk';
|
|
4
4
|
import * as AllServices from './sdk';
|
|
5
|
+
import type * as AllServiceTypes from './sdk';
|
|
5
6
|
|
|
6
7
|
const log = debug('nextplus:sdk');
|
|
7
8
|
|
|
@@ -35,11 +36,88 @@ const isTokenValid = (): boolean => {
|
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
|
|
38
|
-
class NextPlusSDK {
|
|
39
|
+
export class NextPlusSDK {
|
|
39
40
|
private client: any;
|
|
40
41
|
private credentials: { email?: string; username?: string; password: string };
|
|
41
42
|
private returnType: 'raw' | 'data' = 'data';
|
|
42
43
|
|
|
44
|
+
// Wrap plain developer inputs into the right container (body/query)
|
|
45
|
+
// and stringify complex query params when required by LoopBack (filter/where)
|
|
46
|
+
private normalizeOptions(methodName: string, rawOptions: any): any {
|
|
47
|
+
const options: any = rawOptions && typeof rawOptions === 'object' ? { ...rawOptions } : {};
|
|
48
|
+
|
|
49
|
+
// Always ensure client is set (will be set by caller afterwards if missing)
|
|
50
|
+
// We avoid mutating the original object to keep predictable behavior
|
|
51
|
+
|
|
52
|
+
// If developer passed top-level filter/where/fields/order/limit/offset/include
|
|
53
|
+
// without wrapping into query, move them into a filter object for find/findOne
|
|
54
|
+
const method = methodName.toString().toLowerCase();
|
|
55
|
+
const isFind = method.includes('find') && !method.includes('count');
|
|
56
|
+
const isCount = method.includes('count');
|
|
57
|
+
const shouldUseBody = /(create|update|replace|patch|login|upsert)/i.test(methodName.toString());
|
|
58
|
+
|
|
59
|
+
const topLevelKeys = ['filter', 'where', 'fields', 'order', 'limit', 'offset', 'include'];
|
|
60
|
+
const hasTopLevelFilterBits = topLevelKeys.some((k) => Object.prototype.hasOwnProperty.call(options, k));
|
|
61
|
+
|
|
62
|
+
// Only create query if relevant for this method
|
|
63
|
+
if (isFind) {
|
|
64
|
+
options.query = options.query || {};
|
|
65
|
+
// If developer provided a full filter at top-level as object, stringify it
|
|
66
|
+
if (options.filter && typeof options.filter === 'object') {
|
|
67
|
+
options.query.filter = JSON.stringify(options.filter);
|
|
68
|
+
delete options.filter;
|
|
69
|
+
} else if (hasTopLevelFilterBits) {
|
|
70
|
+
const filterObject: any = {};
|
|
71
|
+
if (options.where !== undefined) filterObject.where = options.where;
|
|
72
|
+
if (options.fields !== undefined) filterObject.fields = options.fields;
|
|
73
|
+
if (options.order !== undefined) filterObject.order = options.order;
|
|
74
|
+
if (options.limit !== undefined) filterObject.limit = options.limit;
|
|
75
|
+
if (options.offset !== undefined) filterObject.offset = options.offset;
|
|
76
|
+
if (options.include !== undefined) filterObject.include = options.include;
|
|
77
|
+
if (Object.keys(filterObject).length > 0) {
|
|
78
|
+
options.query.filter = typeof filterObject === 'string' ? filterObject : JSON.stringify(filterObject);
|
|
79
|
+
}
|
|
80
|
+
// Clean moved keys from top-level
|
|
81
|
+
topLevelKeys.forEach((k) => delete options[k]);
|
|
82
|
+
}
|
|
83
|
+
} else if (isCount) {
|
|
84
|
+
options.query = options.query || {};
|
|
85
|
+
// Allow top-level where or query.where as object → stringify
|
|
86
|
+
if (options.where !== undefined) {
|
|
87
|
+
const whereVal = options.where;
|
|
88
|
+
options.query.where = typeof whereVal === 'string' ? whereVal : JSON.stringify(whereVal);
|
|
89
|
+
delete options.where;
|
|
90
|
+
}
|
|
91
|
+
} else if (shouldUseBody) {
|
|
92
|
+
// For create/update-like methods: allow passing the payload at top-level → move to body
|
|
93
|
+
if (options.body === undefined) {
|
|
94
|
+
const bodyCandidate: any = { ...options };
|
|
95
|
+
delete bodyCandidate.client;
|
|
96
|
+
delete bodyCandidate.query;
|
|
97
|
+
delete bodyCandidate.path;
|
|
98
|
+
if (Object.keys(bodyCandidate).length > 0) {
|
|
99
|
+
options.body = bodyCandidate;
|
|
100
|
+
// Keep only body/client/query/path at root
|
|
101
|
+
Object.keys(options).forEach((k) => {
|
|
102
|
+
if (!['body', 'client', 'query', 'path'].includes(k)) delete options[k];
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// If developer already provided query, stringify any object/array values automatically
|
|
109
|
+
if (options.query && typeof options.query === 'object') {
|
|
110
|
+
Object.keys(options.query).forEach((key) => {
|
|
111
|
+
const val = options.query[key];
|
|
112
|
+
if (val && (Array.isArray(val) || typeof val === 'object')) {
|
|
113
|
+
options.query[key] = JSON.stringify(val);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return options;
|
|
119
|
+
}
|
|
120
|
+
|
|
43
121
|
constructor(options: {
|
|
44
122
|
baseURL: string;
|
|
45
123
|
email?: string;
|
|
@@ -160,11 +238,10 @@ class NextPlusSDK {
|
|
|
160
238
|
if (typeof target[prop] === 'function') {
|
|
161
239
|
return async function(...args: any[]) {
|
|
162
240
|
// Automatically inject client if not provided
|
|
163
|
-
if (args[0]
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
241
|
+
if (!args[0]) args[0] = {};
|
|
242
|
+
// Normalize developer-friendly input into OpenAPI options
|
|
243
|
+
args[0] = self.normalizeOptions(String(prop), args[0]);
|
|
244
|
+
if (!args[0].client) args[0].client = self.client;
|
|
168
245
|
|
|
169
246
|
const result = await target[prop].apply(target, args);
|
|
170
247
|
|
|
@@ -194,15 +271,24 @@ class NextPlusSDK {
|
|
|
194
271
|
}
|
|
195
272
|
}
|
|
196
273
|
|
|
274
|
+
// Expose accurate static service method types on the SDK instance for IDE/type safety
|
|
275
|
+
type ServiceStatics = {
|
|
276
|
+
[K in keyof typeof AllServiceTypes as K extends `${string}Service` ? K : never]: typeof AllServiceTypes[K];
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
export interface NextPlusSDK extends ServiceStatics {}
|
|
280
|
+
|
|
197
281
|
// Legacy function for backward compatibility
|
|
282
|
+
type SDKInstance = NextPlusSDK & ServiceStatics;
|
|
283
|
+
|
|
198
284
|
const configure = (options: {
|
|
199
285
|
baseURL: string;
|
|
200
286
|
email?: string;
|
|
201
287
|
username?: string;
|
|
202
288
|
password: string;
|
|
203
289
|
returnType?: 'raw' | 'data';
|
|
204
|
-
}) => {
|
|
205
|
-
return new NextPlusSDK(options);
|
|
290
|
+
}): SDKInstance => {
|
|
291
|
+
return new NextPlusSDK(options) as SDKInstance;
|
|
206
292
|
};
|
|
207
293
|
|
|
208
294
|
// Create SDK instance
|
|
@@ -212,8 +298,9 @@ const createSDK = (options: {
|
|
|
212
298
|
username?: string;
|
|
213
299
|
password: string;
|
|
214
300
|
returnType?: 'raw' | 'data';
|
|
215
|
-
}) => {
|
|
216
|
-
return new NextPlusSDK(options);
|
|
301
|
+
}): SDKInstance => {
|
|
302
|
+
return new NextPlusSDK(options) as SDKInstance;
|
|
217
303
|
};
|
|
218
304
|
|
|
219
|
-
export {
|
|
305
|
+
export type { SDKInstance };
|
|
306
|
+
export { configure, createSDK };
|
package/src/sdk/types.gen.ts
CHANGED
|
@@ -32619,6 +32619,7 @@ export type TableGetTableCountData = {
|
|
|
32619
32619
|
};
|
|
32620
32620
|
query?: {
|
|
32621
32621
|
where?: string;
|
|
32622
|
+
deleted?: boolean;
|
|
32622
32623
|
};
|
|
32623
32624
|
url: '/Tables/getTableCount/{tableId}';
|
|
32624
32625
|
};
|
package/src/smoke.ts
CHANGED
|
@@ -12,12 +12,22 @@ async function main() {
|
|
|
12
12
|
console.log('SDK configured (email)');
|
|
13
13
|
|
|
14
14
|
// Test with returnType: 'data' - should return only the data array
|
|
15
|
-
const tables = await
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
const tables = await sdk.TableService.find({
|
|
16
|
+
query: {
|
|
17
|
+
filter: JSON.stringify({
|
|
18
|
+
language: 'he',
|
|
19
|
+
limit: 10,
|
|
20
|
+
order: 'created DESC',
|
|
21
|
+
fields: {
|
|
22
|
+
id: true,
|
|
23
|
+
name: true,
|
|
24
|
+
created: true
|
|
25
|
+
},
|
|
26
|
+
where: {
|
|
27
|
+
name: 'no-such-table!'
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
}
|
|
21
31
|
});
|
|
22
32
|
|
|
23
33
|
console.log(
|
|
@@ -26,9 +36,7 @@ async function main() {
|
|
|
26
36
|
);
|
|
27
37
|
// Test validation error handling
|
|
28
38
|
try {
|
|
29
|
-
const newTable = await
|
|
30
|
-
body: {},
|
|
31
|
-
});
|
|
39
|
+
const newTable = await sdk.TableService.create({ body: {} } as any);
|
|
32
40
|
console.log('New table created:', newTable);
|
|
33
41
|
} catch (error: any) {
|
|
34
42
|
console.log('Expected validation error caught:', error.message);
|
|
@@ -46,12 +54,15 @@ async function main() {
|
|
|
46
54
|
console.log('SDK configured (username)');
|
|
47
55
|
|
|
48
56
|
// Test with returnType: 'raw' - should return { data, request, response }
|
|
49
|
-
const tablesRaw = await
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
const tablesRaw = await sdk2.TableService.find({
|
|
58
|
+
query: {
|
|
59
|
+
filter: JSON.stringify({
|
|
60
|
+
where: {
|
|
61
|
+
name: 'test'
|
|
62
|
+
},
|
|
63
|
+
limit: 5
|
|
64
|
+
})
|
|
65
|
+
}
|
|
55
66
|
});
|
|
56
67
|
|
|
57
68
|
console.log('Tables found (raw response):', {
|
|
@@ -62,9 +73,7 @@ async function main() {
|
|
|
62
73
|
});
|
|
63
74
|
|
|
64
75
|
try {
|
|
65
|
-
const createTable = await
|
|
66
|
-
body: {},
|
|
67
|
-
});
|
|
76
|
+
const createTable = await sdk2.TableService.create({ body: {} } as any);
|
|
68
77
|
console.log('Table created:', createTable);
|
|
69
78
|
} catch (error: any) {
|
|
70
79
|
console.log('Expected validation error caught (raw mode):', error.message);
|
package/openapi-ts.config.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from '@hey-api/openapi-ts';
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
input: 'http://127.0.0.1:3000/explorer/swagger.json',
|
|
5
|
-
output: {
|
|
6
|
-
format: 'prettier',
|
|
7
|
-
lint: 'eslint',
|
|
8
|
-
path: './src/sdk',
|
|
9
|
-
},
|
|
10
|
-
plugins: [
|
|
11
|
-
'@hey-api/schemas',
|
|
12
|
-
{
|
|
13
|
-
dates: true,
|
|
14
|
-
name: '@hey-api/transformers',
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
enums: 'javascript',
|
|
18
|
-
name: '@hey-api/typescript',
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
name: '@hey-api/sdk',
|
|
22
|
-
asClass: true,
|
|
23
|
-
transformer: true,
|
|
24
|
-
classNameBuilder(name) {
|
|
25
|
-
return `${name}Service`;
|
|
26
|
-
},
|
|
27
|
-
methodNameBuilder(operation) {
|
|
28
|
-
return String(operation.id);
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
enums: 'javascript',
|
|
33
|
-
name: '@hey-api/typescript',
|
|
34
|
-
},
|
|
35
|
-
],
|
|
36
|
-
});
|
package/prettier.config.js
DELETED
package/tsconfig.json
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"useDefineForClassFields": true,
|
|
5
|
-
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
-
"module": "ESNext",
|
|
7
|
-
"skipLibCheck": true,
|
|
8
|
-
"rewriteRelativeImportExtensions": true,
|
|
9
|
-
/* Bundler mode */
|
|
10
|
-
"moduleResolution": "bundler",
|
|
11
|
-
"resolveJsonModule": true,
|
|
12
|
-
"isolatedModules": true,
|
|
13
|
-
"noEmit": false,
|
|
14
|
-
"declaration": true,
|
|
15
|
-
"outDir": "./dist",
|
|
16
|
-
"strict": true,
|
|
17
|
-
"noUnusedLocals": true,
|
|
18
|
-
"noUnusedParameters": true,
|
|
19
|
-
"noFallthroughCasesInSwitch": true
|
|
20
|
-
},
|
|
21
|
-
"include": ["src"],
|
|
22
|
-
"references": [{ "path": "./tsconfig.node.json" }]
|
|
23
|
-
}
|