@backstage/repo-tools 0.5.0-next.0 → 0.5.0-next.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/CHANGELOG.md +24 -0
- package/dist/cjs/{api-reports-0697bd2a.cjs.js → api-reports-143209ff.cjs.js} +172 -144
- package/dist/cjs/{generate-be7745a5.cjs.js → generate-675bd523.cjs.js} +12 -9
- package/dist/cjs/{init-9d8f5e0f.cjs.js → init-5e60457a.cjs.js} +3 -3
- package/dist/index.cjs.js +4 -4
- package/openapitools.json +7 -0
- package/package.json +7 -4
- package/templates/typescript-backstage/api.mustache +114 -0
- package/templates/typescript-backstage/apis/index.mustache +3 -0
- package/templates/typescript-backstage/index.mustache +4 -0
- package/templates/typescript-backstage/model.mustache +43 -0
- package/templates/typescript-backstage/models/models_all.mustache +7 -0
- package/templates/typescript-backstage/pluginId.mustache +6 -0
- package/templates/typescript-backstage/types/discovery.ts +22 -0
- package/templates/typescript-backstage/types/fetch.ts +22 -0
- package/templates/typescript-backstage.yaml +21 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @backstage/repo-tools
|
|
2
2
|
|
|
3
|
+
## 0.5.0-next.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f909e9d: Includes templates in @backstage/repo-tools package and use them in the CLI
|
|
8
|
+
- da3c4db: Updates the `schema openapi generate-client` command to export all generated types from the generated directory.
|
|
9
|
+
- 7959f23: The `api-reports` command now checks for api report files that no longer apply.
|
|
10
|
+
If it finds such files, it's treated basically the same as report errors do, and
|
|
11
|
+
the check fails.
|
|
12
|
+
|
|
13
|
+
For example, if you had an `api-report-alpha.md` but then removed the alpha
|
|
14
|
+
export, the reports generator would now report that this file needs to be
|
|
15
|
+
deleted.
|
|
16
|
+
|
|
17
|
+
- f49e237: Fixed a bug where `schema openapi init` created an invalid test command.
|
|
18
|
+
- f91be2c: Updated dependency `@stoplight/types` to `^14.0.0`.
|
|
19
|
+
- 45bfb20: Execute `openapi-generator-cli` from `@backstage/repo-tools` directory to force it to use our openapitools.json config file.
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
- @backstage/backend-common@0.20.0-next.2
|
|
22
|
+
- @backstage/catalog-model@1.4.3
|
|
23
|
+
- @backstage/cli-common@0.1.13
|
|
24
|
+
- @backstage/cli-node@0.2.0
|
|
25
|
+
- @backstage/errors@1.2.3
|
|
26
|
+
|
|
3
27
|
## 0.5.0-next.0
|
|
4
28
|
|
|
5
29
|
### Minor Changes
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var lodash = require('lodash');
|
|
3
4
|
var path = require('path');
|
|
4
5
|
var child_process = require('child_process');
|
|
5
6
|
var fs = require('fs-extra');
|
|
@@ -255,7 +256,9 @@ async function runApiExtraction({
|
|
|
255
256
|
};
|
|
256
257
|
}
|
|
257
258
|
const warnings = new Array();
|
|
258
|
-
for (const
|
|
259
|
+
for (const [packageDir, group] of Object.entries(
|
|
260
|
+
lodash.groupBy(packageEntryPoints, (ep) => ep.packageDir)
|
|
261
|
+
)) {
|
|
259
262
|
console.log(`## Processing ${packageDir}`);
|
|
260
263
|
const noBail = Array.isArray(allowWarnings) ? allowWarnings.some((aw) => aw === packageDir || minimatch__default["default"](packageDir, aw)) : allowWarnings;
|
|
261
264
|
const projectFolder = paths.paths.resolveTargetRoot(packageDir);
|
|
@@ -263,165 +266,190 @@ async function runApiExtraction({
|
|
|
263
266
|
"./dist-types",
|
|
264
267
|
packageDir
|
|
265
268
|
);
|
|
266
|
-
const
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
269
|
+
const names = group.map((ep) => ep.name);
|
|
270
|
+
const remainingReportFiles = new Set(
|
|
271
|
+
fs__default["default"].readdirSync(projectFolder).filter(
|
|
272
|
+
(filename) => filename.match(/^(.+)-api-report\.md$/) || filename.match(/^api-report(-.+)?\.md$/)
|
|
273
|
+
)
|
|
274
|
+
);
|
|
275
|
+
for (const name of names) {
|
|
276
|
+
const suffix = name === "index" ? "" : `-${name}`;
|
|
277
|
+
const reportFileName = `api-report${suffix}.md`;
|
|
278
|
+
const reportPath = path.resolve(projectFolder, reportFileName);
|
|
279
|
+
remainingReportFiles.delete(reportFileName);
|
|
280
|
+
const warningCountBefore = await countApiReportWarnings(reportPath);
|
|
281
|
+
const extractorConfig = apiExtractor.ExtractorConfig.prepare({
|
|
282
|
+
configObject: {
|
|
283
|
+
mainEntryPointFilePath: path.resolve(
|
|
284
|
+
packageFolder,
|
|
285
|
+
`src/${name}.d.ts`
|
|
286
|
+
),
|
|
287
|
+
bundledPackages: [],
|
|
288
|
+
compiler: {
|
|
289
|
+
tsconfigFilePath
|
|
290
|
+
},
|
|
291
|
+
apiReport: {
|
|
292
|
+
enabled: true,
|
|
293
|
+
reportFileName,
|
|
294
|
+
reportFolder: projectFolder,
|
|
295
|
+
reportTempFolder: path.resolve(
|
|
296
|
+
outputDir,
|
|
297
|
+
`<unscopedPackageName>${suffix}`
|
|
298
|
+
)
|
|
299
|
+
},
|
|
300
|
+
docModel: {
|
|
301
|
+
// TODO(Rugvip): This skips docs for non-index entry points. We can try to work around it, but
|
|
302
|
+
// most likely it makes sense to wait for API Extractor to natively support exports.
|
|
303
|
+
enabled: name === "index",
|
|
304
|
+
apiJsonFilePath: path.resolve(
|
|
305
|
+
outputDir,
|
|
306
|
+
`<unscopedPackageName>${suffix}.api.json`
|
|
307
|
+
)
|
|
308
|
+
},
|
|
309
|
+
dtsRollup: {
|
|
310
|
+
enabled: false
|
|
309
311
|
},
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
312
|
+
tsdocMetadata: {
|
|
313
|
+
enabled: false
|
|
314
|
+
},
|
|
315
|
+
messages: {
|
|
316
|
+
// Silence compiler warnings, as these will prevent the CI build to work
|
|
317
|
+
compilerMessageReporting: {
|
|
318
|
+
default: {
|
|
319
|
+
logLevel: "none"
|
|
320
|
+
// These contain absolute file paths, so can't be included in the report
|
|
321
|
+
// addToApiReportFile: true,
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
extractorMessageReporting: {
|
|
325
|
+
default: {
|
|
326
|
+
logLevel: "warning",
|
|
327
|
+
addToApiReportFile: true
|
|
328
|
+
},
|
|
329
|
+
...messagesConf
|
|
314
330
|
},
|
|
315
|
-
|
|
331
|
+
tsdocMessageReporting: {
|
|
332
|
+
default: {
|
|
333
|
+
logLevel: "warning",
|
|
334
|
+
addToApiReportFile: true
|
|
335
|
+
}
|
|
336
|
+
}
|
|
316
337
|
},
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
338
|
+
newlineKind: "lf",
|
|
339
|
+
projectFolder
|
|
340
|
+
},
|
|
341
|
+
configObjectFullPath: projectFolder,
|
|
342
|
+
packageJsonFullPath: path.resolve(projectFolder, "package.json"),
|
|
343
|
+
tsdocConfigFile: await getTsDocConfig(),
|
|
344
|
+
ignoreMissingEntryPoint: true
|
|
345
|
+
});
|
|
346
|
+
extractorConfig.packageFolder = packageFolder;
|
|
347
|
+
if (!compilerState) {
|
|
348
|
+
compilerState = apiExtractor.CompilerState.create(extractorConfig, {
|
|
349
|
+
additionalEntryPoints: entryPoints
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
apiExtractor.Extractor._checkCompilerCompatibility = () => {
|
|
353
|
+
};
|
|
354
|
+
let shouldLogInstructions = false;
|
|
355
|
+
let conflictingFile = void 0;
|
|
356
|
+
const extractorResult = apiExtractor.Extractor.invoke(extractorConfig, {
|
|
357
|
+
localBuild: isLocalBuild,
|
|
358
|
+
showVerboseMessages: false,
|
|
359
|
+
showDiagnostics: false,
|
|
360
|
+
messageCallback(message) {
|
|
361
|
+
if (message.text.includes("The API report file is missing")) {
|
|
362
|
+
shouldLogInstructions = true;
|
|
363
|
+
}
|
|
364
|
+
if (message.text.includes(
|
|
365
|
+
"You have changed the public API signature for this project."
|
|
366
|
+
)) {
|
|
367
|
+
shouldLogInstructions = true;
|
|
368
|
+
const match = message.text.match(
|
|
369
|
+
/Please copy the file "(.*)" to "api-report\.md"/
|
|
370
|
+
);
|
|
371
|
+
if (match) {
|
|
372
|
+
conflictingFile = match[1];
|
|
321
373
|
}
|
|
322
374
|
}
|
|
323
375
|
},
|
|
324
|
-
|
|
325
|
-
projectFolder
|
|
326
|
-
},
|
|
327
|
-
configObjectFullPath: projectFolder,
|
|
328
|
-
packageJsonFullPath: path.resolve(projectFolder, "package.json"),
|
|
329
|
-
tsdocConfigFile: await getTsDocConfig(),
|
|
330
|
-
ignoreMissingEntryPoint: true
|
|
331
|
-
});
|
|
332
|
-
extractorConfig.packageFolder = packageFolder;
|
|
333
|
-
if (!compilerState) {
|
|
334
|
-
compilerState = apiExtractor.CompilerState.create(extractorConfig, {
|
|
335
|
-
additionalEntryPoints: entryPoints
|
|
376
|
+
compilerState
|
|
336
377
|
});
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
const extractorResult = apiExtractor.Extractor.invoke(extractorConfig, {
|
|
343
|
-
localBuild: isLocalBuild,
|
|
344
|
-
showVerboseMessages: false,
|
|
345
|
-
showDiagnostics: false,
|
|
346
|
-
messageCallback(message) {
|
|
347
|
-
if (message.text.includes("The API report file is missing")) {
|
|
348
|
-
shouldLogInstructions = true;
|
|
349
|
-
}
|
|
350
|
-
if (message.text.includes(
|
|
351
|
-
"You have changed the public API signature for this project."
|
|
352
|
-
)) {
|
|
353
|
-
shouldLogInstructions = true;
|
|
354
|
-
const match = message.text.match(
|
|
355
|
-
/Please copy the file "(.*)" to "api-report\.md"/
|
|
378
|
+
if (validateReleaseTags && fs__default["default"].pathExistsSync(extractorConfig.reportFilePath)) {
|
|
379
|
+
if (["index", "alpha", "beta"].includes(name)) {
|
|
380
|
+
const report = await fs__default["default"].readFile(
|
|
381
|
+
extractorConfig.reportFilePath,
|
|
382
|
+
"utf8"
|
|
356
383
|
);
|
|
357
|
-
|
|
358
|
-
|
|
384
|
+
const lines = report.split(/\r?\n/);
|
|
385
|
+
const expectedTag = name === "index" ? "public" : name;
|
|
386
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
387
|
+
const line = lines[i];
|
|
388
|
+
const match = line.match(/^\/\/ @(alpha|beta|public)/);
|
|
389
|
+
if (match && match[1] !== expectedTag) {
|
|
390
|
+
if (expectedTag !== "public" && match[1] === "public") {
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
throw new Error(
|
|
394
|
+
`Unexpected release tag ${match[1]} in ${extractorConfig.reportFilePath} at line ${i + 1}`
|
|
395
|
+
);
|
|
396
|
+
}
|
|
359
397
|
}
|
|
360
398
|
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
for (let i = 0; i < lines.length; i += 1) {
|
|
373
|
-
const line = lines[i];
|
|
374
|
-
const match = line.match(/^\/\/ @(alpha|beta|public)/);
|
|
375
|
-
if (match && match[1] !== expectedTag) {
|
|
376
|
-
if (expectedTag !== "public" && match[1] === "public") {
|
|
377
|
-
continue;
|
|
378
|
-
}
|
|
379
|
-
throw new Error(
|
|
380
|
-
`Unexpected release tag ${match[1]} in ${extractorConfig.reportFilePath} at line ${i + 1}`
|
|
399
|
+
}
|
|
400
|
+
if (!extractorResult.succeeded) {
|
|
401
|
+
if (shouldLogInstructions) {
|
|
402
|
+
logApiReportInstructions();
|
|
403
|
+
if (conflictingFile) {
|
|
404
|
+
console.log("");
|
|
405
|
+
console.log(
|
|
406
|
+
`The conflicting file is ${path.relative(
|
|
407
|
+
tmpDir,
|
|
408
|
+
conflictingFile
|
|
409
|
+
)}, with the following content:`
|
|
381
410
|
);
|
|
411
|
+
console.log("");
|
|
412
|
+
const content = await fs__default["default"].readFile(conflictingFile, "utf8");
|
|
413
|
+
console.log(content);
|
|
414
|
+
logApiReportInstructions();
|
|
382
415
|
}
|
|
383
416
|
}
|
|
417
|
+
throw new Error(
|
|
418
|
+
`API Extractor completed with ${extractorResult.errorCount} errors and ${extractorResult.warningCount} warnings`
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
const warningCountAfter = await countApiReportWarnings(reportPath);
|
|
422
|
+
if (noBail) {
|
|
423
|
+
console.log(`Skipping warnings check for ${packageDir}`);
|
|
424
|
+
}
|
|
425
|
+
if (warningCountAfter > 0 && !noBail) {
|
|
426
|
+
throw new Error(
|
|
427
|
+
`The API Report for ${packageDir} is not allowed to have warnings`
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
if (warningCountAfter === 0 && allowWarningPkg.includes(packageDir)) {
|
|
431
|
+
console.log(
|
|
432
|
+
`No need to allow warnings for ${packageDir}, it does not have any`
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
if (warningCountAfter > warningCountBefore) {
|
|
436
|
+
warnings.push(
|
|
437
|
+
`The API Report for ${packageDir} introduces new warnings. Please fix these warnings in order to keep the API Reports tidy.`
|
|
438
|
+
);
|
|
384
439
|
}
|
|
385
440
|
}
|
|
386
|
-
if (
|
|
387
|
-
if (
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
console.log(
|
|
391
|
-
console.log(
|
|
392
|
-
`The conflicting file is ${path.relative(
|
|
393
|
-
tmpDir,
|
|
394
|
-
conflictingFile
|
|
395
|
-
)}, with the following content:`
|
|
396
|
-
);
|
|
397
|
-
console.log("");
|
|
398
|
-
const content = await fs__default["default"].readFile(conflictingFile, "utf8");
|
|
399
|
-
console.log(content);
|
|
400
|
-
logApiReportInstructions();
|
|
441
|
+
if (remainingReportFiles.size > 0) {
|
|
442
|
+
if (isLocalBuild) {
|
|
443
|
+
for (const f of remainingReportFiles) {
|
|
444
|
+
fs__default["default"].rmSync(path.resolve(projectFolder, f));
|
|
445
|
+
console.log(`Deleted deprecated API report ${f}`);
|
|
401
446
|
}
|
|
447
|
+
} else {
|
|
448
|
+
const staleList = [...remainingReportFiles].map((f) => path.join(packageDir, f)).join(", ");
|
|
449
|
+
throw new Error(
|
|
450
|
+
`The API Report(s) ${staleList} are no longer relevant and should be deleted`
|
|
451
|
+
);
|
|
402
452
|
}
|
|
403
|
-
throw new Error(
|
|
404
|
-
`API Extractor completed with ${extractorResult.errorCount} errors and ${extractorResult.warningCount} warnings`
|
|
405
|
-
);
|
|
406
|
-
}
|
|
407
|
-
const warningCountAfter = await countApiReportWarnings(reportPath);
|
|
408
|
-
if (noBail) {
|
|
409
|
-
console.log(`Skipping warnings check for ${packageDir}`);
|
|
410
|
-
}
|
|
411
|
-
if (warningCountAfter > 0 && !noBail) {
|
|
412
|
-
throw new Error(
|
|
413
|
-
`The API Report for ${packageDir} is not allowed to have warnings`
|
|
414
|
-
);
|
|
415
|
-
}
|
|
416
|
-
if (warningCountAfter === 0 && allowWarningPkg.includes(packageDir)) {
|
|
417
|
-
console.log(
|
|
418
|
-
`No need to allow warnings for ${packageDir}, it does not have any`
|
|
419
|
-
);
|
|
420
|
-
}
|
|
421
|
-
if (warningCountAfter > warningCountBefore) {
|
|
422
|
-
warnings.push(
|
|
423
|
-
`The API Report for ${packageDir} introduces new warnings. Please fix these warnings in order to keep the API Reports tidy.`
|
|
424
|
-
);
|
|
425
453
|
}
|
|
426
454
|
}
|
|
427
455
|
if (warnings.length > 0) {
|
|
@@ -1150,4 +1178,4 @@ function parseArrayOption(value) {
|
|
|
1150
1178
|
}
|
|
1151
1179
|
|
|
1152
1180
|
exports.buildApiReports = buildApiReports;
|
|
1153
|
-
//# sourceMappingURL=api-reports-
|
|
1181
|
+
//# sourceMappingURL=api-reports-143209ff.cjs.js.map
|
|
@@ -6,6 +6,7 @@ var constants = require('./constants-866c449d.cjs.js');
|
|
|
6
6
|
var paths = require('./paths-9ab9b8a8.cjs.js');
|
|
7
7
|
var fs = require('fs-extra');
|
|
8
8
|
var exec = require('./exec-7bf444eb.cjs.js');
|
|
9
|
+
var backendCommon = require('@backstage/backend-common');
|
|
9
10
|
require('@backstage/cli-common');
|
|
10
11
|
require('@backstage/cli-node');
|
|
11
12
|
require('minimatch');
|
|
@@ -27,10 +28,9 @@ async function generate(spec, outputDirectory) {
|
|
|
27
28
|
constants.OPENAPI_IGNORE_FILES.join("\n")
|
|
28
29
|
);
|
|
29
30
|
await exec.exec(
|
|
30
|
-
|
|
31
|
-
// TODO (sennyeya@): Make this use the actual binary
|
|
32
|
-
`yarn openapi-generator-cli`,
|
|
31
|
+
"node",
|
|
33
32
|
[
|
|
33
|
+
backendCommon.resolvePackagePath("@openapitools/openapi-generator-cli", "main.js"),
|
|
34
34
|
"generate",
|
|
35
35
|
"-i",
|
|
36
36
|
resolvedOpenapiPath,
|
|
@@ -39,24 +39,27 @@ async function generate(spec, outputDirectory) {
|
|
|
39
39
|
"-g",
|
|
40
40
|
"typescript",
|
|
41
41
|
"-c",
|
|
42
|
-
|
|
42
|
+
backendCommon.resolvePackagePath(
|
|
43
|
+
"@backstage/repo-tools",
|
|
44
|
+
"templates/typescript-backstage.yaml"
|
|
45
|
+
),
|
|
43
46
|
"--generator-key",
|
|
44
47
|
"v3.0"
|
|
45
48
|
],
|
|
46
49
|
{
|
|
47
50
|
maxBuffer: Number.MAX_VALUE,
|
|
48
|
-
cwd:
|
|
51
|
+
cwd: backendCommon.resolvePackagePath("@backstage/repo-tools"),
|
|
49
52
|
env: {
|
|
50
53
|
...process.env
|
|
51
|
-
// PWD: outputDirectory,
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
56
|
);
|
|
55
57
|
await exec.exec(
|
|
56
58
|
`yarn backstage-cli package lint --fix ${resolvedOutputDirectory}`
|
|
57
59
|
);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
const prettier = paths.paths.resolveTargetRoot("node_modules/.bin/prettier");
|
|
61
|
+
if (prettier) {
|
|
62
|
+
await exec.exec(`${prettier} --write ${resolvedOutputDirectory}`);
|
|
60
63
|
}
|
|
61
64
|
fs__default["default"].removeSync(path.resolve(resolvedOutputDirectory, ".openapi-generator-ignore"));
|
|
62
65
|
fs__default["default"].rmSync(path.resolve(resolvedOutputDirectory, ".openapi-generator"), {
|
|
@@ -80,4 +83,4 @@ async function singleCommand({
|
|
|
80
83
|
}
|
|
81
84
|
|
|
82
85
|
exports.singleCommand = singleCommand;
|
|
83
|
-
//# sourceMappingURL=generate-
|
|
86
|
+
//# sourceMappingURL=generate-675bd523.cjs.js.map
|
|
@@ -32,7 +32,7 @@ async function init(directoryPath) {
|
|
|
32
32
|
);
|
|
33
33
|
}
|
|
34
34
|
const opticConfigFilePath = path.join(directoryPath, "optic.yml");
|
|
35
|
-
if (
|
|
35
|
+
if (await fs__default["default"].pathExists(opticConfigFilePath)) {
|
|
36
36
|
throw new Error(`This directory already has an optic.yml file. Exiting.`);
|
|
37
37
|
}
|
|
38
38
|
await fs__default["default"].writeFile(
|
|
@@ -53,7 +53,7 @@ capture:
|
|
|
53
53
|
# \u{1F527} Specify a command that will generate traffic
|
|
54
54
|
command: yarn backstage-cli package test --no-watch ${ROUTER_TEST_PATHS.map(
|
|
55
55
|
(e) => `"${e}"`
|
|
56
|
-
).join("
|
|
56
|
+
).join(" ")}
|
|
57
57
|
`
|
|
58
58
|
);
|
|
59
59
|
if (await paths.paths.resolveTargetRoot("node_modules/.bin/prettier")) {
|
|
@@ -83,4 +83,4 @@ async function initCommand(paths = []) {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
exports["default"] = initCommand;
|
|
86
|
-
//# sourceMappingURL=init-
|
|
86
|
+
//# sourceMappingURL=init-5e60457a.cjs.js.map
|
package/dist/index.cjs.js
CHANGED
|
@@ -62,10 +62,10 @@ function registerSchemaCommand(program) {
|
|
|
62
62
|
"Fail on any linting severity messages, not just errors."
|
|
63
63
|
).action(lazy(() => Promise.resolve().then(function () { return require('./cjs/lint-e06bf899.cjs.js'); }).then((m) => m.bulkCommand)));
|
|
64
64
|
openApiCommand.command("test [paths...]").description("Test OpenAPI schemas against written tests").option("--update", "Update the spec on failure.").action(lazy(() => Promise.resolve().then(function () { return require('./cjs/index-ed4aaab1.cjs.js'); }).then((m) => m.bulkCommand)));
|
|
65
|
-
openApiCommand.command("init <paths...>").description("Creates any config needed for the test command.").action(lazy(() => Promise.resolve().then(function () { return require('./cjs/init-
|
|
65
|
+
openApiCommand.command("init <paths...>").description("Creates any config needed for the test command.").action(lazy(() => Promise.resolve().then(function () { return require('./cjs/init-5e60457a.cjs.js'); }).then((m) => m.default)));
|
|
66
66
|
openApiCommand.command("generate-client").requiredOption("--input-spec <file>").requiredOption("--output-directory <directory>").action(
|
|
67
67
|
lazy(
|
|
68
|
-
() => Promise.resolve().then(function () { return require('./cjs/generate-
|
|
68
|
+
() => Promise.resolve().then(function () { return require('./cjs/generate-675bd523.cjs.js'); }).then((m) => m.singleCommand)
|
|
69
69
|
)
|
|
70
70
|
);
|
|
71
71
|
}
|
|
@@ -93,7 +93,7 @@ function registerCommands(program) {
|
|
|
93
93
|
"Turn on release tag validation for the public, beta, and alpha APIs"
|
|
94
94
|
).description("Generate an API report for selected packages").action(
|
|
95
95
|
lazy(
|
|
96
|
-
() => Promise.resolve().then(function () { return require('./cjs/api-reports-
|
|
96
|
+
() => Promise.resolve().then(function () { return require('./cjs/api-reports-143209ff.cjs.js'); }).then((m) => m.buildApiReports)
|
|
97
97
|
)
|
|
98
98
|
);
|
|
99
99
|
program.command("type-deps").description("Find inconsistencies in types of all packages and plugins").action(lazy(() => Promise.resolve().then(function () { return require('./cjs/type-deps-5eacd931.cjs.js'); }).then((m) => m.default)));
|
|
@@ -125,7 +125,7 @@ function lazy(getActionFunc) {
|
|
|
125
125
|
};
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
var version = "0.5.0-next.
|
|
128
|
+
var version = "0.5.0-next.1";
|
|
129
129
|
|
|
130
130
|
const main = (argv) => {
|
|
131
131
|
commander.program.name("backstage-repo-tools").version(version);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/repo-tools",
|
|
3
3
|
"description": "CLI for Backstage repo tooling ",
|
|
4
|
-
"version": "0.5.0-next.
|
|
4
|
+
"version": "0.5.0-next.1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@apidevtools/swagger-parser": "^10.1.0",
|
|
34
34
|
"@apisyouwonthate/style-guide": "^1.4.0",
|
|
35
|
+
"@backstage/backend-common": "^0.20.0-next.2",
|
|
35
36
|
"@backstage/catalog-model": "^1.4.3",
|
|
36
37
|
"@backstage/cli-common": "^0.1.13",
|
|
37
38
|
"@backstage/cli-node": "^0.2.0",
|
|
@@ -46,7 +47,7 @@
|
|
|
46
47
|
"@stoplight/spectral-parsers": "^1.0.2",
|
|
47
48
|
"@stoplight/spectral-rulesets": "^1.18.0",
|
|
48
49
|
"@stoplight/spectral-runtime": "^1.1.2",
|
|
49
|
-
"@stoplight/types": "^
|
|
50
|
+
"@stoplight/types": "^14.0.0",
|
|
50
51
|
"chalk": "^4.0.0",
|
|
51
52
|
"codeowners-utils": "^1.0.2",
|
|
52
53
|
"commander": "^9.1.0",
|
|
@@ -62,7 +63,7 @@
|
|
|
62
63
|
"yaml-diff-patch": "^2.0.0"
|
|
63
64
|
},
|
|
64
65
|
"devDependencies": {
|
|
65
|
-
"@backstage/cli": "^0.25.0-next.
|
|
66
|
+
"@backstage/cli": "^0.25.0-next.2",
|
|
66
67
|
"@backstage/types": "^1.1.1",
|
|
67
68
|
"@types/is-glob": "^4.0.2",
|
|
68
69
|
"@types/mock-fs": "^4.13.0",
|
|
@@ -85,7 +86,9 @@
|
|
|
85
86
|
},
|
|
86
87
|
"files": [
|
|
87
88
|
"bin",
|
|
88
|
-
"dist/**/*.js"
|
|
89
|
+
"dist/**/*.js",
|
|
90
|
+
"templates",
|
|
91
|
+
"openapitools.json"
|
|
89
92
|
],
|
|
90
93
|
"nodemonConfig": {
|
|
91
94
|
"watch": "./src",
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{{>licenseInfo}}
|
|
2
|
+
import { DiscoveryApi } from '../types/discovery';
|
|
3
|
+
import { FetchApi } from '../types/fetch';
|
|
4
|
+
import crossFetch from 'cross-fetch';
|
|
5
|
+
import {pluginId} from '../pluginId';
|
|
6
|
+
import * as parser from 'uri-template';
|
|
7
|
+
|
|
8
|
+
{{#imports}}
|
|
9
|
+
import { {{classname}} } from '{{filename}}.model{{importFileExtension}}';
|
|
10
|
+
{{/imports}}
|
|
11
|
+
|
|
12
|
+
type TypedResponse<T> = Omit<Response, 'json'> & {
|
|
13
|
+
json: () => Promise<T>;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
{{#operations}}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Options you can pass into a request for additional information.
|
|
20
|
+
*
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
export interface RequestOptions {
|
|
24
|
+
token?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* {{{description}}}{{^description}}no description{{/description}}
|
|
29
|
+
*/
|
|
30
|
+
export class {{classname}}Client {
|
|
31
|
+
private readonly discoveryApi: DiscoveryApi;
|
|
32
|
+
private readonly fetchApi: FetchApi;
|
|
33
|
+
|
|
34
|
+
constructor(options: {
|
|
35
|
+
discoveryApi: { getBaseUrl(pluginId: string): Promise<string> };
|
|
36
|
+
fetchApi?: { fetch: typeof fetch };
|
|
37
|
+
}) {
|
|
38
|
+
this.discoveryApi = options.discoveryApi;
|
|
39
|
+
this.fetchApi = options.fetchApi || { fetch: crossFetch };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
{{#operation}}
|
|
43
|
+
/**
|
|
44
|
+
{{#notes}}
|
|
45
|
+
* {{¬es}}
|
|
46
|
+
{{/notes}}
|
|
47
|
+
{{#summary}}
|
|
48
|
+
* {{&summary}}
|
|
49
|
+
{{/summary}}
|
|
50
|
+
{{#allParams}}
|
|
51
|
+
* @param {{paramName}} {{description}}
|
|
52
|
+
{{/allParams}}
|
|
53
|
+
*/
|
|
54
|
+
public async {{nickname}}(
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
request: {
|
|
57
|
+
{{#hasPathParams}}
|
|
58
|
+
path: {
|
|
59
|
+
{{#pathParams}}
|
|
60
|
+
{{paramName}}{{^required}}?{{/required}}: {{{dataType}}},
|
|
61
|
+
{{/pathParams}}
|
|
62
|
+
},
|
|
63
|
+
{{/hasPathParams}}
|
|
64
|
+
{{#hasBodyParam}}
|
|
65
|
+
{{#bodyParam}}
|
|
66
|
+
body: {{{dataType}}},
|
|
67
|
+
{{/bodyParam}}
|
|
68
|
+
{{/hasBodyParam}}
|
|
69
|
+
{{#hasQueryParams}}
|
|
70
|
+
query: {
|
|
71
|
+
{{#queryParams}}
|
|
72
|
+
{{paramName}}{{^required}}?{{/required}}: {{{dataType}}},
|
|
73
|
+
{{/queryParams}}
|
|
74
|
+
},
|
|
75
|
+
{{/hasQueryParams}}
|
|
76
|
+
{{#hasHeaderParams}}
|
|
77
|
+
header: {
|
|
78
|
+
{{#headerParams}}
|
|
79
|
+
{{paramName}}{{^required}}?{{/required}}: {{{dataType}}},
|
|
80
|
+
{{/headerParams}}
|
|
81
|
+
},
|
|
82
|
+
{{/hasHeaderParams}}
|
|
83
|
+
},
|
|
84
|
+
options?: RequestOptions
|
|
85
|
+
): Promise<TypedResponse<{{{returnType}}} {{^returnType}}void{{/returnType}}>> {
|
|
86
|
+
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
|
|
87
|
+
|
|
88
|
+
const uriTemplate = `{{{path}}}{{#hasQueryParams}}{?{{#queryParams}}{{baseName}}{{#isArray}}{{#isExplode}}*{{/isExplode}}{{/isArray}}{{^-last}},{{/-last}}{{/queryParams}}}{{/hasQueryParams}}`;
|
|
89
|
+
|
|
90
|
+
const uri = parser.parse(uriTemplate).expand({
|
|
91
|
+
{{#pathParams}}
|
|
92
|
+
{{baseName}}: request.path.{{paramName}},
|
|
93
|
+
{{/pathParams}}
|
|
94
|
+
{{#hasQueryParams}}
|
|
95
|
+
...request.query,
|
|
96
|
+
{{/hasQueryParams}}
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
return await this.fetchApi.fetch(`${baseUrl}${uri}`, {
|
|
100
|
+
headers: {
|
|
101
|
+
{{#hasHeaderParams}}
|
|
102
|
+
...request.header,
|
|
103
|
+
{{/hasHeaderParams}}
|
|
104
|
+
'Content-Type': 'application/json',
|
|
105
|
+
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
|
|
106
|
+
},
|
|
107
|
+
method: '{{httpMethod}}',
|
|
108
|
+
{{#hasBodyParam}} body: JSON.stringify(request.body), {{/hasBodyParam}}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
{{/operation}}
|
|
113
|
+
}
|
|
114
|
+
{{/operations}}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//
|
|
2
|
+
|
|
3
|
+
{{#models}}
|
|
4
|
+
{{#model}}
|
|
5
|
+
{{#tsImports}}
|
|
6
|
+
import { {{classname}} } from '{{filename}}.model{{importFileExtension}}';
|
|
7
|
+
{{/tsImports}}
|
|
8
|
+
|
|
9
|
+
{{#description}}
|
|
10
|
+
/**
|
|
11
|
+
* {{{.}}}
|
|
12
|
+
*/
|
|
13
|
+
{{/description}}
|
|
14
|
+
{{^isEnum}}
|
|
15
|
+
export interface {{classname}} {
|
|
16
|
+
{{#additionalPropertiesType}}
|
|
17
|
+
[key: string]: {{{additionalPropertiesType}}};
|
|
18
|
+
{{/additionalPropertiesType}}
|
|
19
|
+
{{#vars}}
|
|
20
|
+
{{#description}}
|
|
21
|
+
/**
|
|
22
|
+
* {{{.}}}
|
|
23
|
+
*/
|
|
24
|
+
{{/description}}
|
|
25
|
+
'{{name}}'{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}} | null{{/isNullable}};
|
|
26
|
+
{{/vars}}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
{{#hasEnums}}
|
|
30
|
+
|
|
31
|
+
{{#vars}}
|
|
32
|
+
{{#isEnum}}
|
|
33
|
+
export type {{classname}}{{enumName}} ={{#allowableValues}}{{#values}} "{{.}}" {{^-last}}|{{/-last}}{{/values}}{{/allowableValues}};
|
|
34
|
+
{{/isEnum}}
|
|
35
|
+
{{/vars}}
|
|
36
|
+
|
|
37
|
+
{{/hasEnums}}
|
|
38
|
+
{{/isEnum}}
|
|
39
|
+
{{#isEnum}}
|
|
40
|
+
export type {{classname}} ={{#allowableValues}}{{#values}} "{{.}}" {{^-last}}|{{/-last}}{{/values}}{{/allowableValues}};
|
|
41
|
+
{{/isEnum}}
|
|
42
|
+
{{/model}}
|
|
43
|
+
{{/models}}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2023 The Backstage Authors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* This is a copy of the DiscoveryApi, to avoid importing core-plugin-api.
|
|
19
|
+
*/
|
|
20
|
+
export type DiscoveryApi = {
|
|
21
|
+
getBaseUrl(pluginId: string): Promise<string>;
|
|
22
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2023 The Backstage Authors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* This is a copy of FetchApi, to avoid importing core-plugin-api.
|
|
19
|
+
*/
|
|
20
|
+
export type FetchApi = {
|
|
21
|
+
fetch: typeof fetch;
|
|
22
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
templateDir: templates/typescript-backstage
|
|
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
|
+
models/models_all.mustache:
|
|
12
|
+
templateType: SupportingFiles
|
|
13
|
+
destinationFilename: models/index.ts
|
|
14
|
+
types/fetch.ts: {}
|
|
15
|
+
types/discovery.ts: {}
|
|
16
|
+
apis/index.mustache:
|
|
17
|
+
templateType: SupportingFiles
|
|
18
|
+
destinationFilename: apis/index.ts
|
|
19
|
+
pluginId.mustache:
|
|
20
|
+
templateType: SupportingFiles
|
|
21
|
+
destinationFilename: pluginId.ts
|