@bedrock-rbx/core 0.1.0-beta.11 → 0.1.0-beta.13
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/dist/cli/run.mjs +54 -210
- package/dist/cli/run.mjs.map +1 -1
- package/dist/config.d.mts +2 -2
- package/dist/{define-config-87u2jqjM.d.mts → define-config-Bd0XIiSX.d.mts} +155 -8
- package/dist/{define-config-87u2jqjM.d.mts.map → define-config-Bd0XIiSX.d.mts.map} +1 -1
- package/dist/index.d.mts +1847 -1637
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +26 -2
- package/dist/index.mjs.map +1 -1
- package/dist/{migrate-mantle-state-DjAU-I39.mjs → migrate-mantle-state-CQjWBZwT.mjs} +857 -79
- package/dist/migrate-mantle-state-CQjWBZwT.mjs.map +1 -0
- package/package.json +4 -4
- package/dist/migrate-mantle-state-DjAU-I39.mjs.map +0 -1
package/dist/cli/run.mjs
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { B as createClackProgressAdapter, G as renderMigrationSummary, H as renderDeployError, K as renderParseError, O as serializeStateFile, U as renderMigrateError, V as renderBuildStatePortError, W as renderMigrateParseError, _ as diff, a as buildStatePort, d as selectMergedEnvironment, f as collectRedactionAnnotations, i as loadConfig, l as validatePlan, m as flattenConfig, n as serializeConfig, o as buildDesired, p as resolveStateConfig, q as renderStateWriteError, r as deploy, t as migrateMantleState, u as selectEnvironment, x as createClackPort } from "../migrate-mantle-state-CQjWBZwT.mjs";
|
|
3
|
+
import { isCancel, path, select, text } from "@clack/prompts";
|
|
4
4
|
import process from "node:process";
|
|
5
5
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
6
6
|
import { dirname, join } from "node:path";
|
|
7
7
|
import sade from "sade";
|
|
8
|
-
import { cancel, intro, isCancel, log, outro, path, select, text } from "@clack/prompts";
|
|
9
8
|
//#region package.json
|
|
10
|
-
var version = "0.1.0-beta.
|
|
9
|
+
var version = "0.1.0-beta.13";
|
|
11
10
|
//#endregion
|
|
12
11
|
//#region src/cli/credential-environment-overrides.ts
|
|
13
12
|
/**
|
|
@@ -117,202 +116,6 @@ function pickString(rawOptions, ...keys) {
|
|
|
117
116
|
}
|
|
118
117
|
}
|
|
119
118
|
//#endregion
|
|
120
|
-
//#region src/cli/render.ts
|
|
121
|
-
/**
|
|
122
|
-
* Render a `DeployError` to the supplied `ClackPort` as a single error line.
|
|
123
|
-
* Each variant produces a distinct, terse diagnostic; wrapped variants
|
|
124
|
-
* (`applyFailed`, `buildDesiredFailed`, `configLoadFailed`, `stateReadFailed`,
|
|
125
|
-
* `stateWriteFailed`) surface the inner cause's actionable detail (file path,
|
|
126
|
-
* resource key, parser message, HTTP failure, validator issue) so the reader
|
|
127
|
-
* does not have to inspect the full cause to act.
|
|
128
|
-
* @param err - The deploy error to describe.
|
|
129
|
-
* @param port - The output port the diagnostic is written to.
|
|
130
|
-
*/
|
|
131
|
-
function renderDeployError(err, port) {
|
|
132
|
-
port.logError(deployErrorMessage(err));
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Render a `ParseOptionsError` to the supplied `ClackPort` as a single
|
|
136
|
-
* error line. Each variant names the offending flag so the diagnostic
|
|
137
|
-
* pinpoints what the caller needs to change.
|
|
138
|
-
* @param err - The parse error to describe.
|
|
139
|
-
* @param port - The output port the diagnostic is written to.
|
|
140
|
-
*/
|
|
141
|
-
function renderParseError(err, port) {
|
|
142
|
-
port.logError(parseErrorMessage(err));
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Construct a `ClackPort` whose methods delegate to `@clack/prompts`. The
|
|
146
|
-
* resulting port writes to `process.stdout` via clack's defaults.
|
|
147
|
-
* @returns A port whose six methods each invoke the matching clack helper.
|
|
148
|
-
*/
|
|
149
|
-
function createClackPort() {
|
|
150
|
-
return {
|
|
151
|
-
cancel: (message) => {
|
|
152
|
-
cancel(message);
|
|
153
|
-
},
|
|
154
|
-
intro: (message) => {
|
|
155
|
-
intro(message);
|
|
156
|
-
},
|
|
157
|
-
logError: (message) => {
|
|
158
|
-
log.error(message);
|
|
159
|
-
},
|
|
160
|
-
logMessage: (message) => {
|
|
161
|
-
log.message(message);
|
|
162
|
-
},
|
|
163
|
-
logSuccess: (message) => {
|
|
164
|
-
log.success(message);
|
|
165
|
-
},
|
|
166
|
-
outro: (message) => {
|
|
167
|
-
outro(message);
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Render a `ParseMigrateError` to the supplied `ClackPort`. Reuses
|
|
173
|
-
* `parseErrorMessage` for the three flag-shape variants and adds a
|
|
174
|
-
* dedicated message for `unknownSource` listing the supported sources.
|
|
175
|
-
* @param err - The parse error to describe.
|
|
176
|
-
* @param port - The output port the diagnostic is written to.
|
|
177
|
-
*/
|
|
178
|
-
function renderMigrateParseError(err, port) {
|
|
179
|
-
port.logError(migrateParseErrorMessage(err));
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* Render a `MigrateError` to the supplied `ClackPort` as a single error
|
|
183
|
-
* line. Each variant points at the offending Mantle state file path,
|
|
184
|
-
* primary-environment input, or wrapped `ConfigError` so the reader can
|
|
185
|
-
* act without inspecting the raw error object.
|
|
186
|
-
* @param err - The migrate error to describe.
|
|
187
|
-
* @param port - The output port the diagnostic is written to.
|
|
188
|
-
*/
|
|
189
|
-
function renderMigrateError(err, port) {
|
|
190
|
-
port.logError(migrateErrorMessage(err));
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Render a `MissingCredentialError` or `UnsupportedBackendError`
|
|
194
|
-
* surfaced when the migrate command tried to default-construct the
|
|
195
|
-
* configured `StatePort` and was missing its inputs.
|
|
196
|
-
* @param err - The error returned by `buildStatePort`.
|
|
197
|
-
* @param port - The output port the diagnostic is written to.
|
|
198
|
-
*/
|
|
199
|
-
function renderBuildStatePortError(err, port) {
|
|
200
|
-
port.logError(buildStatePortErrorMessage(err));
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Render the post-migrate review prompt to the supplied `ClackPort`.
|
|
204
|
-
* Three outcomes:
|
|
205
|
-
*
|
|
206
|
-
* - Any `ambiguous` warnings exist: emit a single error line directing
|
|
207
|
-
* the user to the report. The migration ran but there are decisions
|
|
208
|
-
* the user still needs to make before deploy will be meaningful.
|
|
209
|
-
* - No `ambiguous` warnings but non-zero `blocked` / `deferred` /
|
|
210
|
-
* `interpretive`: emit a single success line pointing at the report
|
|
211
|
-
* for auditing.
|
|
212
|
-
* - All counts zero: silent. The closing `outro("migrate succeeded")`
|
|
213
|
-
* already speaks for the run.
|
|
214
|
-
* @param input - Counts plus the path of the Markdown report.
|
|
215
|
-
* @param port - The output port the line is written to.
|
|
216
|
-
*/
|
|
217
|
-
function renderMigrationSummary(input, port) {
|
|
218
|
-
const { ambiguousCount, blockedCount, deferredCount, interpretiveCount } = input.summary;
|
|
219
|
-
if (ambiguousCount > 0) {
|
|
220
|
-
port.logError(`action required: ${String(ambiguousCount)} fields need your input. See ${input.reportPath}`);
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
const reviewable = blockedCount + deferredCount + interpretiveCount;
|
|
224
|
-
if (reviewable > 0) port.logSuccess(`migration complete; see ${input.reportPath} for ${String(reviewable)} auto-mapped or skipped fields`);
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Render a `StateError` produced when the migrator wrote a per-environment
|
|
228
|
-
* state through the `StatePort`. Names the environment alongside the
|
|
229
|
-
* adapter's failure reason so the reader knows which write failed.
|
|
230
|
-
* @param input - Environment + state-error to describe.
|
|
231
|
-
* @param port - The output port the diagnostic is written to.
|
|
232
|
-
*/
|
|
233
|
-
function renderStateWriteError(input, port) {
|
|
234
|
-
port.logError(`state write failed for '${input.environment}' (${input.err.file}): ${input.err.reason}`);
|
|
235
|
-
}
|
|
236
|
-
function permissionDetail(err) {
|
|
237
|
-
const isPlural = err.requiredScopes.length > 1;
|
|
238
|
-
const label = isPlural ? "scopes" : "scope";
|
|
239
|
-
const pronoun = isPlural ? "them" : "it";
|
|
240
|
-
const scopeList = err.requiredScopes.map((scope) => `'${scope}'`).join(", ");
|
|
241
|
-
return `${err.message} on ${err.operationKey}: missing required ${label} ${scopeList}. Grant ${pronoun} on the API key at https://create.roblox.com/credentials`;
|
|
242
|
-
}
|
|
243
|
-
function applyCauseDetail(cause) {
|
|
244
|
-
switch (cause.kind) {
|
|
245
|
-
case "driverFailure":
|
|
246
|
-
if (cause.cause instanceof PermissionError) return permissionDetail(cause.cause);
|
|
247
|
-
return cause.cause.message;
|
|
248
|
-
case "updateUnsupported": return "update not supported";
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
function buildDesiredDetail(cause) {
|
|
252
|
-
switch (cause.kind) {
|
|
253
|
-
case "fileReadFailed": return `(${cause.filePath}): ${cause.reason}`;
|
|
254
|
-
case "iconRemovalRejected": return `: ${cause.message}`;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
function configErrorDetail(err) {
|
|
258
|
-
switch (err.kind) {
|
|
259
|
-
case "configFunctionFailed": return `${err.sourceFile}: config function threw: ${err.message}`;
|
|
260
|
-
case "fileNotFound": return `no bedrock config under ${err.searchedFrom}`;
|
|
261
|
-
case "luauRuntimeMissing": return `${err.sourceFile}: ${err.hint}`;
|
|
262
|
-
case "parseFailed": return `${err.sourceFile}: ${err.message}`;
|
|
263
|
-
case "validationFailed": {
|
|
264
|
-
const first = err.issues[0];
|
|
265
|
-
return first === void 0 ? `${err.sourceFile}: invalid` : `${err.sourceFile}: ${first.path.join(".")} ${first.message}`;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
function stateErrorDetail(cause) {
|
|
270
|
-
return `(${cause.file}): ${cause.reason}`;
|
|
271
|
-
}
|
|
272
|
-
function deployErrorMessage(err) {
|
|
273
|
-
switch (err.kind) {
|
|
274
|
-
case "applyFailed": return `apply failed for '${err.cause.key}': ${applyCauseDetail(err.cause)}`;
|
|
275
|
-
case "buildDesiredFailed": return `build desired state failed for '${err.cause.key}' ${buildDesiredDetail(err.cause)}`;
|
|
276
|
-
case "configLoadFailed": return `config load failed: ${configErrorDetail(err.cause)}`;
|
|
277
|
-
case "incompletePlaceEntry": return `place '${err.key}' is missing '${err.missingField}' under environment '${err.environment}'`;
|
|
278
|
-
case "incompleteUniverseEntry": return `universe is missing '${err.missingField}' under environment '${err.environment}'`;
|
|
279
|
-
case "missingCredential": return `missing credential: environment variable ${err.variable} is not set`;
|
|
280
|
-
case "registryConfigMissing": return `registry config missing '${err.missing}' (${err.hint})`;
|
|
281
|
-
case "stateNotConfigured": return `state not configured for environment '${err.environment}'`;
|
|
282
|
-
case "stateReadFailed": return `state read failed ${stateErrorDetail(err.cause)}`;
|
|
283
|
-
case "stateWriteFailed": return `state write failed ${stateErrorDetail(err.cause)}`;
|
|
284
|
-
case "unknownEnvironment": return `unknown environment '${err.environment}' (declared: ${err.declared.join(", ")})`;
|
|
285
|
-
case "unsupportedBackend": return `unsupported state backend '${err.backend}' (${err.hint})`;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
function parseErrorMessage(err) {
|
|
289
|
-
switch (err.kind) {
|
|
290
|
-
case "invalidValue": return `invalid value for flag '--${err.flag}' (expected a string)`;
|
|
291
|
-
case "missingRequired": return `missing required flag --${err.flag}`;
|
|
292
|
-
case "unknownFlag": return `unknown flag '--${err.flag}'`;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
function migrateParseErrorMessage(err) {
|
|
296
|
-
if (err.kind === "unknownSource") return `unknown migration source '${err.received}' (supported: ${err.supported.join(", ")})`;
|
|
297
|
-
return parseErrorMessage(err);
|
|
298
|
-
}
|
|
299
|
-
function migrateErrorMessage(err) {
|
|
300
|
-
switch (err.kind) {
|
|
301
|
-
case "internalError": return `migrate internal error: ${err.reason} (${configErrorDetail(err.cause)})`;
|
|
302
|
-
case "primaryEnvironmentNotFound": return `primary environment '${err.primary}' not found (available: ${err.available.join(", ")})`;
|
|
303
|
-
case "primaryEnvironmentRequired": return `primary environment required (available: ${err.available.join(", ")})`;
|
|
304
|
-
case "stateFileNotFound": return `Mantle state file not found at '${err.path}'`;
|
|
305
|
-
case "stateParseFailed": return `Mantle state file at '${err.path}' could not be parsed: ${err.reason}`;
|
|
306
|
-
case "unsupportedMantleStateVersion": return `unsupported Mantle state version '${err.found}' (supported: ${err.supported.join(", ")})`;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
function buildStatePortErrorMessage(err) {
|
|
310
|
-
switch (err.kind) {
|
|
311
|
-
case "missingCredential": return `missing credential: environment variable ${err.variable} is not set`;
|
|
312
|
-
case "unsupportedBackend": return `unsupported state backend '${err.backend}' (${err.hint})`;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
//#endregion
|
|
316
119
|
//#region src/cli/commands/deploy.ts
|
|
317
120
|
/**
|
|
318
121
|
* Build the sade action for `bedrock deploy`. The returned function consumes
|
|
@@ -333,11 +136,13 @@ function deployCommand(deps) {
|
|
|
333
136
|
};
|
|
334
137
|
}
|
|
335
138
|
function resolveDeploy(deps) {
|
|
139
|
+
const clack = deps.clack ?? createClackPort();
|
|
336
140
|
return {
|
|
337
|
-
clack
|
|
141
|
+
clack,
|
|
338
142
|
deploy: deps.deploy ?? deploy,
|
|
339
143
|
exit: deps.exit ?? ((code) => process.exit(code)),
|
|
340
|
-
loadConfig: deps.loadConfig ?? loadConfig
|
|
144
|
+
loadConfig: deps.loadConfig ?? loadConfig,
|
|
145
|
+
progress: deps.progress ?? createClackProgressAdapter({ clack })
|
|
341
146
|
};
|
|
342
147
|
}
|
|
343
148
|
function loadOptionsFor$1(parsed) {
|
|
@@ -352,9 +157,17 @@ async function dispatchEnvironments$1(inputs) {
|
|
|
352
157
|
environment,
|
|
353
158
|
getEnv
|
|
354
159
|
});
|
|
355
|
-
if (result.success) resolved.
|
|
160
|
+
if (result.success) resolved.progress.emit({
|
|
161
|
+
environment,
|
|
162
|
+
kind: "deploySuccess",
|
|
163
|
+
resourceCount: result.data.resources.length
|
|
164
|
+
});
|
|
356
165
|
else {
|
|
357
|
-
|
|
166
|
+
resolved.progress.emit({
|
|
167
|
+
environment,
|
|
168
|
+
error: result.err,
|
|
169
|
+
kind: "deployFailure"
|
|
170
|
+
});
|
|
358
171
|
failed.push(environment);
|
|
359
172
|
}
|
|
360
173
|
}
|
|
@@ -453,15 +266,31 @@ function pickStatePort(options, config) {
|
|
|
453
266
|
stateConfig: stateConfig.data
|
|
454
267
|
});
|
|
455
268
|
}
|
|
456
|
-
|
|
457
|
-
const
|
|
458
|
-
if (!
|
|
459
|
-
|
|
269
|
+
function resolveEnvironmentView(config, environment) {
|
|
270
|
+
const merged = selectMergedEnvironment(config, environment);
|
|
271
|
+
if (!merged.success) return {
|
|
272
|
+
err: merged.err,
|
|
273
|
+
success: false
|
|
274
|
+
};
|
|
275
|
+
const selected = selectEnvironment(config, environment);
|
|
460
276
|
if (!selected.success) return {
|
|
461
277
|
err: selected.err,
|
|
462
278
|
success: false
|
|
463
279
|
};
|
|
464
|
-
|
|
280
|
+
return {
|
|
281
|
+
data: {
|
|
282
|
+
effective: selected.data,
|
|
283
|
+
redactions: collectRedactionAnnotations(merged.data.merged)
|
|
284
|
+
},
|
|
285
|
+
success: true
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
async function resolveDeps(options) {
|
|
289
|
+
const config = await pickConfig(options);
|
|
290
|
+
if (!config.success) return config;
|
|
291
|
+
const view = resolveEnvironmentView(config.data, options.environment);
|
|
292
|
+
if (!view.success) return view;
|
|
293
|
+
const { effective, redactions } = view.data;
|
|
465
294
|
const readFile$1 = options.readFile ?? readFile;
|
|
466
295
|
const statePort = pickStatePort(options, effective);
|
|
467
296
|
if (!statePort.success) return statePort;
|
|
@@ -469,6 +298,7 @@ async function resolveDeps(options) {
|
|
|
469
298
|
data: {
|
|
470
299
|
config: effective,
|
|
471
300
|
readFile: readFile$1,
|
|
301
|
+
redactions,
|
|
472
302
|
statePort: statePort.data
|
|
473
303
|
},
|
|
474
304
|
success: true
|
|
@@ -503,7 +333,8 @@ async function runPreview(environment, deps) {
|
|
|
503
333
|
return {
|
|
504
334
|
data: {
|
|
505
335
|
environment,
|
|
506
|
-
ops: diff(desired.data, priorResources)
|
|
336
|
+
ops: diff(desired.data, priorResources),
|
|
337
|
+
redactions: deps.redactions
|
|
507
338
|
},
|
|
508
339
|
success: true
|
|
509
340
|
};
|
|
@@ -556,14 +387,27 @@ function describeOp(op) {
|
|
|
556
387
|
function isDriftOp(op) {
|
|
557
388
|
return op.type !== "noop";
|
|
558
389
|
}
|
|
390
|
+
function describeRedaction(redaction) {
|
|
391
|
+
const suffix = redaction.hasRealValueEdits ? "redacted, real values not pushed" : "redacted";
|
|
392
|
+
return `- ${redaction.kind}:${redaction.key} (${suffix})`;
|
|
393
|
+
}
|
|
394
|
+
function renderRedactions(preview, clack) {
|
|
395
|
+
const driftPairs = new Set(preview.ops.filter(isDriftOp).map((op) => `${op.desired.kind}:${op.key}`));
|
|
396
|
+
const redactedNoops = preview.redactions.filter((redaction) => !driftPairs.has(`${redaction.kind}:${redaction.key}`));
|
|
397
|
+
if (redactedNoops.length === 0) return;
|
|
398
|
+
clack.logMessage(`Redacted in "${preview.environment}":`);
|
|
399
|
+
for (const redaction of redactedNoops) clack.logMessage(describeRedaction(redaction));
|
|
400
|
+
}
|
|
559
401
|
function renderPreview(preview, clack) {
|
|
560
402
|
const drift = preview.ops.filter(isDriftOp);
|
|
561
403
|
if (drift.length === 0) {
|
|
562
404
|
clack.logSuccess(`No drift for "${preview.environment}"`);
|
|
405
|
+
renderRedactions(preview, clack);
|
|
563
406
|
return false;
|
|
564
407
|
}
|
|
565
408
|
clack.logMessage(`Pending changes for "${preview.environment}":`);
|
|
566
409
|
for (const op of drift) clack.logMessage(describeOp(op));
|
|
410
|
+
renderRedactions(preview, clack);
|
|
567
411
|
return true;
|
|
568
412
|
}
|
|
569
413
|
async function dispatchEnvironments(inputs) {
|