@decohere/create 0.0.1-dev.47 → 0.0.1-dev.49
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/commonjs/src/cli.js +3 -3
- package/commonjs/src/resolve-launch.js +53 -0
- package/commonjs/src/runner.js +5 -45
- package/commonjs/src/version.js +1 -1
- package/es6/src/cli.js +3 -3
- package/es6/src/resolve-launch.js +46 -0
- package/es6/src/runner.js +8 -57
- package/es6/src/version.js +3 -3
- package/pack-builder-tgz.mjs +19 -35
- package/package.json +4 -11
- package/types/src/resolve-launch.d.ts +10 -0
- package/types/src/runner.d.ts +3 -13
- package/types/src/version.d.ts +0 -2
- package/commonjs/src/domain/prompt.js +0 -64
- package/commonjs/src/models/compose.model.js +0 -138
- package/commonjs/src/models/config-yaml.model.js +0 -88
- package/commonjs/src/models/const.js +0 -31
- package/commonjs/src/models/dev-container.model.js +0 -100
- package/commonjs/src/models/docker-image.model.js +0 -221
- package/commonjs/src/models/env-file.model.js +0 -47
- package/commonjs/src/models/gitignore.model.js +0 -31
- package/commonjs/src/models/launch-json.model.js +0 -74
- package/commonjs/src/models/package-json.model.js +0 -133
- package/commonjs/src/models/project.model.js +0 -134
- package/commonjs/src/models/source-file.js +0 -6
- package/commonjs/src/models/tsconfig.model.js +0 -34
- package/commonjs/src/models/vscode-settings.model.js +0 -31
- package/commonjs/src/program.js +0 -135
- package/commonjs/src/resolve-target-dir.js +0 -19
- package/commonjs/src/services/scaffold.service.js +0 -62
- package/commonjs/src/webapi/api-name.js +0 -95
- package/commonjs/src/webapi/const.js +0 -50
- package/commonjs/src/webapi/create-api.js +0 -285
- package/commonjs/src/webapi/features/auth.feature.js +0 -463
- package/commonjs/src/webapi/features/auth0-cli.js +0 -406
- package/commonjs/src/webapi/features/biome-format.js +0 -49
- package/commonjs/src/webapi/features/database.feature.js +0 -273
- package/commonjs/src/webapi/features/finalize.feature.js +0 -91
- package/commonjs/src/webapi/features/postman.feature.js +0 -319
- package/commonjs/src/webapi/models/api-package-json.model.js +0 -63
- package/commonjs/src/webapi/models/auth-config.model.js +0 -26
- package/commonjs/src/webapi/models/controller-source-file.model.js +0 -188
- package/commonjs/src/webapi/models/github-ci.model.js +0 -193
- package/commonjs/src/webapi/models/main-source-file.model.js +0 -165
- package/commonjs/src/webapi/models/production-dockerfile.model.js +0 -138
- package/commonjs/src/webapi/models/sample-files.model.js +0 -60
- package/commonjs/src/webapi/models/webapi-image.model.js +0 -22
- package/commonjs/src/webapi/postman/hello-openapi.js +0 -175
- package/commonjs/src/webapi/postman/local-view.js +0 -184
- package/commonjs/src/webapi/postman/openapi-to-postman.js +0 -202
- package/es6/src/domain/prompt.js +0 -43
- package/es6/src/models/compose.model.js +0 -132
- package/es6/src/models/config-yaml.model.js +0 -76
- package/es6/src/models/const.js +0 -21
- package/es6/src/models/dev-container.model.js +0 -90
- package/es6/src/models/docker-image.model.js +0 -185
- package/es6/src/models/env-file.model.js +0 -43
- package/es6/src/models/gitignore.model.js +0 -21
- package/es6/src/models/launch-json.model.js +0 -64
- package/es6/src/models/package-json.model.js +0 -129
- package/es6/src/models/project.model.js +0 -119
- package/es6/src/models/source-file.js +0 -3
- package/es6/src/models/tsconfig.model.js +0 -24
- package/es6/src/models/vscode-settings.model.js +0 -21
- package/es6/src/program.js +0 -76
- package/es6/src/resolve-target-dir.js +0 -9
- package/es6/src/services/scaffold.service.js +0 -52
- package/es6/src/webapi/api-name.js +0 -59
- package/es6/src/webapi/const.js +0 -20
- package/es6/src/webapi/create-api.js +0 -265
- package/es6/src/webapi/features/auth.feature.js +0 -412
- package/es6/src/webapi/features/auth0-cli.js +0 -348
- package/es6/src/webapi/features/biome-format.js +0 -42
- package/es6/src/webapi/features/database.feature.js +0 -263
- package/es6/src/webapi/features/finalize.feature.js +0 -81
- package/es6/src/webapi/features/postman.feature.js +0 -253
- package/es6/src/webapi/models/api-package-json.model.js +0 -58
- package/es6/src/webapi/models/auth-config.model.js +0 -22
- package/es6/src/webapi/models/controller-source-file.model.js +0 -179
- package/es6/src/webapi/models/github-ci.model.js +0 -186
- package/es6/src/webapi/models/main-source-file.model.js +0 -161
- package/es6/src/webapi/models/production-dockerfile.model.js +0 -126
- package/es6/src/webapi/models/sample-files.model.js +0 -42
- package/es6/src/webapi/models/webapi-image.model.js +0 -12
- package/es6/src/webapi/postman/hello-openapi.js +0 -168
- package/es6/src/webapi/postman/local-view.js +0 -169
- package/es6/src/webapi/postman/openapi-to-postman.js +0 -179
- package/types/src/domain/prompt.d.ts +0 -4
- package/types/src/models/compose.model.d.ts +0 -59
- package/types/src/models/config-yaml.model.d.ts +0 -27
- package/types/src/models/const.d.ts +0 -19
- package/types/src/models/dev-container.model.d.ts +0 -33
- package/types/src/models/docker-image.model.d.ts +0 -56
- package/types/src/models/env-file.model.d.ts +0 -15
- package/types/src/models/gitignore.model.d.ts +0 -6
- package/types/src/models/launch-json.model.d.ts +0 -7
- package/types/src/models/package-json.model.d.ts +0 -32
- package/types/src/models/project.model.d.ts +0 -60
- package/types/src/models/source-file.d.ts +0 -11
- package/types/src/models/tsconfig.model.d.ts +0 -5
- package/types/src/models/vscode-settings.model.d.ts +0 -7
- package/types/src/program.d.ts +0 -3
- package/types/src/resolve-target-dir.d.ts +0 -5
- package/types/src/services/scaffold.service.d.ts +0 -22
- package/types/src/webapi/api-name.d.ts +0 -14
- package/types/src/webapi/const.d.ts +0 -17
- package/types/src/webapi/create-api.d.ts +0 -15
- package/types/src/webapi/features/auth.feature.d.ts +0 -10
- package/types/src/webapi/features/auth0-cli.d.ts +0 -72
- package/types/src/webapi/features/biome-format.d.ts +0 -5
- package/types/src/webapi/features/database.feature.d.ts +0 -5
- package/types/src/webapi/features/finalize.feature.d.ts +0 -2
- package/types/src/webapi/features/postman.feature.d.ts +0 -16
- package/types/src/webapi/models/api-package-json.model.d.ts +0 -18
- package/types/src/webapi/models/auth-config.model.d.ts +0 -26
- package/types/src/webapi/models/controller-source-file.model.d.ts +0 -45
- package/types/src/webapi/models/github-ci.model.d.ts +0 -9
- package/types/src/webapi/models/main-source-file.model.d.ts +0 -54
- package/types/src/webapi/models/production-dockerfile.model.d.ts +0 -20
- package/types/src/webapi/models/sample-files.model.d.ts +0 -7
- package/types/src/webapi/models/webapi-image.model.d.ts +0 -5
- package/types/src/webapi/postman/hello-openapi.d.ts +0 -19
- package/types/src/webapi/postman/local-view.d.ts +0 -17
- package/types/src/webapi/postman/openapi-to-postman.d.ts +0 -62
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "DatabaseFeature", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return DatabaseFeature;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _nodecrypto = require("node:crypto");
|
|
12
|
-
const _nodefs = require("node:fs");
|
|
13
|
-
const _nodepath = require("node:path");
|
|
14
|
-
const _prompt = require("../../domain/prompt.js");
|
|
15
|
-
const _const = require("../../models/const.js");
|
|
16
|
-
const _version = require("../../version.js");
|
|
17
|
-
const _apiname = require("../api-name.js");
|
|
18
|
-
/** Read a single KEY= from an existing target `.env` (if any). */ function readExistingEnvValue(workspace, key) {
|
|
19
|
-
try {
|
|
20
|
-
const raw = (0, _nodefs.readFileSync)((0, _nodepath.join)(workspace.targetDir, ".env"), "utf8");
|
|
21
|
-
const line = raw.split("\n").find((l)=>l.startsWith(`${key}=`));
|
|
22
|
-
const value = line?.slice(key.length + 1).trim();
|
|
23
|
-
return value || undefined;
|
|
24
|
-
} catch {
|
|
25
|
-
return undefined;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function randomPassword() {
|
|
29
|
-
return (0, _nodecrypto.randomBytes)(16).toString("hex");
|
|
30
|
-
}
|
|
31
|
-
/** Safe Postgres identifier fragment from the project name. */ function toSqlIdentFragment(name) {
|
|
32
|
-
const cleaned = name.replace(/[^A-Za-z0-9_]/g, "_").replace(/^([^A-Za-z_])/, "p_$1");
|
|
33
|
-
return cleaned.length > 0 ? cleaned.slice(0, 40) : "app";
|
|
34
|
-
}
|
|
35
|
-
function passwordOrExisting(workspace, key, fallbackExistingKeys = []) {
|
|
36
|
-
const existing = readExistingEnvValue(workspace, key);
|
|
37
|
-
if (existing) return existing;
|
|
38
|
-
for (const alt of fallbackExistingKeys){
|
|
39
|
-
const v = readExistingEnvValue(workspace, alt);
|
|
40
|
-
if (v) return v;
|
|
41
|
-
}
|
|
42
|
-
return randomPassword();
|
|
43
|
-
}
|
|
44
|
-
// Production: runtime app role only — no bootstrap, no admin/migrate secrets required.
|
|
45
|
-
function renderBaseDataSource(apiName) {
|
|
46
|
-
const p = (0, _apiname.apiEnvPrefix)(apiName);
|
|
47
|
-
return [
|
|
48
|
-
` - name: ${apiName}`,
|
|
49
|
-
` provider: postgres`,
|
|
50
|
-
` host: \${${p}_DB_HOST}`,
|
|
51
|
-
` port: \${${p}_DB_PORT}`,
|
|
52
|
-
` database: \${${p}_DB_NAME}`,
|
|
53
|
-
` username: \${${p}_DB_USER}`,
|
|
54
|
-
` password: \${${p}_DB_PASSWORD}`,
|
|
55
|
-
` synchronize: false`,
|
|
56
|
-
` seed: false`,
|
|
57
|
-
` bootstrap: false`
|
|
58
|
-
].join("\n");
|
|
59
|
-
}
|
|
60
|
-
// Dev overlay (merged by list index onto config.yaml). Enable bootstrap + migrate role.
|
|
61
|
-
function renderDevDataSource(apiName) {
|
|
62
|
-
const p = (0, _apiname.apiEnvPrefix)(apiName);
|
|
63
|
-
return [
|
|
64
|
-
` - name: ${apiName}`,
|
|
65
|
-
` synchronize: true`,
|
|
66
|
-
` seed: true`,
|
|
67
|
-
` bootstrap: true`,
|
|
68
|
-
` adminUser: \${DB_ADMIN_USER}`,
|
|
69
|
-
` adminPassword: \${DB_ADMIN_PASSWORD}`,
|
|
70
|
-
` migrateUsername: \${${p}_DB_MIGRATE_USER}`,
|
|
71
|
-
` migratePassword: \${${p}_DB_MIGRATE_PASSWORD}`
|
|
72
|
-
].join("\n");
|
|
73
|
-
}
|
|
74
|
-
function renderDatabaseSection(apiNames, items) {
|
|
75
|
-
return `database:\n dataSources:\n${apiNames.map(items).join("\n")}\n`;
|
|
76
|
-
}
|
|
77
|
-
/** Runs once on first Postgres volume init — creates restricted bootstrap role (not superuser). */ const POSTGRES_INIT_BOOTSTRAP_SH = `#!/bin/bash
|
|
78
|
-
set -euo pipefail
|
|
79
|
-
# Container superuser (POSTGRES_USER) creates a restricted provisioner role.
|
|
80
|
-
# App/migrate roles are created later by codex-typeorm prepareDatabase (dev bootstrap).
|
|
81
|
-
: "\${DB_ADMIN_USER:?DB_ADMIN_USER is required}"
|
|
82
|
-
: "\${DB_ADMIN_PASSWORD:?DB_ADMIN_PASSWORD is required}"
|
|
83
|
-
|
|
84
|
-
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" \\
|
|
85
|
-
\t--set=bootstrap_user="$DB_ADMIN_USER" \\
|
|
86
|
-
\t--set=bootstrap_password="$DB_ADMIN_PASSWORD" <<'EOSQL'
|
|
87
|
-
SELECT format(
|
|
88
|
-
\t'CREATE ROLE %I LOGIN PASSWORD %L CREATEDB CREATEROLE NOSUPERUSER NOBYPASSRLS',
|
|
89
|
-
\t:'bootstrap_user',
|
|
90
|
-
\t:'bootstrap_password'
|
|
91
|
-
)
|
|
92
|
-
WHERE NOT EXISTS (
|
|
93
|
-
\tSELECT 1 FROM pg_catalog.pg_roles WHERE rolname = :'bootstrap_user'
|
|
94
|
-
)\\gexec
|
|
95
|
-
|
|
96
|
-
GRANT ALL ON SCHEMA public TO :"bootstrap_user";
|
|
97
|
-
EOSQL
|
|
98
|
-
|
|
99
|
-
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" \\
|
|
100
|
-
\t-c "GRANT ALL PRIVILEGES ON DATABASE \\"$POSTGRES_DB\\" TO \\"$DB_ADMIN_USER\\""
|
|
101
|
-
`;
|
|
102
|
-
const SAMPLE_ENTITY_TS = `import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
|
103
|
-
import type { Entity as IEntity } from "@decohere/codex";
|
|
104
|
-
|
|
105
|
-
@Entity()
|
|
106
|
-
export class SampleEntity implements IEntity {
|
|
107
|
-
\t@PrimaryGeneratedColumn()
|
|
108
|
-
\tpublic id!: number;
|
|
109
|
-
|
|
110
|
-
\t@Column()
|
|
111
|
-
\tpublic name!: string;
|
|
112
|
-
}
|
|
113
|
-
`;
|
|
114
|
-
const SAMPLE_REPOSITORY_TS = `import { injectable } from "@decohere/crucible/decorators";
|
|
115
|
-
import { injectUnitOfWork } from "@decohere/codex";
|
|
116
|
-
import { TypeOrmRepository, TypeOrmUnitOfWork } from "@decohere/codex-typeorm";
|
|
117
|
-
import { SampleEntity } from "../entities/sample.entity.js";
|
|
118
|
-
|
|
119
|
-
@injectable()
|
|
120
|
-
export class SampleEntityRepository extends TypeOrmRepository<SampleEntity> {
|
|
121
|
-
\tpublic constructor(@injectUnitOfWork() unitOfWork: TypeOrmUnitOfWork) {
|
|
122
|
-
\t\tsuper(unitOfWork, SampleEntity);
|
|
123
|
-
\t}
|
|
124
|
-
}
|
|
125
|
-
`;
|
|
126
|
-
async function getOptions(_workspace, cliOptions) {
|
|
127
|
-
if (cliOptions.databaseProvider != null) return {};
|
|
128
|
-
const choices = [
|
|
129
|
-
{
|
|
130
|
-
label: "none"
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
label: "postgres/typeorm"
|
|
134
|
-
}
|
|
135
|
-
];
|
|
136
|
-
const selected = await (0, _prompt.pick)("\n Database: ", choices, (c)=>c.label);
|
|
137
|
-
return {
|
|
138
|
-
databaseProvider: selected?.label ?? "none"
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
function scaffold(workspace, options) {
|
|
142
|
-
if (options.databaseProvider !== "postgres/typeorm") return;
|
|
143
|
-
const name = workspace.name;
|
|
144
|
-
const ident = toSqlIdentFragment(name);
|
|
145
|
-
const apiProjects = workspace.getProjects();
|
|
146
|
-
const apiNames = apiProjects.map((project)=>(0, _apiname.apiNameFromProjectDir)(project.dir));
|
|
147
|
-
// Container init superuser — never reused as an API runtime role.
|
|
148
|
-
const postgresSuperuser = "postgres";
|
|
149
|
-
const postgresPassword = passwordOrExisting(workspace, "POSTGRES_PASSWORD");
|
|
150
|
-
const bootstrapUser = "decohere_bootstrap";
|
|
151
|
-
const bootstrapPassword = passwordOrExisting(workspace, "DB_ADMIN_PASSWORD", [
|
|
152
|
-
"POSTGRES_PASSWORD"
|
|
153
|
-
]);
|
|
154
|
-
const devContainer = workspace.getModel(_const.WELL_KNOWN_FILES.DEVCONTAINER_JSON);
|
|
155
|
-
const compose = workspace.getModel(_const.WELL_KNOWN_FILES.DOCKER_COMPOSE);
|
|
156
|
-
const networkKey = name;
|
|
157
|
-
const volumeName = `${name}-postgres-data`;
|
|
158
|
-
if (compose) {
|
|
159
|
-
// One shared instance. Each API owns a database on it (created at bootstrap).
|
|
160
|
-
// Point `{PREFIX}_DB_HOST` / `{PREFIX}_DB_PORT` at another server to split later.
|
|
161
|
-
compose.addService("postgres", {
|
|
162
|
-
image: "postgres:16",
|
|
163
|
-
container_name: `samples-${name}-postgres`,
|
|
164
|
-
restart: "unless-stopped",
|
|
165
|
-
ports: [
|
|
166
|
-
"127.0.0.1:5433:5432"
|
|
167
|
-
],
|
|
168
|
-
volumes: [
|
|
169
|
-
`${volumeName}:/var/lib/postgresql/data`,
|
|
170
|
-
"../.devcontainer/postgres-init:/docker-entrypoint-initdb.d:ro"
|
|
171
|
-
],
|
|
172
|
-
networks: [
|
|
173
|
-
{
|
|
174
|
-
[networkKey]: {
|
|
175
|
-
aliases: [
|
|
176
|
-
"postgres"
|
|
177
|
-
]
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
],
|
|
181
|
-
healthcheck: {
|
|
182
|
-
test: [
|
|
183
|
-
"CMD-SHELL",
|
|
184
|
-
`pg_isready -U ${postgresSuperuser}`
|
|
185
|
-
],
|
|
186
|
-
interval: "2s",
|
|
187
|
-
timeout: "5s",
|
|
188
|
-
retries: 15
|
|
189
|
-
}
|
|
190
|
-
}).addEnvFile("postgres", "../.env").addVolume(volumeName);
|
|
191
|
-
compose.addService("adminer", {
|
|
192
|
-
image: "adminer",
|
|
193
|
-
profiles: [
|
|
194
|
-
"tools"
|
|
195
|
-
],
|
|
196
|
-
ports: [
|
|
197
|
-
"127.0.0.1:8081:8080"
|
|
198
|
-
],
|
|
199
|
-
networks: [
|
|
200
|
-
networkKey
|
|
201
|
-
]
|
|
202
|
-
});
|
|
203
|
-
workspace.addFile({
|
|
204
|
-
files: ()=>[
|
|
205
|
-
{
|
|
206
|
-
filePath: ".devcontainer/postgres-init/01-create-bootstrap-role.sh",
|
|
207
|
-
content: POSTGRES_INIT_BOOTSTRAP_SH
|
|
208
|
-
}
|
|
209
|
-
]
|
|
210
|
-
});
|
|
211
|
-
compose.addEnvFile("devcontainer", "../.env");
|
|
212
|
-
}
|
|
213
|
-
devContainer?.addExtension("mtxr.sqltools");
|
|
214
|
-
workspace.getModel(_const.WELL_KNOWN_FILES.PACKAGE_JSON)?.addDependency("@decohere/codex", _version.CREATE_VERSION).addDependency("typeorm", "^0.3.28").addDependency("@decohere/codex-typeorm", _version.CREATE_VERSION).addScript("db:up", "docker compose -f .devcontainer/docker-compose.yml up -d postgres").addScript("db:down", "docker compose -f .devcontainer/docker-compose.yml down").addScript("db:reset", "docker compose -f .devcontainer/docker-compose.yml down -v && docker compose -f .devcontainer/docker-compose.yml up -d postgres");
|
|
215
|
-
writeDatabaseConfig(workspace, apiNames);
|
|
216
|
-
for (const project of apiProjects){
|
|
217
|
-
wireApiDatabase(project);
|
|
218
|
-
}
|
|
219
|
-
const env = workspace.getModel(_const.WELL_KNOWN_FILES.ENV_FILE);
|
|
220
|
-
env?.addEntry("POSTGRES_DB", ident).addEntry("POSTGRES_USER", postgresSuperuser).addEntry("POSTGRES_PASSWORD", postgresPassword).addEntry("DB_ADMIN_USER", bootstrapUser).addEntry("DB_ADMIN_PASSWORD", bootstrapPassword);
|
|
221
|
-
for (const apiName of apiNames){
|
|
222
|
-
writeApiDatabaseEnv(workspace, ident, apiName);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
function writeDatabaseConfig(workspace, apiNames) {
|
|
226
|
-
const config = workspace.getModel(_const.WELL_KNOWN_FILES.CONFIG_YAML);
|
|
227
|
-
const devConfig = workspace.getModel(_const.WELL_KNOWN_FILES.CONFIG_DEV_YAML);
|
|
228
|
-
const pending = apiNames.filter((apiName)=>!config?.hasDataSource(apiName));
|
|
229
|
-
if (pending.length === 0) return;
|
|
230
|
-
if (config?.hasDataSources()) {
|
|
231
|
-
for (const apiName of pending){
|
|
232
|
-
config.appendDataSource(renderBaseDataSource(apiName));
|
|
233
|
-
devConfig?.appendDataSource(renderDevDataSource(apiName));
|
|
234
|
-
}
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
config?.addSection(renderDatabaseSection(pending, renderBaseDataSource));
|
|
238
|
-
devConfig?.addSection(renderDatabaseSection(pending, renderDevDataSource));
|
|
239
|
-
}
|
|
240
|
-
function writeApiDatabaseEnv(workspace, ident, apiName) {
|
|
241
|
-
const prefix = (0, _apiname.apiEnvPrefix)(apiName);
|
|
242
|
-
const sqlApi = toSqlIdentFragment(apiName);
|
|
243
|
-
workspace.getModel(_const.WELL_KNOWN_FILES.ENV_FILE)?.addEntry(`${prefix}_DB_HOST`, "postgres").addEntry(`${prefix}_DB_PORT`, "5432").addEntry(`${prefix}_DB_NAME`, `${ident}_${sqlApi}_dev`).addEntry(`${prefix}_DB_USER`, `${ident}_${sqlApi}_app`).addEntry(`${prefix}_DB_PASSWORD`, passwordOrExisting(workspace, `${prefix}_DB_PASSWORD`)).addEntry(`${prefix}_DB_MIGRATE_USER`, `${ident}_${sqlApi}_migrate`).addEntry(`${prefix}_DB_MIGRATE_PASSWORD`, passwordOrExisting(workspace, `${prefix}_DB_MIGRATE_PASSWORD`));
|
|
244
|
-
}
|
|
245
|
-
function wireApiDatabase(project) {
|
|
246
|
-
const apiName = (0, _apiname.apiNameFromProjectDir)(project.dir);
|
|
247
|
-
project.getModel(_const.WELL_KNOWN_FILES.MAIN_TS)?.setDataSourceName(apiName).addSideEffectImport("@decohere/codex-typeorm").addEntity({
|
|
248
|
-
className: "SampleEntity",
|
|
249
|
-
importPath: "./entities/sample.entity.js"
|
|
250
|
-
}).addRepository({
|
|
251
|
-
className: "SampleEntityRepository",
|
|
252
|
-
importPath: "./repositories/sample.repository.js"
|
|
253
|
-
});
|
|
254
|
-
project.getModel(_const.WELL_KNOWN_FILES.API_PACKAGE_JSON)?.addDependency("@decohere/codex", _version.CREATE_VERSION).addDependency("@decohere/codex-typeorm", _version.CREATE_VERSION);
|
|
255
|
-
project.addFile({
|
|
256
|
-
files: ()=>[
|
|
257
|
-
{
|
|
258
|
-
filePath: "src/entities/sample.entity.ts",
|
|
259
|
-
content: SAMPLE_ENTITY_TS
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
filePath: "src/repositories/sample.repository.ts",
|
|
263
|
-
content: SAMPLE_REPOSITORY_TS
|
|
264
|
-
}
|
|
265
|
-
]
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
const DatabaseFeature = {
|
|
269
|
-
getOptions,
|
|
270
|
-
scaffold
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL2ZlYXR1cmVzL2RhdGFiYXNlLmZlYXR1cmUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmFuZG9tQnl0ZXMgfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB7IHJlYWRGaWxlU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgcGljayB9IGZyb20gXCIuLi8uLi9kb21haW4vcHJvbXB0LmpzXCI7XG5pbXBvcnQgdHlwZSB7IERvY2tlckNvbXBvc2UgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL2NvbXBvc2UubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgQ29uZmlnWWFtbCB9IGZyb20gXCIuLi8uLi9tb2RlbHMvY29uZmlnLXlhbWwubW9kZWwuanNcIjtcbmltcG9ydCB7IFdFTExfS05PV05fRklMRVMgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL2NvbnN0LmpzXCI7XG5pbXBvcnQgdHlwZSB7IERldkNvbnRhaW5lciB9IGZyb20gXCIuLi8uLi9tb2RlbHMvZGV2LWNvbnRhaW5lci5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBFbnZGaWxlIH0gZnJvbSBcIi4uLy4uL21vZGVscy9lbnYtZmlsZS5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBQYWNrYWdlSnNvbiB9IGZyb20gXCIuLi8uLi9tb2RlbHMvcGFja2FnZS1qc29uLm1vZGVsLmpzXCI7XG5pbXBvcnQgdHlwZSB7IFByb2plY3RTY2FmZm9sZCwgV29ya3NwYWNlU2NhZmZvbGQgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL3Byb2plY3QubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgRmVhdHVyZSB9IGZyb20gXCIuLi8uLi9zZXJ2aWNlcy9zY2FmZm9sZC5zZXJ2aWNlLmpzXCI7XG5pbXBvcnQgeyBDUkVBVEVfVkVSU0lPTiB9IGZyb20gXCIuLi8uLi92ZXJzaW9uLmpzXCI7XG5pbXBvcnQgeyBhcGlFbnZQcmVmaXgsIGFwaU5hbWVGcm9tUHJvamVjdERpciB9IGZyb20gXCIuLi9hcGktbmFtZS5qc1wiO1xuaW1wb3J0IHR5cGUgeyBBcGlQYWNrYWdlSnNvbiB9IGZyb20gXCIuLi9tb2RlbHMvYXBpLXBhY2thZ2UtanNvbi5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBNYWluU291cmNlRmlsZSB9IGZyb20gXCIuLi9tb2RlbHMvbWFpbi1zb3VyY2UtZmlsZS5tb2RlbC5qc1wiO1xuXG5leHBvcnQgdHlwZSBEYXRhYmFzZU9wdGlvbnMgPSB7XG5cdGRhdGFiYXNlUHJvdmlkZXI/OiBcIm5vbmVcIiB8IFwicG9zdGdyZXMvdHlwZW9ybVwiO1xufTtcblxuLyoqIFJlYWQgYSBzaW5nbGUgS0VZPSBmcm9tIGFuIGV4aXN0aW5nIHRhcmdldCBgLmVudmAgKGlmIGFueSkuICovXG5mdW5jdGlvbiByZWFkRXhpc3RpbmdFbnZWYWx1ZSh3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLCBrZXk6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG5cdHRyeSB7XG5cdFx0Y29uc3QgcmF3ID0gcmVhZEZpbGVTeW5jKGpvaW4od29ya3NwYWNlLnRhcmdldERpciwgXCIuZW52XCIpLCBcInV0ZjhcIik7XG5cdFx0Y29uc3QgbGluZSA9IHJhdy5zcGxpdChcIlxcblwiKS5maW5kKChsKSA9PiBsLnN0YXJ0c1dpdGgoYCR7a2V5fT1gKSk7XG5cdFx0Y29uc3QgdmFsdWUgPSBsaW5lPy5zbGljZShrZXkubGVuZ3RoICsgMSkudHJpbSgpO1xuXHRcdHJldHVybiB2YWx1ZSB8fCB1bmRlZmluZWQ7XG5cdH0gY2F0Y2gge1xuXHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdH1cbn1cblxuZnVuY3Rpb24gcmFuZG9tUGFzc3dvcmQoKTogc3RyaW5nIHtcblx0cmV0dXJuIHJhbmRvbUJ5dGVzKDE2KS50b1N0cmluZyhcImhleFwiKTtcbn1cblxuLyoqIFNhZmUgUG9zdGdyZXMgaWRlbnRpZmllciBmcmFnbWVudCBmcm9tIHRoZSBwcm9qZWN0IG5hbWUuICovXG5mdW5jdGlvbiB0b1NxbElkZW50RnJhZ21lbnQobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcblx0Y29uc3QgY2xlYW5lZCA9IG5hbWUucmVwbGFjZSgvW15BLVphLXowLTlfXS9nLCBcIl9cIikucmVwbGFjZSgvXihbXkEtWmEtel9dKS8sIFwicF8kMVwiKTtcblx0cmV0dXJuIGNsZWFuZWQubGVuZ3RoID4gMCA/IGNsZWFuZWQuc2xpY2UoMCwgNDApIDogXCJhcHBcIjtcbn1cblxuZnVuY3Rpb24gcGFzc3dvcmRPckV4aXN0aW5nKFxuXHR3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLFxuXHRrZXk6IHN0cmluZyxcblx0ZmFsbGJhY2tFeGlzdGluZ0tleXM6IHN0cmluZ1tdID0gW10sXG4pOiBzdHJpbmcge1xuXHRjb25zdCBleGlzdGluZyA9IHJlYWRFeGlzdGluZ0VudlZhbHVlKHdvcmtzcGFjZSwga2V5KTtcblx0aWYgKGV4aXN0aW5nKSByZXR1cm4gZXhpc3Rpbmc7XG5cdGZvciAoY29uc3QgYWx0IG9mIGZhbGxiYWNrRXhpc3RpbmdLZXlzKSB7XG5cdFx0Y29uc3QgdiA9IHJlYWRFeGlzdGluZ0VudlZhbHVlKHdvcmtzcGFjZSwgYWx0KTtcblx0XHRpZiAodikgcmV0dXJuIHY7XG5cdH1cblx0cmV0dXJuIHJhbmRvbVBhc3N3b3JkKCk7XG59XG5cbi8vIFByb2R1Y3Rpb246IHJ1bnRpbWUgYXBwIHJvbGUgb25seSDigJQgbm8gYm9vdHN0cmFwLCBubyBhZG1pbi9taWdyYXRlIHNlY3JldHMgcmVxdWlyZWQuXG5mdW5jdGlvbiByZW5kZXJCYXNlRGF0YVNvdXJjZShhcGlOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuXHRjb25zdCBwID0gYXBpRW52UHJlZml4KGFwaU5hbWUpO1xuXHRyZXR1cm4gW1xuXHRcdGAgICAgLSBuYW1lOiAke2FwaU5hbWV9YCxcblx0XHRgICAgICAgcHJvdmlkZXI6IHBvc3RncmVzYCxcblx0XHRgICAgICAgaG9zdDogXFwkeyR7cH1fREJfSE9TVH1gLFxuXHRcdGAgICAgICBwb3J0OiBcXCR7JHtwfV9EQl9QT1JUfWAsXG5cdFx0YCAgICAgIGRhdGFiYXNlOiBcXCR7JHtwfV9EQl9OQU1FfWAsXG5cdFx0YCAgICAgIHVzZXJuYW1lOiBcXCR7JHtwfV9EQl9VU0VSfWAsXG5cdFx0YCAgICAgIHBhc3N3b3JkOiBcXCR7JHtwfV9EQl9QQVNTV09SRH1gLFxuXHRcdGAgICAgICBzeW5jaHJvbml6ZTogZmFsc2VgLFxuXHRcdGAgICAgICBzZWVkOiBmYWxzZWAsXG5cdFx0YCAgICAgIGJvb3RzdHJhcDogZmFsc2VgLFxuXHRdLmpvaW4oXCJcXG5cIik7XG59XG5cbi8vIERldiBvdmVybGF5IChtZXJnZWQgYnkgbGlzdCBpbmRleCBvbnRvIGNvbmZpZy55YW1sKS4gRW5hYmxlIGJvb3RzdHJhcCArIG1pZ3JhdGUgcm9sZS5cbmZ1bmN0aW9uIHJlbmRlckRldkRhdGFTb3VyY2UoYXBpTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcblx0Y29uc3QgcCA9IGFwaUVudlByZWZpeChhcGlOYW1lKTtcblx0cmV0dXJuIFtcblx0XHRgICAgIC0gbmFtZTogJHthcGlOYW1lfWAsXG5cdFx0YCAgICAgIHN5bmNocm9uaXplOiB0cnVlYCxcblx0XHRgICAgICAgc2VlZDogdHJ1ZWAsXG5cdFx0YCAgICAgIGJvb3RzdHJhcDogdHJ1ZWAsXG5cdFx0YCAgICAgIGFkbWluVXNlcjogXFwke0RCX0FETUlOX1VTRVJ9YCxcblx0XHRgICAgICAgYWRtaW5QYXNzd29yZDogXFwke0RCX0FETUlOX1BBU1NXT1JEfWAsXG5cdFx0YCAgICAgIG1pZ3JhdGVVc2VybmFtZTogXFwkeyR7cH1fREJfTUlHUkFURV9VU0VSfWAsXG5cdFx0YCAgICAgIG1pZ3JhdGVQYXNzd29yZDogXFwkeyR7cH1fREJfTUlHUkFURV9QQVNTV09SRH1gLFxuXHRdLmpvaW4oXCJcXG5cIik7XG59XG5cbmZ1bmN0aW9uIHJlbmRlckRhdGFiYXNlU2VjdGlvbihcblx0YXBpTmFtZXM6IHJlYWRvbmx5IHN0cmluZ1tdLFxuXHRpdGVtczogKG5hbWU6IHN0cmluZykgPT4gc3RyaW5nLFxuKTogc3RyaW5nIHtcblx0cmV0dXJuIGBkYXRhYmFzZTpcXG4gIGRhdGFTb3VyY2VzOlxcbiR7YXBpTmFtZXMubWFwKGl0ZW1zKS5qb2luKFwiXFxuXCIpfVxcbmA7XG59XG5cbi8qKiBSdW5zIG9uY2Ugb24gZmlyc3QgUG9zdGdyZXMgdm9sdW1lIGluaXQg4oCUIGNyZWF0ZXMgcmVzdHJpY3RlZCBib290c3RyYXAgcm9sZSAobm90IHN1cGVydXNlcikuICovXG5jb25zdCBQT1NUR1JFU19JTklUX0JPT1RTVFJBUF9TSCA9IGAjIS9iaW4vYmFzaFxuc2V0IC1ldW8gcGlwZWZhaWxcbiMgQ29udGFpbmVyIHN1cGVydXNlciAoUE9TVEdSRVNfVVNFUikgY3JlYXRlcyBhIHJlc3RyaWN0ZWQgcHJvdmlzaW9uZXIgcm9sZS5cbiMgQXBwL21pZ3JhdGUgcm9sZXMgYXJlIGNyZWF0ZWQgbGF0ZXIgYnkgY29kZXgtdHlwZW9ybSBwcmVwYXJlRGF0YWJhc2UgKGRldiBib290c3RyYXApLlxuOiBcIlxcJHtEQl9BRE1JTl9VU0VSOj9EQl9BRE1JTl9VU0VSIGlzIHJlcXVpcmVkfVwiXG46IFwiXFwke0RCX0FETUlOX1BBU1NXT1JEOj9EQl9BRE1JTl9QQVNTV09SRCBpcyByZXF1aXJlZH1cIlxuXG5wc3FsIC12IE9OX0VSUk9SX1NUT1A9MSAtLXVzZXJuYW1lIFwiJFBPU1RHUkVTX1VTRVJcIiAtLWRibmFtZSBcIiRQT1NUR1JFU19EQlwiIFxcXFxcblxcdC0tc2V0PWJvb3RzdHJhcF91c2VyPVwiJERCX0FETUlOX1VTRVJcIiBcXFxcXG5cXHQtLXNldD1ib290c3RyYXBfcGFzc3dvcmQ9XCIkREJfQURNSU5fUEFTU1dPUkRcIiA8PCdFT1NRTCdcblNFTEVDVCBmb3JtYXQoXG5cXHQnQ1JFQVRFIFJPTEUgJUkgTE9HSU4gUEFTU1dPUkQgJUwgQ1JFQVRFREIgQ1JFQVRFUk9MRSBOT1NVUEVSVVNFUiBOT0JZUEFTU1JMUycsXG5cXHQ6J2Jvb3RzdHJhcF91c2VyJyxcblxcdDonYm9vdHN0cmFwX3Bhc3N3b3JkJ1xuKVxuV0hFUkUgTk9UIEVYSVNUUyAoXG5cXHRTRUxFQ1QgMSBGUk9NIHBnX2NhdGFsb2cucGdfcm9sZXMgV0hFUkUgcm9sbmFtZSA9IDonYm9vdHN0cmFwX3VzZXInXG4pXFxcXGdleGVjXG5cbkdSQU5UIEFMTCBPTiBTQ0hFTUEgcHVibGljIFRPIDpcImJvb3RzdHJhcF91c2VyXCI7XG5FT1NRTFxuXG5wc3FsIC12IE9OX0VSUk9SX1NUT1A9MSAtLXVzZXJuYW1lIFwiJFBPU1RHUkVTX1VTRVJcIiAtLWRibmFtZSBcIiRQT1NUR1JFU19EQlwiIFxcXFxcblxcdC1jIFwiR1JBTlQgQUxMIFBSSVZJTEVHRVMgT04gREFUQUJBU0UgXFxcXFwiJFBPU1RHUkVTX0RCXFxcXFwiIFRPIFxcXFxcIiREQl9BRE1JTl9VU0VSXFxcXFwiXCJcbmA7XG5cbmNvbnN0IFNBTVBMRV9FTlRJVFlfVFMgPSBgaW1wb3J0IHsgQ29sdW1uLCBFbnRpdHksIFByaW1hcnlHZW5lcmF0ZWRDb2x1bW4gfSBmcm9tIFwidHlwZW9ybVwiO1xuaW1wb3J0IHR5cGUgeyBFbnRpdHkgYXMgSUVudGl0eSB9IGZyb20gXCJAZGVjb2hlcmUvY29kZXhcIjtcblxuQEVudGl0eSgpXG5leHBvcnQgY2xhc3MgU2FtcGxlRW50aXR5IGltcGxlbWVudHMgSUVudGl0eSB7XG5cXHRAUHJpbWFyeUdlbmVyYXRlZENvbHVtbigpXG5cXHRwdWJsaWMgaWQhOiBudW1iZXI7XG5cblxcdEBDb2x1bW4oKVxuXFx0cHVibGljIG5hbWUhOiBzdHJpbmc7XG59XG5gO1xuXG5jb25zdCBTQU1QTEVfUkVQT1NJVE9SWV9UUyA9IGBpbXBvcnQgeyBpbmplY3RhYmxlIH0gZnJvbSBcIkBkZWNvaGVyZS9jcnVjaWJsZS9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBpbmplY3RVbml0T2ZXb3JrIH0gZnJvbSBcIkBkZWNvaGVyZS9jb2RleFwiO1xuaW1wb3J0IHsgVHlwZU9ybVJlcG9zaXRvcnksIFR5cGVPcm1Vbml0T2ZXb3JrIH0gZnJvbSBcIkBkZWNvaGVyZS9jb2RleC10eXBlb3JtXCI7XG5pbXBvcnQgeyBTYW1wbGVFbnRpdHkgfSBmcm9tIFwiLi4vZW50aXRpZXMvc2FtcGxlLmVudGl0eS5qc1wiO1xuXG5AaW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgU2FtcGxlRW50aXR5UmVwb3NpdG9yeSBleHRlbmRzIFR5cGVPcm1SZXBvc2l0b3J5PFNhbXBsZUVudGl0eT4ge1xuXFx0cHVibGljIGNvbnN0cnVjdG9yKEBpbmplY3RVbml0T2ZXb3JrKCkgdW5pdE9mV29yazogVHlwZU9ybVVuaXRPZldvcmspIHtcblxcdFxcdHN1cGVyKHVuaXRPZldvcmssIFNhbXBsZUVudGl0eSk7XG5cXHR9XG59XG5gO1xuXG5hc3luYyBmdW5jdGlvbiBnZXRPcHRpb25zKFxuXHRfd29ya3NwYWNlOiBXb3Jrc3BhY2VTY2FmZm9sZCxcblx0Y2xpT3B0aW9uczogUGFydGlhbDxEYXRhYmFzZU9wdGlvbnM+LFxuKTogUHJvbWlzZTxQYXJ0aWFsPERhdGFiYXNlT3B0aW9ucz4+IHtcblx0aWYgKGNsaU9wdGlvbnMuZGF0YWJhc2VQcm92aWRlciAhPSBudWxsKSByZXR1cm4ge307XG5cblx0Y29uc3QgY2hvaWNlcyA9IFt7IGxhYmVsOiBcIm5vbmVcIiBhcyBjb25zdCB9LCB7IGxhYmVsOiBcInBvc3RncmVzL3R5cGVvcm1cIiBhcyBjb25zdCB9XTtcblx0Y29uc3Qgc2VsZWN0ZWQgPSBhd2FpdCBwaWNrKFwiXFxuICBEYXRhYmFzZTogXCIsIGNob2ljZXMsIChjKSA9PiBjLmxhYmVsKTtcblx0cmV0dXJuIHsgZGF0YWJhc2VQcm92aWRlcjogc2VsZWN0ZWQ/LmxhYmVsID8/IFwibm9uZVwiIH07XG59XG5cbmZ1bmN0aW9uIHNjYWZmb2xkKHdvcmtzcGFjZTogV29ya3NwYWNlU2NhZmZvbGQsIG9wdGlvbnM6IERhdGFiYXNlT3B0aW9ucyk6IHZvaWQge1xuXHRpZiAob3B0aW9ucy5kYXRhYmFzZVByb3ZpZGVyICE9PSBcInBvc3RncmVzL3R5cGVvcm1cIikgcmV0dXJuO1xuXG5cdGNvbnN0IG5hbWUgPSB3b3Jrc3BhY2UubmFtZTtcblx0Y29uc3QgaWRlbnQgPSB0b1NxbElkZW50RnJhZ21lbnQobmFtZSk7XG5cdGNvbnN0IGFwaVByb2plY3RzID0gd29ya3NwYWNlLmdldFByb2plY3RzKCk7XG5cdGNvbnN0IGFwaU5hbWVzID0gYXBpUHJvamVjdHMubWFwKChwcm9qZWN0KSA9PiBhcGlOYW1lRnJvbVByb2plY3REaXIocHJvamVjdC5kaXIpKTtcblx0Ly8gQ29udGFpbmVyIGluaXQgc3VwZXJ1c2VyIOKAlCBuZXZlciByZXVzZWQgYXMgYW4gQVBJIHJ1bnRpbWUgcm9sZS5cblx0Y29uc3QgcG9zdGdyZXNTdXBlcnVzZXIgPSBcInBvc3RncmVzXCI7XG5cdGNvbnN0IHBvc3RncmVzUGFzc3dvcmQgPSBwYXNzd29yZE9yRXhpc3Rpbmcod29ya3NwYWNlLCBcIlBPU1RHUkVTX1BBU1NXT1JEXCIpO1xuXHRjb25zdCBib290c3RyYXBVc2VyID0gXCJkZWNvaGVyZV9ib290c3RyYXBcIjtcblx0Y29uc3QgYm9vdHN0cmFwUGFzc3dvcmQgPSBwYXNzd29yZE9yRXhpc3Rpbmcod29ya3NwYWNlLCBcIkRCX0FETUlOX1BBU1NXT1JEXCIsIFtcblx0XHRcIlBPU1RHUkVTX1BBU1NXT1JEXCIsXG5cdF0pO1xuXG5cdGNvbnN0IGRldkNvbnRhaW5lciA9IHdvcmtzcGFjZS5nZXRNb2RlbDxEZXZDb250YWluZXI+KFdFTExfS05PV05fRklMRVMuREVWQ09OVEFJTkVSX0pTT04pO1xuXHRjb25zdCBjb21wb3NlID0gd29ya3NwYWNlLmdldE1vZGVsPERvY2tlckNvbXBvc2U+KFdFTExfS05PV05fRklMRVMuRE9DS0VSX0NPTVBPU0UpO1xuXG5cdGNvbnN0IG5ldHdvcmtLZXkgPSBuYW1lO1xuXHRjb25zdCB2b2x1bWVOYW1lID0gYCR7bmFtZX0tcG9zdGdyZXMtZGF0YWA7XG5cblx0aWYgKGNvbXBvc2UpIHtcblx0XHQvLyBPbmUgc2hhcmVkIGluc3RhbmNlLiBFYWNoIEFQSSBvd25zIGEgZGF0YWJhc2Ugb24gaXQgKGNyZWF0ZWQgYXQgYm9vdHN0cmFwKS5cblx0XHQvLyBQb2ludCBge1BSRUZJWH1fREJfSE9TVGAgLyBge1BSRUZJWH1fREJfUE9SVGAgYXQgYW5vdGhlciBzZXJ2ZXIgdG8gc3BsaXQgbGF0ZXIuXG5cdFx0Y29tcG9zZVxuXHRcdFx0LmFkZFNlcnZpY2UoXCJwb3N0Z3Jlc1wiLCB7XG5cdFx0XHRcdGltYWdlOiBcInBvc3RncmVzOjE2XCIsXG5cdFx0XHRcdGNvbnRhaW5lcl9uYW1lOiBgc2FtcGxlcy0ke25hbWV9LXBvc3RncmVzYCxcblx0XHRcdFx0cmVzdGFydDogXCJ1bmxlc3Mtc3RvcHBlZFwiLFxuXHRcdFx0XHRwb3J0czogW1wiMTI3LjAuMC4xOjU0MzM6NTQzMlwiXSxcblx0XHRcdFx0dm9sdW1lczogW1xuXHRcdFx0XHRcdGAke3ZvbHVtZU5hbWV9Oi92YXIvbGliL3Bvc3RncmVzcWwvZGF0YWAsXG5cdFx0XHRcdFx0XCIuLi8uZGV2Y29udGFpbmVyL3Bvc3RncmVzLWluaXQ6L2RvY2tlci1lbnRyeXBvaW50LWluaXRkYi5kOnJvXCIsXG5cdFx0XHRcdF0sXG5cdFx0XHRcdG5ldHdvcmtzOiBbeyBbbmV0d29ya0tleV06IHsgYWxpYXNlczogW1wicG9zdGdyZXNcIl0gfSB9XSxcblx0XHRcdFx0aGVhbHRoY2hlY2s6IHtcblx0XHRcdFx0XHR0ZXN0OiBbXCJDTUQtU0hFTExcIiwgYHBnX2lzcmVhZHkgLVUgJHtwb3N0Z3Jlc1N1cGVydXNlcn1gXSxcblx0XHRcdFx0XHRpbnRlcnZhbDogXCIyc1wiLFxuXHRcdFx0XHRcdHRpbWVvdXQ6IFwiNXNcIixcblx0XHRcdFx0XHRyZXRyaWVzOiAxNSxcblx0XHRcdFx0fSxcblx0XHRcdH0pXG5cdFx0XHQuYWRkRW52RmlsZShcInBvc3RncmVzXCIsIFwiLi4vLmVudlwiKVxuXHRcdFx0LmFkZFZvbHVtZSh2b2x1bWVOYW1lKTtcblxuXHRcdGNvbXBvc2UuYWRkU2VydmljZShcImFkbWluZXJcIiwge1xuXHRcdFx0aW1hZ2U6IFwiYWRtaW5lclwiLFxuXHRcdFx0cHJvZmlsZXM6IFtcInRvb2xzXCJdLFxuXHRcdFx0cG9ydHM6IFtcIjEyNy4wLjAuMTo4MDgxOjgwODBcIl0sXG5cdFx0XHRuZXR3b3JrczogW25ldHdvcmtLZXldLFxuXHRcdH0pO1xuXG5cdFx0d29ya3NwYWNlLmFkZEZpbGUoe1xuXHRcdFx0ZmlsZXM6ICgpID0+IFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGZpbGVQYXRoOiBcIi5kZXZjb250YWluZXIvcG9zdGdyZXMtaW5pdC8wMS1jcmVhdGUtYm9vdHN0cmFwLXJvbGUuc2hcIixcblx0XHRcdFx0XHRjb250ZW50OiBQT1NUR1JFU19JTklUX0JPT1RTVFJBUF9TSCxcblx0XHRcdFx0fSxcblx0XHRcdF0sXG5cdFx0fSk7XG5cblx0XHRjb21wb3NlLmFkZEVudkZpbGUoXCJkZXZjb250YWluZXJcIiwgXCIuLi8uZW52XCIpO1xuXHR9XG5cblx0ZGV2Q29udGFpbmVyPy5hZGRFeHRlbnNpb24oXCJtdHhyLnNxbHRvb2xzXCIpO1xuXG5cdHdvcmtzcGFjZVxuXHRcdC5nZXRNb2RlbDxQYWNrYWdlSnNvbj4oV0VMTF9LTk9XTl9GSUxFUy5QQUNLQUdFX0pTT04pXG5cdFx0Py5hZGREZXBlbmRlbmN5KFwiQGRlY29oZXJlL2NvZGV4XCIsIENSRUFURV9WRVJTSU9OKVxuXHRcdC5hZGREZXBlbmRlbmN5KFwidHlwZW9ybVwiLCBcIl4wLjMuMjhcIilcblx0XHQuYWRkRGVwZW5kZW5jeShcIkBkZWNvaGVyZS9jb2RleC10eXBlb3JtXCIsIENSRUFURV9WRVJTSU9OKVxuXHRcdC5hZGRTY3JpcHQoXCJkYjp1cFwiLCBcImRvY2tlciBjb21wb3NlIC1mIC5kZXZjb250YWluZXIvZG9ja2VyLWNvbXBvc2UueW1sIHVwIC1kIHBvc3RncmVzXCIpXG5cdFx0LmFkZFNjcmlwdChcImRiOmRvd25cIiwgXCJkb2NrZXIgY29tcG9zZSAtZiAuZGV2Y29udGFpbmVyL2RvY2tlci1jb21wb3NlLnltbCBkb3duXCIpXG5cdFx0LmFkZFNjcmlwdChcblx0XHRcdFwiZGI6cmVzZXRcIixcblx0XHRcdFwiZG9ja2VyIGNvbXBvc2UgLWYgLmRldmNvbnRhaW5lci9kb2NrZXItY29tcG9zZS55bWwgZG93biAtdiAmJiBkb2NrZXIgY29tcG9zZSAtZiAuZGV2Y29udGFpbmVyL2RvY2tlci1jb21wb3NlLnltbCB1cCAtZCBwb3N0Z3Jlc1wiLFxuXHRcdCk7XG5cblx0d3JpdGVEYXRhYmFzZUNvbmZpZyh3b3Jrc3BhY2UsIGFwaU5hbWVzKTtcblxuXHRmb3IgKGNvbnN0IHByb2plY3Qgb2YgYXBpUHJvamVjdHMpIHtcblx0XHR3aXJlQXBpRGF0YWJhc2UocHJvamVjdCk7XG5cdH1cblxuXHRjb25zdCBlbnYgPSB3b3Jrc3BhY2UuZ2V0TW9kZWw8RW52RmlsZT4oV0VMTF9LTk9XTl9GSUxFUy5FTlZfRklMRSk7XG5cdGVudlxuXHRcdD8uYWRkRW50cnkoXCJQT1NUR1JFU19EQlwiLCBpZGVudClcblx0XHQuYWRkRW50cnkoXCJQT1NUR1JFU19VU0VSXCIsIHBvc3RncmVzU3VwZXJ1c2VyKVxuXHRcdC5hZGRFbnRyeShcIlBPU1RHUkVTX1BBU1NXT1JEXCIsIHBvc3RncmVzUGFzc3dvcmQpXG5cdFx0LmFkZEVudHJ5KFwiREJfQURNSU5fVVNFUlwiLCBib290c3RyYXBVc2VyKVxuXHRcdC5hZGRFbnRyeShcIkRCX0FETUlOX1BBU1NXT1JEXCIsIGJvb3RzdHJhcFBhc3N3b3JkKTtcblxuXHRmb3IgKGNvbnN0IGFwaU5hbWUgb2YgYXBpTmFtZXMpIHtcblx0XHR3cml0ZUFwaURhdGFiYXNlRW52KHdvcmtzcGFjZSwgaWRlbnQsIGFwaU5hbWUpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHdyaXRlRGF0YWJhc2VDb25maWcod29ya3NwYWNlOiBXb3Jrc3BhY2VTY2FmZm9sZCwgYXBpTmFtZXM6IHJlYWRvbmx5IHN0cmluZ1tdKTogdm9pZCB7XG5cdGNvbnN0IGNvbmZpZyA9IHdvcmtzcGFjZS5nZXRNb2RlbDxDb25maWdZYW1sPihXRUxMX0tOT1dOX0ZJTEVTLkNPTkZJR19ZQU1MKTtcblx0Y29uc3QgZGV2Q29uZmlnID0gd29ya3NwYWNlLmdldE1vZGVsPENvbmZpZ1lhbWw+KFdFTExfS05PV05fRklMRVMuQ09ORklHX0RFVl9ZQU1MKTtcblx0Y29uc3QgcGVuZGluZyA9IGFwaU5hbWVzLmZpbHRlcigoYXBpTmFtZSkgPT4gIWNvbmZpZz8uaGFzRGF0YVNvdXJjZShhcGlOYW1lKSk7XG5cdGlmIChwZW5kaW5nLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuXG5cdGlmIChjb25maWc/Lmhhc0RhdGFTb3VyY2VzKCkpIHtcblx0XHRmb3IgKGNvbnN0IGFwaU5hbWUgb2YgcGVuZGluZykge1xuXHRcdFx0Y29uZmlnLmFwcGVuZERhdGFTb3VyY2UocmVuZGVyQmFzZURhdGFTb3VyY2UoYXBpTmFtZSkpO1xuXHRcdFx0ZGV2Q29uZmlnPy5hcHBlbmREYXRhU291cmNlKHJlbmRlckRldkRhdGFTb3VyY2UoYXBpTmFtZSkpO1xuXHRcdH1cblx0XHRyZXR1cm47XG5cdH1cblxuXHRjb25maWc/LmFkZFNlY3Rpb24ocmVuZGVyRGF0YWJhc2VTZWN0aW9uKHBlbmRpbmcsIHJlbmRlckJhc2VEYXRhU291cmNlKSk7XG5cdGRldkNvbmZpZz8uYWRkU2VjdGlvbihyZW5kZXJEYXRhYmFzZVNlY3Rpb24ocGVuZGluZywgcmVuZGVyRGV2RGF0YVNvdXJjZSkpO1xufVxuXG5mdW5jdGlvbiB3cml0ZUFwaURhdGFiYXNlRW52KFxuXHR3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLFxuXHRpZGVudDogc3RyaW5nLFxuXHRhcGlOYW1lOiBzdHJpbmcsXG4pOiB2b2lkIHtcblx0Y29uc3QgcHJlZml4ID0gYXBpRW52UHJlZml4KGFwaU5hbWUpO1xuXHRjb25zdCBzcWxBcGkgPSB0b1NxbElkZW50RnJhZ21lbnQoYXBpTmFtZSk7XG5cdHdvcmtzcGFjZVxuXHRcdC5nZXRNb2RlbDxFbnZGaWxlPihXRUxMX0tOT1dOX0ZJTEVTLkVOVl9GSUxFKVxuXHRcdD8uYWRkRW50cnkoYCR7cHJlZml4fV9EQl9IT1NUYCwgXCJwb3N0Z3Jlc1wiKVxuXHRcdC5hZGRFbnRyeShgJHtwcmVmaXh9X0RCX1BPUlRgLCBcIjU0MzJcIilcblx0XHQuYWRkRW50cnkoYCR7cHJlZml4fV9EQl9OQU1FYCwgYCR7aWRlbnR9XyR7c3FsQXBpfV9kZXZgKVxuXHRcdC5hZGRFbnRyeShgJHtwcmVmaXh9X0RCX1VTRVJgLCBgJHtpZGVudH1fJHtzcWxBcGl9X2FwcGApXG5cdFx0LmFkZEVudHJ5KGAke3ByZWZpeH1fREJfUEFTU1dPUkRgLCBwYXNzd29yZE9yRXhpc3Rpbmcod29ya3NwYWNlLCBgJHtwcmVmaXh9X0RCX1BBU1NXT1JEYCkpXG5cdFx0LmFkZEVudHJ5KGAke3ByZWZpeH1fREJfTUlHUkFURV9VU0VSYCwgYCR7aWRlbnR9XyR7c3FsQXBpfV9taWdyYXRlYClcblx0XHQuYWRkRW50cnkoXG5cdFx0XHRgJHtwcmVmaXh9X0RCX01JR1JBVEVfUEFTU1dPUkRgLFxuXHRcdFx0cGFzc3dvcmRPckV4aXN0aW5nKHdvcmtzcGFjZSwgYCR7cHJlZml4fV9EQl9NSUdSQVRFX1BBU1NXT1JEYCksXG5cdFx0KTtcbn1cblxuZnVuY3Rpb24gd2lyZUFwaURhdGFiYXNlKHByb2plY3Q6IFByb2plY3RTY2FmZm9sZCk6IHZvaWQge1xuXHRjb25zdCBhcGlOYW1lID0gYXBpTmFtZUZyb21Qcm9qZWN0RGlyKHByb2plY3QuZGlyKTtcblx0cHJvamVjdFxuXHRcdC5nZXRNb2RlbDxNYWluU291cmNlRmlsZT4oV0VMTF9LTk9XTl9GSUxFUy5NQUlOX1RTKVxuXHRcdD8uc2V0RGF0YVNvdXJjZU5hbWUoYXBpTmFtZSlcblx0XHQuYWRkU2lkZUVmZmVjdEltcG9ydChcIkBkZWNvaGVyZS9jb2RleC10eXBlb3JtXCIpXG5cdFx0LmFkZEVudGl0eSh7IGNsYXNzTmFtZTogXCJTYW1wbGVFbnRpdHlcIiwgaW1wb3J0UGF0aDogXCIuL2VudGl0aWVzL3NhbXBsZS5lbnRpdHkuanNcIiB9KVxuXHRcdC5hZGRSZXBvc2l0b3J5KHtcblx0XHRcdGNsYXNzTmFtZTogXCJTYW1wbGVFbnRpdHlSZXBvc2l0b3J5XCIsXG5cdFx0XHRpbXBvcnRQYXRoOiBcIi4vcmVwb3NpdG9yaWVzL3NhbXBsZS5yZXBvc2l0b3J5LmpzXCIsXG5cdFx0fSk7XG5cdHByb2plY3Rcblx0XHQuZ2V0TW9kZWw8QXBpUGFja2FnZUpzb24+KFdFTExfS05PV05fRklMRVMuQVBJX1BBQ0tBR0VfSlNPTilcblx0XHQ/LmFkZERlcGVuZGVuY3koXCJAZGVjb2hlcmUvY29kZXhcIiwgQ1JFQVRFX1ZFUlNJT04pXG5cdFx0LmFkZERlcGVuZGVuY3koXCJAZGVjb2hlcmUvY29kZXgtdHlwZW9ybVwiLCBDUkVBVEVfVkVSU0lPTik7XG5cdHByb2plY3QuYWRkRmlsZSh7XG5cdFx0ZmlsZXM6ICgpID0+IFtcblx0XHRcdHtcblx0XHRcdFx0ZmlsZVBhdGg6IFwic3JjL2VudGl0aWVzL3NhbXBsZS5lbnRpdHkudHNcIixcblx0XHRcdFx0Y29udGVudDogU0FNUExFX0VOVElUWV9UUyxcblx0XHRcdH0sXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcInNyYy9yZXBvc2l0b3JpZXMvc2FtcGxlLnJlcG9zaXRvcnkudHNcIixcblx0XHRcdFx0Y29udGVudDogU0FNUExFX1JFUE9TSVRPUllfVFMsXG5cdFx0XHR9LFxuXHRcdF0sXG5cdH0pO1xufVxuXG5leHBvcnQgY29uc3QgRGF0YWJhc2VGZWF0dXJlOiBGZWF0dXJlPERhdGFiYXNlT3B0aW9ucz4gPSB7IGdldE9wdGlvbnMsIHNjYWZmb2xkIH07XG4iXSwibmFtZXMiOlsiRGF0YWJhc2VGZWF0dXJlIiwicmVhZEV4aXN0aW5nRW52VmFsdWUiLCJ3b3Jrc3BhY2UiLCJrZXkiLCJyYXciLCJyZWFkRmlsZVN5bmMiLCJqb2luIiwidGFyZ2V0RGlyIiwibGluZSIsInNwbGl0IiwiZmluZCIsImwiLCJzdGFydHNXaXRoIiwidmFsdWUiLCJzbGljZSIsImxlbmd0aCIsInRyaW0iLCJ1bmRlZmluZWQiLCJyYW5kb21QYXNzd29yZCIsInJhbmRvbUJ5dGVzIiwidG9TdHJpbmciLCJ0b1NxbElkZW50RnJhZ21lbnQiLCJuYW1lIiwiY2xlYW5lZCIsInJlcGxhY2UiLCJwYXNzd29yZE9yRXhpc3RpbmciLCJmYWxsYmFja0V4aXN0aW5nS2V5cyIsImV4aXN0aW5nIiwiYWx0IiwidiIsInJlbmRlckJhc2VEYXRhU291cmNlIiwiYXBpTmFtZSIsInAiLCJhcGlFbnZQcmVmaXgiLCJyZW5kZXJEZXZEYXRhU291cmNlIiwicmVuZGVyRGF0YWJhc2VTZWN0aW9uIiwiYXBpTmFtZXMiLCJpdGVtcyIsIm1hcCIsIlBPU1RHUkVTX0lOSVRfQk9PVFNUUkFQX1NIIiwiU0FNUExFX0VOVElUWV9UUyIsIlNBTVBMRV9SRVBPU0lUT1JZX1RTIiwiZ2V0T3B0aW9ucyIsIl93b3Jrc3BhY2UiLCJjbGlPcHRpb25zIiwiZGF0YWJhc2VQcm92aWRlciIsImNob2ljZXMiLCJsYWJlbCIsInNlbGVjdGVkIiwicGljayIsImMiLCJzY2FmZm9sZCIsIm9wdGlvbnMiLCJpZGVudCIsImFwaVByb2plY3RzIiwiZ2V0UHJvamVjdHMiLCJwcm9qZWN0IiwiYXBpTmFtZUZyb21Qcm9qZWN0RGlyIiwiZGlyIiwicG9zdGdyZXNTdXBlcnVzZXIiLCJwb3N0Z3Jlc1Bhc3N3b3JkIiwiYm9vdHN0cmFwVXNlciIsImJvb3RzdHJhcFBhc3N3b3JkIiwiZGV2Q29udGFpbmVyIiwiZ2V0TW9kZWwiLCJXRUxMX0tOT1dOX0ZJTEVTIiwiREVWQ09OVEFJTkVSX0pTT04iLCJjb21wb3NlIiwiRE9DS0VSX0NPTVBPU0UiLCJuZXR3b3JrS2V5Iiwidm9sdW1lTmFtZSIsImFkZFNlcnZpY2UiLCJpbWFnZSIsImNvbnRhaW5lcl9uYW1lIiwicmVzdGFydCIsInBvcnRzIiwidm9sdW1lcyIsIm5ldHdvcmtzIiwiYWxpYXNlcyIsImhlYWx0aGNoZWNrIiwidGVzdCIsImludGVydmFsIiwidGltZW91dCIsInJldHJpZXMiLCJhZGRFbnZGaWxlIiwiYWRkVm9sdW1lIiwicHJvZmlsZXMiLCJhZGRGaWxlIiwiZmlsZXMiLCJmaWxlUGF0aCIsImNvbnRlbnQiLCJhZGRFeHRlbnNpb24iLCJQQUNLQUdFX0pTT04iLCJhZGREZXBlbmRlbmN5IiwiQ1JFQVRFX1ZFUlNJT04iLCJhZGRTY3JpcHQiLCJ3cml0ZURhdGFiYXNlQ29uZmlnIiwid2lyZUFwaURhdGFiYXNlIiwiZW52IiwiRU5WX0ZJTEUiLCJhZGRFbnRyeSIsIndyaXRlQXBpRGF0YWJhc2VFbnYiLCJjb25maWciLCJDT05GSUdfWUFNTCIsImRldkNvbmZpZyIsIkNPTkZJR19ERVZfWUFNTCIsInBlbmRpbmciLCJmaWx0ZXIiLCJoYXNEYXRhU291cmNlIiwiaGFzRGF0YVNvdXJjZXMiLCJhcHBlbmREYXRhU291cmNlIiwiYWRkU2VjdGlvbiIsInByZWZpeCIsInNxbEFwaSIsIk1BSU5fVFMiLCJzZXREYXRhU291cmNlTmFtZSIsImFkZFNpZGVFZmZlY3RJbXBvcnQiLCJhZGRFbnRpdHkiLCJjbGFzc05hbWUiLCJpbXBvcnRQYXRoIiwiYWRkUmVwb3NpdG9yeSIsIkFQSV9QQUNLQUdFX0pTT04iXSwibWFwcGluZ3MiOiI7Ozs7K0JBcVVhQTs7O2VBQUFBOzs7NEJBclVlO3dCQUNDOzBCQUNSO3dCQUNBO3VCQUdZO3lCQU1GO3lCQUNxQjtBQVFwRCxnRUFBZ0UsR0FDaEUsU0FBU0MscUJBQXFCQyxTQUE0QixFQUFFQyxHQUFXO0lBQ3RFLElBQUk7UUFDSCxNQUFNQyxNQUFNQyxJQUFBQSxvQkFBWSxFQUFDQyxJQUFBQSxjQUFJLEVBQUNKLFVBQVVLLFNBQVMsRUFBRSxTQUFTO1FBQzVELE1BQU1DLE9BQU9KLElBQUlLLEtBQUssQ0FBQyxNQUFNQyxJQUFJLENBQUMsQ0FBQ0MsSUFBTUEsRUFBRUMsVUFBVSxDQUFDLEdBQUdULElBQUksQ0FBQyxD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
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "FinalizeFeature", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return FinalizeFeature;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _nodefs = require("node:fs");
|
|
12
|
-
const _nodepath = require("node:path");
|
|
13
|
-
const _interop = require("@decohere/nexus/interop");
|
|
14
|
-
const _prompt = require("../../domain/prompt.js");
|
|
15
|
-
const _const = require("../../models/const.js");
|
|
16
|
-
const _biomeformat = require("./biome-format.js");
|
|
17
|
-
function readExistingEnvValue(workspace, key) {
|
|
18
|
-
try {
|
|
19
|
-
const raw = (0, _nodefs.readFileSync)((0, _nodepath.join)(workspace.targetDir, ".env"), "utf8");
|
|
20
|
-
const line = raw.split("\n").find((l)=>l.startsWith(`${key}=`));
|
|
21
|
-
const value = line?.slice(key.length + 1).trim();
|
|
22
|
-
return value || undefined;
|
|
23
|
-
} catch {
|
|
24
|
-
return undefined;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
// State resolved during scaffold(), consumed by finalize().
|
|
28
|
-
let _pm = null;
|
|
29
|
-
let _shouldInstall = true;
|
|
30
|
-
async function getOptions(_workspace, cliOptions) {
|
|
31
|
-
if (cliOptions.installDependencies != null) {
|
|
32
|
-
_shouldInstall = cliOptions.installDependencies === "yes";
|
|
33
|
-
}
|
|
34
|
-
return {};
|
|
35
|
-
}
|
|
36
|
-
async function scaffold(workspace, options) {
|
|
37
|
-
// Local scaffold default — production deploys must set NODE_ENV explicitly.
|
|
38
|
-
const nodeEnv = readExistingEnvValue(workspace, "NODE_ENV") ?? "dev";
|
|
39
|
-
workspace.getModel(_const.WELL_KNOWN_FILES.ENV_FILE)?.addEntry("NODE_ENV", nodeEnv);
|
|
40
|
-
if (process.env.DECOHERE_BUILDER === "1") {
|
|
41
|
-
_shouldInstall = false;
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
_pm = (0, _interop.detectPackageManager)(workspace.targetDir) ?? await (0, _interop.promptForPackageManager)();
|
|
45
|
-
if (options.installDependencies != null) {
|
|
46
|
-
_shouldInstall = options.installDependencies === "yes";
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
const answer = await (0, _prompt.ask)("\nInstall dependencies now? [yes/no] (yes): ", "yes");
|
|
50
|
-
_shouldInstall = answer.toLowerCase() !== "no";
|
|
51
|
-
}
|
|
52
|
-
async function finalize(workspace, options) {
|
|
53
|
-
const formatPaths = options.add ? workspace.getProjects().map((project)=>project.dir) : [
|
|
54
|
-
"."
|
|
55
|
-
];
|
|
56
|
-
(0, _biomeformat.formatScaffoldedFiles)(workspace.targetDir, formatPaths.length > 0 ? formatPaths : [
|
|
57
|
-
"."
|
|
58
|
-
]);
|
|
59
|
-
if (_shouldInstall) {
|
|
60
|
-
const pm = _pm;
|
|
61
|
-
console.log(`\nScaffolded ${workspace.name}. Installing dependencies...\n`);
|
|
62
|
-
await pm.install({
|
|
63
|
-
cwd: workspace.targetDir
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
const apiNames = workspace.getProjects().map((project)=>project.dir.replace(/^projects\//, ""));
|
|
67
|
-
console.log(`\nDone! ${_shouldInstall ? "Next" : "To get started:"} steps:\n`);
|
|
68
|
-
if (!options.add) {
|
|
69
|
-
console.log(` cd ${workspace.name}`);
|
|
70
|
-
}
|
|
71
|
-
if (!_shouldInstall) {
|
|
72
|
-
const pmName = _pm?.name ?? "pnpm";
|
|
73
|
-
console.log(` ${pmName} install`);
|
|
74
|
-
}
|
|
75
|
-
if (options.add && apiNames[0] != null) {
|
|
76
|
-
console.log(` pnpm run start:${apiNames[0]}`);
|
|
77
|
-
console.log(` docker build -f Dockerfile.${apiNames[0]} .`);
|
|
78
|
-
} else {
|
|
79
|
-
console.log(" code . # open in VS Code");
|
|
80
|
-
console.log(" # then: Reopen in Container\n");
|
|
81
|
-
}
|
|
82
|
-
// Drop readline's stdin hold so the CLI / container can exit.
|
|
83
|
-
(0, _prompt.closePrompt)();
|
|
84
|
-
}
|
|
85
|
-
const FinalizeFeature = {
|
|
86
|
-
getOptions,
|
|
87
|
-
scaffold,
|
|
88
|
-
finalize
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL2ZlYXR1cmVzL2ZpbmFsaXplLmZlYXR1cmUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmVhZEZpbGVTeW5jIH0gZnJvbSBcIm5vZGU6ZnNcIjtcbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgdHlwZSB7IFBhY2thZ2VNYW5hZ2VyIH0gZnJvbSBcIkBkZWNvaGVyZS9uZXh1cy9pbnRlcm9wXCI7XG5pbXBvcnQgeyBkZXRlY3RQYWNrYWdlTWFuYWdlciwgcHJvbXB0Rm9yUGFja2FnZU1hbmFnZXIgfSBmcm9tIFwiQGRlY29oZXJlL25leHVzL2ludGVyb3BcIjtcbmltcG9ydCB7IGFzaywgY2xvc2VQcm9tcHQgfSBmcm9tIFwiLi4vLi4vZG9tYWluL3Byb21wdC5qc1wiO1xuaW1wb3J0IHsgV0VMTF9LTk9XTl9GSUxFUyB9IGZyb20gXCIuLi8uLi9tb2RlbHMvY29uc3QuanNcIjtcbmltcG9ydCB0eXBlIHsgRW52RmlsZSB9IGZyb20gXCIuLi8uLi9tb2RlbHMvZW52LWZpbGUubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgV29ya3NwYWNlU2NhZmZvbGQgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL3Byb2plY3QubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgRmVhdHVyZSB9IGZyb20gXCIuLi8uLi9zZXJ2aWNlcy9zY2FmZm9sZC5zZXJ2aWNlLmpzXCI7XG5pbXBvcnQgeyBmb3JtYXRTY2FmZm9sZGVkRmlsZXMgfSBmcm9tIFwiLi9iaW9tZS1mb3JtYXQuanNcIjtcblxuZnVuY3Rpb24gcmVhZEV4aXN0aW5nRW52VmFsdWUod29ya3NwYWNlOiBXb3Jrc3BhY2VTY2FmZm9sZCwga2V5OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuXHR0cnkge1xuXHRcdGNvbnN0IHJhdyA9IHJlYWRGaWxlU3luYyhqb2luKHdvcmtzcGFjZS50YXJnZXREaXIsIFwiLmVudlwiKSwgXCJ1dGY4XCIpO1xuXHRcdGNvbnN0IGxpbmUgPSByYXcuc3BsaXQoXCJcXG5cIikuZmluZCgobCkgPT4gbC5zdGFydHNXaXRoKGAke2tleX09YCkpO1xuXHRcdGNvbnN0IHZhbHVlID0gbGluZT8uc2xpY2Uoa2V5Lmxlbmd0aCArIDEpLnRyaW0oKTtcblx0XHRyZXR1cm4gdmFsdWUgfHwgdW5kZWZpbmVkO1xuXHR9IGNhdGNoIHtcblx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHR9XG59XG5cbi8vIFN0YXRlIHJlc29sdmVkIGR1cmluZyBzY2FmZm9sZCgpLCBjb25zdW1lZCBieSBmaW5hbGl6ZSgpLlxubGV0IF9wbTogUGFja2FnZU1hbmFnZXIgfCBudWxsID0gbnVsbDtcbmxldCBfc2hvdWxkSW5zdGFsbCA9IHRydWU7XG5cbnR5cGUgRmluYWxpemVPcHRpb25zID0ge1xuXHRpbnN0YWxsRGVwZW5kZW5jaWVzPzogXCJ5ZXNcIiB8IFwibm9cIjtcblx0YWRkPzogYm9vbGVhbjtcbn07XG5cbmFzeW5jIGZ1bmN0aW9uIGdldE9wdGlvbnMoXG5cdF93b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLFxuXHRjbGlPcHRpb25zOiBQYXJ0aWFsPEZpbmFsaXplT3B0aW9ucz4sXG4pOiBQcm9taXNlPG9iamVjdD4ge1xuXHRpZiAoY2xpT3B0aW9ucy5pbnN0YWxsRGVwZW5kZW5jaWVzICE9IG51bGwpIHtcblx0XHRfc2hvdWxkSW5zdGFsbCA9IGNsaU9wdGlvbnMuaW5zdGFsbERlcGVuZGVuY2llcyA9PT0gXCJ5ZXNcIjtcblx0fVxuXHRyZXR1cm4ge307XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNjYWZmb2xkKFxuXHR3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLFxuXHRvcHRpb25zOiBGaW5hbGl6ZU9wdGlvbnMsXG4pOiBQcm9taXNlPHZvaWQ+IHtcblx0Ly8gTG9jYWwgc2NhZmZvbGQgZGVmYXVsdCDigJQgcHJvZHVjdGlvbiBkZXBsb3lzIG11c3Qgc2V0IE5PREVfRU5WIGV4cGxpY2l0bHkuXG5cdGNvbnN0IG5vZGVFbnYgPSByZWFkRXhpc3RpbmdFbnZWYWx1ZSh3b3Jrc3BhY2UsIFwiTk9ERV9FTlZcIikgPz8gXCJkZXZcIjtcblx0d29ya3NwYWNlLmdldE1vZGVsPEVudkZpbGU+KFdFTExfS05PV05fRklMRVMuRU5WX0ZJTEUpPy5hZGRFbnRyeShcIk5PREVfRU5WXCIsIG5vZGVFbnYpO1xuXG5cdGlmIChwcm9jZXNzLmVudi5ERUNPSEVSRV9CVUlMREVSID09PSBcIjFcIikge1xuXHRcdF9zaG91bGRJbnN0YWxsID0gZmFsc2U7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdF9wbSA9IGRldGVjdFBhY2thZ2VNYW5hZ2VyKHdvcmtzcGFjZS50YXJnZXREaXIpID8/IChhd2FpdCBwcm9tcHRGb3JQYWNrYWdlTWFuYWdlcigpKTtcblx0aWYgKG9wdGlvbnMuaW5zdGFsbERlcGVuZGVuY2llcyAhPSBudWxsKSB7XG5cdFx0X3Nob3VsZEluc3RhbGwgPSBvcHRpb25zLmluc3RhbGxEZXBlbmRlbmNpZXMgPT09IFwieWVzXCI7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0Y29uc3QgYW5zd2VyID0gYXdhaXQgYXNrKFwiXFxuSW5zdGFsbCBkZXBlbmRlbmNpZXMgbm93PyBbeWVzL25vXSAoeWVzKTogXCIsIFwieWVzXCIpO1xuXHRfc2hvdWxkSW5zdGFsbCA9IGFuc3dlci50b0xvd2VyQ2FzZSgpICE9PSBcIm5vXCI7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpbmFsaXplKFxuXHR3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLFxuXHRvcHRpb25zOiBGaW5hbGl6ZU9wdGlvbnMsXG4pOiBQcm9taXNlPHZvaWQ+IHtcblx0Y29uc3QgZm9ybWF0UGF0aHMgPSBvcHRpb25zLmFkZFxuXHRcdD8gd29ya3NwYWNlLmdldFByb2plY3RzKCkubWFwKChwcm9qZWN0KSA9PiBwcm9qZWN0LmRpcilcblx0XHQ6IFtcIi5cIl07XG5cdGZvcm1hdFNjYWZmb2xkZWRGaWxlcyh3b3Jrc3BhY2UudGFyZ2V0RGlyLCBmb3JtYXRQYXRocy5sZW5ndGggPiAwID8gZm9ybWF0UGF0aHMgOiBbXCIuXCJdKTtcblxuXHRpZiAoX3Nob3VsZEluc3RhbGwpIHtcblx0XHRjb25zdCBwbSA9IF9wbSE7XG5cdFx0Y29uc29sZS5sb2coYFxcblNjYWZmb2xkZWQgJHt3b3Jrc3BhY2UubmFtZX0uIEluc3RhbGxpbmcgZGVwZW5kZW5jaWVzLi4uXFxuYCk7XG5cdFx0YXdhaXQgcG0uaW5zdGFsbCh7IGN3ZDogd29ya3NwYWNlLnRhcmdldERpciB9KTtcblx0fVxuXG5cdGNvbnN0IGFwaU5hbWVzID0gd29ya3NwYWNlXG5cdFx0LmdldFByb2plY3RzKClcblx0XHQubWFwKChwcm9qZWN0KSA9PiBwcm9qZWN0LmRpci5yZXBsYWNlKC9ecHJvamVjdHNcXC8vLCBcIlwiKSk7XG5cdGNvbnNvbGUubG9nKGBcXG5Eb25lISAke19zaG91bGRJbnN0YWxsID8gXCJOZXh0XCIgOiBcIlRvIGdldCBzdGFydGVkOlwifSBzdGVwczpcXG5gKTtcblx0aWYgKCFvcHRpb25zLmFkZCkge1xuXHRcdGNvbnNvbGUubG9nKGAgIGNkICR7d29ya3NwYWNlLm5hbWV9YCk7XG5cdH1cblx0aWYgKCFfc2hvdWxkSW5zdGFsbCkge1xuXHRcdGNvbnN0IHBtTmFtZSA9IF9wbT8ubmFtZSA/PyBcInBucG1cIjtcblx0XHRjb25zb2xlLmxvZyhgICAke3BtTmFtZX0gaW5zdGFsbGApO1xuXHR9XG5cdGlmIChvcHRpb25zLmFkZCAmJiBhcGlOYW1lc1swXSAhPSBudWxsKSB7XG5cdFx0Y29uc29sZS5sb2coYCAgcG5wbSBydW4gc3RhcnQ6JHthcGlOYW1lc1swXX1gKTtcblx0XHRjb25zb2xlLmxvZyhgICBkb2NrZXIgYnVpbGQgLWYgRG9ja2VyZmlsZS4ke2FwaU5hbWVzWzBdfSAuYCk7XG5cdH0gZWxzZSB7XG5cdFx0Y29uc29sZS5sb2coXCIgIGNvZGUgLiAgICAgICAgICMgb3BlbiBpbiBWUyBDb2RlXCIpO1xuXHRcdGNvbnNvbGUubG9nKFwiICAgICAgICAgICAgICAgICAjIHRoZW46IFJlb3BlbiBpbiBDb250YWluZXJcXG5cIik7XG5cdH1cblxuXHQvLyBEcm9wIHJlYWRsaW5lJ3Mgc3RkaW4gaG9sZCBzbyB0aGUgQ0xJIC8gY29udGFpbmVyIGNhbiBleGl0LlxuXHRjbG9zZVByb21wdCgpO1xufVxuXG5leHBvcnQgY29uc3QgRmluYWxpemVGZWF0dXJlOiBGZWF0dXJlID0geyBnZXRPcHRpb25zLCBzY2FmZm9sZCwgZmluYWxpemUgfTtcbiJdLCJuYW1lcyI6WyJGaW5hbGl6ZUZlYXR1cmUiLCJyZWFkRXhpc3RpbmdFbnZWYWx1ZSIsIndvcmtzcGFjZSIsImtleSIsInJhdyIsInJlYWRGaWxlU3luYyIsImpvaW4iLCJ0YXJnZXREaXIiLCJsaW5lIiwic3BsaXQiLCJmaW5kIiwibCIsInN0YXJ0c1dpdGgiLCJ2YWx1ZSIsInNsaWNlIiwibGVuZ3RoIiwidHJpbSIsInVuZGVmaW5lZCIsIl9wbSIsIl9zaG91bGRJbnN0YWxsIiwiZ2V0T3B0aW9ucyIsIl93b3Jrc3BhY2UiLCJjbGlPcHRpb25zIiwiaW5zdGFsbERlcGVuZGVuY2llcyIsInNjYWZmb2xkIiwib3B0aW9ucyIsIm5vZGVFbnYiLCJnZXRNb2RlbCIsIldFTExfS05PV05fRklMRVMiLCJFTlZfRklMRSIsImFkZEVudHJ5IiwicHJvY2VzcyIsImVudiIsIkRFQ09IRVJFX0JVSUxERVIiLCJkZXRlY3RQYWNrYWdlTWFuYWdlciIsInByb21wdEZvclBhY2thZ2VNYW5hZ2VyIiwiYW5zd2VyIiwiYXNrIiwidG9Mb3dlckNhc2UiLCJmaW5hbGl6ZSIsImZvcm1hdFBhdGhzIiwiYWRkIiwiZ2V0UHJvamVjdHMiLCJtYXAiLCJwcm9qZWN0IiwiZGlyIiwiZm9ybWF0U2NhZmZvbGRlZEZpbGVzIiwicG0iLCJjb25zb2xlIiwibG9nIiwibmFtZSIsImluc3RhbGwiLCJjd2QiLCJhcGlOYW1lcyIsInJlcGxhY2UiLCJwbU5hbWUiLCJjbG9z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
|