devflare 1.0.0-next.51 → 1.0.0-next.53
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/LLM.md +3 -0
- package/dist/_chunks/{cli-CU7wSG1-.js → cli-CqIDn-Hy.js} +10 -2
- package/dist/_chunks/{productions-DK7xwbEs.js → productions-DXQ045cq.js} +95 -2
- package/dist/cli/commands/productions.d.ts.map +1 -1
- package/dist/cli/help-pages/pages/productions.d.ts.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/index.js +1 -1
- package/dist/test/index.d.ts +1 -1
- package/dist/test/index.d.ts.map +1 -1
- package/dist/test/index.js +66 -2
- package/dist/test/offline-bindings.d.ts +10 -1
- package/dist/test/offline-bindings.d.ts.map +1 -1
- package/dist/test/utilities/env.d.ts +2 -0
- package/dist/test/utilities/env.d.ts.map +1 -1
- package/dist/test/utilities/send-email.d.ts +27 -0
- package/dist/test/utilities/send-email.d.ts.map +1 -0
- package/dist/test/utilities.d.ts +1 -0
- package/dist/test/utilities.d.ts.map +1 -1
- package/package.json +1 -1
package/LLM.md
CHANGED
|
@@ -4800,6 +4800,8 @@ The `devflare/test` entrypoint intentionally has multiple lanes: runtime-shaped
|
|
|
4800
4800
|
| `createMockArtifacts` | Mock Artifacts repo APIs. |
|
|
4801
4801
|
| `createMockVectorize` | Mock a Vectorize index (in-memory cosine query). |
|
|
4802
4802
|
| `createMockAnalyticsEngine` | Mock an Analytics Engine dataset (write-only recording stub). |
|
|
4803
|
+
| `createMockSendEmail` | Mock a SendEmail binding (records dispatched mail, enforces allow-lists). |
|
|
4804
|
+
| `createLocalSendEmailBinding` | Underlying pure SendEmail simulator (non-recording). |
|
|
4803
4805
|
| `createMockSecretsStoreSecret` | Mock a Secrets Store secret. |
|
|
4804
4806
|
| `createMockEnv` | Create a pure env with selected mock bindings. |
|
|
4805
4807
|
| `hasServiceBindings` | Advanced/internal service-binding resolution predicate. |
|
|
@@ -11351,6 +11353,7 @@ test('sends an outbound transactional email', async () => {
|
|
|
11351
11353
|
|
|
11352
11354
|
- Use the outbound binding directly when the worker is sending mail.
|
|
11353
11355
|
- Use the inbound `email` helper surface (`cf.email.send(...)` from `devflare/test`) when the worker is handling inbound email in `src/email.ts`.
|
|
11356
|
+
- For pure offline tests, `createMockSendEmail()` (or `createMockEnv({ sendEmail })` / `createOfflineEnv()`) records every dispatched message into `.sentEmails` while still enforcing the configured sender/destination allow-lists; `createLocalSendEmailBinding()` is the underlying non-recording simulator.
|
|
11354
11357
|
- Keep address restrictions visible in tests when those restrictions are part of the safety story.
|
|
11355
11358
|
|
|
11356
11359
|
#### When to move beyond the default harness
|
|
@@ -712,13 +712,15 @@ const PRODUCTION_HELP_PAGES = [
|
|
|
712
712
|
usage: [
|
|
713
713
|
"devflare productions [--config <path>] [--env <name>] [--account <id>] [--worker <name>]",
|
|
714
714
|
"devflare productions versions [--config <path>] [--env <name>] [--account <id>] [--worker <name>]",
|
|
715
|
+
"devflare productions deployments [--config <path>] [--env <name>] [--account <id>] [--worker <name>]",
|
|
715
716
|
"devflare productions rollback [--config <path>] [--account <id>] [--worker <name>] [--version-id <id>] [--message <text>] [--apply]",
|
|
716
717
|
"devflare productions delete [--config <path>] [--account <id>] [--worker <name>] [--apply]"
|
|
717
718
|
],
|
|
718
|
-
description: ["The default view inspects live Cloudflare production deployment state for locally configured Workers, or for one explicitly selected Worker.", "Other subcommands list recent production versions or mutate a single Worker by rolling back or deleting its live production script."],
|
|
719
|
+
description: ["The default view inspects live Cloudflare production deployment state for locally configured Workers, or for one explicitly selected Worker.", "Other subcommands list recent production versions, show the full deployment history, or mutate a single Worker by rolling back or deleting its live production script."],
|
|
719
720
|
subcommands: [
|
|
720
721
|
entry("list", "List live production Workers and their active deployments (default)"),
|
|
721
722
|
entry("versions", "Show recent stored production versions and which one is currently active"),
|
|
723
|
+
entry("deployments", "Show the full chronological production deployment history with traffic splits"),
|
|
722
724
|
entry("rollback", "Roll a Worker back to the previous or specified production version"),
|
|
723
725
|
entry("delete", "Delete a live production Worker script")
|
|
724
726
|
],
|
|
@@ -757,6 +759,12 @@ const PRODUCTION_HELP_PAGES = [
|
|
|
757
759
|
entry("--account <id>", "Use a specific Cloudflare account"),
|
|
758
760
|
entry("--worker <name>", "Target a specific Worker instead of the locally configured set")
|
|
759
761
|
], [entry("devflare productions versions", "Show recent stored production versions for the resolved Workers"), entry("devflare productions versions --worker my-worker", "Show recent stored production versions for `my-worker`")]),
|
|
762
|
+
createProductionsSubcommandPage("deployments", "Show the full chronological production deployment history", ["devflare productions deployments [--config <path>] [--env <name>] [--account <id>] [--worker <name>]"], ["Lists every production deployment for the selected Worker set in reverse-chronological order, including each deployment id, strategy, per-version traffic split, source, who triggered it, and the deployment message."], [
|
|
763
|
+
entry("--config <path>", "Use a specific devflare config file"),
|
|
764
|
+
entry("--env <name>", "Resolve `config.env[name]` while discovering related production Workers (defaults to `production`)"),
|
|
765
|
+
entry("--account <id>", "Use a specific Cloudflare account"),
|
|
766
|
+
entry("--worker <name>", "Target a specific Worker instead of the locally configured set")
|
|
767
|
+
], [entry("devflare productions deployments", "Show the full production deployment history for the resolved Workers"), entry("devflare productions deployments --worker my-worker", "Show the full production deployment history for `my-worker`")], ["This view is read-only and is backed by live Cloudflare deployment history."]),
|
|
760
768
|
createProductionsSubcommandPage("rollback", "Roll a Worker back to the previous or specified production version", ["devflare productions rollback [--config <path>] [--account <id>] [--worker <name>] [--version-id <id>] [--message <text>] [--apply]"], ["Uses Wrangler rollback to create a fresh production deployment that points at the previous or explicitly selected version."], [
|
|
761
769
|
entry("--config <path>", "Use a specific devflare config file"),
|
|
762
770
|
entry("--account <id>", "Use a specific Cloudflare account"),
|
|
@@ -1132,7 +1140,7 @@ async function runPreviews(parsed, logger, options) {
|
|
|
1132
1140
|
return runPreviewsCommand(parsed, logger, options);
|
|
1133
1141
|
}
|
|
1134
1142
|
async function runProductions(parsed, logger, options) {
|
|
1135
|
-
const { runProductionsCommand } = await import("./productions-
|
|
1143
|
+
const { runProductionsCommand } = await import("./productions-DXQ045cq.js");
|
|
1136
1144
|
return runProductionsCommand(parsed, logger, options);
|
|
1137
1145
|
}
|
|
1138
1146
|
async function runWorker(parsed, logger, options) {
|
|
@@ -10,6 +10,7 @@ const CLI_API_OPTIONS = { timeout: 1e4 };
|
|
|
10
10
|
const PRODUCTION_SUBCOMMANDS = [
|
|
11
11
|
"list",
|
|
12
12
|
"versions",
|
|
13
|
+
"deployments",
|
|
13
14
|
"rollback",
|
|
14
15
|
"delete"
|
|
15
16
|
];
|
|
@@ -23,6 +24,10 @@ function shortenVersionId(versionId, length = 12) {
|
|
|
23
24
|
function selectDeploymentVersionId(deployment) {
|
|
24
25
|
return deployment.versions.find((version) => version.percentage === 100)?.versionId ?? deployment.versions[0]?.versionId;
|
|
25
26
|
}
|
|
27
|
+
function formatDeploymentSplit(deployment) {
|
|
28
|
+
if (deployment.versions.length === 0) return "N/A";
|
|
29
|
+
return deployment.versions.map((version) => `${version.percentage}% → ${shortenVersionId(version.versionId, 8)}`).join(", ");
|
|
30
|
+
}
|
|
26
31
|
function getWorkerVersionTimestamp(version) {
|
|
27
32
|
return version.metadata.modifiedOn ?? version.metadata.createdOn;
|
|
28
33
|
}
|
|
@@ -282,7 +287,7 @@ function showProductionOverview(logger, context, rows, theme) {
|
|
|
282
287
|
titleAccent: "green"
|
|
283
288
|
});
|
|
284
289
|
logLine(logger);
|
|
285
|
-
logLine(logger, dim("Use `devflare productions versions` for recent production versions, or `rollback` / `delete` to mutate one Worker.", theme));
|
|
290
|
+
logLine(logger, dim("Use `devflare productions versions` for recent production versions, `deployments` for the full deployment history, or `rollback` / `delete` to mutate one Worker.", theme));
|
|
286
291
|
logLine(logger);
|
|
287
292
|
}
|
|
288
293
|
function showWorkerVersions(logger, overviews, theme) {
|
|
@@ -309,6 +314,82 @@ function showWorkerVersions(logger, overviews, theme) {
|
|
|
309
314
|
}
|
|
310
315
|
logLine(logger);
|
|
311
316
|
}
|
|
317
|
+
function buildDeploymentColumns(theme) {
|
|
318
|
+
return [
|
|
319
|
+
{
|
|
320
|
+
label: "Deployed",
|
|
321
|
+
width: 19,
|
|
322
|
+
value: (row) => whiteDim(formatRecordDate(row.createdOn), theme)
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
label: "Deployment",
|
|
326
|
+
width: 12,
|
|
327
|
+
value: (row) => shortenVersionId(row.deploymentId, 11)
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
label: "Strategy",
|
|
331
|
+
width: 12,
|
|
332
|
+
value: (row) => row.strategy || dim("N/A", theme)
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
label: "Traffic split",
|
|
336
|
+
width: 28,
|
|
337
|
+
value: (row) => row.split
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
label: "Source",
|
|
341
|
+
width: 12,
|
|
342
|
+
value: (row) => row.source || dim("N/A", theme)
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
label: "Triggered by",
|
|
346
|
+
width: 18,
|
|
347
|
+
value: (row) => row.triggeredBy ? whiteDim(row.triggeredBy, theme) : dim("N/A", theme)
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
label: "Message",
|
|
351
|
+
value: (row) => row.message ? row.message : dim("N/A", theme)
|
|
352
|
+
}
|
|
353
|
+
];
|
|
354
|
+
}
|
|
355
|
+
async function loadWorkerDeploymentHistory(accountId, workerName, apiOptions) {
|
|
356
|
+
return {
|
|
357
|
+
workerName,
|
|
358
|
+
rows: [...await account.workerDeployments(accountId, workerName, apiOptions)].sort((left, right) => right.createdOn.getTime() - left.createdOn.getTime()).map((deployment) => ({
|
|
359
|
+
createdOn: deployment.createdOn,
|
|
360
|
+
deploymentId: deployment.id,
|
|
361
|
+
strategy: deployment.strategy,
|
|
362
|
+
split: formatDeploymentSplit(deployment),
|
|
363
|
+
source: deployment.source,
|
|
364
|
+
message: deployment.message,
|
|
365
|
+
triggeredBy: deployment.triggeredBy ?? deployment.authorEmail
|
|
366
|
+
}))
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
function showWorkerDeployments(logger, overviews, theme) {
|
|
370
|
+
logLine(logger);
|
|
371
|
+
if (overviews.length === 0) {
|
|
372
|
+
logLine(logger, dim("No production deployments were found for the current selection.", theme));
|
|
373
|
+
logLine(logger);
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
for (const [index, overview] of overviews.entries()) {
|
|
377
|
+
if (index > 0) logLine(logger);
|
|
378
|
+
logLine(logger, `${bold("worker", theme)} ${green(overview.workerName, theme)}`);
|
|
379
|
+
if (overview.rows.length === 0) {
|
|
380
|
+
logLine(logger, dim("No production deployments were found for this Worker.", theme));
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
logTable(logger, {
|
|
384
|
+
title: "Deployments",
|
|
385
|
+
rows: overview.rows,
|
|
386
|
+
columns: buildDeploymentColumns(theme),
|
|
387
|
+
theme,
|
|
388
|
+
titleAccent: "cyan"
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
logLine(logger);
|
|
392
|
+
}
|
|
312
393
|
async function runRollback(context, parsed, options, logger, theme) {
|
|
313
394
|
if (!context.workerName) {
|
|
314
395
|
logger.error("A worker name is required for production rollback.");
|
|
@@ -357,6 +438,9 @@ async function runDelete(context, parsed, logger) {
|
|
|
357
438
|
logger.warn("Devflare deleted the Worker script only. Review any shared account resources separately before cleaning them up.");
|
|
358
439
|
return { exitCode: 0 };
|
|
359
440
|
}
|
|
441
|
+
function resolveSelectedWorkerNames(context, selectedFamilies) {
|
|
442
|
+
return Array.from(new Set(context.workerName ? [context.workerName] : selectedFamilies.map((family) => family.baseName))).sort((left, right) => left.localeCompare(right));
|
|
443
|
+
}
|
|
360
444
|
async function runProductionsCommand(parsed, logger, options) {
|
|
361
445
|
if (!await account.isAuthenticated()) {
|
|
362
446
|
logger.error("Not authenticated with Cloudflare");
|
|
@@ -381,7 +465,7 @@ async function runProductionsCommand(parsed, logger, options) {
|
|
|
381
465
|
}] : [];
|
|
382
466
|
switch (subcommand) {
|
|
383
467
|
case "versions": {
|
|
384
|
-
const workerNames =
|
|
468
|
+
const workerNames = resolveSelectedWorkerNames(context, selectedFamilies);
|
|
385
469
|
if (workerNames.length === 0) {
|
|
386
470
|
logger.error("No production Workers could be resolved. Use --worker or run inside a configured package.");
|
|
387
471
|
return { exitCode: 1 };
|
|
@@ -389,6 +473,15 @@ async function runProductionsCommand(parsed, logger, options) {
|
|
|
389
473
|
showWorkerVersions(logger, await Promise.all(workerNames.map((workerName) => loadWorkerVersionOverview(context.accountId, workerName, CLI_API_OPTIONS))), theme);
|
|
390
474
|
return { exitCode: 0 };
|
|
391
475
|
}
|
|
476
|
+
case "deployments": {
|
|
477
|
+
const workerNames = resolveSelectedWorkerNames(context, selectedFamilies);
|
|
478
|
+
if (workerNames.length === 0) {
|
|
479
|
+
logger.error("No production Workers could be resolved. Use --worker or run inside a configured package.");
|
|
480
|
+
return { exitCode: 1 };
|
|
481
|
+
}
|
|
482
|
+
showWorkerDeployments(logger, await Promise.all(workerNames.map((workerName) => loadWorkerDeploymentHistory(context.accountId, workerName, CLI_API_OPTIONS))), theme);
|
|
483
|
+
return { exitCode: 0 };
|
|
484
|
+
}
|
|
392
485
|
case "rollback": return runRollback(context, parsed, options, logger, theme);
|
|
393
486
|
case "delete": return runDelete(context, parsed, logger);
|
|
394
487
|
default:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"productions.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/productions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAgB9C,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"productions.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/productions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAgB9C,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAwxBjE,wBAAsB,qBAAqB,CAC1C,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,UAAU,GACjB,OAAO,CAAC,SAAS,CAAC,CAoGpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"productions.d.ts","sourceRoot":"","sources":["../../../../src/cli/help-pages/pages/productions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAExC,eAAO,MAAM,qBAAqB,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"productions.d.ts","sourceRoot":"","sources":["../../../../src/cli/help-pages/pages/productions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAExC,eAAO,MAAM,qBAAqB,EAAE,QAAQ,EA6N3C,CAAA"}
|
package/dist/cli/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as runCli, t as parseArgs } from "../_chunks/cli-
|
|
1
|
+
import { n as runCli, t as parseArgs } from "../_chunks/cli-CqIDn-Hy.js";
|
|
2
2
|
export { parseArgs, runCli };
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,6 @@ import { a as ConfigResourceResolutionError, d as configSchema, n as ConfigValid
|
|
|
4
4
|
import { n as compileConfig, s as stringifyConfig } from "./_chunks/compiler-BtLp9T9N.js";
|
|
5
5
|
import { t as workerName } from "./_chunks/workerName-CFJsLZA-.js";
|
|
6
6
|
import { n as getDurableObjectOptions, t as durableObject } from "./_chunks/decorators-QmV57ixr.js";
|
|
7
|
-
import { n as runCli, t as parseArgs } from "./_chunks/cli-
|
|
7
|
+
import { n as runCli, t as parseArgs } from "./_chunks/cli-CqIDn-Hy.js";
|
|
8
8
|
import { i as vars, r as env } from "./_chunks/env-S0_nMVz1.js";
|
|
9
9
|
export { ConfigNotFoundError, ConfigResourceResolutionError, ConfigValidationError, compileConfig, configSchema, defineConfig as default, defineConfig, durableObject, env, getDurableObjectOptions, loadConfig, loadResolvedConfig, parseArgs, preview, ref, runCli, stringifyConfig, vars, workerName };
|
package/dist/test/index.d.ts
CHANGED
|
@@ -17,5 +17,5 @@ export { shouldSkip } from './should-skip.js';
|
|
|
17
17
|
export { containers, createContainerManager, detectContainerEngine, getContainerSkipReason, stopActiveContainers, type ContainerCommandResult, type ContainerCommandRunner, type ContainerEngineCheck, type ContainerEngineName, type ContainerEnginePreference, type ContainerEngineStatus, type ContainerManager, type ContainerManagerOptions, type DevflareContainerInstance, type LocalContainerState, type StartContainerOptions } from './containers.js';
|
|
18
18
|
export { createOfflineBindings, createOfflineEnv, describeOfflineSupport, getOfflineSupportMatrix, type OfflineBindingFixtures, type OfflineBindingsResult, type OfflineMissingFixture, type OfflineRemoteBoundary, type OfflineSupportEntry, type OfflineSupportTier } from './offline-bindings.js';
|
|
19
19
|
export { createMockAISearchInstance, createMockAISearchNamespace, type MockAISearchInstance, type MockAISearchInstanceOptions, type MockAISearchItemFixture, type MockAISearchNamespace, type MockAISearchNamespaceOptions } from './ai-search.js';
|
|
20
|
-
export { createMockTestContext, createMockKV, createMockD1, createMockR2, createMockQueue, createMockRateLimit, createMockVersionMetadata, createMockHyperdrive, createMockWorkerLoader, createMockMTLSCertificate, createMockDispatchNamespace, createMockWorkflow, createMockPipeline, createMockImagesBinding, createMockMediaBinding, createMockStreamBinding, createMockFlagshipBinding, createMockArtifacts, createMockVectorize, createMockAnalyticsEngine, createMockSecretsStoreSecret, createMockEnv, withTestContext, type TestContext, type TestContextOptions, type MockEnvOptions, type MockRateLimitOptions, type MockWorkerLoaderOptions, type MockFetchInput, type MockFetcherHandler, type MockDispatchNamespaceOptions, type MockWorkflowOptions, type MockWorkflowInstanceOptions, type MockPipeline, type MockImagesBindingOptions, type MockMediaBindingOptions, type MockStreamBindingOptions, type MockFlagshipBindingOptions, type MockArtifactsOptions, type MockVectorizeOptions, type MockVectorizeIndex, type MockAnalyticsEngineDataset } from './utilities.js';
|
|
20
|
+
export { createMockTestContext, createMockKV, createMockD1, createMockR2, createMockQueue, createMockRateLimit, createMockVersionMetadata, createMockHyperdrive, createMockWorkerLoader, createMockMTLSCertificate, createMockDispatchNamespace, createMockWorkflow, createMockPipeline, createMockImagesBinding, createMockMediaBinding, createMockStreamBinding, createMockFlagshipBinding, createMockArtifacts, createMockVectorize, createMockAnalyticsEngine, createMockSendEmail, createLocalSendEmailBinding, createMockSecretsStoreSecret, createMockEnv, withTestContext, type TestContext, type TestContextOptions, type MockEnvOptions, type MockRateLimitOptions, type MockWorkerLoaderOptions, type MockFetchInput, type MockFetcherHandler, type MockDispatchNamespaceOptions, type MockWorkflowOptions, type MockWorkflowInstanceOptions, type MockPipeline, type MockImagesBindingOptions, type MockMediaBindingOptions, type MockStreamBindingOptions, type MockFlagshipBindingOptions, type MockArtifactsOptions, type MockVectorizeOptions, type MockVectorizeIndex, type MockAnalyticsEngineDataset, type MockSendEmailBinding, type LocalSendEmailBindingConfig } from './utilities.js';
|
|
21
21
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/test/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"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"}
|
package/dist/test/index.js
CHANGED
|
@@ -1437,6 +1437,42 @@ function createMockAnalyticsEngine() {
|
|
|
1437
1437
|
};
|
|
1438
1438
|
}
|
|
1439
1439
|
//#endregion
|
|
1440
|
+
//#region src/test/utilities/send-email.ts
|
|
1441
|
+
/**
|
|
1442
|
+
* Creates a recording SendEmail binding for pure unit tests.
|
|
1443
|
+
*
|
|
1444
|
+
* Delegates `from`/destination allow-list enforcement to
|
|
1445
|
+
* {@link createLocalSendEmailBinding} (so disallowed senders/recipients throw
|
|
1446
|
+
* exactly as they would locally), and records each accepted message.
|
|
1447
|
+
*
|
|
1448
|
+
* @example
|
|
1449
|
+
* ```ts
|
|
1450
|
+
* const email = createMockSendEmail()
|
|
1451
|
+
* await email.send(new EmailMessage('from@a.com', 'to@b.com', '...'))
|
|
1452
|
+
* expect(email.sentEmails).toHaveLength(1)
|
|
1453
|
+
* ```
|
|
1454
|
+
*/
|
|
1455
|
+
function createMockSendEmail(config = {}) {
|
|
1456
|
+
const sentEmails = [];
|
|
1457
|
+
const binding = createLocalSendEmailBinding(config, { onSend(message) {
|
|
1458
|
+
sentEmails.push(message);
|
|
1459
|
+
} });
|
|
1460
|
+
return {
|
|
1461
|
+
send(message) {
|
|
1462
|
+
return binding.send(message);
|
|
1463
|
+
},
|
|
1464
|
+
get sentEmails() {
|
|
1465
|
+
return sentEmails;
|
|
1466
|
+
},
|
|
1467
|
+
get messages() {
|
|
1468
|
+
return sentEmails;
|
|
1469
|
+
},
|
|
1470
|
+
clear() {
|
|
1471
|
+
sentEmails.length = 0;
|
|
1472
|
+
}
|
|
1473
|
+
};
|
|
1474
|
+
}
|
|
1475
|
+
//#endregion
|
|
1440
1476
|
//#region src/test/utilities/env.ts
|
|
1441
1477
|
function isVectorizeBinding$1(value) {
|
|
1442
1478
|
return typeof value.query === "function";
|
|
@@ -1451,6 +1487,16 @@ function addVectorizeMockBindings(env, vectorize) {
|
|
|
1451
1487
|
function addAnalyticsEngineMockBindings(env, analyticsEngine) {
|
|
1452
1488
|
for (const name of analyticsEngine ?? []) env[name] = createMockAnalyticsEngine();
|
|
1453
1489
|
}
|
|
1490
|
+
function isSendEmailBinding$1(value) {
|
|
1491
|
+
return typeof value.send === "function";
|
|
1492
|
+
}
|
|
1493
|
+
function addSendEmailMockBindings(env, sendEmail) {
|
|
1494
|
+
if (Array.isArray(sendEmail)) {
|
|
1495
|
+
for (const name of sendEmail) env[name] = createMockSendEmail();
|
|
1496
|
+
return;
|
|
1497
|
+
}
|
|
1498
|
+
if (sendEmail) for (const [name, value] of Object.entries(sendEmail)) env[name] = isSendEmailBinding$1(value) ? value : createMockSendEmail(value);
|
|
1499
|
+
}
|
|
1454
1500
|
/**
|
|
1455
1501
|
* Creates a complete mock environment with specified bindings
|
|
1456
1502
|
*
|
|
@@ -1490,6 +1536,7 @@ function createMockEnv(options = {}) {
|
|
|
1490
1536
|
else if (options.artifacts) for (const [name, artifactsOptions] of Object.entries(options.artifacts)) env[name] = isArtifactsBinding$1(artifactsOptions) ? artifactsOptions : createMockArtifacts(artifactsOptions);
|
|
1491
1537
|
addVectorizeMockBindings(env, options.vectorize);
|
|
1492
1538
|
addAnalyticsEngineMockBindings(env, options.analyticsEngine);
|
|
1539
|
+
addSendEmailMockBindings(env, options.sendEmail);
|
|
1493
1540
|
if (options.secretsStore) for (const [name, value] of Object.entries(options.secretsStore)) env[name] = createMockSecretsStoreSecret(value);
|
|
1494
1541
|
if (options.vars) Object.assign(env, options.vars);
|
|
1495
1542
|
if (options.secrets) Object.assign(env, options.secrets);
|
|
@@ -4666,6 +4713,12 @@ const SUPPORT_MATRIX = {
|
|
|
4666
4713
|
reason: "Analytics Engine writes are recordable in-memory (createMockAnalyticsEngine), but there is no in-worker read API — querying is the hosted SQL API/dashboard.",
|
|
4667
4714
|
recommendation: "Use createMockAnalyticsEngine() to assert recorded writeDataPoint() calls; query analytics through the hosted SQL API/dashboard."
|
|
4668
4715
|
},
|
|
4716
|
+
sendEmail: {
|
|
4717
|
+
service: "sendEmail",
|
|
4718
|
+
tier: "offline-native",
|
|
4719
|
+
reason: "SendEmail is send-only (Email Routing has no in-worker read API), so Devflare provides a complete pure mock: send() enforces the configured sender/destination allow-lists locally and records dispatched mail. Real delivery is Cloudflare Email Routing.",
|
|
4720
|
+
recommendation: "Use createOfflineEnv() or createMockSendEmail() to assert dispatched mail in pure tests; use Cloudflare Email Routing for real delivery."
|
|
4721
|
+
},
|
|
4669
4722
|
builds: {
|
|
4670
4723
|
service: "builds",
|
|
4671
4724
|
tier: "remote-boundary",
|
|
@@ -4736,6 +4789,9 @@ function isAISearchInstance(value) {
|
|
|
4736
4789
|
function isVectorizeBinding(value) {
|
|
4737
4790
|
return typeof value?.query === "function";
|
|
4738
4791
|
}
|
|
4792
|
+
function isSendEmailBinding(value) {
|
|
4793
|
+
return typeof value?.send === "function";
|
|
4794
|
+
}
|
|
4739
4795
|
function isAISearchNamespace(value) {
|
|
4740
4796
|
return typeof value?.get === "function";
|
|
4741
4797
|
}
|
|
@@ -4774,6 +4830,12 @@ function addVectorizeBindings(env, bindings, fixtures) {
|
|
|
4774
4830
|
function addAnalyticsEngineBindings(env, bindings, fixtures) {
|
|
4775
4831
|
for (const name of Object.keys(bindings?.analyticsEngine ?? {})) env[name] = fixtures.analyticsEngine?.[name] ?? createMockAnalyticsEngine();
|
|
4776
4832
|
}
|
|
4833
|
+
function addSendEmailBindings(env, bindings, fixtures) {
|
|
4834
|
+
for (const [name, binding] of Object.entries(bindings?.sendEmail ?? {})) {
|
|
4835
|
+
const fixture = fixtures.sendEmail?.[name];
|
|
4836
|
+
env[name] = isSendEmailBinding(fixture) ? fixture : createMockSendEmail(fixture ?? binding);
|
|
4837
|
+
}
|
|
4838
|
+
}
|
|
4777
4839
|
function addVersionMetadataBinding(env, bindings) {
|
|
4778
4840
|
if (bindings?.versionMetadata) env[bindings.versionMetadata.binding] = createMockVersionMetadata();
|
|
4779
4841
|
}
|
|
@@ -4921,7 +4983,8 @@ function addRemoteBoundaries(remoteBoundaries, bindings) {
|
|
|
4921
4983
|
* entry overrides the auto-mock), alongside rate limits, version metadata,
|
|
4922
4984
|
* hyperdrive, worker loaders, mTLS, dispatch namespaces, workflows, pipelines,
|
|
4923
4985
|
* images, media, stream, flagship, artifacts, secrets store, AI Search,
|
|
4924
|
-
* Vectorize,
|
|
4986
|
+
* Vectorize, Analytics Engine, and SendEmail. It does **not** create the wiring
|
|
4987
|
+
* bindings
|
|
4925
4988
|
* (`durableObjects`, `services`) — those require a real Miniflare runtime, which
|
|
4926
4989
|
* only `createTestContext()` provides. When such a binding is present in config
|
|
4927
4990
|
* it is reported in the returned `missingFixtures` (its `env` entry is left
|
|
@@ -4940,6 +5003,7 @@ function createOfflineBindings(config, fixtures = {}, options = {}) {
|
|
|
4940
5003
|
addQueueBindings(env, bindings, fixtures);
|
|
4941
5004
|
addVectorizeBindings(env, bindings, fixtures);
|
|
4942
5005
|
addAnalyticsEngineBindings(env, bindings, fixtures);
|
|
5006
|
+
addSendEmailBindings(env, bindings, fixtures);
|
|
4943
5007
|
addRateLimitBindings(env, bindings);
|
|
4944
5008
|
addVersionMetadataBinding(env, bindings);
|
|
4945
5009
|
addHyperdriveBindings(env, bindings, fixtures, missingFixtures);
|
|
@@ -4979,4 +5043,4 @@ function createOfflineEnv(config, fixtures = {}, options = {}) {
|
|
|
4979
5043
|
return createOfflineBindings(config, fixtures, options).env;
|
|
4980
5044
|
}
|
|
4981
5045
|
//#endregion
|
|
4982
|
-
export { alarm, cf, clearBundleCache, containers, createContainerManager, createMockAISearchInstance, createMockAISearchNamespace, createMockAnalyticsEngine, createMockArtifacts, createMockD1, createMockDispatchNamespace, createMockEnv, createMockFlagshipBinding, createMockHyperdrive, createMockImagesBinding, createMockKV, createMockMTLSCertificate, createMockMediaBinding, createMockPipeline, createMockQueue, createMockR2, createMockRateLimit, createMockSecretsStoreSecret, createMockStreamBinding, createMockTestContext, createMockVectorize, createMockVersionMetadata, createMockWorkerLoader, createMockWorkflow, createOfflineBindings, createOfflineEnv, createTestContext, describeOfflineSupport, detectContainerEngine, email, env, getContainerSkipReason, getOfflineSupportMatrix, hasCrossWorkerDOs, hasServiceBindings, queue, resolveDOBindings, resolveServiceBindings, scheduled, shouldSkip, stopActiveContainers, tail, withTestContext, worker };
|
|
5046
|
+
export { alarm, cf, clearBundleCache, containers, createContainerManager, createLocalSendEmailBinding, createMockAISearchInstance, createMockAISearchNamespace, createMockAnalyticsEngine, createMockArtifacts, createMockD1, createMockDispatchNamespace, createMockEnv, createMockFlagshipBinding, createMockHyperdrive, createMockImagesBinding, createMockKV, createMockMTLSCertificate, createMockMediaBinding, createMockPipeline, createMockQueue, createMockR2, createMockRateLimit, createMockSecretsStoreSecret, createMockSendEmail, createMockStreamBinding, createMockTestContext, createMockVectorize, createMockVersionMetadata, createMockWorkerLoader, createMockWorkflow, createOfflineBindings, createOfflineEnv, createTestContext, describeOfflineSupport, detectContainerEngine, email, env, getContainerSkipReason, getOfflineSupportMatrix, hasCrossWorkerDOs, hasServiceBindings, queue, resolveDOBindings, resolveServiceBindings, scheduled, shouldSkip, stopActiveContainers, tail, withTestContext, worker };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Pipeline } from 'cloudflare:pipelines';
|
|
2
2
|
import { type DevflareConfig } from '../config/index.js';
|
|
3
|
+
import type { LocalSendEmailBindingConfig } from '../utils/send-email.js';
|
|
3
4
|
import { type MockAISearchInstanceOptions, type MockAISearchNamespaceOptions } from './ai-search.js';
|
|
4
5
|
import { type MockArtifactsOptions, type MockDispatchNamespaceOptions, type MockFetcherHandler, type MockFlagshipBindingOptions, type MockImagesBindingOptions, type MockMediaBindingOptions, type MockStreamBindingOptions, type MockVectorizeOptions, type MockWorkerLoaderOptions, type MockWorkflowOptions } from './utilities.js';
|
|
5
6
|
export type OfflineSupportTier = 'offline-native' | 'offline-fixture' | 'remote-boundary';
|
|
@@ -51,6 +52,13 @@ export interface OfflineBindingFixtures {
|
|
|
51
52
|
* without an entry here is auto-created with `createMockAnalyticsEngine()`.
|
|
52
53
|
*/
|
|
53
54
|
analyticsEngine?: Record<string, AnalyticsEngineDataset>;
|
|
55
|
+
/**
|
|
56
|
+
* SendEmail bindings. Any sendEmail binding in config without an entry here
|
|
57
|
+
* is auto-created with `createMockSendEmail()` using the binding's configured
|
|
58
|
+
* sender/destination allow-lists, so dispatched mail is recorded for
|
|
59
|
+
* assertions. Provide a `SendEmail` to inject a fully custom fake.
|
|
60
|
+
*/
|
|
61
|
+
sendEmail?: Record<string, SendEmail | LocalSendEmailBindingConfig>;
|
|
54
62
|
secretsStore?: Record<string, string>;
|
|
55
63
|
workerLoaders?: Record<string, MockWorkerLoaderOptions>;
|
|
56
64
|
mtlsCertificates?: Record<string, MockFetcherHandler>;
|
|
@@ -94,7 +102,8 @@ export declare function describeOfflineSupport(service: string): OfflineSupportE
|
|
|
94
102
|
* entry overrides the auto-mock), alongside rate limits, version metadata,
|
|
95
103
|
* hyperdrive, worker loaders, mTLS, dispatch namespaces, workflows, pipelines,
|
|
96
104
|
* images, media, stream, flagship, artifacts, secrets store, AI Search,
|
|
97
|
-
* Vectorize,
|
|
105
|
+
* Vectorize, Analytics Engine, and SendEmail. It does **not** create the wiring
|
|
106
|
+
* bindings
|
|
98
107
|
* (`durableObjects`, `services`) — those require a real Miniflare runtime, which
|
|
99
108
|
* only `createTestContext()` provides. When such a binding is present in config
|
|
100
109
|
* it is reported in the returned `missingFixtures` (its `env` entry is left
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"offline-bindings.d.ts","sourceRoot":"","sources":["../../src/test/offline-bindings.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,KAAK,cAAc,EAA8B,MAAM,WAAW,CAAA;AAE3E,OAAO,EACN,KAAK,2BAA2B,EAChC,KAAK,4BAA4B,EAGjC,MAAM,aAAa,CAAA;AACpB,OAAO,EACN,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EACjC,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,
|
|
1
|
+
{"version":3,"file":"offline-bindings.d.ts","sourceRoot":"","sources":["../../src/test/offline-bindings.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Pipeline } from 'cloudflare:pipelines';
|
|
2
|
+
import type { LocalSendEmailBindingConfig } from '../../utils/send-email.js';
|
|
2
3
|
import { type MockArtifactsOptions } from './artifacts.js';
|
|
3
4
|
import { type MockDispatchNamespaceOptions, type MockFetcherHandler, type MockRateLimitOptions, type MockWorkerLoaderOptions } from './platform.js';
|
|
4
5
|
import { type MockVectorizeOptions } from './vectorize.js';
|
|
@@ -21,6 +22,7 @@ export interface MockEnvOptions {
|
|
|
21
22
|
artifacts?: string[] | Record<string, MockArtifactsOptions | Artifacts>;
|
|
22
23
|
vectorize?: string[] | Record<string, MockVectorizeOptions | VectorizeIndex>;
|
|
23
24
|
analyticsEngine?: string[];
|
|
25
|
+
sendEmail?: string[] | Record<string, SendEmail | LocalSendEmailBindingConfig>;
|
|
24
26
|
secretsStore?: Record<string, string>;
|
|
25
27
|
durableObjects?: string[];
|
|
26
28
|
vars?: Record<string, string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/test/utilities/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/test/utilities/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAA;AAEzE,OAAO,EAAE,KAAK,oBAAoB,EAA2C,MAAM,aAAa,CAAA;AAIhG,OAAO,EACN,KAAK,4BAA4B,EACjC,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAQ5B,MAAM,YAAY,CAAA;AAInB,OAAO,EAAE,KAAK,oBAAoB,EAAuB,MAAM,aAAa,CAAA;AAC5E,OAAO,EAAE,KAAK,mBAAmB,EAA0C,MAAM,aAAa,CAAA;AAE9F,MAAM,WAAW,cAAc;IAC9B,EAAE,CAAC,EAAE,MAAM,EAAE,CAAA;IACb,EAAE,CAAC,EAAE,MAAM,EAAE,CAAA;IACb,EAAE,CAAC,EAAE,MAAM,EAAE,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAA;IACjD,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC,CAAA;IAChD,aAAa,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAA;IAClE,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAA;IAChE,kBAAkB,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAA;IAC5E,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,mBAAmB,GAAG,QAAQ,CAAC,CAAA;IACrE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IAC/C,MAAM,CAAC,EAAE,MAAM,GAAG,aAAa,CAAA;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,YAAY,CAAA;IAC7B,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,oBAAoB,GAAG,SAAS,CAAC,CAAA;IACvE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,oBAAoB,GAAG,cAAc,CAAC,CAAA;IAC5E,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,2BAA2B,CAAC,CAAA;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC;AAyDD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,cAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAqKnF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type LocalSendEmailBindingConfig, createLocalSendEmailBinding } from '../../utils/send-email.js';
|
|
2
|
+
export { createLocalSendEmailBinding, type LocalSendEmailBindingConfig };
|
|
3
|
+
type SentEmail = Parameters<SendEmail['send']>[0];
|
|
4
|
+
export type MockSendEmailBinding = SendEmail & {
|
|
5
|
+
/** Every message accepted by `send()`, in call order. */
|
|
6
|
+
readonly sentEmails: SentEmail[];
|
|
7
|
+
/** Alias for {@link sentEmails} (parity with other record-only mocks). */
|
|
8
|
+
readonly messages: SentEmail[];
|
|
9
|
+
/** Clear the recorded messages. */
|
|
10
|
+
clear(): void;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Creates a recording SendEmail binding for pure unit tests.
|
|
14
|
+
*
|
|
15
|
+
* Delegates `from`/destination allow-list enforcement to
|
|
16
|
+
* {@link createLocalSendEmailBinding} (so disallowed senders/recipients throw
|
|
17
|
+
* exactly as they would locally), and records each accepted message.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* const email = createMockSendEmail()
|
|
22
|
+
* await email.send(new EmailMessage('from@a.com', 'to@b.com', '...'))
|
|
23
|
+
* expect(email.sentEmails).toHaveLength(1)
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function createMockSendEmail(config?: LocalSendEmailBindingConfig): MockSendEmailBinding;
|
|
27
|
+
//# sourceMappingURL=send-email.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send-email.d.ts","sourceRoot":"","sources":["../../../src/test/utilities/send-email.ts"],"names":[],"mappings":"AAcA,OAAO,EACN,KAAK,2BAA2B,EAChC,2BAA2B,EAC3B,MAAM,wBAAwB,CAAA;AAI/B,OAAO,EAAE,2BAA2B,EAAE,KAAK,2BAA2B,EAAE,CAAA;AAExE,KAAK,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAEjD,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG;IAC9C,yDAAyD;IACzD,QAAQ,CAAC,UAAU,EAAE,SAAS,EAAE,CAAA;IAChC,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAA;IAC9B,mCAAmC;IACnC,KAAK,IAAI,IAAI,CAAA;CACb,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAClC,MAAM,GAAE,2BAAgC,GACtC,oBAAoB,CAuBtB"}
|
package/dist/test/utilities.d.ts
CHANGED
|
@@ -10,5 +10,6 @@ export * from './utilities/stream-flagship.js';
|
|
|
10
10
|
export * from './utilities/artifacts.js';
|
|
11
11
|
export * from './utilities/vectorize.js';
|
|
12
12
|
export * from './utilities/analytics-engine.js';
|
|
13
|
+
export * from './utilities/send-email.js';
|
|
13
14
|
export * from './utilities/env.js';
|
|
14
15
|
//# sourceMappingURL=utilities.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../../src/test/utilities.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA;AACjC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,iBAAiB,CAAA"}
|
|
1
|
+
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../../src/test/utilities.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA;AACjC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,wBAAwB,CAAA;AACtC,cAAc,iBAAiB,CAAA"}
|
package/package.json
CHANGED