@decohere/create 0.0.1-dev.20 → 0.0.1-dev.20261105.110

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.
Files changed (94) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +255 -0
  3. package/es6/src/cli.js +1 -34
  4. package/es6/src/index.js +2 -0
  5. package/es6/src/resolve-launch.js +87 -0
  6. package/es6/src/runner.js +67 -24
  7. package/es6/src/version.js +14 -6
  8. package/pack-builder-tgz.mjs +177 -0
  9. package/package.json +23 -11
  10. package/types/src/index.d.ts +3 -0
  11. package/types/src/resolve-launch.d.ts +20 -0
  12. package/types/src/runner.d.ts +3 -11
  13. package/types/src/version.d.ts +1 -1
  14. package/commonjs/src/cli.js +0 -40
  15. package/commonjs/src/domain/prompt.js +0 -55
  16. package/commonjs/src/models/compose.model.js +0 -82
  17. package/commonjs/src/models/config-yaml.model.js +0 -34
  18. package/commonjs/src/models/const.js +0 -29
  19. package/commonjs/src/models/container-image.model.js +0 -88
  20. package/commonjs/src/models/dev-container.model.js +0 -73
  21. package/commonjs/src/models/env-file.model.js +0 -33
  22. package/commonjs/src/models/gitignore.model.js +0 -32
  23. package/commonjs/src/models/launch-json.model.js +0 -52
  24. package/commonjs/src/models/package-json.model.js +0 -64
  25. package/commonjs/src/models/project.model.js +0 -126
  26. package/commonjs/src/models/source-file.js +0 -6
  27. package/commonjs/src/models/tsconfig.model.js +0 -34
  28. package/commonjs/src/models/vscode-settings.model.js +0 -31
  29. package/commonjs/src/runner.js +0 -56
  30. package/commonjs/src/services/scaffold.service.js +0 -62
  31. package/commonjs/src/version.js +0 -32
  32. package/commonjs/src/webapi/create-api.js +0 -169
  33. package/commonjs/src/webapi/features/auth.feature.js +0 -166
  34. package/commonjs/src/webapi/features/auth0-cli.js +0 -151
  35. package/commonjs/src/webapi/features/database.feature.js +0 -151
  36. package/commonjs/src/webapi/features/finalize.feature.js +0 -51
  37. package/commonjs/src/webapi/features/postman.feature.js +0 -309
  38. package/commonjs/src/webapi/models/api-package-json.model.js +0 -57
  39. package/commonjs/src/webapi/models/auth-config.model.js +0 -23
  40. package/commonjs/src/webapi/models/controller-source-file.model.js +0 -180
  41. package/commonjs/src/webapi/models/main-source-file.model.js +0 -132
  42. package/commonjs/src/webapi/models/sample-files.model.js +0 -60
  43. package/es6/src/domain/prompt.js +0 -37
  44. package/es6/src/models/compose.model.js +0 -77
  45. package/es6/src/models/config-yaml.model.js +0 -30
  46. package/es6/src/models/const.js +0 -19
  47. package/es6/src/models/container-image.model.js +0 -84
  48. package/es6/src/models/dev-container.model.js +0 -68
  49. package/es6/src/models/env-file.model.js +0 -29
  50. package/es6/src/models/gitignore.model.js +0 -22
  51. package/es6/src/models/launch-json.model.js +0 -42
  52. package/es6/src/models/package-json.model.js +0 -60
  53. package/es6/src/models/project.model.js +0 -111
  54. package/es6/src/models/source-file.js +0 -3
  55. package/es6/src/models/tsconfig.model.js +0 -24
  56. package/es6/src/models/vscode-settings.model.js +0 -21
  57. package/es6/src/services/scaffold.service.js +0 -52
  58. package/es6/src/webapi/create-api.js +0 -151
  59. package/es6/src/webapi/features/auth.feature.js +0 -115
  60. package/es6/src/webapi/features/auth0-cli.js +0 -116
  61. package/es6/src/webapi/features/database.feature.js +0 -141
  62. package/es6/src/webapi/features/finalize.feature.js +0 -41
  63. package/es6/src/webapi/features/postman.feature.js +0 -258
  64. package/es6/src/webapi/models/api-package-json.model.js +0 -52
  65. package/es6/src/webapi/models/auth-config.model.js +0 -19
  66. package/es6/src/webapi/models/controller-source-file.model.js +0 -171
  67. package/es6/src/webapi/models/main-source-file.model.js +0 -128
  68. package/es6/src/webapi/models/sample-files.model.js +0 -42
  69. package/types/src/domain/prompt.d.ts +0 -2
  70. package/types/src/models/compose.model.d.ts +0 -32
  71. package/types/src/models/config-yaml.model.d.ts +0 -16
  72. package/types/src/models/const.d.ts +0 -17
  73. package/types/src/models/container-image.model.d.ts +0 -15
  74. package/types/src/models/dev-container.model.d.ts +0 -21
  75. package/types/src/models/env-file.model.d.ts +0 -14
  76. package/types/src/models/gitignore.model.d.ts +0 -6
  77. package/types/src/models/launch-json.model.d.ts +0 -5
  78. package/types/src/models/package-json.model.d.ts +0 -18
  79. package/types/src/models/project.model.d.ts +0 -55
  80. package/types/src/models/source-file.d.ts +0 -11
  81. package/types/src/models/tsconfig.model.d.ts +0 -5
  82. package/types/src/models/vscode-settings.model.d.ts +0 -7
  83. package/types/src/services/scaffold.service.d.ts +0 -22
  84. package/types/src/webapi/create-api.d.ts +0 -7
  85. package/types/src/webapi/features/auth.feature.d.ts +0 -7
  86. package/types/src/webapi/features/auth0-cli.d.ts +0 -22
  87. package/types/src/webapi/features/database.feature.d.ts +0 -5
  88. package/types/src/webapi/features/finalize.feature.d.ts +0 -2
  89. package/types/src/webapi/features/postman.feature.d.ts +0 -7
  90. package/types/src/webapi/models/api-package-json.model.d.ts +0 -17
  91. package/types/src/webapi/models/auth-config.model.d.ts +0 -18
  92. package/types/src/webapi/models/controller-source-file.model.d.ts +0 -42
  93. package/types/src/webapi/models/main-source-file.model.d.ts +0 -36
  94. package/types/src/webapi/models/sample-files.model.d.ts +0 -7
@@ -1,151 +0,0 @@
1
- import { resolve } from "node:path";
2
- import { DockerCompose } from "../models/compose.model.js";
3
- import { ConfigYaml } from "../models/config-yaml.model.js";
4
- import { WELL_KNOWN_FILES } from "../models/const.js";
5
- import { DockerfileModel } from "../models/container-image.model.js";
6
- import { DevContainer } from "../models/dev-container.model.js";
7
- import { EnvFile } from "../models/env-file.model.js";
8
- import { Gitignore } from "../models/gitignore.model.js";
9
- import { LaunchJson } from "../models/launch-json.model.js";
10
- import { PackageJson } from "../models/package-json.model.js";
11
- import { MonoRepoScaffold, ProjectScaffold } from "../models/project.model.js";
12
- import { TsConfig } from "../models/tsconfig.model.js";
13
- import { VSCodeSettings } from "../models/vscode-settings.model.js";
14
- import { ScaffoldService } from "../services/scaffold.service.js";
15
- import { AuthFeature } from "./features/auth.feature.js";
16
- import { DatabaseFeature } from "./features/database.feature.js";
17
- import { FinalizeFeature } from "./features/finalize.feature.js";
18
- import { PostmanFeature } from "./features/postman.feature.js";
19
- import { ApiPackageJson } from "./models/api-package-json.model.js";
20
- import { ControllerSourceFile } from "./models/controller-source-file.model.js";
21
- import { MainSourceFile } from "./models/main-source-file.model.js";
22
- import { SampleConfigModel, SampleServiceModel } from "./models/sample-files.model.js";
23
- export const WEBAPI_PROJECT_DIR = "projects/api";
24
- const features = [
25
- DatabaseFeature,
26
- AuthFeature,
27
- PostmanFeature,
28
- FinalizeFeature
29
- ];
30
- export async function scaffoldApi(cliOptions) {
31
- const targetDir = resolve(cliOptions.d ?? ".");
32
- const workspace = createWorkspace(targetDir);
33
- await ScaffoldService.scaffold(workspace, cliOptions, features);
34
- }
35
- function createWorkspace(targetDir) {
36
- const monoRepo = new MonoRepoScaffold();
37
- monoRepo.targetDir = targetDir;
38
- const name = monoRepo.name;
39
- const compose = new DockerCompose().addService("devcontainer", {
40
- build: ".",
41
- volumes: [
42
- `\${HOME}/.npm/${name}:/home/node/.npm-config`,
43
- "webapi-node-modules:/workspace/node_modules"
44
- ],
45
- environment: {
46
- NPM_CONFIG_USERCONFIG: "/home/node/.npm-config/.npmrc"
47
- },
48
- command: "sleep infinity"
49
- }).addVolume("webapi-node-modules");
50
- const devContainer = new DevContainer().addExtension("biomejs.biome", "vitest.explorer").setPostStartCommand("npm whoami 2>/dev/null || npm login").useCompose();
51
- // Workspace-level models (repo root)
52
- monoRepo.addModel(compose);
53
- monoRepo.addModel(devContainer);
54
- monoRepo.addModel(new DockerfileModel());
55
- monoRepo.addModel(new VSCodeSettings(name));
56
- monoRepo.addModel(new LaunchJson());
57
- monoRepo.addModel(new TsConfig());
58
- monoRepo.addModel(new PackageJson(`${name}.api`));
59
- monoRepo.addModel(new ConfigYaml(WELL_KNOWN_FILES.CONFIG_YAML, "config/config.yaml", ""));
60
- monoRepo.addModel(new ConfigYaml(WELL_KNOWN_FILES.CONFIG_DEV_YAML, "config/config.dev.yaml", ""));
61
- monoRepo.addModel(new Gitignore());
62
- monoRepo.addModel(new EnvFile());
63
- // Biome formatter/linter config
64
- monoRepo.addFile({
65
- files: ()=>[
66
- {
67
- filePath: "biome.json",
68
- content: JSON.stringify({
69
- $schema: "https://biomejs.dev/schemas/2.0.0/schema.json",
70
- files: {
71
- includes: [
72
- "**/*.ts",
73
- "**/*.js",
74
- "**/*.json",
75
- "**/*.yml",
76
- "**/*.yaml"
77
- ]
78
- },
79
- assist: {
80
- actions: {
81
- source: {
82
- organizeImports: "on"
83
- }
84
- }
85
- },
86
- vcs: {
87
- enabled: true,
88
- clientKind: "git",
89
- useIgnoreFile: true
90
- },
91
- formatter: {
92
- enabled: true,
93
- formatWithErrors: true,
94
- indentStyle: "tab",
95
- lineWidth: 95
96
- },
97
- javascript: {
98
- parser: {
99
- unsafeParameterDecoratorsEnabled: true
100
- }
101
- },
102
- linter: {
103
- rules: {
104
- style: {
105
- useConsistentMemberAccessibility: {
106
- level: "error",
107
- options: {
108
- accessibility: "explicit"
109
- }
110
- }
111
- }
112
- }
113
- },
114
- overrides: [
115
- {
116
- includes: [
117
- "**/*.json"
118
- ],
119
- formatter: {
120
- indentStyle: "space",
121
- indentWidth: 2
122
- }
123
- }
124
- ]
125
- }, null, 2)
126
- }
127
- ]
128
- });
129
- // NPM token placeholder — gitignored, set manually after scaffold
130
- monoRepo.addFile({
131
- files: ()=>[
132
- {
133
- filePath: ".env.local",
134
- content: "# Set your npm access token here (created with: npm token create)\nNPM_TOKEN=\n"
135
- }
136
- ]
137
- });
138
- // Project-level models (paths relative to projects/api)
139
- const apiProject = new ProjectScaffold(WEBAPI_PROJECT_DIR);
140
- apiProject.addModel(new ApiPackageJson(name));
141
- apiProject.addModel(new MainSourceFile(`${name}.api`));
142
- apiProject.addModel(new ControllerSourceFile());
143
- // SampleService + SampleConfig are part of the core scaffold — HelloController
144
- // injects SampleService to demonstrate config-driven behaviour out of the box.
145
- apiProject.addFile(new SampleConfigModel());
146
- apiProject.addFile(new SampleServiceModel());
147
- monoRepo.addProject(apiProject);
148
- return monoRepo;
149
- }
150
-
151
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL2NyZWF0ZS1hcGkudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7IERvY2tlckNvbXBvc2UgfSBmcm9tIFwiLi4vbW9kZWxzL2NvbXBvc2UubW9kZWwuanNcIjtcbmltcG9ydCB7IENvbmZpZ1lhbWwgfSBmcm9tIFwiLi4vbW9kZWxzL2NvbmZpZy15YW1sLm1vZGVsLmpzXCI7XG5pbXBvcnQgeyBXRUxMX0tOT1dOX0ZJTEVTIH0gZnJvbSBcIi4uL21vZGVscy9jb25zdC5qc1wiO1xuaW1wb3J0IHsgRG9ja2VyZmlsZU1vZGVsIH0gZnJvbSBcIi4uL21vZGVscy9jb250YWluZXItaW1hZ2UubW9kZWwuanNcIjtcbmltcG9ydCB7IERldkNvbnRhaW5lciB9IGZyb20gXCIuLi9tb2RlbHMvZGV2LWNvbnRhaW5lci5tb2RlbC5qc1wiO1xuaW1wb3J0IHsgRW52RmlsZSB9IGZyb20gXCIuLi9tb2RlbHMvZW52LWZpbGUubW9kZWwuanNcIjtcbmltcG9ydCB7IEdpdGlnbm9yZSB9IGZyb20gXCIuLi9tb2RlbHMvZ2l0aWdub3JlLm1vZGVsLmpzXCI7XG5pbXBvcnQgeyBMYXVuY2hKc29uIH0gZnJvbSBcIi4uL21vZGVscy9sYXVuY2gtanNvbi5tb2RlbC5qc1wiO1xuaW1wb3J0IHsgUGFja2FnZUpzb24gfSBmcm9tIFwiLi4vbW9kZWxzL3BhY2thZ2UtanNvbi5tb2RlbC5qc1wiO1xuaW1wb3J0IHsgTW9ub1JlcG9TY2FmZm9sZCwgUHJvamVjdFNjYWZmb2xkIH0gZnJvbSBcIi4uL21vZGVscy9wcm9qZWN0Lm1vZGVsLmpzXCI7XG5pbXBvcnQgeyBUc0NvbmZpZyB9IGZyb20gXCIuLi9tb2RlbHMvdHNjb25maWcubW9kZWwuanNcIjtcbmltcG9ydCB7IFZTQ29kZVNldHRpbmdzIH0gZnJvbSBcIi4uL21vZGVscy92c2NvZGUtc2V0dGluZ3MubW9kZWwuanNcIjtcbmltcG9ydCB7IFNjYWZmb2xkU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9zY2FmZm9sZC5zZXJ2aWNlLmpzXCI7XG5pbXBvcnQgeyBBdXRoRmVhdHVyZSB9IGZyb20gXCIuL2ZlYXR1cmVzL2F1dGguZmVhdHVyZS5qc1wiO1xuaW1wb3J0IHsgRGF0YWJhc2VGZWF0dXJlIH0gZnJvbSBcIi4vZmVhdHVyZXMvZGF0YWJhc2UuZmVhdHVyZS5qc1wiO1xuaW1wb3J0IHsgRmluYWxpemVGZWF0dXJlIH0gZnJvbSBcIi4vZmVhdHVyZXMvZmluYWxpemUuZmVhdHVyZS5qc1wiO1xuaW1wb3J0IHsgUG9zdG1hbkZlYXR1cmUgfSBmcm9tIFwiLi9mZWF0dXJlcy9wb3N0bWFuLmZlYXR1cmUuanNcIjtcbmltcG9ydCB7IEFwaVBhY2thZ2VKc29uIH0gZnJvbSBcIi4vbW9kZWxzL2FwaS1wYWNrYWdlLWpzb24ubW9kZWwuanNcIjtcbmltcG9ydCB7IENvbnRyb2xsZXJTb3VyY2VGaWxlIH0gZnJvbSBcIi4vbW9kZWxzL2NvbnRyb2xsZXItc291cmNlLWZpbGUubW9kZWwuanNcIjtcbmltcG9ydCB7IE1haW5Tb3VyY2VGaWxlIH0gZnJvbSBcIi4vbW9kZWxzL21haW4tc291cmNlLWZpbGUubW9kZWwuanNcIjtcbmltcG9ydCB7IFNhbXBsZUNvbmZpZ01vZGVsLCBTYW1wbGVTZXJ2aWNlTW9kZWwgfSBmcm9tIFwiLi9tb2RlbHMvc2FtcGxlLWZpbGVzLm1vZGVsLmpzXCI7XG5cbmV4cG9ydCBjb25zdCBXRUJBUElfUFJPSkVDVF9ESVIgPSBcInByb2plY3RzL2FwaVwiO1xuXG5leHBvcnQgdHlwZSBBcGlPcHRpb25zID0ge1xuXHRkPzogc3RyaW5nO1xuXHRhdXRoUHJvdmlkZXI/OiBzdHJpbmc7XG5cdGRhdGFiYXNlUHJvdmlkZXI/OiBcIm5vbmVcIiB8IFwicG9zdGdyZXMvdHlwZW9ybVwiO1xufTtcblxuY29uc3QgZmVhdHVyZXMgPSBbRGF0YWJhc2VGZWF0dXJlLCBBdXRoRmVhdHVyZSwgUG9zdG1hbkZlYXR1cmUsIEZpbmFsaXplRmVhdHVyZV07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzY2FmZm9sZEFwaShjbGlPcHRpb25zOiBBcGlPcHRpb25zKSB7XG5cdGNvbnN0IHRhcmdldERpciA9IHJlc29sdmUoY2xpT3B0aW9ucy5kID8/IFwiLlwiKTtcblx0Y29uc3Qgd29ya3NwYWNlID0gY3JlYXRlV29ya3NwYWNlKHRhcmdldERpcik7XG5cdGF3YWl0IFNjYWZmb2xkU2VydmljZS5zY2FmZm9sZCh3b3Jrc3BhY2UsIGNsaU9wdGlvbnMsIGZlYXR1cmVzKTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlV29ya3NwYWNlKHRhcmdldERpcjogc3RyaW5nKTogTW9ub1JlcG9TY2FmZm9sZCB7XG5cdGNvbnN0IG1vbm9SZXBvID0gbmV3IE1vbm9SZXBvU2NhZmZvbGQoKTtcblx0bW9ub1JlcG8udGFyZ2V0RGlyID0gdGFyZ2V0RGlyO1xuXHRjb25zdCBuYW1lID0gbW9ub1JlcG8ubmFtZTtcblxuXHRjb25zdCBjb21wb3NlID0gbmV3IERvY2tlckNvbXBvc2UoKVxuXHRcdC5hZGRTZXJ2aWNlKFwiZGV2Y29udGFpbmVyXCIsIHtcblx0XHRcdGJ1aWxkOiBcIi5cIixcblx0XHRcdHZvbHVtZXM6IFtcblx0XHRcdFx0YFxcJHtIT01FfS8ubnBtLyR7bmFtZX06L2hvbWUvbm9kZS8ubnBtLWNvbmZpZ2AsXG5cdFx0XHRcdFwid2ViYXBpLW5vZGUtbW9kdWxlczovd29ya3NwYWNlL25vZGVfbW9kdWxlc1wiLFxuXHRcdFx0XSxcblx0XHRcdGVudmlyb25tZW50OiB7IE5QTV9DT05GSUdfVVNFUkNPTkZJRzogXCIvaG9tZS9ub2RlLy5ucG0tY29uZmlnLy5ucG1yY1wiIH0sXG5cdFx0XHRjb21tYW5kOiBcInNsZWVwIGluZmluaXR5XCIsXG5cdFx0fSlcblx0XHQuYWRkVm9sdW1lKFwid2ViYXBpLW5vZGUtbW9kdWxlc1wiKTtcblxuXHRjb25zdCBkZXZDb250YWluZXIgPSBuZXcgRGV2Q29udGFpbmVyKClcblx0XHQuYWRkRXh0ZW5zaW9uKFwiYmlvbWVqcy5iaW9tZVwiLCBcInZpdGVzdC5leHBsb3JlclwiKVxuXHRcdC5zZXRQb3N0U3RhcnRDb21tYW5kKFwibnBtIHdob2FtaSAyPi9kZXYvbnVsbCB8fCBucG0gbG9naW5cIilcblx0XHQudXNlQ29tcG9zZSgpO1xuXG5cdC8vIFdvcmtzcGFjZS1sZXZlbCBtb2RlbHMgKHJlcG8gcm9vdClcblx0bW9ub1JlcG8uYWRkTW9kZWwoY29tcG9zZSk7XG5cdG1vbm9SZXBvLmFkZE1vZGVsKGRldkNvbnRhaW5lcik7XG5cdG1vbm9SZXBvLmFkZE1vZGVsKG5ldyBEb2NrZXJmaWxlTW9kZWwoKSk7XG5cdG1vbm9SZXBvLmFkZE1vZGVsKG5ldyBWU0NvZGVTZXR0aW5ncyhuYW1lKSk7XG5cdG1vbm9SZXBvLmFkZE1vZGVsKG5ldyBMYXVuY2hKc29uKCkpO1xuXHRtb25vUmVwby5hZGRNb2RlbChuZXcgVHNDb25maWcoKSk7XG5cdG1vbm9SZXBvLmFkZE1vZGVsKG5ldyBQYWNrYWdlSnNvbihgJHtuYW1lfS5hcGlgKSk7XG5cdG1vbm9SZXBvLmFkZE1vZGVsKG5ldyBDb25maWdZYW1sKFdFTExfS05PV05fRklMRVMuQ09ORklHX1lBTUwsIFwiY29uZmlnL2NvbmZpZy55YW1sXCIsIFwiXCIpKTtcblx0bW9ub1JlcG8uYWRkTW9kZWwoXG5cdFx0bmV3IENvbmZpZ1lhbWwoV0VMTF9LTk9XTl9GSUxFUy5DT05GSUdfREVWX1lBTUwsIFwiY29uZmlnL2NvbmZpZy5kZXYueWFtbFwiLCBcIlwiKSxcblx0KTtcblx0bW9ub1JlcG8uYWRkTW9kZWwobmV3IEdpdGlnbm9yZSgpKTtcblx0bW9ub1JlcG8uYWRkTW9kZWwobmV3IEVudkZpbGUoKSk7XG5cblx0Ly8gQmlvbWUgZm9ybWF0dGVyL2xpbnRlciBjb25maWdcblx0bW9ub1JlcG8uYWRkRmlsZSh7XG5cdFx0ZmlsZXM6ICgpID0+IFtcblx0XHRcdHtcblx0XHRcdFx0ZmlsZVBhdGg6IFwiYmlvbWUuanNvblwiLFxuXHRcdFx0XHRjb250ZW50OiBKU09OLnN0cmluZ2lmeShcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHQkc2NoZW1hOiBcImh0dHBzOi8vYmlvbWVqcy5kZXYvc2NoZW1hcy8yLjAuMC9zY2hlbWEuanNvblwiLFxuXHRcdFx0XHRcdFx0ZmlsZXM6IHtcblx0XHRcdFx0XHRcdFx0aW5jbHVkZXM6IFtcIioqLyoudHNcIiwgXCIqKi8qLmpzXCIsIFwiKiovKi5qc29uXCIsIFwiKiovKi55bWxcIiwgXCIqKi8qLnlhbWxcIl0sXG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0YXNzaXN0OiB7IGFjdGlvbnM6IHsgc291cmNlOiB7IG9yZ2FuaXplSW1wb3J0czogXCJvblwiIH0gfSB9LFxuXHRcdFx0XHRcdFx0dmNzOiB7IGVuYWJsZWQ6IHRydWUsIGNsaWVudEtpbmQ6IFwiZ2l0XCIsIHVzZUlnbm9yZUZpbGU6IHRydWUgfSxcblx0XHRcdFx0XHRcdGZvcm1hdHRlcjoge1xuXHRcdFx0XHRcdFx0XHRlbmFibGVkOiB0cnVlLFxuXHRcdFx0XHRcdFx0XHRmb3JtYXRXaXRoRXJyb3JzOiB0cnVlLFxuXHRcdFx0XHRcdFx0XHRpbmRlbnRTdHlsZTogXCJ0YWJcIixcblx0XHRcdFx0XHRcdFx0bGluZVdpZHRoOiA5NSxcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRqYXZhc2NyaXB0OiB7IHBhcnNlcjogeyB1bnNhZmVQYXJhbWV0ZXJEZWNvcmF0b3JzRW5hYmxlZDogdHJ1ZSB9IH0sXG5cdFx0XHRcdFx0XHRsaW50ZXI6IHtcblx0XHRcdFx0XHRcdFx0cnVsZXM6IHtcblx0XHRcdFx0XHRcdFx0XHRzdHlsZToge1xuXHRcdFx0XHRcdFx0XHRcdFx0dXNlQ29uc2lzdGVudE1lbWJlckFjY2Vzc2liaWxpdHk6IHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0bGV2ZWw6IFwiZXJyb3JcIixcblx0XHRcdFx0XHRcdFx0XHRcdFx0b3B0aW9uczogeyBhY2Nlc3NpYmlsaXR5OiBcImV4cGxpY2l0XCIgfSxcblx0XHRcdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRvdmVycmlkZXM6IFtcblx0XHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRcdGluY2x1ZGVzOiBbXCIqKi8qLmpzb25cIl0sXG5cdFx0XHRcdFx0XHRcdFx0Zm9ybWF0dGVyOiB7IGluZGVudFN0eWxlOiBcInNwYWNlXCIsIGluZGVudFdpZHRoOiAyIH0sXG5cdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRdLFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0bnVsbCxcblx0XHRcdFx0XHQyLFxuXHRcdFx0XHQpLFxuXHRcdFx0fSxcblx0XHRdLFxuXHR9KTtcblxuXHQvLyBOUE0gdG9rZW4gcGxhY2Vob2xkZXIg4oCUIGdpdGlnbm9yZWQsIHNldCBtYW51YWxseSBhZnRlciBzY2FmZm9sZFxuXHRtb25vUmVwby5hZGRGaWxlKHtcblx0XHRmaWxlczogKCkgPT4gW1xuXHRcdFx0e1xuXHRcdFx0XHRmaWxlUGF0aDogXCIuZW52LmxvY2FsXCIsXG5cdFx0XHRcdGNvbnRlbnQ6XG5cdFx0XHRcdFx0XCIjIFNldCB5b3VyIG5wbSBhY2Nlc3MgdG9rZW4gaGVyZSAoY3JlYXRlZCB3aXRoOiBucG0gdG9rZW4gY3JlYXRlKVxcbk5QTV9UT0tFTj1cXG5cIixcblx0XHRcdH0sXG5cdFx0XSxcblx0fSk7XG5cblx0Ly8gUHJvamVjdC1sZXZlbCBtb2RlbHMgKHBhdGhzIHJlbGF0aXZlIHRvIHByb2plY3RzL2FwaSlcblx0Y29uc3QgYXBpUHJvamVjdCA9IG5ldyBQcm9qZWN0U2NhZmZvbGQoV0VCQVBJX1BST0pFQ1RfRElSKTtcblx0YXBpUHJvamVjdC5hZGRNb2RlbChuZXcgQXBpUGFja2FnZUpzb24obmFtZSkpO1xuXHRhcGlQcm9qZWN0LmFkZE1vZGVsKG5ldyBNYWluU291cmNlRmlsZShgJHtuYW1lfS5hcGlgKSk7XG5cdGFwaVByb2plY3QuYWRkTW9kZWwobmV3IENvbnRyb2xsZXJTb3VyY2VGaWxlKCkpO1xuXG5cdC8vIFNhbXBsZVNlcnZpY2UgKyBTYW1wbGVDb25maWcgYXJlIHBhcnQgb2YgdGhlIGNvcmUgc2NhZmZvbGQg4oCUIEhlbGxvQ29udHJvbGxlclxuXHQvLyBpbmplY3RzIFNhbXBsZVNlcnZpY2UgdG8gZGVtb25zdHJhdGUgY29uZmlnLWRyaXZlbiBiZWhhdmlvdXIgb3V0IG9mIHRoZSBib3guXG5cdGFwaVByb2plY3QuYWRkRmlsZShuZXcgU2FtcGxlQ29uZmlnTW9kZWwoKSk7XG5cdGFwaVByb2plY3QuYWRkRmlsZShuZXcgU2FtcGxlU2VydmljZU1vZGVsKCkpO1xuXG5cdG1vbm9SZXBvLmFkZFByb2plY3QoYXBpUHJvamVjdCk7XG5cblx0cmV0dXJuIG1vbm9SZXBvO1xufVxuIl0sIm5hbWVzIjpbInJlc29sdmUiLCJEb2NrZXJDb21wb3NlIiwiQ29uZmlnWWFtbCIsIldFTExfS05PV05fRklMRVMiLCJEb2NrZXJmaWxlTW9kZWwiLCJEZXZDb250YWluZXIiLCJFbnZGaWxlIiwiR2l0aWdub3JlIiwiTGF1bmNoSnNvbiIsIlBhY2thZ2VKc29uIiwiTW9ub1JlcG9TY2FmZm9sZCIsIlByb2plY3RTY2FmZm9sZCIsIlRzQ29uZmlnIiwiVlNDb2RlU2V0dGluZ3MiLCJTY2FmZm9sZFNlcnZpY2UiLCJBdXRoRmVhdHVyZSIsIkRhdGFiYXNlRmVhdHVyZSIsIkZpbmFsaXplRmVhdHVyZSIsIlBvc3RtYW5GZWF0dXJlIiwiQXBpUGFja2FnZUpzb24iLCJDb250cm9sbGVyU291cmNlRmlsZSIsIk1haW5Tb3VyY2VGaWxlIiwiU2FtcGxlQ29uZmlnTW9kZWwiLCJTYW1wbGVTZXJ2aWNlTW9kZWwiLCJXRUJBUElfUFJPSkVDVF9ESVIiLCJmZWF0dXJlcyIsInNjYWZmb2xkQXBpIiwiY2xpT3B0aW9ucyIsInRhcmdldERpciIsImQiLCJ3b3Jrc3BhY2UiLCJjcmVhdGVXb3Jrc3BhY2UiLCJzY2FmZm9sZCIsIm1vbm9SZXBvIiwibmFtZSIsImNvbXBvc2UiLCJhZGRTZXJ2aWNlIiwiYnVpbGQiLCJ2b2x1bWVzIiwiZW52aXJvbm1lbnQiLCJOUE1fQ09ORklHX1VTRVJDT05GSUciLCJjb21tYW5kIiwiYWRkVm9sdW1lIiwiZGV2Q29udGFpbmVyIiwiYWRkRXh0ZW5zaW9uIiwic2V0UG9zdFN0YXJ0Q29tbWFuZCIsInVzZUNvbXBvc2UiLCJhZGRNb2RlbCIsIkNPTkZJR19ZQU1MIiwiQ09ORklHX0RFVl9ZQU1MIiwiYWRkRmlsZSIsImZpbGVzIiwiZmlsZVBhdGgiLCJjb250ZW50IiwiSlNPTiIsInN0cmluZ2lmeSIsIiRzY2hlbWEiLCJpbmNsdWRlcyIsImFzc2lzdCIsImFjdGlvbnMiLCJzb3VyY2UiLCJvcmdhbml6ZUltcG9ydHMiLCJ2Y3MiLCJlbmFibGVkIiwiY2xpZW50S2luZCIsInVzZUlnbm9yZUZpbGUiLCJmb3JtYXR0ZXIiLCJmb3JtYXRXaXRoRXJyb3JzIiwiaW5kZW50U3R5bGUiLCJsaW5lV2lkdGgiLCJqYXZhc2NyaXB0IiwicGFyc2VyIiwidW5zYWZlUGFyYW1ldGVyRGVjb3JhdG9yc0VuYWJsZWQiLCJsaW50ZXIiLCJydWxlcyIsInN0eWxlIiwidXNlQ29uc2lzdGVudE1lbWJlckFjY2Vzc2liaWxpdHkiLCJsZXZlbCIsIm9wdGlvbnMiLCJhY2Nlc3NpYmlsaXR5Iiwib3ZlcnJpZGVzIiwiaW5kZW50V2lkdGgiLCJhcGlQcm9qZWN0IiwiYWRkUHJvamVjdCJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsT0FBTyxRQUFRLFlBQVk7QUFDcEMsU0FBU0MsYUFBYSxRQUFRLDZCQUE2QjtBQUMzRCxTQUFTQyxVQUFVLFFBQVEsaUNBQWlDO0FBQzVELFNBQVNDLGdCQUFnQixRQUFRLHFCQUFxQjtBQUN0RCxTQUFTQyxlQUFlLFFBQVEscUNBQXFDO0FBQ3JFLFNBQVNDLFlBQVksUUFBUSxtQ0FBbUM7QUFDaEUsU0FBU0MsT0FBTyxRQUFRLDhCQUE4QjtBQUN0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
@@ -1,115 +0,0 @@
1
- import { ask, pick } from "../../domain/prompt.js";
2
- import { WELL_KNOWN_FILES } from "../../models/const.js";
3
- import { AuthConfigModel } from "../models/auth-config.model.js";
4
- import { ControllerSourceFile } from "../models/controller-source-file.model.js";
5
- import * as auth0Cli from "./auth0-cli.js";
6
- async function getOptions(workspace, cliOptions) {
7
- if (cliOptions.authProvider != null) return {};
8
- const choices = [
9
- {
10
- label: "none"
11
- },
12
- {
13
- label: "auth0"
14
- }
15
- ];
16
- const selected = await pick("\n Auth provider: ", choices, (c)=>c.label);
17
- const provider = selected?.label ?? "none";
18
- if (provider !== "auth0") return {
19
- authProvider: "none"
20
- };
21
- return getAuth0Options(workspace);
22
- }
23
- async function getAuth0Options(workspace) {
24
- if (!auth0Cli.isInstalled()) {
25
- console.error("\n The Auth0 CLI is required for automated setup.\n" + " Install: brew install auth0/auth0-cli/auth0\n" + " Or visit: https://github.com/auth0/auth0-cli\n");
26
- process.exit(1);
27
- }
28
- process.stdout.write("\n Checking Auth0 credentials...");
29
- let tenants = auth0Cli.listTenants();
30
- if (tenants.length === 0) {
31
- process.stdout.write(" not logged in.\n");
32
- console.log(" Logging in to Auth0 (your browser will open)...");
33
- if (!auth0Cli.login()) {
34
- console.error("\n Auth0 login failed.");
35
- process.exit(1);
36
- }
37
- tenants = auth0Cli.listTenants();
38
- }
39
- try {
40
- auth0Cli.listApis();
41
- process.stdout.write(" ok.\n");
42
- } catch (err) {
43
- if (err instanceof auth0Cli.Auth0AuthError) {
44
- process.stdout.write(" token expired.\n");
45
- console.log(" Re-authenticating (your browser will open)...");
46
- if (!auth0Cli.login()) {
47
- console.error("\n Auth0 login failed.");
48
- process.exit(1);
49
- }
50
- }
51
- }
52
- const active = tenants.find((t)=>t.active) ?? tenants[0];
53
- const issuerBaseUrl = `https://${active.name}`;
54
- console.log(`\n ✓ Auth0 tenant: ${issuerBaseUrl}`);
55
- process.stdout.write("\n Fetching Auth0 APIs...");
56
- const userApis = auth0Cli.listApis().filter((a)=>!a.name.includes("Management API"));
57
- process.stdout.write(` found ${userApis.length}.\n`);
58
- const projectName = workspace.name;
59
- const apiChoices = [
60
- {
61
- label: `<new> https://api.${projectName}`,
62
- existing: null
63
- },
64
- ...userApis.map((a)=>({
65
- label: `${a.name} — ${a.identifier}`,
66
- existing: a.identifier
67
- }))
68
- ];
69
- const apiSelected = await pick("\n Select Auth0 API: ", apiChoices, (c)=>c.label);
70
- let audience;
71
- if (!apiSelected || apiSelected.existing === null) {
72
- const defaultId = `https://api.${projectName}`;
73
- audience = await ask(` API Identifier [${defaultId}]: `, defaultId);
74
- console.log("\n Creating Auth0 API...");
75
- audience = auth0Cli.createApi(`${projectName} API`, audience).identifier;
76
- console.log(` \u2713 API created: ${audience}`);
77
- } else {
78
- audience = apiSelected.existing;
79
- console.log(` \u2713 Selected: ${audience}`);
80
- }
81
- return {
82
- authProvider: "auth0",
83
- issuerBaseUrl,
84
- audience
85
- };
86
- }
87
- function scaffold(workspace, options) {
88
- if (options.authProvider !== "auth0") return;
89
- const resource = "Hello";
90
- for (const controller of workspace.getModels(ControllerSourceFile)){
91
- controller.addDecorator(`@Authorize("read", "${resource}")`).addCortexImport("AllowAnonymous").addCortexImport("Authorize").addCortexImport("IPrincipalProviderToken").addCortexImport("IPrincipalProvider", true).addImport("inject", "@decohere/crucible/decorators").addConstructorParam(`@inject(IPrincipalProviderToken) private readonly principalProvider: IPrincipalProvider`);
92
- controller.getMethod("getAll").addDecorator("@AllowAnonymous()");
93
- controller.getMethod("create").addDecorator(`@Authorize("create", "${resource}")`);
94
- controller.getMethod("update").addDecorator(`@Authorize("update", "${resource}")`);
95
- controller.getMethod("remove").addDecorator(`@Authorize("delete", "${resource}")`);
96
- }
97
- workspace.getModel(WELL_KNOWN_FILES.MAIN_TS)?.addSideEffectImport("@decohere/cortex/auth").addBuilderCall(".withAuth()");
98
- // biome-ignore lint/suspicious/noTemplateCurlyInString: intentional YAML env-var placeholders
99
- const issuerPlaceholder = "${AUTH0_ISSUER_BASE_URL}";
100
- // biome-ignore lint/suspicious/noTemplateCurlyInString: intentional YAML env-var placeholders
101
- const audPlaceholder = "${AUTH0_AUDIENCE}";
102
- const configSection = `auth:\n discoveryUrl: ${issuerPlaceholder}\n audience: ${audPlaceholder}\n`;
103
- workspace.getModel(WELL_KNOWN_FILES.CONFIG_YAML)?.addSection(configSection);
104
- workspace.getModel(WELL_KNOWN_FILES.ENV_FILE)?.addEntry("AUTH0_ISSUER_BASE_URL", options.issuerBaseUrl ?? "").addEntry("AUTH0_AUDIENCE", options.audience ?? "");
105
- workspace.addModel(new AuthConfigModel({
106
- issuerBaseUrl: options.issuerBaseUrl ?? "",
107
- audience: options.audience ?? ""
108
- }));
109
- }
110
- export const AuthFeature = {
111
- getOptions,
112
- scaffold
113
- };
114
-
115
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL2ZlYXR1cmVzL2F1dGguZmVhdHVyZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBhc2ssIHBpY2sgfSBmcm9tIFwiLi4vLi4vZG9tYWluL3Byb21wdC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBDb25maWdZYW1sIH0gZnJvbSBcIi4uLy4uL21vZGVscy9jb25maWcteWFtbC5tb2RlbC5qc1wiO1xuaW1wb3J0IHsgV0VMTF9LTk9XTl9GSUxFUyB9IGZyb20gXCIuLi8uLi9tb2RlbHMvY29uc3QuanNcIjtcbmltcG9ydCB0eXBlIHsgRW52RmlsZSB9IGZyb20gXCIuLi8uLi9tb2RlbHMvZW52LWZpbGUubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgV29ya3NwYWNlU2NhZmZvbGQgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL3Byb2plY3QubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgRmVhdHVyZSB9IGZyb20gXCIuLi8uLi9zZXJ2aWNlcy9zY2FmZm9sZC5zZXJ2aWNlLmpzXCI7XG5pbXBvcnQgeyBBdXRoQ29uZmlnTW9kZWwgfSBmcm9tIFwiLi4vbW9kZWxzL2F1dGgtY29uZmlnLm1vZGVsLmpzXCI7XG5pbXBvcnQgeyBDb250cm9sbGVyU291cmNlRmlsZSB9IGZyb20gXCIuLi9tb2RlbHMvY29udHJvbGxlci1zb3VyY2UtZmlsZS5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBNYWluU291cmNlRmlsZSB9IGZyb20gXCIuLi9tb2RlbHMvbWFpbi1zb3VyY2UtZmlsZS5tb2RlbC5qc1wiO1xuaW1wb3J0ICogYXMgYXV0aDBDbGkgZnJvbSBcIi4vYXV0aDAtY2xpLmpzXCI7XG5cbmV4cG9ydCB0eXBlIEF1dGhPcHRpb25zID0ge1xuXHRhdXRoUHJvdmlkZXI/OiBcImF1dGgwXCIgfCBcIm5vbmVcIjtcblx0aXNzdWVyQmFzZVVybD86IHN0cmluZztcblx0YXVkaWVuY2U/OiBzdHJpbmc7XG59O1xuXG5hc3luYyBmdW5jdGlvbiBnZXRPcHRpb25zKFxuXHR3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLFxuXHRjbGlPcHRpb25zOiBQYXJ0aWFsPEF1dGhPcHRpb25zPixcbik6IFByb21pc2U8UGFydGlhbDxBdXRoT3B0aW9ucz4+IHtcblx0aWYgKGNsaU9wdGlvbnMuYXV0aFByb3ZpZGVyICE9IG51bGwpIHJldHVybiB7fTtcblxuXHRjb25zdCBjaG9pY2VzID0gW3sgbGFiZWw6IFwibm9uZVwiIGFzIGNvbnN0IH0sIHsgbGFiZWw6IFwiYXV0aDBcIiBhcyBjb25zdCB9XTtcblx0Y29uc3Qgc2VsZWN0ZWQgPSBhd2FpdCBwaWNrKFwiXFxuICBBdXRoIHByb3ZpZGVyOiBcIiwgY2hvaWNlcywgKGMpID0+IGMubGFiZWwpO1xuXHRjb25zdCBwcm92aWRlciA9IHNlbGVjdGVkPy5sYWJlbCA/PyBcIm5vbmVcIjtcblxuXHRpZiAocHJvdmlkZXIgIT09IFwiYXV0aDBcIikgcmV0dXJuIHsgYXV0aFByb3ZpZGVyOiBcIm5vbmVcIiB9O1xuXG5cdHJldHVybiBnZXRBdXRoME9wdGlvbnMod29ya3NwYWNlKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0QXV0aDBPcHRpb25zKHdvcmtzcGFjZTogV29ya3NwYWNlU2NhZmZvbGQpOiBQcm9taXNlPFBhcnRpYWw8QXV0aE9wdGlvbnM+PiB7XG5cdGlmICghYXV0aDBDbGkuaXNJbnN0YWxsZWQoKSkge1xuXHRcdGNvbnNvbGUuZXJyb3IoXG5cdFx0XHRcIlxcbiAgVGhlIEF1dGgwIENMSSBpcyByZXF1aXJlZCBmb3IgYXV0b21hdGVkIHNldHVwLlxcblwiICtcblx0XHRcdFx0XCIgIEluc3RhbGw6IGJyZXcgaW5zdGFsbCBhdXRoMC9hdXRoMC1jbGkvYXV0aDBcXG5cIiArXG5cdFx0XHRcdFwiICBPciB2aXNpdDogaHR0cHM6Ly9naXRodWIuY29tL2F1dGgwL2F1dGgwLWNsaVxcblwiLFxuXHRcdCk7XG5cdFx0cHJvY2Vzcy5leGl0KDEpO1xuXHR9XG5cblx0cHJvY2Vzcy5zdGRvdXQud3JpdGUoXCJcXG4gIENoZWNraW5nIEF1dGgwIGNyZWRlbnRpYWxzLi4uXCIpO1xuXHRsZXQgdGVuYW50cyA9IGF1dGgwQ2xpLmxpc3RUZW5hbnRzKCk7XG5cdGlmICh0ZW5hbnRzLmxlbmd0aCA9PT0gMCkge1xuXHRcdHByb2Nlc3Muc3Rkb3V0LndyaXRlKFwiIG5vdCBsb2dnZWQgaW4uXFxuXCIpO1xuXHRcdGNvbnNvbGUubG9nKFwiICBMb2dnaW5nIGluIHRvIEF1dGgwICh5b3VyIGJyb3dzZXIgd2lsbCBvcGVuKS4uLlwiKTtcblx0XHRpZiAoIWF1dGgwQ2xpLmxvZ2luKCkpIHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoXCJcXG4gIEF1dGgwIGxvZ2luIGZhaWxlZC5cIik7XG5cdFx0XHRwcm9jZXNzLmV4aXQoMSk7XG5cdFx0fVxuXHRcdHRlbmFudHMgPSBhdXRoMENsaS5saXN0VGVuYW50cygpO1xuXHR9XG5cblx0dHJ5IHtcblx0XHRhdXRoMENsaS5saXN0QXBpcygpO1xuXHRcdHByb2Nlc3Muc3Rkb3V0LndyaXRlKFwiIG9rLlxcblwiKTtcblx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0aWYgKGVyciBpbnN0YW5jZW9mIGF1dGgwQ2xpLkF1dGgwQXV0aEVycm9yKSB7XG5cdFx0XHRwcm9jZXNzLnN0ZG91dC53cml0ZShcIiB0b2tlbiBleHBpcmVkLlxcblwiKTtcblx0XHRcdGNvbnNvbGUubG9nKFwiICBSZS1hdXRoZW50aWNhdGluZyAoeW91ciBicm93c2VyIHdpbGwgb3BlbikuLi5cIik7XG5cdFx0XHRpZiAoIWF1dGgwQ2xpLmxvZ2luKCkpIHtcblx0XHRcdFx0Y29uc29sZS5lcnJvcihcIlxcbiAgQXV0aDAgbG9naW4gZmFpbGVkLlwiKTtcblx0XHRcdFx0cHJvY2Vzcy5leGl0KDEpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGNvbnN0IGFjdGl2ZSA9IHRlbmFudHMuZmluZCgodCkgPT4gdC5hY3RpdmUpID8/IHRlbmFudHNbMF07XG5cdGNvbnN0IGlzc3VlckJhc2VVcmwgPSBgaHR0cHM6Ly8ke2FjdGl2ZS5uYW1lfWA7XG5cdGNvbnNvbGUubG9nKGBcXG4gIOKckyBBdXRoMCB0ZW5hbnQ6ICR7aXNzdWVyQmFzZVVybH1gKTtcblxuXHRwcm9jZXNzLnN0ZG91dC53cml0ZShcIlxcbiAgRmV0Y2hpbmcgQXV0aDAgQVBJcy4uLlwiKTtcblx0Y29uc3QgdXNlckFwaXMgPSBhdXRoMENsaS5saXN0QXBpcygpLmZpbHRlcigoYSkgPT4gIWEubmFtZS5pbmNsdWRlcyhcIk1hbmFnZW1lbnQgQVBJXCIpKTtcblx0cHJvY2Vzcy5zdGRvdXQud3JpdGUoYCBmb3VuZCAke3VzZXJBcGlzLmxlbmd0aH0uXFxuYCk7XG5cblx0dHlwZSBBcGlDaG9pY2UgPSB7IGxhYmVsOiBzdHJpbmc7IGV4aXN0aW5nOiBzdHJpbmcgfCBudWxsIH07XG5cdGNvbnN0IHByb2plY3ROYW1lID0gd29ya3NwYWNlLm5hbWU7XG5cdGNvbnN0IGFwaUNob2ljZXM6IEFwaUNob2ljZVtdID0gW1xuXHRcdHsgbGFiZWw6IGA8bmV3PiBodHRwczovL2FwaS4ke3Byb2plY3ROYW1lfWAsIGV4aXN0aW5nOiBudWxsIH0sXG5cdFx0Li4udXNlckFwaXMubWFwKChhKSA9PiAoeyBsYWJlbDogYCR7YS5uYW1lfSDigJQgJHthLmlkZW50aWZpZXJ9YCwgZXhpc3Rpbmc6IGEuaWRlbnRpZmllciB9KSksXG5cdF07XG5cblx0Y29uc3QgYXBpU2VsZWN0ZWQgPSBhd2FpdCBwaWNrKFwiXFxuICBTZWxlY3QgQXV0aDAgQVBJOiBcIiwgYXBpQ2hvaWNlcywgKGMpID0+IGMubGFiZWwpO1xuXG5cdGxldCBhdWRpZW5jZTogc3RyaW5nO1xuXHRpZiAoIWFwaVNlbGVjdGVkIHx8IGFwaVNlbGVjdGVkLmV4aXN0aW5nID09PSBudWxsKSB7XG5cdFx0Y29uc3QgZGVmYXVsdElkID0gYGh0dHBzOi8vYXBpLiR7cHJvamVjdE5hbWV9YDtcblx0XHRhdWRpZW5jZSA9IGF3YWl0IGFzayhgICBBUEkgSWRlbnRpZmllciBbJHtkZWZhdWx0SWR9XTogYCwgZGVmYXVsdElkKTtcblx0XHRjb25zb2xlLmxvZyhcIlxcbiAgQ3JlYXRpbmcgQXV0aDAgQVBJLi4uXCIpO1xuXHRcdGF1ZGllbmNlID0gYXV0aDBDbGkuY3JlYXRlQXBpKGAke3Byb2plY3ROYW1lfSBBUElgLCBhdWRpZW5jZSkuaWRlbnRpZmllcjtcblx0XHRjb25zb2xlLmxvZyhgICBcXHUyNzEzIEFQSSBjcmVhdGVkOiAke2F1ZGllbmNlfWApO1xuXHR9IGVsc2Uge1xuXHRcdGF1ZGllbmNlID0gYXBpU2VsZWN0ZWQuZXhpc3Rpbmc7XG5cdFx0Y29uc29sZS5sb2coYCAgXFx1MjcxMyBTZWxlY3RlZDogJHthdWRpZW5jZX1gKTtcblx0fVxuXG5cdHJldHVybiB7IGF1dGhQcm92aWRlcjogXCJhdXRoMFwiLCBpc3N1ZXJCYXNlVXJsLCBhdWRpZW5jZSB9O1xufVxuXG5mdW5jdGlvbiBzY2FmZm9sZCh3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLCBvcHRpb25zOiBBdXRoT3B0aW9ucyk6IHZvaWQge1xuXHRpZiAob3B0aW9ucy5hdXRoUHJvdmlkZXIgIT09IFwiYXV0aDBcIikgcmV0dXJuO1xuXG5cdGNvbnN0IHJlc291cmNlID0gXCJIZWxsb1wiO1xuXG5cdGZvciAoY29uc3QgY29udHJvbGxlciBvZiB3b3Jrc3BhY2UuZ2V0TW9kZWxzKENvbnRyb2xsZXJTb3VyY2VGaWxlKSkge1xuXHRcdGNvbnRyb2xsZXJcblx0XHRcdC5hZGREZWNvcmF0b3IoYEBBdXRob3JpemUoXCJyZWFkXCIsIFwiJHtyZXNvdXJjZX1cIilgKVxuXHRcdFx0LmFkZENvcnRleEltcG9ydChcIkFsbG93QW5vbnltb3VzXCIpXG5cdFx0XHQuYWRkQ29ydGV4SW1wb3J0KFwiQXV0aG9yaXplXCIpXG5cdFx0XHQuYWRkQ29ydGV4SW1wb3J0KFwiSVByaW5jaXBhbFByb3ZpZGVyVG9rZW5cIilcblx0XHRcdC5hZGRDb3J0ZXhJbXBvcnQoXCJJUHJpbmNpcGFsUHJvdmlkZXJcIiwgdHJ1ZSlcblx0XHRcdC5hZGRJbXBvcnQoXCJpbmplY3RcIiwgXCJAZGVjb2hlcmUvY3J1Y2libGUvZGVjb3JhdG9yc1wiKVxuXHRcdFx0LmFkZENvbnN0cnVjdG9yUGFyYW0oXG5cdFx0XHRcdGBAaW5qZWN0KElQcmluY2lwYWxQcm92aWRlclRva2VuKSBwcml2YXRlIHJlYWRvbmx5IHByaW5jaXBhbFByb3ZpZGVyOiBJUHJpbmNpcGFsUHJvdmlkZXJgLFxuXHRcdFx0KTtcblx0XHRjb250cm9sbGVyLmdldE1ldGhvZChcImdldEFsbFwiKS5hZGREZWNvcmF0b3IoXCJAQWxsb3dBbm9ueW1vdXMoKVwiKTtcblx0XHRjb250cm9sbGVyLmdldE1ldGhvZChcImNyZWF0ZVwiKS5hZGREZWNvcmF0b3IoYEBBdXRob3JpemUoXCJjcmVhdGVcIiwgXCIke3Jlc291cmNlfVwiKWApO1xuXHRcdGNvbnRyb2xsZXIuZ2V0TWV0aG9kKFwidXBkYXRlXCIpLmFkZERlY29yYXRvcihgQEF1dGhvcml6ZShcInVwZGF0ZVwiLCBcIiR7cmVzb3VyY2V9XCIpYCk7XG5cdFx0Y29udHJvbGxlci5nZXRNZXRob2QoXCJyZW1vdmVcIikuYWRkRGVjb3JhdG9yKGBAQXV0aG9yaXplKFwiZGVsZXRlXCIsIFwiJHtyZXNvdXJjZX1cIilgKTtcblx0fVxuXG5cdHdvcmtzcGFjZVxuXHRcdC5nZXRNb2RlbDxNYWluU291cmNlRmlsZT4oV0VMTF9LTk9XTl9GSUxFUy5NQUlOX1RTKVxuXHRcdD8uYWRkU2lkZUVmZmVjdEltcG9ydChcIkBkZWNvaGVyZS9jb3J0ZXgvYXV0aFwiKVxuXHRcdC5hZGRCdWlsZGVyQ2FsbChcIi53aXRoQXV0aCgpXCIpO1xuXG5cdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9UZW1wbGF0ZUN1cmx5SW5TdHJpbmc6IGludGVudGlvbmFsIFlBTUwgZW52LXZhciBwbGFjZWhvbGRlcnNcblx0Y29uc3QgaXNzdWVyUGxhY2Vob2xkZXIgPSBcIiR7QVVUSDBfSVNTVUVSX0JBU0VfVVJMfVwiO1xuXHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vVGVtcGxhdGVDdXJseUluU3RyaW5nOiBpbnRlbnRpb25hbCBZQU1MIGVudi12YXIgcGxhY2Vob2xkZXJzXG5cdGNvbnN0IGF1ZFBsYWNlaG9sZGVyID0gXCIke0FVVEgwX0FVRElFTkNFfVwiO1xuXG5cdGNvbnN0IGNvbmZpZ1NlY3Rpb24gPSBgYXV0aDpcXG4gIGRpc2NvdmVyeVVybDogJHtpc3N1ZXJQbGFjZWhvbGRlcn1cXG4gIGF1ZGllbmNlOiAke2F1ZFBsYWNlaG9sZGVyfVxcbmA7XG5cblx0d29ya3NwYWNlLmdldE1vZGVsPENvbmZpZ1lhbWw+KFdFTExfS05PV05fRklMRVMuQ09ORklHX1lBTUwpPy5hZGRTZWN0aW9uKGNvbmZpZ1NlY3Rpb24pO1xuXG5cdHdvcmtzcGFjZVxuXHRcdC5nZXRNb2RlbDxFbnZGaWxlPihXRUxMX0tOT1dOX0ZJTEVTLkVOVl9GSUxFKVxuXHRcdD8uYWRkRW50cnkoXCJBVVRIMF9JU1NVRVJfQkFTRV9VUkxcIiwgb3B0aW9ucy5pc3N1ZXJCYXNlVXJsID8/IFwiXCIpXG5cdFx0LmFkZEVudHJ5KFwiQVVUSDBfQVVESUVOQ0VcIiwgb3B0aW9ucy5hdWRpZW5jZSA/PyBcIlwiKTtcblxuXHR3b3Jrc3BhY2UuYWRkTW9kZWwoXG5cdFx0bmV3IEF1dGhDb25maWdNb2RlbCh7XG5cdFx0XHRpc3N1ZXJCYXNlVXJsOiBvcHRpb25zLmlzc3VlckJhc2VVcmwgPz8gXCJcIixcblx0XHRcdGF1ZGllbmNlOiBvcHRpb25zLmF1ZGllbmNlID8/IFwiXCIsXG5cdFx0fSksXG5cdCk7XG59XG5cbmV4cG9ydCBjb25zdCBBdXRoRmVhdHVyZTogRmVhdHVyZTxBdXRoT3B0aW9ucz4gPSB7IGdldE9wdGlvbnMsIHNjYWZmb2xkIH07XG4iXSwibmFtZXMiOlsiYXNrIiwicGljayIsIldFTExfS05PV05fRklMRVMiLCJBdXRoQ29uZmlnTW9kZWwiLCJDb250cm9sbGVyU291cmNlRmlsZSIsImF1dGgwQ2xpIiwiZ2V0T3B0aW9ucyIsIndvcmtzcGFjZSIsImNsaU9wdGlvbnMiLCJhdXRoUHJvdmlkZXIiLCJjaG9pY2VzIiwibGFiZWwiLCJzZWxlY3RlZCIsImMiLCJwcm92aWRlciIsImdldEF1dGgwT3B0aW9ucyIsImlzSW5zdGFsbGVkIiwiY29uc29sZSIsImVycm9yIiwicHJvY2VzcyIsImV4aXQiLCJzdGRvdXQiLCJ3cml0ZSIsInRlbmFudHMiLCJsaXN0VGVuYW50cyIsImxlbmd0aCIsImxvZyIsImxvZ2luIiwibGlzdEFwaXMiLCJlcnIiLCJBdXRoMEF1dGhFcnJvciIsImFjdGl2ZSIsImZpbmQiLCJ0IiwiaXNzdWVyQmFzZVVybCIsIm5hbWUiLCJ1c2VyQXBpcyIsImZpbHRlciIsImEiLCJpbmNsdWRlcyIsInByb2plY3ROYW1lIiwiYXBpQ2hvaWNlcyIsImV4aXN0aW5nIiwibWFwIiwiaWRlbnRpZmllciIsImFwaVNlbGVjdGVkIiwiYXVkaWVuY2UiLCJkZWZhdWx0SWQiLCJjcmVhdGVBcGkiLCJzY2FmZm9sZCIsIm9wdGlvbnMiLCJyZXNvdXJjZSIsImNvbnRyb2xsZXIiLCJnZXRNb2RlbHMiLCJhZGREZWNvcmF0b3IiLCJhZGRDb3J0ZXhJbXBvcnQiLCJhZGRJbXBvcnQiLCJhZGRDb25zdHJ1Y3RvclBhcmFtIiwiZ2V0TWV0aG9kIiwiZ2V0TW9kZWwiLCJNQUlOX1RTIiwiYWRkU2lkZUVmZmVjdEltcG9ydCIsImFkZEJ1aWxkZXJDYWxsIiwiaXNzdWVyUGxhY2Vob2xkZXIiLCJhdWRQbGFjZWhvbGRlciIsImNvbmZpZ1NlY3Rpb24iLCJDT05GSUdfWUFNTCIsImFkZFNlY3Rpb24iLCJFTlZfRklMRSIsImFkZEVudHJ5IiwiYWRkTW9kZWwiLCJBdXRoRmVhdHVyZSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsR0FBRyxFQUFFQyxJQUFJLFFBQVEseUJBQXlCO0FBRW5ELFNBQVNDLGdCQUFnQixRQUFRLHdCQUF3QjtBQUl6RCxTQUFTQyxlQUFlLFFBQVEsaUNBQWlD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
@@ -1,116 +0,0 @@
1
- import { execFileSync, spawnSync } from "node:child_process";
2
- const REQUIRED_SCOPES = "create:clients";
3
- /** Hard timeout for any Management API call. Prevents indefinite hangs on token re-auth. */ const API_TIMEOUT_MS = 8_000;
4
- export class Auth0AuthError extends Error {
5
- constructor(message){
6
- super(message);
7
- this.name = "Auth0AuthError";
8
- }
9
- }
10
- /** Returns true if an error or stderr output looks like an expired/missing token. */ function isAuthError(text) {
11
- return text.includes("renew access token") || text.includes("log in") || text.includes("Unauthorized");
12
- }
13
- /** Run an auth0 CLI command with a hard timeout. Returns stdout on success, throws on failure. */ function runAuth0(args) {
14
- const result = spawnSync("auth0", args, {
15
- encoding: "utf8",
16
- timeout: API_TIMEOUT_MS,
17
- input: "",
18
- stdio: "pipe"
19
- });
20
- if (result.error) {
21
- // ETIMEDOUT means the process was killed by the timeout
22
- const msg = result.error.message;
23
- if (isAuthError(msg) || result.error.code === "ETIMEDOUT") {
24
- throw new Auth0AuthError(msg);
25
- }
26
- throw result.error;
27
- }
28
- if (result.status !== 0) {
29
- const stderr = result.stderr ?? "";
30
- if (isAuthError(stderr)) throw new Auth0AuthError(stderr);
31
- throw new Error(stderr || `auth0 exited with code ${result.status}`);
32
- }
33
- return result.stdout;
34
- }
35
- export function isInstalled() {
36
- try {
37
- execFileSync("auth0", [
38
- "--version"
39
- ], {
40
- stdio: "pipe"
41
- });
42
- return true;
43
- } catch {
44
- return false;
45
- }
46
- }
47
- export function listTenants() {
48
- try {
49
- const out = execFileSync("auth0", [
50
- "tenants",
51
- "list",
52
- "--json"
53
- ], {
54
- encoding: "utf8",
55
- stdio: "pipe"
56
- });
57
- return JSON.parse(out);
58
- } catch {
59
- return [];
60
- }
61
- }
62
- export function login() {
63
- const result = spawnSync("auth0", [
64
- "login",
65
- "--scopes",
66
- REQUIRED_SCOPES
67
- ], {
68
- stdio: "inherit"
69
- });
70
- return result.status === 0;
71
- }
72
- export function listApis() {
73
- try {
74
- const out = runAuth0([
75
- "apis",
76
- "list",
77
- "--json",
78
- "--no-input"
79
- ]);
80
- return JSON.parse(out);
81
- } catch (err) {
82
- if (err instanceof Auth0AuthError) throw err;
83
- return [];
84
- }
85
- }
86
- export function createApi(name, identifier) {
87
- const out = runAuth0([
88
- "apis",
89
- "create",
90
- "--name",
91
- name,
92
- "--identifier",
93
- identifier,
94
- "--json",
95
- "--no-input"
96
- ]);
97
- return JSON.parse(out);
98
- }
99
- export function createSpaApp(name, callbackUrl) {
100
- const out = runAuth0([
101
- "apps",
102
- "create",
103
- "--name",
104
- name,
105
- "--type",
106
- "spa",
107
- "--callbacks",
108
- callbackUrl,
109
- "--json",
110
- "--no-input"
111
- ]);
112
- return JSON.parse(out);
113
- }
114
- export { REQUIRED_SCOPES };
115
-
116
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL2ZlYXR1cmVzL2F1dGgwLWNsaS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBleGVjRmlsZVN5bmMsIHNwYXduU3luYyB9IGZyb20gXCJub2RlOmNoaWxkX3Byb2Nlc3NcIjtcblxuY29uc3QgUkVRVUlSRURfU0NPUEVTID0gXCJjcmVhdGU6Y2xpZW50c1wiO1xuLyoqIEhhcmQgdGltZW91dCBmb3IgYW55IE1hbmFnZW1lbnQgQVBJIGNhbGwuIFByZXZlbnRzIGluZGVmaW5pdGUgaGFuZ3Mgb24gdG9rZW4gcmUtYXV0aC4gKi9cbmNvbnN0IEFQSV9USU1FT1VUX01TID0gOF8wMDA7XG5cbmV4cG9ydCBjbGFzcyBBdXRoMEF1dGhFcnJvciBleHRlbmRzIEVycm9yIHtcblx0cHVibGljIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZykge1xuXHRcdHN1cGVyKG1lc3NhZ2UpO1xuXHRcdHRoaXMubmFtZSA9IFwiQXV0aDBBdXRoRXJyb3JcIjtcblx0fVxufVxuXG4vKiogUmV0dXJucyB0cnVlIGlmIGFuIGVycm9yIG9yIHN0ZGVyciBvdXRwdXQgbG9va3MgbGlrZSBhbiBleHBpcmVkL21pc3NpbmcgdG9rZW4uICovXG5mdW5jdGlvbiBpc0F1dGhFcnJvcih0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcblx0cmV0dXJuIChcblx0XHR0ZXh0LmluY2x1ZGVzKFwicmVuZXcgYWNjZXNzIHRva2VuXCIpIHx8XG5cdFx0dGV4dC5pbmNsdWRlcyhcImxvZyBpblwiKSB8fFxuXHRcdHRleHQuaW5jbHVkZXMoXCJVbmF1dGhvcml6ZWRcIilcblx0KTtcbn1cblxuLyoqIFJ1biBhbiBhdXRoMCBDTEkgY29tbWFuZCB3aXRoIGEgaGFyZCB0aW1lb3V0LiBSZXR1cm5zIHN0ZG91dCBvbiBzdWNjZXNzLCB0aHJvd3Mgb24gZmFpbHVyZS4gKi9cbmZ1bmN0aW9uIHJ1bkF1dGgwKGFyZ3M6IHN0cmluZ1tdKTogc3RyaW5nIHtcblx0Y29uc3QgcmVzdWx0ID0gc3Bhd25TeW5jKFwiYXV0aDBcIiwgYXJncywge1xuXHRcdGVuY29kaW5nOiBcInV0ZjhcIixcblx0XHR0aW1lb3V0OiBBUElfVElNRU9VVF9NUyxcblx0XHRpbnB1dDogXCJcIixcblx0XHRzdGRpbzogXCJwaXBlXCIsXG5cdH0pO1xuXG5cdGlmIChyZXN1bHQuZXJyb3IpIHtcblx0XHQvLyBFVElNRURPVVQgbWVhbnMgdGhlIHByb2Nlc3Mgd2FzIGtpbGxlZCBieSB0aGUgdGltZW91dFxuXHRcdGNvbnN0IG1zZyA9IHJlc3VsdC5lcnJvci5tZXNzYWdlO1xuXHRcdGlmIChpc0F1dGhFcnJvcihtc2cpIHx8IChyZXN1bHQuZXJyb3IgYXMgTm9kZUpTLkVycm5vRXhjZXB0aW9uKS5jb2RlID09PSBcIkVUSU1FRE9VVFwiKSB7XG5cdFx0XHR0aHJvdyBuZXcgQXV0aDBBdXRoRXJyb3IobXNnKTtcblx0XHR9XG5cdFx0dGhyb3cgcmVzdWx0LmVycm9yO1xuXHR9XG5cblx0aWYgKHJlc3VsdC5zdGF0dXMgIT09IDApIHtcblx0XHRjb25zdCBzdGRlcnIgPSByZXN1bHQuc3RkZXJyID8/IFwiXCI7XG5cdFx0aWYgKGlzQXV0aEVycm9yKHN0ZGVycikpIHRocm93IG5ldyBBdXRoMEF1dGhFcnJvcihzdGRlcnIpO1xuXHRcdHRocm93IG5ldyBFcnJvcihzdGRlcnIgfHwgYGF1dGgwIGV4aXRlZCB3aXRoIGNvZGUgJHtyZXN1bHQuc3RhdHVzfWApO1xuXHR9XG5cblx0cmV0dXJuIHJlc3VsdC5zdGRvdXQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXV0aDBUZW5hbnQge1xuXHRuYW1lOiBzdHJpbmc7XG5cdGFjdGl2ZT86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0luc3RhbGxlZCgpOiBib29sZWFuIHtcblx0dHJ5IHtcblx0XHRleGVjRmlsZVN5bmMoXCJhdXRoMFwiLCBbXCItLXZlcnNpb25cIl0sIHsgc3RkaW86IFwicGlwZVwiIH0pO1xuXHRcdHJldHVybiB0cnVlO1xuXHR9IGNhdGNoIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpc3RUZW5hbnRzKCk6IEF1dGgwVGVuYW50W10ge1xuXHR0cnkge1xuXHRcdGNvbnN0IG91dCA9IGV4ZWNGaWxlU3luYyhcImF1dGgwXCIsIFtcInRlbmFudHNcIiwgXCJsaXN0XCIsIFwiLS1qc29uXCJdLCB7XG5cdFx0XHRlbmNvZGluZzogXCJ1dGY4XCIsXG5cdFx0XHRzdGRpbzogXCJwaXBlXCIsXG5cdFx0fSk7XG5cdFx0cmV0dXJuIEpTT04ucGFyc2Uob3V0KSBhcyBBdXRoMFRlbmFudFtdO1xuXHR9IGNhdGNoIHtcblx0XHRyZXR1cm4gW107XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxvZ2luKCk6IGJvb2xlYW4ge1xuXHRjb25zdCByZXN1bHQgPSBzcGF3blN5bmMoXCJhdXRoMFwiLCBbXCJsb2dpblwiLCBcIi0tc2NvcGVzXCIsIFJFUVVJUkVEX1NDT1BFU10sIHtcblx0XHRzdGRpbzogXCJpbmhlcml0XCIsXG5cdH0pO1xuXHRyZXR1cm4gcmVzdWx0LnN0YXR1cyA9PT0gMDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpc3RBcGlzKCk6IEFycmF5PHsgaWRlbnRpZmllcjogc3RyaW5nOyBuYW1lOiBzdHJpbmcgfT4ge1xuXHR0cnkge1xuXHRcdGNvbnN0IG91dCA9IHJ1bkF1dGgwKFtcImFwaXNcIiwgXCJsaXN0XCIsIFwiLS1qc29uXCIsIFwiLS1uby1pbnB1dFwiXSk7XG5cdFx0cmV0dXJuIEpTT04ucGFyc2Uob3V0KSBhcyBBcnJheTx7IGlkZW50aWZpZXI6IHN0cmluZzsgbmFtZTogc3RyaW5nIH0+O1xuXHR9IGNhdGNoIChlcnIpIHtcblx0XHRpZiAoZXJyIGluc3RhbmNlb2YgQXV0aDBBdXRoRXJyb3IpIHRocm93IGVycjtcblx0XHRyZXR1cm4gW107XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUFwaShuYW1lOiBzdHJpbmcsIGlkZW50aWZpZXI6IHN0cmluZyk6IHsgaWRlbnRpZmllcjogc3RyaW5nIH0ge1xuXHRjb25zdCBvdXQgPSBydW5BdXRoMChbXG5cdFx0XCJhcGlzXCIsXG5cdFx0XCJjcmVhdGVcIixcblx0XHRcIi0tbmFtZVwiLFxuXHRcdG5hbWUsXG5cdFx0XCItLWlkZW50aWZpZXJcIixcblx0XHRpZGVudGlmaWVyLFxuXHRcdFwiLS1qc29uXCIsXG5cdFx0XCItLW5vLWlucHV0XCIsXG5cdF0pO1xuXHRyZXR1cm4gSlNPTi5wYXJzZShvdXQpIGFzIHsgaWRlbnRpZmllcjogc3RyaW5nIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTcGFBcHAobmFtZTogc3RyaW5nLCBjYWxsYmFja1VybDogc3RyaW5nKTogeyBjbGllbnRfaWQ6IHN0cmluZyB9IHtcblx0Y29uc3Qgb3V0ID0gcnVuQXV0aDAoW1xuXHRcdFwiYXBwc1wiLFxuXHRcdFwiY3JlYXRlXCIsXG5cdFx0XCItLW5hbWVcIixcblx0XHRuYW1lLFxuXHRcdFwiLS10eXBlXCIsXG5cdFx0XCJzcGFcIixcblx0XHRcIi0tY2FsbGJhY2tzXCIsXG5cdFx0Y2FsbGJhY2tVcmwsXG5cdFx0XCItLWpzb25cIixcblx0XHRcIi0tbm8taW5wdXRcIixcblx0XSk7XG5cdHJldHVybiBKU09OLnBhcnNlKG91dCkgYXMgeyBjbGllbnRfaWQ6IHN0cmluZyB9O1xufVxuXG5leHBvcnQgeyBSRVFVSVJFRF9TQ09QRVMgfTtcbiJdLCJuYW1lcyI6WyJleGVjRmlsZVN5bmMiLCJzcGF3blN5bmMiLCJSRVFVSVJFRF9TQ09QRVMiLCJBUElfVElNRU9VVF9NUyIsIkF1dGgwQXV0aEVycm9yIiwiRXJyb3IiLCJtZXNzYWdlIiwibmFtZSIsImlzQXV0aEVycm9yIiwidGV4dCIsImluY2x1ZGVzIiwicnVuQXV0aDAiLCJhcmdzIiwicmVzdWx0IiwiZW5jb2RpbmciLCJ0aW1lb3V0IiwiaW5wdXQiLCJzdGRpbyIsImVycm9yIiwibXNnIiwiY29kZSIsInN0YXR1cyIsInN0ZGVyciIsInN0ZG91dCIsImlzSW5zdGFsbGVkIiwibGlzdFRlbmFudHMiLCJvdXQiLCJKU09OIiwicGFyc2UiLCJsb2dpbiIsImxpc3RBcGlzIiwiZXJyIiwiY3JlYXRlQXBpIiwiaWRlbnRpZmllciIsImNyZWF0ZVNwYUFwcCIsImNhbGxiYWNrVXJsIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxZQUFZLEVBQUVDLFNBQVMsUUFBUSxxQkFBcUI7QUFFN0QsTUFBTUMsa0JBQWtCO0FBQ3hCLDBGQUEwRixHQUMxRixNQUFNQyxpQkFBaUI7QUFFdkIsT0FBTyxNQUFNQyx1QkFBdUJDO0lBQ25DLFlBQW1CQyxPQUFlLENBQUU7UUFDbkMsS0FBSyxDQUFDQTtRQUNOLElBQUksQ0FBQ0MsSUFBSSxHQUFHO0lBQ2I7QUFDRDtBQUVBLG1GQUFtRixHQUNuRixTQUFTQyxZQUFZQyxJQUFZO0lBQ2hDLE9BQ0NBLEtBQUtDLFFBQVEsQ0FBQyx5QkFDZEQsS0FBS0MsUUFBUSxDQUFDLGFBQ2RELEtBQUtDLFFBQVEsQ0FBQztBQUVoQjtBQUVBLGdHQUFnRyxHQUNoRyxTQUFTQyxTQUFTQyxJQUFjO0lBQy9CLE1BQU1DLFNBQVNaLFVBQVUsU0FBU1csTUFBTTtRQUN2Q0UsVUFBVTtRQUNWQyxTQUFTWjtRQUNUYSxPQUFPO1FBQ1BDLE9BQU87SUFDUjtJQUVBLElBQUlKLE9BQU9LLEtBQUssRUFBRTtRQUNqQix3REFBd0Q7UUFDeEQsTUFBTUMsTUFBTU4sT0FBT0ssS0FBSyxDQUFDWixPQUFPO1FBQ2hDLElBQUlFLFlBQVlXLFFBQVEsQUFBQ04sT0FBT0ssS0FBSyxDQUEyQkUsSUFBSSxLQUFLLGFBQWE7WUFDckYsTUFBTSxJQUFJaEIsZUFBZWU7UUFDMUI7UUFDQSxNQUFNTixPQUFPSyxLQUFLO0lBQ25CO0lBRUEsSUFBSUwsT0FBT1EsTUFBTSxLQUFLLEdBQUc7UUFDeEIsTUFBTUMsU0FBU1QsT0FBT1MsTUFBTSxJQUFJO1FBQ2hDLElBQUlkLFlBQVljLFNBQVMsTUFBTSxJQUFJbEIsZUFBZWtCO1FBQ2xELE1BQU0sSUFBSWpCLE1BQU1pQixVQUFVLENBQUMsdUJBQXVCLEVBQUVULE9BQU9RLE1BQU0sRUFBRTtJQUNwRTtJQUVBLE9BQU9SLE9BQU9VLE1BQU07QUFDckI7QUFPQSxPQUFPLFNBQVNDO0lBQ2YsSUFBSTtRQUNIeEIsYUFBYSxTQUFTO1lBQUM7U0FBWSxFQUFFO1lBQUVpQixPQUFPO1FBQU87UUFDckQsT0FBTztJQUNSLEVBQUUsT0FBTTtRQUNQLE9BQU87SUFDUjtBQUNEO0FBRUEsT0FBTyxTQUFTUTtJQUNmLElBQUk7UUFDSCxNQUFNQyxNQUFNMUIsYUFBYSxTQUFTO1lBQUM7WUFBVztZQUFRO1NBQVMsRUFBRTtZQUNoRWMsVUFBVTtZQUNWRyxPQUFPO1FBQ1I7UUFDQSxPQUFPVSxLQUFLQyxLQUFLLENBQUNGO0lBQ25CLEVBQUUsT0FBTTtRQUNQLE9BQU8sRUFBRTtJQUNWO0FBQ0Q7QUFFQSxPQUFPLFNBQVNHO0lBQ2YsTUFBTWhCLFNBQVNaLFVBQVUsU0FBUztRQUFDO1FBQVM7UUFBWUM7S0FBZ0IsRUFBRTtRQUN6RWUsT0FBTztJQUNSO0lBQ0EsT0FBT0osT0FBT1EsTUFBTSxLQUFLO0FBQzFCO0FBRUEsT0FBTyxTQUFTUztJQUNmLElBQUk7UUFDSCxNQUFNSixNQUFNZixTQUFTO1lBQUM7WUFBUTtZQUFRO1lBQVU7U0FBYTtRQUM3RCxPQUFPZ0IsS0FBS0MsS0FBSyxDQUFDRjtJQUNuQixFQUFFLE9BQU9LLEtBQUs7UUFDYixJQUFJQSxlQUFlM0IsZ0JBQWdCLE1BQU0yQjtRQUN6QyxPQUFPLEVBQUU7SUFDVjtBQUNEO0FBRUEsT0FBTyxTQUFTQyxVQUFVekIsSUFBWSxFQUFFMEIsVUFBa0I7SUFDekQsTUFBTVAsTUFBTWYsU0FBUztRQUNwQjtRQUNBO1FBQ0E7UUFDQUo7UUFDQTtRQUNBMEI7UUFDQTtRQUNBO0tBQ0E7SUFDRCxPQUFPTixLQUFLQyxLQUFLLENBQUNGO0FBQ25CO0FBRUEsT0FBTyxTQUFTUSxhQUFhM0IsSUFBWSxFQUFFNEIsV0FBbUI7SUFDN0QsTUFBTVQsTUFBTWYsU0FBUztRQUNwQjtRQUNBO1FBQ0E7UUFDQUo7UUFDQTtRQUNBO1FBQ0E7UUFDQTRCO1FBQ0E7UUFDQTtLQUNBO0lBQ0QsT0FBT1IsS0FBS0MsS0FBSyxDQUFDRjtBQUNuQjtBQUVBLFNBQVN4QixlQUFlLEdBQUcifQ==
@@ -1,141 +0,0 @@
1
- import { randomBytes } from "node:crypto";
2
- import { pick } from "../../domain/prompt.js";
3
- import { WELL_KNOWN_FILES } from "../../models/const.js";
4
- import { CREATE_VERSION } from "../../version.js";
5
- import { WEBAPI_PROJECT_DIR } from "../create-api.js";
6
- // Base config uses env-var references for production; the dev config section
7
- // written below overrides only the concrete values needed locally.
8
- const DATABASE_BASE_CONFIG_YAML = `database:
9
- dataSources:
10
- - name: default
11
- provider: postgres
12
- host: \${DB_HOST}
13
- port: \${DB_PORT}
14
- database: \${DB_NAME}
15
- username: \${DB_USER}
16
- password: \${DB_PASSWORD}
17
- synchronize: false
18
- seed: false
19
- adminUser: \${DB_ADMIN_USER}
20
- adminPassword: \${DB_ADMIN_PASSWORD}
21
- `;
22
- // Dev config only overrides what differs from base — credentials come from .env via env-var references.
23
- const DATABASE_DEV_CONFIG_YAML = `database:
24
- dataSources:
25
- - host: postgres
26
- synchronize: true
27
- seed: true
28
- `;
29
- const SAMPLE_ENTITY_TS = `import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
30
- import type { Entity as IEntity } from "@decohere/codex";
31
-
32
- @Entity()
33
- export class SampleEntity implements IEntity {
34
- \t@PrimaryGeneratedColumn()
35
- \tpublic id!: number;
36
-
37
- \t@Column()
38
- \tpublic name!: string;
39
- }
40
- `;
41
- const SAMPLE_REPOSITORY_TS = `import { injectable } from "@decohere/crucible/decorators";
42
- import { injectUnitOfWork } from "@decohere/codex";
43
- import { TypeOrmRepository, TypeOrmUnitOfWork } from "@decohere/codex-typeorm";
44
- import { SampleEntity } from "../entities/sample.entity.js";
45
-
46
- @injectable()
47
- export class SampleEntityRepository extends TypeOrmRepository<SampleEntity> {
48
- \tpublic constructor(@injectUnitOfWork() unitOfWork: TypeOrmUnitOfWork) {
49
- \t\tsuper(unitOfWork, SampleEntity);
50
- \t}
51
- }
52
- `;
53
- async function getOptions(_workspace, cliOptions) {
54
- if (cliOptions.databaseProvider != null) return {};
55
- const choices = [
56
- {
57
- label: "none"
58
- },
59
- {
60
- label: "postgres/typeorm"
61
- }
62
- ];
63
- const selected = await pick("\n Database: ", choices, (c)=>c.label);
64
- return {
65
- databaseProvider: selected?.label ?? "none"
66
- };
67
- }
68
- function scaffold(workspace, options) {
69
- if (options.databaseProvider !== "postgres/typeorm") return;
70
- const name = workspace.name;
71
- const password = randomBytes(16).toString("hex");
72
- const db = `${name}_dev`;
73
- const user = "postgres";
74
- const devContainer = workspace.getModel(WELL_KNOWN_FILES.DEVCONTAINER_JSON);
75
- const compose = workspace.getModel(WELL_KNOWN_FILES.DOCKER_COMPOSE);
76
- // Add postgres service to compose
77
- compose?.addService("postgres", {
78
- image: "postgres:16",
79
- restart: "unless-stopped",
80
- environment: {
81
- // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose reads these from .env
82
- POSTGRES_DB: "${POSTGRES_DB}",
83
- // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose reads these from .env
84
- POSTGRES_USER: "${POSTGRES_USER}",
85
- // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose reads these from .env
86
- POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
87
- },
88
- ports: [
89
- "5432:5432"
90
- ],
91
- volumes: [
92
- "postgres-data:/var/lib/postgresql/data"
93
- ]
94
- }).addVolume("postgres-data");
95
- compose?.addService("adminer", {
96
- image: "adminer",
97
- ports: [
98
- "8080:8080"
99
- ]
100
- });
101
- // Add SQLTools extension for DB browsing in VS Code
102
- devContainer?.addExtension("mtxr.sqltools");
103
- // Wire up main.ts
104
- workspace.getModel(WELL_KNOWN_FILES.MAIN_TS)?.addSideEffectImport("@decohere/codex-typeorm").addEntity({
105
- className: "SampleEntity",
106
- importPath: "./entities/sample.entity.js"
107
- }).addRepository({
108
- className: "SampleEntityRepository",
109
- importPath: "./repositories/sample.repository.js"
110
- });
111
- // Add codex + typeorm deps to root package.json
112
- workspace.getModel(WELL_KNOWN_FILES.PACKAGE_JSON)?.addDependency("@decohere/codex", CREATE_VERSION).addDependency("typeorm", "^0.3.28").addDependency("@decohere/codex-typeorm", CREATE_VERSION);
113
- // Add codex deps to api package.json
114
- workspace.getModel(WELL_KNOWN_FILES.API_PACKAGE_JSON)?.addDependency("@decohere/codex", CREATE_VERSION).addDependency("@decohere/codex-typeorm", CREATE_VERSION);
115
- // Append database config sections
116
- workspace.getModel(WELL_KNOWN_FILES.CONFIG_YAML)?.addSection(DATABASE_BASE_CONFIG_YAML);
117
- workspace.getModel(WELL_KNOWN_FILES.CONFIG_DEV_YAML)?.addSection(DATABASE_DEV_CONFIG_YAML);
118
- // Register entity and repository source files in the api project
119
- workspace.getProject(WEBAPI_PROJECT_DIR)?.addFile({
120
- files: ()=>[
121
- {
122
- filePath: "src/entities/sample.entity.ts",
123
- content: SAMPLE_ENTITY_TS
124
- },
125
- {
126
- filePath: "src/repositories/sample.repository.ts",
127
- content: SAMPLE_REPOSITORY_TS
128
- }
129
- ]
130
- });
131
- // .env at workspace root — mounted by compose via ../.env so both postgres
132
- // and the devcontainer service can read credentials
133
- compose?.addEnvFile("postgres", "../.env").addEnvFile("devcontainer", "../.env");
134
- workspace.getModel(WELL_KNOWN_FILES.ENV_FILE)?.addEntry("POSTGRES_DB", db).addEntry("POSTGRES_USER", user).addEntry("POSTGRES_PASSWORD", password).addEntry("DB_HOST", "localhost").addEntry("DB_PORT", "5432").addEntry("DB_NAME", db).addEntry("DB_USER", user).addEntry("DB_PASSWORD", password).addEntry("DB_ADMIN_USER", user).addEntry("DB_ADMIN_PASSWORD", password);
135
- }
136
- export const DatabaseFeature = {
137
- getOptions,
138
- scaffold
139
- };
140
-
141
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL2ZlYXR1cmVzL2RhdGFiYXNlLmZlYXR1cmUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmFuZG9tQnl0ZXMgfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB7IHBpY2sgfSBmcm9tIFwiLi4vLi4vZG9tYWluL3Byb21wdC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBEb2NrZXJDb21wb3NlIH0gZnJvbSBcIi4uLy4uL21vZGVscy9jb21wb3NlLm1vZGVsLmpzXCI7XG5pbXBvcnQgdHlwZSB7IENvbmZpZ1lhbWwgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL2NvbmZpZy15YW1sLm1vZGVsLmpzXCI7XG5pbXBvcnQgeyBXRUxMX0tOT1dOX0ZJTEVTIH0gZnJvbSBcIi4uLy4uL21vZGVscy9jb25zdC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBEZXZDb250YWluZXIgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL2Rldi1jb250YWluZXIubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgRW52RmlsZSB9IGZyb20gXCIuLi8uLi9tb2RlbHMvZW52LWZpbGUubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgUGFja2FnZUpzb24gfSBmcm9tIFwiLi4vLi4vbW9kZWxzL3BhY2thZ2UtanNvbi5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBXb3Jrc3BhY2VTY2FmZm9sZCB9IGZyb20gXCIuLi8uLi9tb2RlbHMvcHJvamVjdC5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBGZWF0dXJlIH0gZnJvbSBcIi4uLy4uL3NlcnZpY2VzL3NjYWZmb2xkLnNlcnZpY2UuanNcIjtcbmltcG9ydCB7IENSRUFURV9WRVJTSU9OIH0gZnJvbSBcIi4uLy4uL3ZlcnNpb24uanNcIjtcbmltcG9ydCB7IFdFQkFQSV9QUk9KRUNUX0RJUiB9IGZyb20gXCIuLi9jcmVhdGUtYXBpLmpzXCI7XG5pbXBvcnQgdHlwZSB7IEFwaVBhY2thZ2VKc29uIH0gZnJvbSBcIi4uL21vZGVscy9hcGktcGFja2FnZS1qc29uLm1vZGVsLmpzXCI7XG5pbXBvcnQgdHlwZSB7IE1haW5Tb3VyY2VGaWxlIH0gZnJvbSBcIi4uL21vZGVscy9tYWluLXNvdXJjZS1maWxlLm1vZGVsLmpzXCI7XG5cbmV4cG9ydCB0eXBlIERhdGFiYXNlT3B0aW9ucyA9IHtcblx0ZGF0YWJhc2VQcm92aWRlcj86IFwibm9uZVwiIHwgXCJwb3N0Z3Jlcy90eXBlb3JtXCI7XG59O1xuXG4vLyBCYXNlIGNvbmZpZyB1c2VzIGVudi12YXIgcmVmZXJlbmNlcyBmb3IgcHJvZHVjdGlvbjsgdGhlIGRldiBjb25maWcgc2VjdGlvblxuLy8gd3JpdHRlbiBiZWxvdyBvdmVycmlkZXMgb25seSB0aGUgY29uY3JldGUgdmFsdWVzIG5lZWRlZCBsb2NhbGx5LlxuY29uc3QgREFUQUJBU0VfQkFTRV9DT05GSUdfWUFNTCA9IGBkYXRhYmFzZTpcbiAgZGF0YVNvdXJjZXM6XG4gICAgLSBuYW1lOiBkZWZhdWx0XG4gICAgICBwcm92aWRlcjogcG9zdGdyZXNcbiAgICAgIGhvc3Q6IFxcJHtEQl9IT1NUfVxuICAgICAgcG9ydDogXFwke0RCX1BPUlR9XG4gICAgICBkYXRhYmFzZTogXFwke0RCX05BTUV9XG4gICAgICB1c2VybmFtZTogXFwke0RCX1VTRVJ9XG4gICAgICBwYXNzd29yZDogXFwke0RCX1BBU1NXT1JEfVxuICAgICAgc3luY2hyb25pemU6IGZhbHNlXG4gICAgICBzZWVkOiBmYWxzZVxuICAgICAgYWRtaW5Vc2VyOiBcXCR7REJfQURNSU5fVVNFUn1cbiAgICAgIGFkbWluUGFzc3dvcmQ6IFxcJHtEQl9BRE1JTl9QQVNTV09SRH1cbmA7XG5cbi8vIERldiBjb25maWcgb25seSBvdmVycmlkZXMgd2hhdCBkaWZmZXJzIGZyb20gYmFzZSDigJQgY3JlZGVudGlhbHMgY29tZSBmcm9tIC5lbnYgdmlhIGVudi12YXIgcmVmZXJlbmNlcy5cbmNvbnN0IERBVEFCQVNFX0RFVl9DT05GSUdfWUFNTCA9IGBkYXRhYmFzZTpcbiAgZGF0YVNvdXJjZXM6XG4gICAgLSBob3N0OiBwb3N0Z3Jlc1xuICAgICAgc3luY2hyb25pemU6IHRydWVcbiAgICAgIHNlZWQ6IHRydWVcbmA7XG5cbmNvbnN0IFNBTVBMRV9FTlRJVFlfVFMgPSBgaW1wb3J0IHsgQ29sdW1uLCBFbnRpdHksIFByaW1hcnlHZW5lcmF0ZWRDb2x1bW4gfSBmcm9tIFwidHlwZW9ybVwiO1xuaW1wb3J0IHR5cGUgeyBFbnRpdHkgYXMgSUVudGl0eSB9IGZyb20gXCJAZGVjb2hlcmUvY29kZXhcIjtcblxuQEVudGl0eSgpXG5leHBvcnQgY2xhc3MgU2FtcGxlRW50aXR5IGltcGxlbWVudHMgSUVudGl0eSB7XG5cXHRAUHJpbWFyeUdlbmVyYXRlZENvbHVtbigpXG5cXHRwdWJsaWMgaWQhOiBudW1iZXI7XG5cblxcdEBDb2x1bW4oKVxuXFx0cHVibGljIG5hbWUhOiBzdHJpbmc7XG59XG5gO1xuXG5jb25zdCBTQU1QTEVfUkVQT1NJVE9SWV9UUyA9IGBpbXBvcnQgeyBpbmplY3RhYmxlIH0gZnJvbSBcIkBkZWNvaGVyZS9jcnVjaWJsZS9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBpbmplY3RVbml0T2ZXb3JrIH0gZnJvbSBcIkBkZWNvaGVyZS9jb2RleFwiO1xuaW1wb3J0IHsgVHlwZU9ybVJlcG9zaXRvcnksIFR5cGVPcm1Vbml0T2ZXb3JrIH0gZnJvbSBcIkBkZWNvaGVyZS9jb2RleC10eXBlb3JtXCI7XG5pbXBvcnQgeyBTYW1wbGVFbnRpdHkgfSBmcm9tIFwiLi4vZW50aXRpZXMvc2FtcGxlLmVudGl0eS5qc1wiO1xuXG5AaW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgU2FtcGxlRW50aXR5UmVwb3NpdG9yeSBleHRlbmRzIFR5cGVPcm1SZXBvc2l0b3J5PFNhbXBsZUVudGl0eT4ge1xuXFx0cHVibGljIGNvbnN0cnVjdG9yKEBpbmplY3RVbml0T2ZXb3JrKCkgdW5pdE9mV29yazogVHlwZU9ybVVuaXRPZldvcmspIHtcblxcdFxcdHN1cGVyKHVuaXRPZldvcmssIFNhbXBsZUVudGl0eSk7XG5cXHR9XG59XG5gO1xuXG5hc3luYyBmdW5jdGlvbiBnZXRPcHRpb25zKFxuXHRfd29ya3NwYWNlOiBXb3Jrc3BhY2VTY2FmZm9sZCxcblx0Y2xpT3B0aW9uczogUGFydGlhbDxEYXRhYmFzZU9wdGlvbnM+LFxuKTogUHJvbWlzZTxQYXJ0aWFsPERhdGFiYXNlT3B0aW9ucz4+IHtcblx0aWYgKGNsaU9wdGlvbnMuZGF0YWJhc2VQcm92aWRlciAhPSBudWxsKSByZXR1cm4ge307XG5cblx0Y29uc3QgY2hvaWNlcyA9IFt7IGxhYmVsOiBcIm5vbmVcIiBhcyBjb25zdCB9LCB7IGxhYmVsOiBcInBvc3RncmVzL3R5cGVvcm1cIiBhcyBjb25zdCB9XTtcblx0Y29uc3Qgc2VsZWN0ZWQgPSBhd2FpdCBwaWNrKFwiXFxuICBEYXRhYmFzZTogXCIsIGNob2ljZXMsIChjKSA9PiBjLmxhYmVsKTtcblx0cmV0dXJuIHsgZGF0YWJhc2VQcm92aWRlcjogc2VsZWN0ZWQ/LmxhYmVsID8/IFwibm9uZVwiIH07XG59XG5cbmZ1bmN0aW9uIHNjYWZmb2xkKHdvcmtzcGFjZTogV29ya3NwYWNlU2NhZmZvbGQsIG9wdGlvbnM6IERhdGFiYXNlT3B0aW9ucyk6IHZvaWQge1xuXHRpZiAob3B0aW9ucy5kYXRhYmFzZVByb3ZpZGVyICE9PSBcInBvc3RncmVzL3R5cGVvcm1cIikgcmV0dXJuO1xuXG5cdGNvbnN0IG5hbWUgPSB3b3Jrc3BhY2UubmFtZTtcblx0Y29uc3QgcGFzc3dvcmQgPSByYW5kb21CeXRlcygxNikudG9TdHJpbmcoXCJoZXhcIik7XG5cdGNvbnN0IGRiID0gYCR7bmFtZX1fZGV2YDtcblx0Y29uc3QgdXNlciA9IFwicG9zdGdyZXNcIjtcblxuXHRjb25zdCBkZXZDb250YWluZXIgPSB3b3Jrc3BhY2UuZ2V0TW9kZWw8RGV2Q29udGFpbmVyPihXRUxMX0tOT1dOX0ZJTEVTLkRFVkNPTlRBSU5FUl9KU09OKTtcblx0Y29uc3QgY29tcG9zZSA9IHdvcmtzcGFjZS5nZXRNb2RlbDxEb2NrZXJDb21wb3NlPihXRUxMX0tOT1dOX0ZJTEVTLkRPQ0tFUl9DT01QT1NFKTtcblxuXHQvLyBBZGQgcG9zdGdyZXMgc2VydmljZSB0byBjb21wb3NlXG5cdGNvbXBvc2Vcblx0XHQ/LmFkZFNlcnZpY2UoXCJwb3N0Z3Jlc1wiLCB7XG5cdFx0XHRpbWFnZTogXCJwb3N0Z3JlczoxNlwiLFxuXHRcdFx0cmVzdGFydDogXCJ1bmxlc3Mtc3RvcHBlZFwiLFxuXHRcdFx0ZW52aXJvbm1lbnQ6IHtcblx0XHRcdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub1RlbXBsYXRlQ3VybHlJblN0cmluZzogRG9ja2VyIENvbXBvc2UgcmVhZHMgdGhlc2UgZnJvbSAuZW52XG5cdFx0XHRcdFBPU1RHUkVTX0RCOiBcIiR7UE9TVEdSRVNfREJ9XCIsXG5cdFx0XHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9UZW1wbGF0ZUN1cmx5SW5TdHJpbmc6IERvY2tlciBDb21wb3NlIHJlYWRzIHRoZXNlIGZyb20gLmVudlxuXHRcdFx0XHRQT1NUR1JFU19VU0VSOiBcIiR7UE9TVEdSRVNfVVNFUn1cIixcblx0XHRcdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub1RlbXBsYXRlQ3VybHlJblN0cmluZzogRG9ja2VyIENvbXBvc2UgcmVhZHMgdGhlc2UgZnJvbSAuZW52XG5cdFx0XHRcdFBPU1RHUkVTX1BBU1NXT1JEOiBcIiR7UE9TVEdSRVNfUEFTU1dPUkR9XCIsXG5cdFx0XHR9LFxuXHRcdFx0cG9ydHM6IFtcIjU0MzI6NTQzMlwiXSxcblx0XHRcdHZvbHVtZXM6IFtcInBvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhXCJdLFxuXHRcdH0pXG5cdFx0LmFkZFZvbHVtZShcInBvc3RncmVzLWRhdGFcIik7XG5cblx0Y29tcG9zZT8uYWRkU2VydmljZShcImFkbWluZXJcIiwge1xuXHRcdGltYWdlOiBcImFkbWluZXJcIixcblx0XHRwb3J0czogW1wiODA4MDo4MDgwXCJdLFxuXHR9KTtcblxuXHQvLyBBZGQgU1FMVG9vbHMgZXh0ZW5zaW9uIGZvciBEQiBicm93c2luZyBpbiBWUyBDb2RlXG5cdGRldkNvbnRhaW5lcj8uYWRkRXh0ZW5zaW9uKFwibXR4ci5zcWx0b29sc1wiKTtcblxuXHQvLyBXaXJlIHVwIG1haW4udHNcblx0d29ya3NwYWNlXG5cdFx0LmdldE1vZGVsPE1haW5Tb3VyY2VGaWxlPihXRUxMX0tOT1dOX0ZJTEVTLk1BSU5fVFMpXG5cdFx0Py5hZGRTaWRlRWZmZWN0SW1wb3J0KFwiQGRlY29oZXJlL2NvZGV4LXR5cGVvcm1cIilcblx0XHQuYWRkRW50aXR5KHsgY2xhc3NOYW1lOiBcIlNhbXBsZUVudGl0eVwiLCBpbXBvcnRQYXRoOiBcIi4vZW50aXRpZXMvc2FtcGxlLmVudGl0eS5qc1wiIH0pXG5cdFx0LmFkZFJlcG9zaXRvcnkoe1xuXHRcdFx0Y2xhc3NOYW1lOiBcIlNhbXBsZUVudGl0eVJlcG9zaXRvcnlcIixcblx0XHRcdGltcG9ydFBhdGg6IFwiLi9yZXBvc2l0b3JpZXMvc2FtcGxlLnJlcG9zaXRvcnkuanNcIixcblx0XHR9KTtcblxuXHQvLyBBZGQgY29kZXggKyB0eXBlb3JtIGRlcHMgdG8gcm9vdCBwYWNrYWdlLmpzb25cblx0d29ya3NwYWNlXG5cdFx0LmdldE1vZGVsPFBhY2thZ2VKc29uPihXRUxMX0tOT1dOX0ZJTEVTLlBBQ0tBR0VfSlNPTilcblx0XHQ/LmFkZERlcGVuZGVuY3koXCJAZGVjb2hlcmUvY29kZXhcIiwgQ1JFQVRFX1ZFUlNJT04pXG5cdFx0LmFkZERlcGVuZGVuY3koXCJ0eXBlb3JtXCIsIFwiXjAuMy4yOFwiKVxuXHRcdC5hZGREZXBlbmRlbmN5KFwiQGRlY29oZXJlL2NvZGV4LXR5cGVvcm1cIiwgQ1JFQVRFX1ZFUlNJT04pO1xuXG5cdC8vIEFkZCBjb2RleCBkZXBzIHRvIGFwaSBwYWNrYWdlLmpzb25cblx0d29ya3NwYWNlXG5cdFx0LmdldE1vZGVsPEFwaVBhY2thZ2VKc29uPihXRUxMX0tOT1dOX0ZJTEVTLkFQSV9QQUNLQUdFX0pTT04pXG5cdFx0Py5hZGREZXBlbmRlbmN5KFwiQGRlY29oZXJlL2NvZGV4XCIsIENSRUFURV9WRVJTSU9OKVxuXHRcdC5hZGREZXBlbmRlbmN5KFwiQGRlY29oZXJlL2NvZGV4LXR5cGVvcm1cIiwgQ1JFQVRFX1ZFUlNJT04pO1xuXG5cdC8vIEFwcGVuZCBkYXRhYmFzZSBjb25maWcgc2VjdGlvbnNcblx0d29ya3NwYWNlXG5cdFx0LmdldE1vZGVsPENvbmZpZ1lhbWw+KFdFTExfS05PV05fRklMRVMuQ09ORklHX1lBTUwpXG5cdFx0Py5hZGRTZWN0aW9uKERBVEFCQVNFX0JBU0VfQ09ORklHX1lBTUwpO1xuXHR3b3Jrc3BhY2Vcblx0XHQuZ2V0TW9kZWw8Q29uZmlnWWFtbD4oV0VMTF9LTk9XTl9GSUxFUy5DT05GSUdfREVWX1lBTUwpXG5cdFx0Py5hZGRTZWN0aW9uKERBVEFCQVNFX0RFVl9DT05GSUdfWUFNTCk7XG5cblx0Ly8gUmVnaXN0ZXIgZW50aXR5IGFuZCByZXBvc2l0b3J5IHNvdXJjZSBmaWxlcyBpbiB0aGUgYXBpIHByb2plY3Rcblx0d29ya3NwYWNlLmdldFByb2plY3QoV0VCQVBJX1BST0pFQ1RfRElSKT8uYWRkRmlsZSh7XG5cdFx0ZmlsZXM6ICgpID0+IFtcblx0XHRcdHtcblx0XHRcdFx0ZmlsZVBhdGg6IFwic3JjL2VudGl0aWVzL3NhbXBsZS5lbnRpdHkudHNcIixcblx0XHRcdFx0Y29udGVudDogU0FNUExFX0VOVElUWV9UUyxcblx0XHRcdH0sXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcInNyYy9yZXBvc2l0b3JpZXMvc2FtcGxlLnJlcG9zaXRvcnkudHNcIixcblx0XHRcdFx0Y29udGVudDogU0FNUExFX1JFUE9TSVRPUllfVFMsXG5cdFx0XHR9LFxuXHRcdF0sXG5cdH0pO1xuXG5cdC8vIC5lbnYgYXQgd29ya3NwYWNlIHJvb3Qg4oCUIG1vdW50ZWQgYnkgY29tcG9zZSB2aWEgLi4vLmVudiBzbyBib3RoIHBvc3RncmVzXG5cdC8vIGFuZCB0aGUgZGV2Y29udGFpbmVyIHNlcnZpY2UgY2FuIHJlYWQgY3JlZGVudGlhbHNcblx0Y29tcG9zZT8uYWRkRW52RmlsZShcInBvc3RncmVzXCIsIFwiLi4vLmVudlwiKS5hZGRFbnZGaWxlKFwiZGV2Y29udGFpbmVyXCIsIFwiLi4vLmVudlwiKTtcblxuXHR3b3Jrc3BhY2Vcblx0XHQuZ2V0TW9kZWw8RW52RmlsZT4oV0VMTF9LTk9XTl9GSUxFUy5FTlZfRklMRSlcblx0XHQ/LmFkZEVudHJ5KFwiUE9TVEdSRVNfREJcIiwgZGIpXG5cdFx0LmFkZEVudHJ5KFwiUE9TVEdSRVNfVVNFUlwiLCB1c2VyKVxuXHRcdC5hZGRFbnRyeShcIlBPU1RHUkVTX1BBU1NXT1JEXCIsIHBhc3N3b3JkKVxuXHRcdC5hZGRFbnRyeShcIkRCX0hPU1RcIiwgXCJsb2NhbGhvc3RcIilcblx0XHQuYWRkRW50cnkoXCJEQl9QT1JUXCIsIFwiNTQzMlwiKVxuXHRcdC5hZGRFbnRyeShcIkRCX05BTUVcIiwgZGIpXG5cdFx0LmFkZEVudHJ5KFwiREJfVVNFUlwiLCB1c2VyKVxuXHRcdC5hZGRFbnRyeShcIkRCX1BBU1NXT1JEXCIsIHBhc3N3b3JkKVxuXHRcdC5hZGRFbnRyeShcIkRCX0FETUlOX1VTRVJcIiwgdXNlcilcblx0XHQuYWRkRW50cnkoXCJEQl9BRE1JTl9QQVNTV09SRFwiLCBwYXNzd29yZCk7XG59XG5cbmV4cG9ydCBjb25zdCBEYXRhYmFzZUZlYXR1cmU6IEZlYXR1cmU8RGF0YWJhc2VPcHRpb25zPiA9IHsgZ2V0T3B0aW9ucywgc2NhZmZvbGQgfTtcbiJdLCJuYW1lcyI6WyJyYW5kb21CeXRlcyIsInBpY2siLCJXRUxMX0tOT1dOX0ZJTEVTIiwiQ1JFQVRFX1ZFUlNJT04iLCJXRUJBUElfUFJPSkVDVF9ESVIiLCJEQVRBQkFTRV9CQVNFX0NPTkZJR19ZQU1MIiwiREFUQUJBU0VfREVWX0NPTkZJR19ZQU1MIiwiU0FNUExFX0VOVElUWV9UUyIsIlNBTVBMRV9SRVBPU0lUT1JZX1RTIiwiZ2V0T3B0aW9ucyIsIl93b3Jrc3BhY2UiLCJjbGlPcHRpb25zIiwiZGF0YWJhc2VQcm92aWRlciIsImNob2ljZXMiLCJsYWJlbCIsInNlbGVjdGVkIiwiYyIsInNjYWZmb2xkIiwid29ya3NwYWNlIiwib3B0aW9ucyIsIm5hbWUiLCJwYXNzd29yZCIsInRvU3RyaW5nIiwiZGIiLCJ1c2VyIiwiZGV2Q29udGFpbmVyIiwiZ2V0TW9kZWwiLCJERVZDT05UQUlORVJfSlNPTiIsImNvbXBvc2UiLCJET0NLRVJfQ09NUE9TRSIsImFkZFNlcnZpY2UiLCJpbWFnZSIsInJlc3RhcnQiLCJlbnZpcm9ubWVudCIsIlBPU1RHUkVTX0RCIiwiUE9TVEdSRVNfVVNFUiIsIlBPU1RHUkVTX1BBU1NXT1JEIiwicG9ydHMiLCJ2b2x1bWVzIiwiYWRkVm9sdW1lIiwiYWRkRXh0ZW5zaW9uIiwiTUFJTl9UUyIsImFkZFNpZGVFZmZlY3RJbXBvcnQiLCJhZGRFbnRpdHkiLCJjbGFzc05hbWUiLCJpbXBvcnRQYXRoIiwiYWRkUmVwb3NpdG9yeSIsIlBBQ0tBR0VfSlNPTiIsImFkZERlcGVuZGVuY3kiLCJBUElfUEFDS0FHRV9KU09OIiwiQ09ORklHX1lBTUwiLCJhZGRTZWN0aW9uIiwiQ09ORklHX0RFVl9ZQU1MIiwiZ2V0UHJvamVjdCIsImFkZEZpbGUiLCJmaWxlcyIsImZpbGVQYXRoIiwiY29udGVudCIsImFkZEVudkZpbGUiLCJFTlZfRklMRSIsImFkZEVudHJ5IiwiRGF0YWJhc2VGZWF0dXJlIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxXQUFXLFFBQVEsY0FBYztBQUMxQyxTQUFTQyxJQUFJLFFBQVEseUJBQXlCO0FBRzlDLFNBQVNDLGdCQUFnQixRQUFRLHdCQUF3QjtBQU16RCxTQUFTQyxjQUFjLFFBQVEsbUJBQW1CO0FBQ2xELFNBQVNDLGtCQUFrQixRQUFRLG1CQUFtQjtBQVF0RCw2RUFBNkU7QUFDN0UsbUVBQW1FO0FBQ25F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