swaggie 2.1.4 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/cli.js +12 -6
- package/dist/generated/bundledTemplates.js +1 -1
- package/dist/index.js +144 -20
- package/dist/types.d.ts +5 -0
- package/package.json +1 -1
- package/templates/swr/swrOperation.ejs +2 -2
package/README.md
CHANGED
|
@@ -543,4 +543,5 @@ function error(e) {
|
|
|
543
543
|
<a href="https://www.britishcouncil.org"><img alt="British Council" src="./docs/public/used-in/bc-logo.png" /></a>
|
|
544
544
|
<a href="https://kpmg.com/"><img alt="KPMG" src="./docs/public/used-in/kpmg-logo.png" /></a>
|
|
545
545
|
<a href="https://klarna.com/"><img alt="Klarna" src="./docs/public/used-in/klarna-logo.png" /></a>
|
|
546
|
+
<a href="https://cribl.io/"><img alt="Cribl" src="./docs/public/used-in/cribl-logo.png" /></a>
|
|
546
547
|
</div>
|
package/dist/cli.js
CHANGED
|
@@ -131,12 +131,18 @@ const options = program.opts();
|
|
|
131
131
|
|
|
132
132
|
_index.runCodeGenerator.call(void 0, options ).then(complete, error);
|
|
133
133
|
|
|
134
|
-
function complete(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
134
|
+
function complete(result) {
|
|
135
|
+
const results = Array.isArray(result[0])
|
|
136
|
+
? (result )
|
|
137
|
+
: [result ];
|
|
138
|
+
|
|
139
|
+
for (const [code, opts] of results) {
|
|
140
|
+
if (opts.out) {
|
|
141
|
+
const from = typeof opts.src === 'string' ? `from ${_picocolors.bold.call(void 0, opts.src)} ` : '';
|
|
142
|
+
console.info(_picocolors.cyan.call(void 0, `Api ${from}code generated into ${_picocolors.bold.call(void 0, opts.out)}`));
|
|
143
|
+
} else {
|
|
144
|
+
console.log(code);
|
|
145
|
+
}
|
|
140
146
|
}
|
|
141
147
|
|
|
142
148
|
process.exit(0);
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"client.ejs": "export const <%= it.camelCaseName -%>Client = {\n <% it.operations.forEach((operation) => { %>\n<%~ include('operation.ejs', operation); %>\n\n <% }); %>\n};\n\n<% if (!it.splitMode) { %>\n<%\nvar getOperations = it.operations.filter((o) => o.method === 'GET');\nvar mutationOperations = it.operations.filter((o) => o.method !== 'GET');\n%>\n\nexport const <%= it.hooksCamelCaseName %> = {\n queries: {\n<% getOperations.forEach((operation) => {\n var opName = it.toOpName(operation.name);\n var swrOperation = Object.assign({\n swrOpName: 'use' + opName,\n clientName: it.hooksCamelCaseName,\n httpClientName: it.camelCaseName,\n httpConfigType: it.httpConfigType,\n responseMapper: it.responseMapper,\n }, it.safeOperation(operation, it.camelCaseName));\n%>\n<%~ include('swrOperation.ejs', swrOperation); %>\n\n<% }); %>\n },\n\n mutations: {\n<% mutationOperations.forEach((operation) => {\n var opName = operation.name.charAt(0).toUpperCase() + operation.name.slice(1);\n var swrMutationOperation = Object.assign({\n mutOpName: 'use' + opName,\n clientName: it.hooksCamelCaseName,\n httpClientName: it.camelCaseName,\n httpConfigType: it.httpConfigType,\n responseMapper: it.responseMapper,\n }, it.safeOperation(operation, it.camelCaseName));\n%>\n<%~ include('swrMutationOperation.ejs', swrMutationOperation); %>\n\n<% }); %>\n },\n\n queryKeys: {\n<% getOperations.forEach((operation) => {\n var opName = it.toOpName(operation.name);\n var keyName = opName.charAt(0).toLowerCase() + opName.slice(1);\n var safeOp = it.safeOperation(operation, it.camelCaseName);\n%>\n <%= keyName %>: (<% safeOp.parameters.forEach((parameter) => { %><%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %><%= parameter.optional ? (parameter.skippable ? ' | null' : ' | null | undefined') : '' %>, <% }); %>) => `<%= operation.url %><% if(safeOp.query && safeOp.query.length > 0) { %>?${encodeParams({<% safeOp.query.forEach((parameter) => { %>'<%= parameter.originalName %>': <%= safeOp.queryParamObject ? `${safeOp.queryParamObject.name}?.${parameter.name}` : parameter.name %>, <% }); %>})}<% } %>`,\n<% }); %>\n },\n};\n<% } /* end !splitMode */ %>\n",
|
|
42
42
|
"hooksClient.ejs": "<%\nvar getOperations = it.operations.filter((o) => o.method === 'GET');\nvar mutationOperations = it.operations.filter((o) => o.method !== 'GET');\nvar httpClientPrefix = 'API.' + it.camelCaseName;\n%>\n\nexport const <%= it.hooksCamelCaseName %> = {\n queries: {\n<% getOperations.forEach((operation) => {\n var opName = it.toOpName(operation.name);\n var safe = it.safeOperation(operation, it.camelCaseName);\n var swrOperation = Object.assign({}, safe, {\n swrOpName: 'use' + opName,\n clientName: it.hooksCamelCaseName,\n httpClientName: httpClientPrefix,\n httpConfigType: it.httpConfigType,\n responseMapper: it.responseMapper,\n returnType: it.prefixApiType(safe.returnType),\n parameters: safe.parameters.map(function(p) {\n return Object.assign({}, p, { type: it.prefixApiType(p.type) });\n }),\n });\n%>\n<%~ include('swrOperation.ejs', swrOperation); %>\n\n<% }); %>\n },\n\n mutations: {\n<% mutationOperations.forEach((operation) => {\n var opName = operation.name.charAt(0).toUpperCase() + operation.name.slice(1);\n var safe = it.safeOperation(operation, it.camelCaseName);\n var swrMutationOperation = Object.assign({}, safe, {\n mutOpName: 'use' + opName,\n clientName: it.hooksCamelCaseName,\n httpClientName: httpClientPrefix,\n httpConfigType: it.httpConfigType,\n responseMapper: it.responseMapper,\n returnType: it.prefixApiType(safe.returnType),\n parameters: safe.parameters.map(function(p) {\n return Object.assign({}, p, { type: it.prefixApiType(p.type) });\n }),\n });\n%>\n<%~ include('swrMutationOperation.ejs', swrMutationOperation); %>\n\n<% }); %>\n },\n\n queryKeys: {\n<% getOperations.forEach((operation) => {\n var opName = it.toOpName(operation.name);\n var keyName = opName.charAt(0).toLowerCase() + opName.slice(1);\n var safeOp = it.safeOperation(operation, it.camelCaseName);\n var prefixedParams = safeOp.parameters.map(function(p) {\n return Object.assign({}, p, { type: it.prefixApiType(p.type) });\n });\n%>\n <%= keyName %>: (<% prefixedParams.forEach((parameter) => { %><%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %><%= parameter.optional ? (parameter.skippable ? ' | null' : ' | null | undefined') : '' %>, <% }); %>) => `<%= operation.url %><% if(safeOp.query && safeOp.query.length > 0) { %>?${API.encodeParams({<% safeOp.query.forEach((parameter) => { %>'<%= parameter.originalName %>': <%= safeOp.queryParamObject ? `${safeOp.queryParamObject.name}?.${parameter.name}` : parameter.name %>, <% }); %>})}<% } %>`,\n<% }); %>\n },\n};\n",
|
|
43
43
|
"swrMutationOperation.ejs": "<%\nvar hasParams = it.parameters.length > 0;\n\nvar variablesType;\nif (!hasParams) {\n variablesType = 'void';\n} else {\n var parts = it.parameters.map(function(p) {\n return p.name + (p.skippable ? '?' : '') + ': ' + p.type + (p.optional ? ' | null' : '');\n });\n variablesType = '{ ' + parts.join('; ') + ' }';\n}\n\nvar callArgs = it.parameters.map(function(p) { return 'arg.' + p.name; });\n\n// Stable SWR key: replace all ${...} path expressions with *\nvar swrKey = it.url.replace(/\\$\\{(?:[^{}]|\\{[^{}]*\\})*\\}/g, '*');\n\nvar docs = it.jsDocs ? it.jsDocs.replace(/^/gm, ' ') + '\\n' : '';\nvar httpClientName = it.httpClientName || it.clientName;\n%>\n<%~ docs %>\n <%= it.mutOpName %>(\n $config?: SWRMutationConfiguration<<%~ it.returnType %>, Error, string, <%~ variablesType %>>,\n $httpConfig?: <%= it.httpConfigType %>\n ) {\n return useSWRMutation<<%~ it.returnType %>, Error, string, <%~ variablesType %>>(\n '<%= swrKey %>',\n (_key: string, { arg }<%~ hasParams ? ': { arg: ' + variablesType + ' }' : '' %>) =>\n <%= httpClientName %>Client.<%= it.name %>(<%= callArgs.join(', ') %><%= callArgs.length > 0 ? ', ' : '' %>$httpConfig)<%~ it.responseMapper %>,\n $config\n );\n },\n",
|
|
44
|
-
"swrOperation.ejs": "<% var docs = it.jsDocs ? it.jsDocs.replace(/^/gm, ' ') + '\\n' : ''; %>\n<% var httpClientName = it.httpClientName || it.clientName; %>\n<%~ docs %>\n <%= it.swrOpName %>(\n<% it.parameters.forEach((parameter) => { %> <%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %><%= parameter.optional ? (parameter.skippable ? ' | null' : ' | null | undefined') : '' %>,\n<% }); %> $config?: Omit<SwrConfig, 'key'> & { key?: Key },\n $httpConfig?: <%= it.httpConfigType %>\n ) {\n const { key, ...config } = $config || {};\n const cacheUrl = key ?? <%= it.clientName %>.queryKeys.<%= it.swrOpName.charAt(3).toLowerCase() + it.swrOpName.slice(4) %>(<% it.parameters.forEach((parameter) => { %><%= parameter.name %>, <% }); %>);\n\n const { data, error, isLoading, mutate } = useSWR<<%~ it.returnType %>>(\n cacheUrl,\n () => <%= httpClientName %>Client.<%= it.name %>(<% it.parameters.forEach((parameter) => { %><%= parameter.name %>, <% }); %>$httpConfig)<%~ it.responseMapper %>,\n config\n );\n\n return { data, isLoading, error, mutate };\n },\n"
|
|
44
|
+
"swrOperation.ejs": "<% var docs = it.jsDocs ? it.jsDocs.replace(/^/gm, ' ') + '\\n' : ''; %>\n<% var httpClientName = it.httpClientName || it.clientName; %>\n<%~ docs %>\n <%= it.swrOpName %>(\n<% it.parameters.forEach((parameter) => { %> <%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %><%= parameter.optional ? (parameter.skippable ? ' | null' : ' | null | undefined') : '' %>,\n<% }); %> $config?: Omit<SwrConfig, 'key'> & { key?: Key },\n $httpConfig?: <%= it.httpConfigType %>\n ) {\n const { key, ...config } = $config || {};\n const cacheUrl = key ?? <%= it.clientName %>.queryKeys.<%= it.swrOpName.charAt(3).toLowerCase() + it.swrOpName.slice(4) %>(<% it.parameters.forEach((parameter) => { %><%= parameter.name %>, <% }); %>);\n\n const { data, error, isLoading, isValidating, mutate } = useSWR<<%~ it.returnType %>>(\n cacheUrl,\n () => <%= httpClientName %>Client.<%= it.name %>(<% it.parameters.forEach((parameter) => { %><%= parameter.name %>, <% }); %>$httpConfig)<%~ it.responseMapper %>,\n config\n );\n\n return { data, isLoading, isValidating, error, mutate };\n },\n"
|
|
45
45
|
},
|
|
46
46
|
"tsq": {
|
|
47
47
|
"baseClient.ejs": "import { type UseQueryOptions, type UseMutationOptions, useQuery, useMutation } from '@tanstack/react-query';\n",
|
package/dist/index.js
CHANGED
|
@@ -3,23 +3,47 @@
|
|
|
3
3
|
|
|
4
4
|
var _gen = require('./gen'); var _gen2 = _interopRequireDefault(_gen);
|
|
5
5
|
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
6
13
|
var _utils = require('./utils');
|
|
7
14
|
var _templateValidator = require('./utils/templateValidator');
|
|
8
15
|
var _swagger = require('./swagger');
|
|
9
16
|
|
|
10
17
|
/**
|
|
11
18
|
* Runs the whole code generation process.
|
|
12
|
-
*
|
|
19
|
+
* When the config file contains an array of configs, returns `BatchCodeGenResult`
|
|
20
|
+
* (an array of results, one per entry, fail-fast on first error).
|
|
21
|
+
* Otherwise returns a single `CodeGenResult`.
|
|
13
22
|
**/
|
|
14
|
-
async function runCodeGenerator(
|
|
23
|
+
async function runCodeGenerator(
|
|
24
|
+
options
|
|
25
|
+
) {
|
|
15
26
|
try {
|
|
16
27
|
verifyOptions(options);
|
|
17
|
-
const
|
|
18
|
-
|
|
28
|
+
const optsOrArray = await applyConfigFile(options);
|
|
29
|
+
|
|
30
|
+
if (Array.isArray(optsOrArray)) {
|
|
31
|
+
const results = [];
|
|
32
|
+
for (const opts of optsOrArray) {
|
|
33
|
+
verifyEntryOptions(opts);
|
|
34
|
+
const spec = await _utils.loadSpecDocument.call(void 0, opts.src);
|
|
35
|
+
const verifiedSpec = _utils.verifyDocumentSpec.call(void 0, spec);
|
|
36
|
+
const code = await gen(verifiedSpec, opts);
|
|
37
|
+
results.push([code, opts]);
|
|
38
|
+
}
|
|
39
|
+
return results;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const spec = await _utils.loadSpecDocument.call(void 0, optsOrArray.src);
|
|
19
43
|
const verifiedSpec = _utils.verifyDocumentSpec.call(void 0, spec);
|
|
20
|
-
const code = await gen(verifiedSpec,
|
|
44
|
+
const code = await gen(verifiedSpec, optsOrArray);
|
|
21
45
|
|
|
22
|
-
return [code,
|
|
46
|
+
return [code, optsOrArray];
|
|
23
47
|
} catch (e) {
|
|
24
48
|
return Promise.reject(e);
|
|
25
49
|
}
|
|
@@ -64,6 +88,82 @@ function verifyOptions(options) {
|
|
|
64
88
|
}
|
|
65
89
|
}
|
|
66
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Validates options that apply to each individual entry in an array config.
|
|
93
|
+
* Covers the same constraints as `verifyOptions` but scoped to a single
|
|
94
|
+
* fully-resolved `AppOptions` entry (after config merging and defaults).
|
|
95
|
+
*/
|
|
96
|
+
function verifyEntryOptions(opts) {
|
|
97
|
+
if (!opts.src) {
|
|
98
|
+
throw new Error('Each config entry must have "src" set');
|
|
99
|
+
}
|
|
100
|
+
if (!!opts.mocks !== !!opts.testingFramework) {
|
|
101
|
+
throw new Error('--mocks and --testingFramework must be used together');
|
|
102
|
+
}
|
|
103
|
+
if (opts.mocks && !opts.out) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
'"mocks" requires "out" to be set, since the mock file needs to import the generated client'
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
if (opts.hooksOut && !opts.out) {
|
|
109
|
+
throw new Error('"hooksOut" requires "out" to be set');
|
|
110
|
+
}
|
|
111
|
+
if (opts.clientSetup && !opts.out) {
|
|
112
|
+
throw new Error('"clientSetup" requires "out" to be set');
|
|
113
|
+
}
|
|
114
|
+
if (opts.forceSetup && !opts.clientSetup) {
|
|
115
|
+
throw new Error('"forceSetup" requires "clientSetup" to be set');
|
|
116
|
+
}
|
|
117
|
+
if (opts.hooksOut) {
|
|
118
|
+
const tpl = opts.template;
|
|
119
|
+
const isL2 =
|
|
120
|
+
(typeof tpl === 'string' && _templateValidator.isL2Template.call(void 0, tpl)) ||
|
|
121
|
+
(Array.isArray(tpl) && typeof tpl[0] === 'string' && _templateValidator.isL2Template.call(void 0, tpl[0]));
|
|
122
|
+
if (!isL2) {
|
|
123
|
+
throw new Error(
|
|
124
|
+
'"hooksOut" requires an L2 template (swr, tsq). ' +
|
|
125
|
+
'Reactive hooks are only generated for L2 template pairs.'
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Throws if any per-entry-only keys are present as top-level defaults in a
|
|
133
|
+
* multi-config file. These keys must live inside each entry under "configs".
|
|
134
|
+
*/
|
|
135
|
+
function verifyTopLevelDefaults(configUrl, defaults) {
|
|
136
|
+
const blocked = ['src', 'out', 'hooksOut', 'mocks', 'clientSetup'];
|
|
137
|
+
for (const key of blocked) {
|
|
138
|
+
if (key in defaults) {
|
|
139
|
+
throw new Error(
|
|
140
|
+
`"${key}" cannot be a top-level default in multi-config file "${configUrl}". ` +
|
|
141
|
+
`Set it inside each entry under "configs" instead.`
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Throws if any file-path CLI flags are combined with a multi-config file.
|
|
149
|
+
* Each entry in "configs" must define its own output paths.
|
|
150
|
+
*/
|
|
151
|
+
function verifyOptionsForArrayConfig(options) {
|
|
152
|
+
const blocked = [
|
|
153
|
+
['out', '--out'],
|
|
154
|
+
['hooksOut', '--hooksOut'],
|
|
155
|
+
['mocks', '--mocks'],
|
|
156
|
+
['clientSetup', '--clientSetup'],
|
|
157
|
+
];
|
|
158
|
+
for (const [key, flag] of blocked) {
|
|
159
|
+
if (options[key]) {
|
|
160
|
+
throw new Error(
|
|
161
|
+
`${flag} cannot be used with a multi-config file. Set "${key}" in each entry under "configs" instead.`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
67
167
|
function gen(spec, options) {
|
|
68
168
|
if (options.generationMode === 'full') {
|
|
69
169
|
_templateValidator.validateTemplate.call(void 0, options.template);
|
|
@@ -76,25 +176,49 @@ function gen(spec, options) {
|
|
|
76
176
|
async function applyConfigFile(
|
|
77
177
|
options
|
|
78
178
|
) {
|
|
179
|
+
if (!options.config) {
|
|
180
|
+
return prepareAppOptions(options );
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const configUrl = options.config;
|
|
184
|
+
let configContents;
|
|
185
|
+
let parsedConfig;
|
|
186
|
+
|
|
79
187
|
try {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
188
|
+
configContents = await readFile(configUrl);
|
|
189
|
+
parsedConfig = JSON.parse(configContents);
|
|
190
|
+
} catch (_e) {
|
|
191
|
+
return Promise.reject(
|
|
192
|
+
new Error('Could not correctly load config file. It does not exist or you cannot access it')
|
|
193
|
+
);
|
|
194
|
+
}
|
|
83
195
|
|
|
84
|
-
|
|
85
|
-
const configContents = await readFile(configUrl);
|
|
86
|
-
const parsedConfig = JSON.parse(configContents);
|
|
87
|
-
if (!parsedConfig || parsedConfig.length < 1) {
|
|
88
|
-
throw new Error(
|
|
89
|
-
`Could not correctly parse config file from "${configUrl}". Is it a valid JSON file?`
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
return prepareAppOptions({ ...parsedConfig, ...options });
|
|
93
|
-
} catch (e) {
|
|
196
|
+
if (!parsedConfig || typeof parsedConfig !== 'object') {
|
|
94
197
|
return Promise.reject(
|
|
95
198
|
new Error('Could not correctly load config file. It does not exist or you cannot access it')
|
|
96
199
|
);
|
|
97
200
|
}
|
|
201
|
+
|
|
202
|
+
if ('configs' in (parsedConfig )) {
|
|
203
|
+
const { configs: entries, ...topLevelDefaults } = parsedConfig
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
;
|
|
207
|
+
if (!Array.isArray(entries) || entries.length < 1) {
|
|
208
|
+
return Promise.reject(
|
|
209
|
+
new Error(
|
|
210
|
+
`Config file "${configUrl}" has a "configs" key but it is not a non-empty array. Provide at least one config entry.`
|
|
211
|
+
)
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
verifyTopLevelDefaults(configUrl, topLevelDefaults);
|
|
215
|
+
verifyOptionsForArrayConfig(options);
|
|
216
|
+
return entries.map((entry) =>
|
|
217
|
+
prepareAppOptions({ ...topLevelDefaults, ...entry, ...options })
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return prepareAppOptions({ ...parsedConfig, ...options } );
|
|
98
222
|
} exports.applyConfigFile = applyConfigFile;
|
|
99
223
|
|
|
100
224
|
function readFile(filePath) {
|
|
@@ -103,7 +227,7 @@ function readFile(filePath) {
|
|
|
103
227
|
});
|
|
104
228
|
}
|
|
105
229
|
|
|
106
|
-
|
|
230
|
+
;
|
|
107
231
|
|
|
108
232
|
/**
|
|
109
233
|
* CLI options are flat, but within the app we use nested objects.
|
package/dist/types.d.ts
CHANGED
|
@@ -171,6 +171,11 @@ export interface AppOptions extends ClientOptions {
|
|
|
171
171
|
mocks?: string;
|
|
172
172
|
testingFramework?: TestingFramework;
|
|
173
173
|
}
|
|
174
|
+
export type CodeGenResult = [string, AppOptions];
|
|
175
|
+
/**
|
|
176
|
+
* Result of a batch run — one entry per config in the array.
|
|
177
|
+
*/
|
|
178
|
+
export type BatchCodeGenResult = CodeGenResult[];
|
|
174
179
|
/**
|
|
175
180
|
* Local type that represent Operation as understood by Swaggie
|
|
176
181
|
**/
|
package/package.json
CHANGED
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
const { key, ...config } = $config || {};
|
|
10
10
|
const cacheUrl = key ?? <%= it.clientName %>.queryKeys.<%= it.swrOpName.charAt(3).toLowerCase() + it.swrOpName.slice(4) %>(<% it.parameters.forEach((parameter) => { %><%= parameter.name %>, <% }); %>);
|
|
11
11
|
|
|
12
|
-
const { data, error, isLoading, mutate } = useSWR<<%~ it.returnType %>>(
|
|
12
|
+
const { data, error, isLoading, isValidating, mutate } = useSWR<<%~ it.returnType %>>(
|
|
13
13
|
cacheUrl,
|
|
14
14
|
() => <%= httpClientName %>Client.<%= it.name %>(<% it.parameters.forEach((parameter) => { %><%= parameter.name %>, <% }); %>$httpConfig)<%~ it.responseMapper %>,
|
|
15
15
|
config
|
|
16
16
|
);
|
|
17
17
|
|
|
18
|
-
return { data, isLoading, error, mutate };
|
|
18
|
+
return { data, isLoading, isValidating, error, mutate };
|
|
19
19
|
},
|