@backstage/repo-tools 0.11.0-next.0 → 0.11.0-next.2
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/CHANGELOG.md +30 -0
- package/dist/commands/generate-patch/generate-patch.cjs.js +321 -0
- package/dist/commands/index.cjs.js +22 -0
- package/dist/commands/package/schema/openapi/generate/client.cjs.js +10 -6
- package/dist/commands/package/schema/openapi/generate/server.cjs.js +84 -17
- package/dist/commands/repo/schema/openapi/verify.cjs.js +8 -3
- package/dist/lib/openapi/constants.cjs.js +5 -2
- package/dist/package.json.cjs.js +1 -1
- package/package.json +9 -8
- package/templates/{typescript-backstage → typescript-backstage-client}/api.mustache +37 -29
- package/templates/{typescript-backstage → typescript-backstage-client}/modelAlias.mustache +3 -0
- package/templates/{typescript-backstage → typescript-backstage-client}/modelEnum.mustache +9 -0
- package/templates/{typescript-backstage → typescript-backstage-client}/modelGeneric.mustache +11 -4
- package/templates/{typescript-backstage → typescript-backstage-client}/modelGenericEnums.mustache +13 -0
- package/templates/{typescript-backstage → typescript-backstage-client}/modelOneOf.mustache +3 -2
- package/templates/typescript-backstage-client.yaml +40 -0
- package/templates/typescript-backstage-server/api.mustache +54 -0
- package/templates/typescript-backstage-server/apis/index.mustache +3 -0
- package/templates/typescript-backstage-server/index.mustache +4 -0
- package/templates/typescript-backstage-server/licenseInfo.mustache +5 -0
- package/templates/typescript-backstage-server/model.mustache +11 -0
- package/templates/typescript-backstage-server/modelAlias.mustache +6 -0
- package/templates/typescript-backstage-server/modelEnum.mustache +31 -0
- package/templates/typescript-backstage-server/modelGeneric.mustache +45 -0
- package/templates/typescript-backstage-server/modelGenericAdditionalProperties.mustache +5 -0
- package/templates/typescript-backstage-server/modelGenericEnums.mustache +45 -0
- package/templates/typescript-backstage-server/modelOneOf.mustache +17 -0
- package/templates/typescript-backstage-server/modelTaggedUnion.mustache +23 -0
- package/templates/typescript-backstage-server/models/models_all.mustache +7 -0
- package/templates/{typescript-backstage.yaml → typescript-backstage-server.yaml} +9 -11
- /package/templates/{typescript-backstage → typescript-backstage-client}/apis/index.mustache +0 -0
- /package/templates/{typescript-backstage → typescript-backstage-client}/index.mustache +0 -0
- /package/templates/{typescript-backstage → typescript-backstage-client}/licenseInfo.mustache +0 -0
- /package/templates/{typescript-backstage → typescript-backstage-client}/model.mustache +0 -0
- /package/templates/{typescript-backstage → typescript-backstage-client}/modelGenericAdditionalProperties.mustache +0 -0
- /package/templates/{typescript-backstage → typescript-backstage-client}/modelTaggedUnion.mustache +0 -0
- /package/templates/{typescript-backstage → typescript-backstage-client}/models/models_all.mustache +0 -0
- /package/templates/{typescript-backstage → typescript-backstage-client}/pluginId.mustache +0 -0
- /package/templates/{typescript-backstage → typescript-backstage-client}/types/discovery.ts +0 -0
- /package/templates/{typescript-backstage → typescript-backstage-client}/types/fetch.ts +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @backstage/repo-tools
|
|
2
2
|
|
|
3
|
+
## 0.11.0-next.2
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 1440232: `backstage-repo-tools package schema openapi generate --server` now generates complete TS interfaces for all request/response objects in your OpenAPI schema. This fixes an edge case around recursive schemas and standardizes both the generated client and server to have similar generated types.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
- @backstage/backend-plugin-api@1.0.2-next.2
|
|
13
|
+
- @backstage/catalog-model@1.7.0
|
|
14
|
+
- @backstage/cli-common@0.1.15-next.0
|
|
15
|
+
- @backstage/cli-node@0.2.10-next.0
|
|
16
|
+
- @backstage/config-loader@1.9.2-next.0
|
|
17
|
+
- @backstage/errors@1.2.4
|
|
18
|
+
|
|
19
|
+
## 0.11.0-next.1
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- dde85ee: Added a new `generate-patch` command that can be used to generate patches for current changes in a source workspace to be installed it a target workspace.
|
|
24
|
+
- 702f41d: Bumped dev dependencies `@types/node`
|
|
25
|
+
- Updated dependencies
|
|
26
|
+
- @backstage/cli-common@0.1.15-next.0
|
|
27
|
+
- @backstage/backend-plugin-api@1.0.2-next.1
|
|
28
|
+
- @backstage/catalog-model@1.7.0
|
|
29
|
+
- @backstage/cli-node@0.2.10-next.0
|
|
30
|
+
- @backstage/config-loader@1.9.2-next.0
|
|
31
|
+
- @backstage/errors@1.2.4
|
|
32
|
+
|
|
3
33
|
## 0.11.0-next.0
|
|
4
34
|
|
|
5
35
|
### Minor Changes
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var getPackages = require('@manypkg/get-packages');
|
|
6
|
+
var os = require('os');
|
|
7
|
+
var fs = require('fs-extra');
|
|
8
|
+
var path = require('path');
|
|
9
|
+
var exec = require('../../lib/exec.cjs.js');
|
|
10
|
+
var errors = require('@backstage/errors');
|
|
11
|
+
var stream = require('stream');
|
|
12
|
+
var promises = require('stream/promises');
|
|
13
|
+
var tar = require('tar');
|
|
14
|
+
|
|
15
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
16
|
+
|
|
17
|
+
var os__default = /*#__PURE__*/_interopDefaultCompat(os);
|
|
18
|
+
var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
19
|
+
var tar__default = /*#__PURE__*/_interopDefaultCompat(tar);
|
|
20
|
+
|
|
21
|
+
const DEFAULT_REGISTRY_URL = "https://registry.npmjs.org";
|
|
22
|
+
const PATCH_GITIGNORE = [
|
|
23
|
+
// Avoid generating patches for source maps
|
|
24
|
+
"*.map",
|
|
25
|
+
// Patching package.json has no effect, so exclude
|
|
26
|
+
"package.json",
|
|
27
|
+
// No point patching docs
|
|
28
|
+
"/*.md",
|
|
29
|
+
"/docs"
|
|
30
|
+
];
|
|
31
|
+
const GIT_ENV = {
|
|
32
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
33
|
+
HOME: "",
|
|
34
|
+
XDG_CONFIG_HOME: "",
|
|
35
|
+
USERPROFILE: ""
|
|
36
|
+
};
|
|
37
|
+
var generatePatch = async (packageArg, opts) => {
|
|
38
|
+
const sourceRepo = await getPackages.getPackages(process.cwd());
|
|
39
|
+
const targetRepo = await getPackages.getPackages(opts.target);
|
|
40
|
+
const registryUrl = opts.registryUrl || DEFAULT_REGISTRY_URL;
|
|
41
|
+
if (targetRepo.tool !== "yarn") {
|
|
42
|
+
throw new Error(
|
|
43
|
+
`Unable to generate patch for target repo, tool is not supported: ${targetRepo.tool}`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
if (sourceRepo.root.dir === targetRepo.root.dir) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`Unexpected workspace roots, source and target repo are the same: ${sourceRepo.root.dir}`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
await verifyYarnVersion(sourceRepo.root.dir);
|
|
52
|
+
await verifyYarnVersion(targetRepo.root.dir);
|
|
53
|
+
const sourcePkg = sourceRepo.packages.find(
|
|
54
|
+
(pkg) => pkg.packageJson.name === packageArg || path.relative(sourceRepo.root.dir, pkg.dir) === packageArg
|
|
55
|
+
);
|
|
56
|
+
if (!sourcePkg) {
|
|
57
|
+
throw new Error(`Could not find package ${packageArg} in source repo`);
|
|
58
|
+
}
|
|
59
|
+
const tmpDir = await fs__default.default.mkdtemp(os__default.default.tmpdir());
|
|
60
|
+
const ctx = {
|
|
61
|
+
sourceRepo,
|
|
62
|
+
targetRepo,
|
|
63
|
+
sourcePkg,
|
|
64
|
+
packageName: sourcePkg.packageJson.name,
|
|
65
|
+
targetRoot: targetRepo.root.dir,
|
|
66
|
+
registryUrl,
|
|
67
|
+
workDir: tmpDir
|
|
68
|
+
};
|
|
69
|
+
try {
|
|
70
|
+
const updateTargetRootPkg = await loadTrimmedRootPkg(ctx, opts.query);
|
|
71
|
+
console.log(
|
|
72
|
+
`Building and packaging target package ${sourcePkg.packageJson.name}`
|
|
73
|
+
);
|
|
74
|
+
const targetArchive = await buildTargetArchive(ctx);
|
|
75
|
+
console.log(`Generating patch from ${sourcePkg.packageJson.version}`);
|
|
76
|
+
const patchEntry = await generatePatch$1(
|
|
77
|
+
ctx,
|
|
78
|
+
targetArchive,
|
|
79
|
+
opts.baseVersion || sourcePkg.packageJson.version
|
|
80
|
+
);
|
|
81
|
+
await updateTargetRootPkg(patchEntry);
|
|
82
|
+
if (!opts.skipInstall) {
|
|
83
|
+
console.log("Running 'yarn install' in target workspace");
|
|
84
|
+
await exec.exec("yarn", ["install"], {
|
|
85
|
+
cwd: ctx.targetRoot
|
|
86
|
+
}).catch(() => {
|
|
87
|
+
throw new Error(
|
|
88
|
+
"Failed to run 'yarn install' in target workspace, please run it manually to troubleshoot"
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
} else {
|
|
92
|
+
console.log("Skipped running 'yarn install'");
|
|
93
|
+
}
|
|
94
|
+
} finally {
|
|
95
|
+
fs__default.default.rmSync(tmpDir, { force: true, recursive: true, maxRetries: 3 });
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
async function loadTrimmedRootPkg(ctx, query) {
|
|
99
|
+
const newPkgJson = JSON.parse(
|
|
100
|
+
JSON.stringify(ctx.targetRepo.root.packageJson)
|
|
101
|
+
);
|
|
102
|
+
const resolutionsObj = newPkgJson.resolutions || (newPkgJson.resolutions = {});
|
|
103
|
+
const searchEntry = query ? `${ctx.packageName}@${query}` : ctx.packageName;
|
|
104
|
+
if (query || resolutionsObj[searchEntry]) {
|
|
105
|
+
const existingPatchFile = tryParsePatchResolution(
|
|
106
|
+
resolutionsObj[searchEntry]
|
|
107
|
+
);
|
|
108
|
+
if (existingPatchFile) {
|
|
109
|
+
await fs__default.default.rm(path.resolve(ctx.targetRoot, existingPatchFile), {
|
|
110
|
+
force: true
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return async (patchEntry) => {
|
|
114
|
+
resolutionsObj[searchEntry] = patchEntry;
|
|
115
|
+
await fs__default.default.writeJson(
|
|
116
|
+
path.resolve(ctx.targetRoot, "package.json"),
|
|
117
|
+
newPkgJson,
|
|
118
|
+
{
|
|
119
|
+
spaces: 2
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const resolutionMap = await readResolutionMap(ctx);
|
|
125
|
+
const entriesToRemove = Object.entries(resolutionsObj).filter(
|
|
126
|
+
([key]) => key.startsWith(`${ctx.packageName}@`)
|
|
127
|
+
);
|
|
128
|
+
for (const [key, value] of entriesToRemove) {
|
|
129
|
+
delete resolutionsObj[key];
|
|
130
|
+
const existingPatchFile = tryParsePatchResolution(value);
|
|
131
|
+
if (existingPatchFile) {
|
|
132
|
+
await fs__default.default.rm(path.resolve(ctx.targetRoot, existingPatchFile), {
|
|
133
|
+
force: true
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const descriptors = new Array();
|
|
138
|
+
for (const [descriptor, locator] of resolutionMap) {
|
|
139
|
+
if (!locator.includes("@npm:")) {
|
|
140
|
+
if (!locator.includes("@virtual:")) {
|
|
141
|
+
console.warn(`Skipping resolution for ${descriptor}, no version found`);
|
|
142
|
+
}
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
descriptors.push(descriptor);
|
|
146
|
+
}
|
|
147
|
+
return async (patchEntry) => {
|
|
148
|
+
for (const descriptor of descriptors) {
|
|
149
|
+
resolutionsObj[descriptor] = patchEntry;
|
|
150
|
+
}
|
|
151
|
+
await fs__default.default.writeJson(
|
|
152
|
+
path.resolve(ctx.targetRoot, "package.json"),
|
|
153
|
+
newPkgJson,
|
|
154
|
+
{
|
|
155
|
+
spaces: 2
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
async function verifyYarnVersion(cwd) {
|
|
161
|
+
const exists = await fs__default.default.pathExists(path.join(cwd, ".yarnrc.yml"));
|
|
162
|
+
if (!exists) {
|
|
163
|
+
throw new Error(
|
|
164
|
+
`Missing .yarnrc.yml in ${cwd}, Yarn v1 (classic) is not support by this command`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
async function generatePatch$1(ctx, targetArchive, version) {
|
|
169
|
+
const baseArchive = await downloadArchive(ctx, version);
|
|
170
|
+
const patch = await generatePatchForArchives(ctx, baseArchive, targetArchive);
|
|
171
|
+
if (!patch) {
|
|
172
|
+
console.warn(`Generated patch for ${ctx.packageName} is empty`);
|
|
173
|
+
return void 0;
|
|
174
|
+
}
|
|
175
|
+
const cleanPackageName = ctx.packageName.replace("/", "-");
|
|
176
|
+
const describeResult = await exec.exec(
|
|
177
|
+
"git",
|
|
178
|
+
["describe", "--always", "--dirty", "--exclude='*'"],
|
|
179
|
+
{
|
|
180
|
+
cwd: ctx.sourceRepo.root.dir,
|
|
181
|
+
env: { ...process.env, ...GIT_ENV }
|
|
182
|
+
}
|
|
183
|
+
);
|
|
184
|
+
const describe = describeResult.stdout.toString("utf8").trim();
|
|
185
|
+
const name = `${cleanPackageName}-${version}-${describe}.patch`;
|
|
186
|
+
const patchDir = path.join(ctx.targetRepo.root.dir, ".yarn", "patches");
|
|
187
|
+
await fs__default.default.ensureDir(patchDir);
|
|
188
|
+
await fs__default.default.writeFile(path.join(patchDir, name), patch, "utf8");
|
|
189
|
+
const locator = `${ctx.sourcePkg.packageJson.name}@npm:${version}`;
|
|
190
|
+
return `patch:${encodeURIComponent(locator)}#${path.posix.join(
|
|
191
|
+
".",
|
|
192
|
+
".yarn",
|
|
193
|
+
"patches",
|
|
194
|
+
name
|
|
195
|
+
)}`;
|
|
196
|
+
}
|
|
197
|
+
function tryParsePatchResolution(value) {
|
|
198
|
+
if (!value) {
|
|
199
|
+
return void 0;
|
|
200
|
+
}
|
|
201
|
+
if (!value.startsWith("patch:")) {
|
|
202
|
+
return void 0;
|
|
203
|
+
}
|
|
204
|
+
const patchFilePath = value.split("#")[1];
|
|
205
|
+
return patchFilePath;
|
|
206
|
+
}
|
|
207
|
+
async function readResolutionMap(ctx) {
|
|
208
|
+
const { stdout: whyOutput } = await exec.exec(
|
|
209
|
+
"yarn",
|
|
210
|
+
["why", "--json", ctx.packageName],
|
|
211
|
+
{
|
|
212
|
+
cwd: ctx.targetRoot,
|
|
213
|
+
maxBuffer: 64 * 1024 * 1024
|
|
214
|
+
}
|
|
215
|
+
);
|
|
216
|
+
const resolutionMap = /* @__PURE__ */ new Map();
|
|
217
|
+
for (const line of whyOutput.toString("utf8").trim().split(/\r?\n/)) {
|
|
218
|
+
for (const { locator, descriptor } of Object.values(
|
|
219
|
+
JSON.parse(line).children
|
|
220
|
+
)) {
|
|
221
|
+
const existing = resolutionMap.get(descriptor);
|
|
222
|
+
if (existing) {
|
|
223
|
+
if (existing !== locator) {
|
|
224
|
+
throw new Error(
|
|
225
|
+
`Conflicting resolutions in target package for ${descriptor}: ${existing} vs ${locator}`
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
} else {
|
|
229
|
+
resolutionMap.set(descriptor, locator);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return resolutionMap;
|
|
234
|
+
}
|
|
235
|
+
async function buildTargetArchive(ctx) {
|
|
236
|
+
await exec.exec("yarn", ["build"], {
|
|
237
|
+
cwd: ctx.sourcePkg.dir
|
|
238
|
+
});
|
|
239
|
+
const archiveName = "target.tgz";
|
|
240
|
+
await exec.exec("yarn", ["pack", "--out", path.join(ctx.workDir, archiveName)], {
|
|
241
|
+
cwd: ctx.sourcePkg.dir
|
|
242
|
+
});
|
|
243
|
+
return archiveName;
|
|
244
|
+
}
|
|
245
|
+
async function downloadArchive(ctx, version) {
|
|
246
|
+
const nameWithoutScope = ctx.packageName.replace(/^@.+\//, "");
|
|
247
|
+
const tarName = `${nameWithoutScope}-${version}.tgz`;
|
|
248
|
+
if (await fs__default.default.pathExists(path.join(ctx.workDir, tarName))) {
|
|
249
|
+
return tarName;
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
const url = `${ctx.registryUrl}/${ctx.packageName}/-/${tarName}`;
|
|
253
|
+
const res = await fetch(url);
|
|
254
|
+
if (!res.ok) {
|
|
255
|
+
throw new Error(
|
|
256
|
+
`Request to ${url} failed with status ${res.status} ${res.statusText}`
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
if (!res.body) {
|
|
260
|
+
throw new Error("Missing response body");
|
|
261
|
+
}
|
|
262
|
+
const write = fs__default.default.createWriteStream(path.join(ctx.workDir, tarName));
|
|
263
|
+
await promises.finished(stream.Readable.fromWeb(res.body).pipe(write));
|
|
264
|
+
return tarName;
|
|
265
|
+
} catch (error) {
|
|
266
|
+
throw new errors.ForwardedError(
|
|
267
|
+
`Failed to fetch tarball for ${ctx.packageName}@${version}`,
|
|
268
|
+
error
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
async function generatePatchForArchives(ctx, baseArchive, headArchive) {
|
|
273
|
+
const basePath = path.join(ctx.workDir, baseArchive);
|
|
274
|
+
const headPath = path.join(ctx.workDir, headArchive);
|
|
275
|
+
const patchDir = await fs__default.default.mkdtemp(path.join(ctx.workDir, "patch-"));
|
|
276
|
+
await tar__default.default.extract({ file: basePath, cwd: patchDir, strip: 1 });
|
|
277
|
+
await fs__default.default.writeFile(
|
|
278
|
+
path.join(patchDir, ".gitignore"),
|
|
279
|
+
PATCH_GITIGNORE.join(os__default.default.EOL)
|
|
280
|
+
);
|
|
281
|
+
await exec.exec("git", ["init"], {
|
|
282
|
+
cwd: patchDir,
|
|
283
|
+
env: { ...process.env, ...GIT_ENV }
|
|
284
|
+
});
|
|
285
|
+
await exec.exec("git", ["add", "."], {
|
|
286
|
+
cwd: patchDir,
|
|
287
|
+
env: { ...process.env, ...GIT_ENV }
|
|
288
|
+
});
|
|
289
|
+
for (const path$1 of await fs__default.default.readdir(patchDir)) {
|
|
290
|
+
if (path$1 !== ".git" && path$1 !== ".gitignore") {
|
|
291
|
+
await fs__default.default.rm(path.join(patchDir, path$1), {
|
|
292
|
+
recursive: true,
|
|
293
|
+
maxRetries: 3,
|
|
294
|
+
force: true
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
await tar__default.default.extract({ file: headPath, cwd: patchDir, strip: 1 });
|
|
299
|
+
const { stdout: patch } = await exec.exec(
|
|
300
|
+
"git",
|
|
301
|
+
[
|
|
302
|
+
"-c",
|
|
303
|
+
"core.safecrlf=false",
|
|
304
|
+
"diff",
|
|
305
|
+
"--src-prefix=a/",
|
|
306
|
+
"--dst-prefix=b/",
|
|
307
|
+
"--ignore-cr-at-eol",
|
|
308
|
+
"--full-index",
|
|
309
|
+
"--no-renames",
|
|
310
|
+
"--text"
|
|
311
|
+
],
|
|
312
|
+
{
|
|
313
|
+
cwd: patchDir,
|
|
314
|
+
env: { ...process.env, ...GIT_ENV }
|
|
315
|
+
}
|
|
316
|
+
);
|
|
317
|
+
return patch.toString("utf8");
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
exports.default = generatePatch;
|
|
321
|
+
//# sourceMappingURL=generate-patch.cjs.js.map
|
|
@@ -133,6 +133,28 @@ function registerCommands(program) {
|
|
|
133
133
|
)
|
|
134
134
|
)
|
|
135
135
|
);
|
|
136
|
+
program.command("generate-patch <package>").requiredOption(
|
|
137
|
+
"--target <target-repo>",
|
|
138
|
+
"The target repository to generate patches for"
|
|
139
|
+
).option(
|
|
140
|
+
"--registry-url <registry-url>",
|
|
141
|
+
"The registry to use for downloading artifacts (default: https://registry.npmjs.org)"
|
|
142
|
+
).option(
|
|
143
|
+
"--base-version <version>",
|
|
144
|
+
"Override the base version to generate the patch towards instead"
|
|
145
|
+
).option(
|
|
146
|
+
"--query <query>",
|
|
147
|
+
"Only apply the patch for a specific version query in the target repository"
|
|
148
|
+
).option(
|
|
149
|
+
"--skip-install",
|
|
150
|
+
"Skip dependency installation in the target repository after applying the patch"
|
|
151
|
+
).description(
|
|
152
|
+
"Generate a patch for the selected package in the target repository"
|
|
153
|
+
).action(
|
|
154
|
+
lazy(
|
|
155
|
+
() => Promise.resolve().then(function () { return require('./generate-patch/generate-patch.cjs.js'); }).then((m) => m.default)
|
|
156
|
+
)
|
|
157
|
+
);
|
|
136
158
|
program.command("knip-reports [paths...]").option("--ci", "CI run checks that there is no changes on knip reports").description("Generate a knip report for selected packages").action(
|
|
137
159
|
lazy(
|
|
138
160
|
() => Promise.resolve().then(function () { return require('./knip-reports/knip-reports.cjs.js'); }).then((m) => m.buildKnipReports)
|
|
@@ -41,7 +41,7 @@ async function generate(outputDirectory, clientAdditionalProperties, abortSignal
|
|
|
41
41
|
"-c",
|
|
42
42
|
backendPluginApi.resolvePackagePath(
|
|
43
43
|
"@backstage/repo-tools",
|
|
44
|
-
"templates/typescript-backstage.yaml"
|
|
44
|
+
"templates/typescript-backstage-client.yaml"
|
|
45
45
|
),
|
|
46
46
|
"--generator-key",
|
|
47
47
|
"v3.0",
|
|
@@ -56,14 +56,18 @@ async function generate(outputDirectory, clientAdditionalProperties, abortSignal
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
const parentDirectory = path.resolve(resolvedOutputDirectory, "..");
|
|
60
|
+
await fs__default.default.writeFile(
|
|
61
|
+
path.resolve(parentDirectory, "index.ts"),
|
|
62
|
+
`//
|
|
63
|
+
export * from './generated';`
|
|
63
64
|
);
|
|
65
|
+
await exec.exec(`yarn backstage-cli package lint --fix ${parentDirectory}`, [], {
|
|
66
|
+
signal: abortSignal?.signal
|
|
67
|
+
});
|
|
64
68
|
const prettier = paths.paths.resolveTargetRoot("node_modules/.bin/prettier");
|
|
65
69
|
if (prettier) {
|
|
66
|
-
await exec.exec(`${prettier} --write ${
|
|
70
|
+
await exec.exec(`${prettier} --write ${parentDirectory}`, [], {
|
|
67
71
|
signal: abortSignal?.signal
|
|
68
72
|
});
|
|
69
73
|
}
|
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var fs = require('fs-extra');
|
|
4
|
-
var YAML = require('js-yaml');
|
|
5
3
|
var chalk = require('chalk');
|
|
6
|
-
var
|
|
4
|
+
var path = require('path');
|
|
5
|
+
var YAML = require('js-yaml');
|
|
7
6
|
var constants = require('../../../../../lib/openapi/constants.cjs.js');
|
|
8
|
-
var
|
|
9
|
-
var
|
|
7
|
+
var paths = require('../../../../../lib/paths.cjs.js');
|
|
8
|
+
var fs = require('fs-extra');
|
|
9
|
+
var exec = require('../../../../../lib/exec.cjs.js');
|
|
10
|
+
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
10
11
|
var helpers = require('../../../../../lib/openapi/helpers.cjs.js');
|
|
11
12
|
|
|
12
13
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
13
14
|
|
|
14
|
-
var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
15
|
-
var YAML__default = /*#__PURE__*/_interopDefaultCompat(YAML);
|
|
16
15
|
var chalk__default = /*#__PURE__*/_interopDefaultCompat(chalk);
|
|
16
|
+
var YAML__default = /*#__PURE__*/_interopDefaultCompat(YAML);
|
|
17
|
+
var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
async function generate(abortSignal) {
|
|
19
|
+
async function generateSpecFile() {
|
|
20
20
|
const openapiPath = await helpers.getPathToCurrentOpenApiSpec();
|
|
21
21
|
const yaml = YAML__default.default.load(await fs__default.default.readFile(openapiPath, "utf8"));
|
|
22
22
|
const tsPath = paths.paths.resolveTarget(constants.TS_SCHEMA_PATH);
|
|
23
|
+
const schemaDir = path.dirname(tsPath);
|
|
24
|
+
await fs__default.default.mkdirp(schemaDir);
|
|
25
|
+
const oldTsPath = paths.paths.resolveTarget(constants.OLD_SCHEMA_PATH);
|
|
26
|
+
if (fs__default.default.existsSync(oldTsPath)) {
|
|
27
|
+
console.warn(`Removing old schema file at ${oldTsPath}`);
|
|
28
|
+
fs__default.default.removeSync(oldTsPath);
|
|
29
|
+
}
|
|
23
30
|
await fs__default.default.writeFile(
|
|
24
31
|
tsPath,
|
|
25
32
|
`//
|
|
@@ -27,22 +34,82 @@ async function generate(abortSignal) {
|
|
|
27
34
|
// ******************************************************************
|
|
28
35
|
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
|
|
29
36
|
// ******************************************************************
|
|
30
|
-
import {
|
|
37
|
+
import {createValidatedOpenApiRouterFromGeneratedEndpointMap} from '@backstage/backend-openapi-utils';
|
|
38
|
+
import {EndpointMap} from './';
|
|
31
39
|
export const spec = ${JSON.stringify(yaml, null, 2)} as const;
|
|
32
40
|
export const createOpenApiRouter = async (
|
|
33
|
-
options?: Parameters<typeof
|
|
34
|
-
) =>
|
|
41
|
+
options?: Parameters<typeof createValidatedOpenApiRouterFromGeneratedEndpointMap>['1'],
|
|
42
|
+
) => createValidatedOpenApiRouterFromGeneratedEndpointMap<EndpointMap>(spec, options);
|
|
35
43
|
`
|
|
36
44
|
);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
const indexFile = path.join(schemaDir, "..", "index.ts");
|
|
46
|
+
await fs__default.default.writeFile(
|
|
47
|
+
indexFile,
|
|
48
|
+
`//
|
|
49
|
+
export * from './generated';`
|
|
50
|
+
);
|
|
51
|
+
await exec.exec(`yarn backstage-cli package lint`, ["--fix", tsPath, indexFile]);
|
|
40
52
|
if (await paths.paths.resolveTargetRoot("node_modules/.bin/prettier")) {
|
|
41
|
-
await exec(`yarn prettier --write
|
|
42
|
-
cwd: paths.paths.targetRoot
|
|
53
|
+
await exec.exec(`yarn prettier`, ["--write", tsPath, indexFile], {
|
|
54
|
+
cwd: paths.paths.targetRoot
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function generate(abortSignal) {
|
|
59
|
+
const resolvedOpenapiPath = await helpers.getPathToCurrentOpenApiSpec();
|
|
60
|
+
const resolvedOutputDirectory = await helpers.getRelativePathToFile(constants.OUTPUT_PATH);
|
|
61
|
+
await fs__default.default.mkdirp(resolvedOutputDirectory);
|
|
62
|
+
await fs__default.default.writeFile(
|
|
63
|
+
path.resolve(resolvedOutputDirectory, ".openapi-generator-ignore"),
|
|
64
|
+
constants.OPENAPI_IGNORE_FILES.join("\n")
|
|
65
|
+
);
|
|
66
|
+
await exec.exec(
|
|
67
|
+
"node",
|
|
68
|
+
[
|
|
69
|
+
backendPluginApi.resolvePackagePath("@openapitools/openapi-generator-cli", "main.js"),
|
|
70
|
+
"generate",
|
|
71
|
+
"-i",
|
|
72
|
+
resolvedOpenapiPath,
|
|
73
|
+
"-o",
|
|
74
|
+
resolvedOutputDirectory,
|
|
75
|
+
"-g",
|
|
76
|
+
"typescript",
|
|
77
|
+
"-c",
|
|
78
|
+
backendPluginApi.resolvePackagePath(
|
|
79
|
+
"@backstage/repo-tools",
|
|
80
|
+
"templates/typescript-backstage-server.yaml"
|
|
81
|
+
),
|
|
82
|
+
"--generator-key",
|
|
83
|
+
"v3.0"
|
|
84
|
+
],
|
|
85
|
+
{
|
|
86
|
+
maxBuffer: Number.MAX_VALUE,
|
|
87
|
+
cwd: backendPluginApi.resolvePackagePath("@backstage/repo-tools"),
|
|
88
|
+
env: {
|
|
89
|
+
...process.env
|
|
90
|
+
},
|
|
91
|
+
signal: abortSignal?.signal
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
await exec.exec(
|
|
95
|
+
`yarn backstage-cli package lint --fix ${resolvedOutputDirectory}`,
|
|
96
|
+
[],
|
|
97
|
+
{
|
|
98
|
+
signal: abortSignal?.signal
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
const prettier = paths.paths.resolveTargetRoot("node_modules/.bin/prettier");
|
|
102
|
+
if (prettier) {
|
|
103
|
+
await exec.exec(`${prettier} --write ${resolvedOutputDirectory}`, [], {
|
|
43
104
|
signal: abortSignal?.signal
|
|
44
105
|
});
|
|
45
106
|
}
|
|
107
|
+
fs__default.default.removeSync(path.resolve(resolvedOutputDirectory, ".openapi-generator-ignore"));
|
|
108
|
+
fs__default.default.rmSync(path.resolve(resolvedOutputDirectory, ".openapi-generator"), {
|
|
109
|
+
recursive: true,
|
|
110
|
+
force: true
|
|
111
|
+
});
|
|
112
|
+
await generateSpecFile();
|
|
46
113
|
}
|
|
47
114
|
async function command({
|
|
48
115
|
abortSignal,
|
|
@@ -22,11 +22,16 @@ async function verify(directoryPath) {
|
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
24
|
const yaml = await helpers.loadAndValidateOpenApiYaml(openapiPath);
|
|
25
|
-
|
|
26
|
-
if (!await fs__default.default.pathExists(schemaPath)) {
|
|
25
|
+
let schemaPath = path.join(directoryPath, constants.TS_SCHEMA_PATH);
|
|
26
|
+
if (!await fs__default.default.pathExists(schemaPath) && !await fs__default.default.pathExists(path.join(directoryPath, constants.OLD_SCHEMA_PATH))) {
|
|
27
27
|
throw new Error(`No \`${constants.TS_SCHEMA_PATH}\` file found.`);
|
|
28
|
+
} else if (await fs__default.default.pathExists(path.join(directoryPath, constants.OLD_SCHEMA_PATH))) {
|
|
29
|
+
console.warn(
|
|
30
|
+
`\`${constants.OLD_SCHEMA_PATH}\` is deprecated. Please re-run \`yarn backstage-repo-tools package schema openapi generate\` to update it.`
|
|
31
|
+
);
|
|
32
|
+
schemaPath = path.join(directoryPath, constants.OLD_SCHEMA_PATH);
|
|
28
33
|
}
|
|
29
|
-
const schema = await import(path.resolve(
|
|
34
|
+
const schema = await import(path.resolve(schemaPath));
|
|
30
35
|
if (!schema.spec) {
|
|
31
36
|
throw new Error(`\`${constants.TS_SCHEMA_PATH}\` needs to have a 'spec' export.`);
|
|
32
37
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const YAML_SCHEMA_PATH = "src/schema/openapi.yaml";
|
|
4
|
-
const
|
|
4
|
+
const OUTPUT_PATH = "src/schema/openapi/generated";
|
|
5
|
+
const TS_MODULE = `${OUTPUT_PATH}/router`;
|
|
6
|
+
const OLD_SCHEMA_PATH = `src/schema/openapi.generated.ts`;
|
|
5
7
|
const TS_SCHEMA_PATH = `${TS_MODULE}.ts`;
|
|
6
|
-
const OUTPUT_PATH = "src/generated";
|
|
7
8
|
const OPENAPI_IGNORE_FILES = [
|
|
8
9
|
// Get rid of the default files.
|
|
9
10
|
"*.md",
|
|
@@ -22,6 +23,7 @@ const OPENAPI_IGNORE_FILES = [
|
|
|
22
23
|
// Override the created version.
|
|
23
24
|
"apis/*.ts",
|
|
24
25
|
"!apis/*.client.ts",
|
|
26
|
+
"!apis/*.server.ts",
|
|
25
27
|
"models/*.ts",
|
|
26
28
|
"!models/*.model.ts",
|
|
27
29
|
// Always include index.ts files.
|
|
@@ -36,6 +38,7 @@ const OPENAPI_IGNORE_FILES = [
|
|
|
36
38
|
"tsconfig.json"
|
|
37
39
|
];
|
|
38
40
|
|
|
41
|
+
exports.OLD_SCHEMA_PATH = OLD_SCHEMA_PATH;
|
|
39
42
|
exports.OPENAPI_IGNORE_FILES = OPENAPI_IGNORE_FILES;
|
|
40
43
|
exports.OUTPUT_PATH = OUTPUT_PATH;
|
|
41
44
|
exports.TS_MODULE = TS_MODULE;
|
package/dist/package.json.cjs.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/repo-tools",
|
|
3
|
-
"version": "0.11.0-next.
|
|
3
|
+
"version": "0.11.0-next.2",
|
|
4
4
|
"description": "CLI for Backstage repo tooling ",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "cli"
|
|
@@ -43,11 +43,11 @@
|
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@apidevtools/swagger-parser": "^10.1.0",
|
|
45
45
|
"@apisyouwonthate/style-guide": "^1.4.0",
|
|
46
|
-
"@backstage/backend-plugin-api": "1.0.2-next.
|
|
46
|
+
"@backstage/backend-plugin-api": "1.0.2-next.2",
|
|
47
47
|
"@backstage/catalog-model": "1.7.0",
|
|
48
|
-
"@backstage/cli-common": "0.1.
|
|
49
|
-
"@backstage/cli-node": "0.2.
|
|
50
|
-
"@backstage/config-loader": "1.9.
|
|
48
|
+
"@backstage/cli-common": "0.1.15-next.0",
|
|
49
|
+
"@backstage/cli-node": "0.2.10-next.0",
|
|
50
|
+
"@backstage/config-loader": "1.9.2-next.0",
|
|
51
51
|
"@backstage/errors": "1.2.4",
|
|
52
52
|
"@manypkg/get-packages": "^1.1.3",
|
|
53
53
|
"@microsoft/api-documenter": "^7.25.7",
|
|
@@ -74,15 +74,16 @@
|
|
|
74
74
|
"minimatch": "^9.0.0",
|
|
75
75
|
"p-limit": "^3.0.2",
|
|
76
76
|
"portfinder": "^1.0.32",
|
|
77
|
+
"tar": "^6.1.12",
|
|
77
78
|
"ts-morph": "^23.0.0",
|
|
78
79
|
"yaml-diff-patch": "^2.0.0"
|
|
79
80
|
},
|
|
80
81
|
"devDependencies": {
|
|
81
|
-
"@backstage/backend-test-utils": "1.0
|
|
82
|
-
"@backstage/cli": "0.29.0-next.
|
|
82
|
+
"@backstage/backend-test-utils": "1.1.0-next.2",
|
|
83
|
+
"@backstage/cli": "0.29.0-next.2",
|
|
83
84
|
"@backstage/types": "1.1.1",
|
|
84
85
|
"@types/is-glob": "^4.0.2",
|
|
85
|
-
"@types/node": "^
|
|
86
|
+
"@types/node": "^20.16.0",
|
|
86
87
|
"@types/prettier": "^2.0.0"
|
|
87
88
|
},
|
|
88
89
|
"peerDependencies": {
|
|
@@ -29,8 +29,43 @@ export interface RequestOptions {
|
|
|
29
29
|
token?: string;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
{{#operation}}
|
|
33
|
+
/**
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export type {{#lambda.pascalcase}}{{nickname}}{{/lambda.pascalcase}} = {
|
|
37
|
+
{{#hasPathParams}}
|
|
38
|
+
path: {
|
|
39
|
+
{{#pathParams}}
|
|
40
|
+
{{paramName}}{{^required}}?{{/required}}: {{{dataType}}},
|
|
41
|
+
{{/pathParams}}
|
|
42
|
+
},
|
|
43
|
+
{{/hasPathParams}}
|
|
44
|
+
{{#hasBodyParam}}
|
|
45
|
+
{{#bodyParam}}
|
|
46
|
+
body: {{{dataType}}},
|
|
47
|
+
{{/bodyParam}}
|
|
48
|
+
{{/hasBodyParam}}
|
|
49
|
+
{{#hasQueryParams}}
|
|
50
|
+
query: {
|
|
51
|
+
{{#queryParams}}
|
|
52
|
+
{{paramName}}{{^required}}?{{/required}}: {{{dataType}}},
|
|
53
|
+
{{/queryParams}}
|
|
54
|
+
},
|
|
55
|
+
{{/hasQueryParams}}
|
|
56
|
+
{{#hasHeaderParams}}
|
|
57
|
+
header: {
|
|
58
|
+
{{#headerParams}}
|
|
59
|
+
{{paramName}}{{^required}}?{{/required}}: {{{dataType}}},
|
|
60
|
+
{{/headerParams}}
|
|
61
|
+
},
|
|
62
|
+
{{/hasHeaderParams}}
|
|
63
|
+
}
|
|
64
|
+
{{/operation}}
|
|
65
|
+
|
|
32
66
|
/**
|
|
33
67
|
* {{{description}}}{{^description}}no description{{/description}}
|
|
68
|
+
* @public
|
|
34
69
|
*/
|
|
35
70
|
export class {{classname}}Client {
|
|
36
71
|
private readonly discoveryApi: DiscoveryApi;
|
|
@@ -53,39 +88,12 @@ export class {{classname}}Client {
|
|
|
53
88
|
* {{&summary}}
|
|
54
89
|
{{/summary}}
|
|
55
90
|
{{#allParams}}
|
|
56
|
-
* @param {{paramName}} {{description}}
|
|
91
|
+
* @param {{paramName}} - {{description}}
|
|
57
92
|
{{/allParams}}
|
|
58
93
|
*/
|
|
59
94
|
public async {{nickname}}(
|
|
60
95
|
// @ts-ignore
|
|
61
|
-
request: {
|
|
62
|
-
{{#hasPathParams}}
|
|
63
|
-
path: {
|
|
64
|
-
{{#pathParams}}
|
|
65
|
-
{{paramName}}{{^required}}?{{/required}}: {{{dataType}}},
|
|
66
|
-
{{/pathParams}}
|
|
67
|
-
},
|
|
68
|
-
{{/hasPathParams}}
|
|
69
|
-
{{#hasBodyParam}}
|
|
70
|
-
{{#bodyParam}}
|
|
71
|
-
body: {{{dataType}}},
|
|
72
|
-
{{/bodyParam}}
|
|
73
|
-
{{/hasBodyParam}}
|
|
74
|
-
{{#hasQueryParams}}
|
|
75
|
-
query: {
|
|
76
|
-
{{#queryParams}}
|
|
77
|
-
{{paramName}}{{^required}}?{{/required}}: {{{dataType}}},
|
|
78
|
-
{{/queryParams}}
|
|
79
|
-
},
|
|
80
|
-
{{/hasQueryParams}}
|
|
81
|
-
{{#hasHeaderParams}}
|
|
82
|
-
header: {
|
|
83
|
-
{{#headerParams}}
|
|
84
|
-
{{paramName}}{{^required}}?{{/required}}: {{{dataType}}},
|
|
85
|
-
{{/headerParams}}
|
|
86
|
-
},
|
|
87
|
-
{{/hasHeaderParams}}
|
|
88
|
-
},
|
|
96
|
+
request: {{#lambda.pascalcase}}{{nickname}}{{/lambda.pascalcase}},
|
|
89
97
|
options?: RequestOptions
|
|
90
98
|
): Promise<TypedResponse<{{{returnType}}} {{^returnType}}void{{/returnType}}>> {
|
|
91
99
|
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{{! Sourced from https://github.com/OpenAPITools/openapi-generator/blob/7347daec61b2cb8d3d28e1ed06fe8b5e682090f8/modules/openapi-generator/src/main/resources/typescript-angular/modelEnum.mustache }}
|
|
2
2
|
|
|
3
3
|
{{#stringEnums}}
|
|
4
|
+
/**
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
4
7
|
export enum {{classname}} {
|
|
5
8
|
{{#allowableValues}}
|
|
6
9
|
{{#enumVars}}
|
|
@@ -10,8 +13,14 @@ export enum {{classname}} {
|
|
|
10
13
|
}
|
|
11
14
|
{{/stringEnums}}
|
|
12
15
|
{{^stringEnums}}
|
|
16
|
+
/**
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
13
19
|
export type {{classname}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}} | {{/-last}}{{/enumVars}}{{/allowableValues}};
|
|
14
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
15
24
|
export const {{classname}} = {
|
|
16
25
|
{{#allowableValues}}
|
|
17
26
|
{{#enumVars}}
|
package/templates/{typescript-backstage → typescript-backstage-client}/modelGeneric.mustache
RENAMED
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
{{#models}}
|
|
4
4
|
{{#model}}
|
|
5
5
|
|
|
6
|
-
{{#description}}
|
|
7
6
|
/**
|
|
7
|
+
{{#description}}
|
|
8
8
|
* {{{.}}}
|
|
9
|
-
*/
|
|
10
9
|
{{/description}}
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
11
12
|
{{^isEnum}}
|
|
12
|
-
export interface {{classname}} {
|
|
13
|
+
export {{#isNullable}}type{{/isNullable}}{{^isNullable}}interface{{/isNullable}} {{classname}} {{#isNullable}}={{/isNullable}} {
|
|
13
14
|
{{>modelGenericAdditionalProperties}}
|
|
14
15
|
{{#vars}}
|
|
15
16
|
{{#description}}
|
|
@@ -19,12 +20,15 @@ export interface {{classname}} {
|
|
|
19
20
|
{{/description}}
|
|
20
21
|
'{{name}}'{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}} | null{{/isNullable}};
|
|
21
22
|
{{/vars}}
|
|
22
|
-
}
|
|
23
|
+
}{{#isNullable}} | null{{/isNullable}}
|
|
23
24
|
|
|
24
25
|
{{#hasEnums}}
|
|
25
26
|
|
|
26
27
|
{{#vars}}
|
|
27
28
|
{{#isEnum}}
|
|
29
|
+
/**
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
28
32
|
export type {{classname}}{{enumName}} ={{#allowableValues}}{{#values}} "{{.}}" {{^-last}}|{{/-last}}{{/values}}{{/allowableValues}};
|
|
29
33
|
{{/isEnum}}
|
|
30
34
|
{{/vars}}
|
|
@@ -32,6 +36,9 @@ export type {{classname}}{{enumName}} ={{#allowableValues}}{{#values}} "{{.}}" {
|
|
|
32
36
|
{{/hasEnums}}
|
|
33
37
|
{{/isEnum}}
|
|
34
38
|
{{#isEnum}}
|
|
39
|
+
/**
|
|
40
|
+
* @public
|
|
41
|
+
*/
|
|
35
42
|
export type {{classname}} ={{#allowableValues}}{{#values}} "{{.}}" {{^-last}}|{{/-last}}{{/values}}{{/allowableValues}};
|
|
36
43
|
{{/isEnum}}
|
|
37
44
|
{{/model}}
|
package/templates/{typescript-backstage → typescript-backstage-client}/modelGenericEnums.mustache
RENAMED
|
@@ -3,11 +3,17 @@
|
|
|
3
3
|
{{#hasEnums}}
|
|
4
4
|
|
|
5
5
|
{{^stringEnums}}
|
|
6
|
+
/**
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
6
9
|
export namespace {{classname}} {
|
|
7
10
|
{{/stringEnums}}
|
|
8
11
|
{{#vars}}
|
|
9
12
|
{{#isEnum}}
|
|
10
13
|
{{#stringEnums}}
|
|
14
|
+
/**
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
11
17
|
export enum {{classname}}{{enumName}} {
|
|
12
18
|
{{#allowableValues}}
|
|
13
19
|
{{#enumVars}}
|
|
@@ -17,7 +23,14 @@ export enum {{classname}}{{enumName}} {
|
|
|
17
23
|
};
|
|
18
24
|
{{/stringEnums}}
|
|
19
25
|
{{^stringEnums}}
|
|
26
|
+
/**
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
20
29
|
export type {{enumName}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}} | {{/-last}}{{/enumVars}}{{/allowableValues}};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @public
|
|
33
|
+
*/
|
|
21
34
|
export const {{enumName}} = {
|
|
22
35
|
{{#allowableValues}}
|
|
23
36
|
{{#enumVars}}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
templateDir: templates/typescript-backstage-client
|
|
2
|
+
|
|
3
|
+
files:
|
|
4
|
+
api.mustache:
|
|
5
|
+
templateType: API
|
|
6
|
+
# For some reason, they check for destinationFilename differences. We have to change the ending to override the file.
|
|
7
|
+
destinationFilename: .client.ts
|
|
8
|
+
model.mustache:
|
|
9
|
+
templateType: Model
|
|
10
|
+
destinationFilename: .model.ts
|
|
11
|
+
modelGeneric.mustache:
|
|
12
|
+
templateType: SupportingFiles
|
|
13
|
+
modelOneOf.mustache:
|
|
14
|
+
templateType: SupportingFiles
|
|
15
|
+
modelGenericAdditionalProperties.mustache:
|
|
16
|
+
templateType: SupportingFiles
|
|
17
|
+
modelGenericEnums.mustache:
|
|
18
|
+
templateType: SupportingFiles
|
|
19
|
+
modelAlias.mustache:
|
|
20
|
+
templateType: SupportingFiles
|
|
21
|
+
modelEnum.mustache:
|
|
22
|
+
templateType: SupportingFiles
|
|
23
|
+
modelTaggedUnion.mustache:
|
|
24
|
+
templateType: SupportingFiles
|
|
25
|
+
models/models_all.mustache:
|
|
26
|
+
templateType: SupportingFiles
|
|
27
|
+
destinationFilename: models/index.ts
|
|
28
|
+
types/fetch.ts:
|
|
29
|
+
destinationFilename: types/fetch.ts
|
|
30
|
+
types/discovery.ts:
|
|
31
|
+
destinationFilename: types/discovery.ts
|
|
32
|
+
apis/index.mustache:
|
|
33
|
+
templateType: SupportingFiles
|
|
34
|
+
destinationFilename: apis/index.ts
|
|
35
|
+
pluginId.mustache:
|
|
36
|
+
templateType: SupportingFiles
|
|
37
|
+
destinationFilename: pluginId.ts
|
|
38
|
+
index.mustache:
|
|
39
|
+
templateType: SupportingFiles
|
|
40
|
+
destinationFilename: index.ts
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{{>licenseInfo}}
|
|
2
|
+
{{#imports}}
|
|
3
|
+
import { {{classname}} } from '{{filename}}.model{{importFileExtension}}';
|
|
4
|
+
{{/imports}}
|
|
5
|
+
|
|
6
|
+
{{#operations}}
|
|
7
|
+
|
|
8
|
+
{{#operation}}
|
|
9
|
+
/**
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export type {{#lambda.pascalcase}}{{nickname}}{{/lambda.pascalcase}} = {
|
|
13
|
+
{{#hasPathParams}}
|
|
14
|
+
path: {
|
|
15
|
+
{{#pathParams}}
|
|
16
|
+
{{paramName}}{{^required}}?{{/required}}: {{{dataType}}},
|
|
17
|
+
{{/pathParams}}
|
|
18
|
+
},
|
|
19
|
+
{{/hasPathParams}}
|
|
20
|
+
{{#hasBodyParam}}
|
|
21
|
+
{{#bodyParam}}
|
|
22
|
+
body: {{{dataType}}},
|
|
23
|
+
{{/bodyParam}}
|
|
24
|
+
{{/hasBodyParam}}
|
|
25
|
+
{{#hasQueryParams}}
|
|
26
|
+
query: {
|
|
27
|
+
{{#queryParams}}
|
|
28
|
+
{{paramName}}{{^required}}?{{/required}}: {{{dataType}}},
|
|
29
|
+
{{/queryParams}}
|
|
30
|
+
},
|
|
31
|
+
{{/hasQueryParams}}
|
|
32
|
+
{{#hasHeaderParams}}
|
|
33
|
+
header: {
|
|
34
|
+
{{#headerParams}}
|
|
35
|
+
{{paramName}}{{^required}}?{{/required}}: {{{dataType}}},
|
|
36
|
+
{{/headerParams}}
|
|
37
|
+
},
|
|
38
|
+
{{/hasHeaderParams}}
|
|
39
|
+
response: {{#responses}} {{{dataType}}}{{^dataType}}void{{/dataType}} {{^-last}} | {{/-last}} {{/responses}}
|
|
40
|
+
}
|
|
41
|
+
{{/operation}}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* {{{description}}}{{^description}}no description{{/description}}
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
export type EndpointMap = {
|
|
48
|
+
{{#operation}}
|
|
49
|
+
|
|
50
|
+
'#{{#lambda.lowercase}}{{httpMethod}}{{/lambda.lowercase}}|{{path}}': {{#lambda.pascalcase}}{{nickname}}{{/lambda.pascalcase}},
|
|
51
|
+
|
|
52
|
+
{{/operation}}
|
|
53
|
+
}
|
|
54
|
+
{{/operations}}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{{! Sourced from https://github.com/OpenAPITools/openapi-generator/blob/7347daec61b2cb8d3d28e1ed06fe8b5e682090f8/modules/openapi-generator/src/main/resources/typescript-angular/model.mustache#L17. }}
|
|
2
|
+
{{>licenseInfo}}
|
|
3
|
+
{{#models}}
|
|
4
|
+
{{#model}}
|
|
5
|
+
{{#tsImports}}
|
|
6
|
+
import { {{classname}} } from '{{filename}}.model';
|
|
7
|
+
{{/tsImports}}
|
|
8
|
+
|
|
9
|
+
{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#isAlias}}{{>modelAlias}}{{/isAlias}}{{^isAlias}}{{#taggedUnions}}{{>modelTaggedUnion}}{{/taggedUnions}}{{^taggedUnions}}{{#oneOf}}{{#-first}}{{>modelOneOf}}{{/-first}}{{/oneOf}}{{^oneOf}}{{>modelGeneric}}{{/oneOf}}{{/taggedUnions}}{{/isAlias}}{{/isEnum}}
|
|
10
|
+
{{/model}}
|
|
11
|
+
{{/models}}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{{! Sourced from https://github.com/OpenAPITools/openapi-generator/blob/7347daec61b2cb8d3d28e1ed06fe8b5e682090f8/modules/openapi-generator/src/main/resources/typescript-angular/modelEnum.mustache }}
|
|
2
|
+
|
|
3
|
+
{{#stringEnums}}
|
|
4
|
+
/**
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export enum {{classname}} {
|
|
8
|
+
{{#allowableValues}}
|
|
9
|
+
{{#enumVars}}
|
|
10
|
+
{{name}} = {{{value}}}{{^-last}},{{/-last}}
|
|
11
|
+
{{/enumVars}}
|
|
12
|
+
{{/allowableValues}}
|
|
13
|
+
}
|
|
14
|
+
{{/stringEnums}}
|
|
15
|
+
{{^stringEnums}}
|
|
16
|
+
/**
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
export type {{classname}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}} | {{/-last}}{{/enumVars}}{{/allowableValues}};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export const {{classname}} = {
|
|
25
|
+
{{#allowableValues}}
|
|
26
|
+
{{#enumVars}}
|
|
27
|
+
{{name}}: {{{value}}} as {{classname}}{{^-last}},{{/-last}}
|
|
28
|
+
{{/enumVars}}
|
|
29
|
+
{{/allowableValues}}
|
|
30
|
+
};
|
|
31
|
+
{{/stringEnums}}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{{! Sourced from https://github.com/OpenAPITools/openapi-generator/blob/7347daec61b2cb8d3d28e1ed06fe8b5e682090f8/modules/openapi-generator/src/main/resources/typescript-angular/modelGeneric.mustache }}
|
|
2
|
+
|
|
3
|
+
{{#models}}
|
|
4
|
+
{{#model}}
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
{{#description}}
|
|
8
|
+
* {{{.}}}
|
|
9
|
+
{{/description}}
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
{{^isEnum}}
|
|
13
|
+
export {{#isNullable}}type{{/isNullable}}{{^isNullable}}interface{{/isNullable}} {{classname}} {{#isNullable}}={{/isNullable}} {
|
|
14
|
+
{{>modelGenericAdditionalProperties}}
|
|
15
|
+
{{#vars}}
|
|
16
|
+
{{#description}}
|
|
17
|
+
/**
|
|
18
|
+
* {{{.}}}
|
|
19
|
+
*/
|
|
20
|
+
{{/description}}
|
|
21
|
+
'{{name}}'{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}} | null{{/isNullable}};
|
|
22
|
+
{{/vars}}
|
|
23
|
+
}{{#isNullable}} | null{{/isNullable}}
|
|
24
|
+
|
|
25
|
+
{{#hasEnums}}
|
|
26
|
+
|
|
27
|
+
{{#vars}}
|
|
28
|
+
{{#isEnum}}
|
|
29
|
+
/**
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
export type {{classname}}{{enumName}} ={{#allowableValues}}{{#values}} "{{.}}" {{^-last}}|{{/-last}}{{/values}}{{/allowableValues}};
|
|
33
|
+
{{/isEnum}}
|
|
34
|
+
{{/vars}}
|
|
35
|
+
|
|
36
|
+
{{/hasEnums}}
|
|
37
|
+
{{/isEnum}}
|
|
38
|
+
{{#isEnum}}
|
|
39
|
+
/**
|
|
40
|
+
* @public
|
|
41
|
+
*/
|
|
42
|
+
export type {{classname}} ={{#allowableValues}}{{#values}} "{{.}}" {{^-last}}|{{/-last}}{{/values}}{{/allowableValues}};
|
|
43
|
+
{{/isEnum}}
|
|
44
|
+
{{/model}}
|
|
45
|
+
{{/models}}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
{{! Sourced from https://github.com/OpenAPITools/openapi-generator/blob/7347daec61b2cb8d3d28e1ed06fe8b5e682090f8/modules/openapi-generator/src/main/resources/typescript-angular/modelGenericAdditionalProperties.mustache }}
|
|
2
|
+
|
|
3
|
+
{{#additionalPropertiesType}}
|
|
4
|
+
[key: string]: {{{additionalPropertiesType}}};
|
|
5
|
+
{{/additionalPropertiesType}}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{{! Sourced from https://github.com/OpenAPITools/openapi-generator/blob/7347daec61b2cb8d3d28e1ed06fe8b5e682090f8/modules/openapi-generator/src/main/resources/typescript-angular/modelGenericEnums.mustache }}
|
|
2
|
+
|
|
3
|
+
{{#hasEnums}}
|
|
4
|
+
|
|
5
|
+
{{^stringEnums}}
|
|
6
|
+
/**
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export namespace {{classname}} {
|
|
10
|
+
{{/stringEnums}}
|
|
11
|
+
{{#vars}}
|
|
12
|
+
{{#isEnum}}
|
|
13
|
+
{{#stringEnums}}
|
|
14
|
+
/**
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export enum {{classname}}{{enumName}} {
|
|
18
|
+
{{#allowableValues}}
|
|
19
|
+
{{#enumVars}}
|
|
20
|
+
{{name}} = {{{value}}}{{^-last}},{{/-last}}
|
|
21
|
+
{{/enumVars}}
|
|
22
|
+
{{/allowableValues}}
|
|
23
|
+
};
|
|
24
|
+
{{/stringEnums}}
|
|
25
|
+
{{^stringEnums}}
|
|
26
|
+
/**
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
export type {{enumName}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}} | {{/-last}}{{/enumVars}}{{/allowableValues}};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @public
|
|
33
|
+
*/
|
|
34
|
+
export const {{enumName}} = {
|
|
35
|
+
{{#allowableValues}}
|
|
36
|
+
{{#enumVars}}
|
|
37
|
+
{{name}}: {{{value}}} as {{enumName}}{{^-last}},{{/-last}}
|
|
38
|
+
{{/enumVars}}
|
|
39
|
+
{{/allowableValues}}
|
|
40
|
+
};
|
|
41
|
+
{{/stringEnums}}
|
|
42
|
+
{{/isEnum}}
|
|
43
|
+
{{/vars}}
|
|
44
|
+
{{^stringEnums}}}{{/stringEnums}}
|
|
45
|
+
{{/hasEnums}}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{{! Sourced from https://github.com/OpenAPITools/openapi-generator/blob/7347daec61b2cb8d3d28e1ed06fe8b5e682090f8/modules/openapi-generator/src/main/resources/typescript-angular/modelOneOf.mustache }}
|
|
2
|
+
|
|
3
|
+
{{#hasImports}}
|
|
4
|
+
import {
|
|
5
|
+
{{#imports}}
|
|
6
|
+
{{{.}}},
|
|
7
|
+
{{/imports}}
|
|
8
|
+
} from './';
|
|
9
|
+
|
|
10
|
+
{{/hasImports}}
|
|
11
|
+
/**
|
|
12
|
+
{{#description}}
|
|
13
|
+
* {{{.}}}
|
|
14
|
+
{{/description}}
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export type {{classname}} = {{#oneOf}}{{{.}}}{{^-last}} | {{/-last}}{{/oneOf}};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{{! Sourced from https://github.com/OpenAPITools/openapi-generator/blob/7347daec61b2cb8d3d28e1ed06fe8b5e682090f8/modules/openapi-generator/src/main/resources/typescript-angular/modelTaggedUnion.mustache }}
|
|
2
|
+
|
|
3
|
+
{{#discriminator}}
|
|
4
|
+
export type {{classname}} = {{#children}}{{^-first}} | {{/-first}}{{classname}}{{/children}};
|
|
5
|
+
{{/discriminator}}
|
|
6
|
+
{{^discriminator}}
|
|
7
|
+
{{#parent}}
|
|
8
|
+
export interface {{classname}} { {{>modelGenericAdditionalProperties}}
|
|
9
|
+
{{#allVars}}
|
|
10
|
+
{{#description}}
|
|
11
|
+
/**
|
|
12
|
+
* {{{.}}}
|
|
13
|
+
*/
|
|
14
|
+
{{/description}}
|
|
15
|
+
{{name}}{{^required}}?{{/required}}: {{#discriminatorValue}}'{{.}}'{{/discriminatorValue}}{{^discriminatorValue}}{{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{/discriminatorValue}}{{#isNullable}} | null{{/isNullable}};
|
|
16
|
+
{{/allVars}}
|
|
17
|
+
}
|
|
18
|
+
{{>modelGenericEnums}}
|
|
19
|
+
{{/parent}}
|
|
20
|
+
{{^parent}}
|
|
21
|
+
{{>modelGeneric}}
|
|
22
|
+
{{/parent}}
|
|
23
|
+
{{/discriminator}}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
templateDir: templates/typescript-backstage
|
|
1
|
+
templateDir: templates/typescript-backstage-server
|
|
2
2
|
|
|
3
3
|
files:
|
|
4
4
|
api.mustache:
|
|
5
5
|
templateType: API
|
|
6
6
|
# For some reason, they check for destinationFilename differences. We have to change the ending to override the file.
|
|
7
|
-
destinationFilename: .
|
|
7
|
+
destinationFilename: .server.ts
|
|
8
|
+
apis/index.mustache:
|
|
9
|
+
templateType: SupportingFiles
|
|
10
|
+
destinationFilename: apis/index.ts
|
|
11
|
+
index.mustache:
|
|
12
|
+
templateType: SupportingFiles
|
|
13
|
+
destinationFilename: index.ts
|
|
8
14
|
model.mustache:
|
|
9
15
|
templateType: Model
|
|
10
16
|
destinationFilename: .model.ts
|
|
@@ -24,12 +30,4 @@ files:
|
|
|
24
30
|
templateType: SupportingFiles
|
|
25
31
|
models/models_all.mustache:
|
|
26
32
|
templateType: SupportingFiles
|
|
27
|
-
destinationFilename: models/index.ts
|
|
28
|
-
types/fetch.ts: {}
|
|
29
|
-
types/discovery.ts: {}
|
|
30
|
-
apis/index.mustache:
|
|
31
|
-
templateType: SupportingFiles
|
|
32
|
-
destinationFilename: apis/index.ts
|
|
33
|
-
pluginId.mustache:
|
|
34
|
-
templateType: SupportingFiles
|
|
35
|
-
destinationFilename: pluginId.ts
|
|
33
|
+
destinationFilename: models/index.ts
|
|
File without changes
|
|
File without changes
|
/package/templates/{typescript-backstage → typescript-backstage-client}/licenseInfo.mustache
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/{typescript-backstage → typescript-backstage-client}/modelTaggedUnion.mustache
RENAMED
|
File without changes
|
/package/templates/{typescript-backstage → typescript-backstage-client}/models/models_all.mustache
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|