@c9up/bay 0.1.13 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -16
- package/dist/BayProvider.d.ts +51 -11
- package/dist/BayProvider.d.ts.map +1 -1
- package/dist/BayProvider.js +36 -13
- package/dist/BayProvider.js.map +1 -1
- package/dist/Job.d.ts +99 -0
- package/dist/Job.d.ts.map +1 -0
- package/dist/Job.js +78 -0
- package/dist/Job.js.map +1 -0
- package/dist/QueueManager.d.ts +140 -21
- package/dist/QueueManager.d.ts.map +1 -1
- package/dist/QueueManager.js +247 -53
- package/dist/QueueManager.js.map +1 -1
- package/dist/adapters.d.ts +68 -0
- package/dist/adapters.d.ts.map +1 -0
- package/dist/adapters.js +56 -0
- package/dist/adapters.js.map +1 -0
- package/dist/augmentations.d.ts +28 -0
- package/dist/augmentations.d.ts.map +1 -0
- package/dist/augmentations.js +17 -0
- package/dist/augmentations.js.map +1 -0
- package/dist/configure.d.ts +1 -0
- package/dist/configure.d.ts.map +1 -1
- package/dist/configure.js +24 -7
- package/dist/configure.js.map +1 -1
- package/dist/console/contract.d.ts +60 -0
- package/dist/console/contract.d.ts.map +1 -0
- package/dist/console/contract.js +36 -0
- package/dist/console/contract.js.map +1 -0
- package/dist/console/index.d.ts +29 -0
- package/dist/console/index.d.ts.map +1 -0
- package/dist/console/index.js +45 -0
- package/dist/console/index.js.map +1 -0
- package/dist/console/makeJob.d.ts +32 -0
- package/dist/console/makeJob.d.ts.map +1 -0
- package/dist/console/makeJob.js +118 -0
- package/dist/console/makeJob.js.map +1 -0
- package/dist/console/queueWork.d.ts +18 -0
- package/dist/console/queueWork.d.ts.map +1 -0
- package/dist/console/queueWork.js +58 -0
- package/dist/console/queueWork.js.map +1 -0
- package/dist/drivers/MemoryDriver.d.ts +14 -8
- package/dist/drivers/MemoryDriver.d.ts.map +1 -1
- package/dist/drivers/MemoryDriver.js +61 -7
- package/dist/drivers/MemoryDriver.js.map +1 -1
- package/dist/drivers/RedisDriver.d.ts +60 -8
- package/dist/drivers/RedisDriver.d.ts.map +1 -1
- package/dist/drivers/RedisDriver.js +214 -30
- package/dist/drivers/RedisDriver.js.map +1 -1
- package/dist/index.d.ts +10 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -4
- package/dist/index.js.map +1 -1
- package/dist/jobs.d.ts +55 -0
- package/dist/jobs.d.ts.map +1 -0
- package/dist/jobs.js +135 -0
- package/dist/jobs.js.map +1 -0
- package/dist/quasar.d.ts +6 -9
- package/dist/quasar.d.ts.map +1 -1
- package/dist/quasar.js +27 -55
- package/dist/quasar.js.map +1 -1
- package/dist/testing/FakeQueue.d.ts +15 -9
- package/dist/testing/FakeQueue.d.ts.map +1 -1
- package/dist/testing/FakeQueue.js +13 -3
- package/dist/testing/FakeQueue.js.map +1 -1
- package/dist/vendor/nodeEnv.d.ts +5 -0
- package/dist/vendor/nodeEnv.d.ts.map +1 -0
- package/dist/{nodeEnv.js → vendor/nodeEnv.js} +13 -7
- package/dist/vendor/nodeEnv.js.map +1 -0
- package/dist/vendor/quasarConnection.d.ts +35 -0
- package/dist/vendor/quasarConnection.d.ts.map +1 -0
- package/dist/vendor/quasarConnection.js +62 -0
- package/dist/vendor/quasarConnection.js.map +1 -0
- package/package.json +5 -3
- package/src/BayProvider.ts +92 -26
- package/src/Job.ts +137 -0
- package/src/QueueManager.ts +411 -56
- package/src/adapters.ts +75 -0
- package/src/augmentations.ts +31 -0
- package/src/configure.ts +25 -7
- package/src/console/contract.ts +94 -0
- package/src/console/index.ts +68 -0
- package/src/console/makeJob.ts +139 -0
- package/src/console/queueWork.ts +70 -0
- package/src/drivers/MemoryDriver.ts +66 -14
- package/src/drivers/RedisDriver.ts +303 -43
- package/src/index.ts +35 -6
- package/src/jobs.ts +144 -0
- package/src/quasar.ts +28 -72
- package/src/testing/FakeQueue.ts +25 -15
- package/src/{nodeEnv.ts → vendor/nodeEnv.ts} +14 -7
- package/src/vendor/quasarConnection.ts +129 -0
- package/dist/nodeEnv.d.ts +0 -16
- package/dist/nodeEnv.d.ts.map +0 -1
- package/dist/nodeEnv.js.map +0 -1
- package/dist/stores.d.ts +0 -41
- package/dist/stores.d.ts.map +0 -1
- package/dist/stores.js +0 -46
- package/dist/stores.js.map +0 -1
- package/src/stores.ts +0 -59
package/src/quasar.ts
CHANGED
|
@@ -1,84 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Resolving a Redis connection by name, from `@c9up/quasar`.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* The shape is checked before use rather than asserted, the same way bay
|
|
10
|
-
* duck-types its host framework.
|
|
4
|
+
* The loading, the shape check and the messages are the same in every package
|
|
5
|
+
* that offers a Redis-backed option, so they are vendored rather than written
|
|
6
|
+
* again: `src/vendor/quasarConnection.ts`, generated from one source. What is
|
|
7
|
+
* specific to this package — the commands it issues, and what it does with
|
|
8
|
+
* them — stays here, because that is the part a reader needs.
|
|
11
9
|
*/
|
|
12
10
|
|
|
13
11
|
import type { RedisClient } from "./drivers/RedisDriver.js";
|
|
12
|
+
import { quasarConnection as loadQuasarConnection } from "./vendor/quasarConnection.js";
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
function isRedisClient(value: unknown): value is RedisClient {
|
|
29
|
-
if (typeof value !== "object" || value === null) return false;
|
|
30
|
-
// The commands this driver actually issues — every non-optional member of
|
|
31
|
-
// `RedisClient`. A connection missing one would fail on the first job push,
|
|
32
|
-
// far from the cause. `lmove` is deliberately absent: the driver declares it
|
|
33
|
-
// optional and falls back when it is not there.
|
|
34
|
-
const required = [
|
|
35
|
-
"rpush",
|
|
36
|
-
"lpop",
|
|
37
|
-
"lrem",
|
|
38
|
-
"llen",
|
|
39
|
-
"lrange",
|
|
40
|
-
"del",
|
|
41
|
-
"set",
|
|
42
|
-
"get",
|
|
43
|
-
];
|
|
44
|
-
return required.every(
|
|
45
|
-
(name) => typeof Reflect.get(value, name) === "function",
|
|
46
|
-
);
|
|
47
|
-
}
|
|
14
|
+
// The commands this driver actually issues — every non-optional member of
|
|
15
|
+
// `RedisClient`. `lmove` is deliberately absent: the driver declares it
|
|
16
|
+
// optional and falls back when it is not there.
|
|
17
|
+
const REQUIRED = [
|
|
18
|
+
"rpush",
|
|
19
|
+
"lpop",
|
|
20
|
+
"lrem",
|
|
21
|
+
"llen",
|
|
22
|
+
"lrange",
|
|
23
|
+
"del",
|
|
24
|
+
"set",
|
|
25
|
+
"get",
|
|
26
|
+
] as const;
|
|
48
27
|
|
|
49
28
|
/**
|
|
50
|
-
* A resolver
|
|
51
|
-
* loaded on the first queue command, not at config time.
|
|
29
|
+
* A resolver — quasar is loaded on first use, not at config time.
|
|
52
30
|
*/
|
|
53
31
|
export function quasarConnection(name?: string): () => Promise<RedisClient> {
|
|
54
|
-
return async () =>
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
" pnpm add @c9up/quasar",
|
|
63
|
-
{ cause },
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const manager = isConnectionSource(loaded)
|
|
68
|
-
? loaded
|
|
69
|
-
: Reflect.get(Object(loaded), "default");
|
|
70
|
-
if (!isConnectionSource(manager)) {
|
|
71
|
-
throw new Error(
|
|
72
|
-
"Bay: @c9up/quasar/services/main did not expose a connection() manager",
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const connection = manager.connection(name);
|
|
77
|
-
if (!isRedisClient(connection)) {
|
|
78
|
-
throw new Error(
|
|
79
|
-
`Bay: quasar connection "${name ?? "default"}" does not carry the commands this queue needs`,
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
return connection;
|
|
83
|
-
};
|
|
32
|
+
return async () =>
|
|
33
|
+
loadQuasarConnection<RedisClient>({
|
|
34
|
+
pkg: "bay",
|
|
35
|
+
name,
|
|
36
|
+
required: REQUIRED,
|
|
37
|
+
what: "the queue driver",
|
|
38
|
+
raise: (_reason, message, cause) => new Error(message, { cause }),
|
|
39
|
+
});
|
|
84
40
|
}
|
package/src/testing/FakeQueue.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* the fake into a runtime build.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import type {
|
|
12
|
+
import type { JobRecord, QueueDriver } from "../QueueManager.js";
|
|
13
13
|
|
|
14
14
|
export interface FakeQueuePredicate {
|
|
15
15
|
/** Custom payload predicate — receives the job's `payload` and
|
|
@@ -23,12 +23,12 @@ export interface FakeQueuePredicate {
|
|
|
23
23
|
|
|
24
24
|
export type FakeQueuePredicateArg =
|
|
25
25
|
| FakeQueuePredicate
|
|
26
|
-
| ((job:
|
|
26
|
+
| ((job: JobRecord) => boolean);
|
|
27
27
|
|
|
28
28
|
export class FakeQueue implements QueueDriver {
|
|
29
|
-
#pushed:
|
|
29
|
+
#pushed: JobRecord[] = [];
|
|
30
30
|
|
|
31
|
-
async push(job:
|
|
31
|
+
async push(job: JobRecord): Promise<void> {
|
|
32
32
|
// Reject duplicate ids to surface the most common test-fixture
|
|
33
33
|
// mistake — two `makeJob({ id: 'x' })` reused across pushes
|
|
34
34
|
// silently corrupts later `fail`/`complete`/`retry` lookups.
|
|
@@ -43,25 +43,35 @@ export class FakeQueue implements QueueDriver {
|
|
|
43
43
|
/** Always returns `null` — fake queues never auto-dispatch.
|
|
44
44
|
* Tests that need handler execution should use the memory
|
|
45
45
|
* driver directly. */
|
|
46
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Always empty: this fake captures what was dispatched, it does not run it.
|
|
48
|
+
*
|
|
49
|
+
* The parameter is declared so the queue names a caller asks for are part of
|
|
50
|
+
* the signature a test reads, even though nothing here serves them.
|
|
51
|
+
*/
|
|
52
|
+
async pop(_queues?: readonly string[]): Promise<JobRecord | null> {
|
|
47
53
|
return null;
|
|
48
54
|
}
|
|
49
55
|
|
|
50
|
-
async fail(job:
|
|
56
|
+
async fail(job: JobRecord, error: string): Promise<void> {
|
|
51
57
|
const found = this.#requireJob(job, "fail");
|
|
52
58
|
found.status = "failed";
|
|
53
59
|
found.error = error;
|
|
54
60
|
}
|
|
55
61
|
|
|
56
|
-
async complete(job:
|
|
62
|
+
async complete(job: JobRecord): Promise<void> {
|
|
57
63
|
const found = this.#requireJob(job, "complete");
|
|
58
64
|
found.status = "completed";
|
|
59
65
|
found.processedAt = Date.now();
|
|
60
66
|
}
|
|
61
67
|
|
|
62
|
-
async retry(job:
|
|
68
|
+
async retry(job: JobRecord): Promise<void> {
|
|
63
69
|
const found = this.#requireJob(job, "retry");
|
|
64
|
-
|
|
70
|
+
// `attempts` is the WORKER's counter, not the driver's: `processOne`
|
|
71
|
+
// increments it before it calls this, and neither real driver touches it
|
|
72
|
+
// again. Incrementing here counted the same attempt twice, so a fake
|
|
73
|
+
// exhausted `maxAttempts` in half the tries the real queue takes — a
|
|
74
|
+
// test double that disagrees with what it stands in for.
|
|
65
75
|
found.status = "pending";
|
|
66
76
|
// Reset transient state from the prior failure so a retried
|
|
67
77
|
// job's invariants match a fresh push (a real driver would
|
|
@@ -73,9 +83,9 @@ export class FakeQueue implements QueueDriver {
|
|
|
73
83
|
|
|
74
84
|
/** Look up the captured copy of a job by id. Throws when the id
|
|
75
85
|
* isn't present — silent no-op on a missing job is the most
|
|
76
|
-
* insidious test bug (caller's local
|
|
86
|
+
* insidious test bug (caller's local job ref shows the new
|
|
77
87
|
* status while the FakeQueue's internal capture is unchanged). */
|
|
78
|
-
#requireJob(job:
|
|
88
|
+
#requireJob(job: JobRecord, verb: string): JobRecord {
|
|
79
89
|
const found = this.#pushed.find((j) => j.id === job.id);
|
|
80
90
|
if (!found) {
|
|
81
91
|
throw new Error(
|
|
@@ -85,7 +95,7 @@ export class FakeQueue implements QueueDriver {
|
|
|
85
95
|
return found;
|
|
86
96
|
}
|
|
87
97
|
|
|
88
|
-
async failed(): Promise<
|
|
98
|
+
async failed(): Promise<JobRecord[]> {
|
|
89
99
|
return this.#pushed
|
|
90
100
|
.filter((j) => j.status === "failed")
|
|
91
101
|
.map((j) => ({ ...j }));
|
|
@@ -100,7 +110,7 @@ export class FakeQueue implements QueueDriver {
|
|
|
100
110
|
* shallow clone so test-side mutations can't bleed back into the
|
|
101
111
|
* internal capture store — avoids cross-test contamination.
|
|
102
112
|
*/
|
|
103
|
-
getPushed():
|
|
113
|
+
getPushed(): JobRecord[] {
|
|
104
114
|
return this.#pushed.map((j) => ({ ...j }));
|
|
105
115
|
}
|
|
106
116
|
|
|
@@ -129,7 +139,7 @@ export class FakeQueue implements QueueDriver {
|
|
|
129
139
|
function makeMatcher(
|
|
130
140
|
name: string,
|
|
131
141
|
predicate: FakeQueuePredicateArg | undefined,
|
|
132
|
-
): (j:
|
|
142
|
+
): (j: JobRecord) => boolean {
|
|
133
143
|
// Function-form predicate — caller does ALL the matching, the
|
|
134
144
|
// `name` arg is still a hard prerequisite.
|
|
135
145
|
if (typeof predicate === "function") {
|
|
@@ -162,7 +172,7 @@ function describePredicate(
|
|
|
162
172
|
return `, ${JSON.stringify(predicate)}`;
|
|
163
173
|
}
|
|
164
174
|
|
|
165
|
-
function describeCaptured(captured:
|
|
175
|
+
function describeCaptured(captured: JobRecord[]): string {
|
|
166
176
|
if (captured.length === 0) return "Captured: (none)";
|
|
167
177
|
const lines = captured.map(
|
|
168
178
|
(j, i) =>
|
|
@@ -1,13 +1,20 @@
|
|
|
1
|
+
// Generated from scripts/vendor/nodeEnv.ts — do not edit.
|
|
2
|
+
//
|
|
3
|
+
// This package is published and built from its own repository, so the file
|
|
4
|
+
// has to exist here rather than be imported. `pnpm vendor:sync` rewrites it,
|
|
5
|
+
// and `pnpm vendor:check` fails if this copy has drifted from the original.
|
|
6
|
+
|
|
1
7
|
/**
|
|
2
|
-
*
|
|
8
|
+
* `NODE_ENV`, read the way every runtime actually spells it.
|
|
3
9
|
*
|
|
4
|
-
* `NODE_ENV=prod` is ordinary in a Dockerfile or a platform dashboard
|
|
5
|
-
*
|
|
6
|
-
*
|
|
10
|
+
* `NODE_ENV=prod` is ordinary in a Dockerfile or a platform dashboard, and a
|
|
11
|
+
* bare `=== "production"` answers "not production" for it. What that costs
|
|
12
|
+
* differs per package, so the consequence is stated where the decision is
|
|
13
|
+
* taken, not here.
|
|
7
14
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
15
|
+
* The tables mirror the framework's (`@c9up/ream`, src/env/nodeEnv.ts), which
|
|
16
|
+
* is the origin rather than a peer: it formats to different rules and exposes
|
|
17
|
+
* `currentNodeEnv()` instead of `inProduction()`.
|
|
11
18
|
*/
|
|
12
19
|
|
|
13
20
|
const DEV_ENVS = ["dev", "develop", "development"];
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// Generated from scripts/vendor/quasarConnection.ts — do not edit.
|
|
2
|
+
//
|
|
3
|
+
// This package is published and built from its own repository, so the file
|
|
4
|
+
// has to exist here rather than be imported. `pnpm vendor:sync` rewrites it,
|
|
5
|
+
// and `pnpm vendor:check` fails if this copy has drifted from the original.
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Resolving a Redis connection by name, from `@c9up/quasar`.
|
|
9
|
+
*
|
|
10
|
+
* No package here depends on quasar: it is an optional peer, and this module
|
|
11
|
+
* never imports it statically — the specifier is built at runtime so the
|
|
12
|
+
* TypeScript build stays free of it too. A host that never names a connection
|
|
13
|
+
* neither installs it nor pays for it.
|
|
14
|
+
*
|
|
15
|
+
* What varies between callers is passed in rather than copied: which commands
|
|
16
|
+
* they will issue, and what they are doing with them. Both end up in the
|
|
17
|
+
* message, because "the connection is missing lpop" is only useful next to
|
|
18
|
+
* "which the queue's atomic pop issues".
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/** The slice of quasar's manager this needs: a connection, by name. */
|
|
22
|
+
interface ConnectionSource {
|
|
23
|
+
connection(name?: string): unknown;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Read a member without assuming how the object answers.
|
|
28
|
+
*
|
|
29
|
+
* Two shapes have to work, and they disagree about `in`. Quasar's accessor is
|
|
30
|
+
* a Proxy over an empty null-prototype object with only a `get` trap, so
|
|
31
|
+
* `"connection" in manager` is FALSE while reading it returns the function —
|
|
32
|
+
* gating on `in` rejected the real manager. And a module namespace under a
|
|
33
|
+
* test double RAISES for an export it does not have, rather than answering
|
|
34
|
+
* undefined, so a bare read fails on the mock. Reading through a catch is what
|
|
35
|
+
* satisfies both.
|
|
36
|
+
*/
|
|
37
|
+
function readMember(value: unknown, name: string): unknown {
|
|
38
|
+
if (typeof value !== "object" || value === null) return undefined;
|
|
39
|
+
try {
|
|
40
|
+
return Reflect.get(value, name);
|
|
41
|
+
} catch {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function isConnectionSource(value: unknown): value is ConnectionSource {
|
|
47
|
+
return typeof readMember(value, "connection") === "function";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface QuasarConnectionRequest {
|
|
51
|
+
/** The package asking. It prefixes every message this can raise. */
|
|
52
|
+
pkg: string;
|
|
53
|
+
/**
|
|
54
|
+
* How this package builds an error.
|
|
55
|
+
*
|
|
56
|
+
* Not optional, and not `new Error` by default: a package with its own
|
|
57
|
+
* error type carries codes (`E_<PKG>_<REASON>`) that a caller catches on,
|
|
58
|
+
* and a shared helper throwing a bare Error would silently drop them. The
|
|
59
|
+
* two reasons are distinguished so the codes can be too.
|
|
60
|
+
*/
|
|
61
|
+
raise: (
|
|
62
|
+
reason: "quasar-missing" | "incomplete-connection",
|
|
63
|
+
message: string,
|
|
64
|
+
cause?: unknown,
|
|
65
|
+
) => Error;
|
|
66
|
+
/** Connection name, or `undefined` for quasar's default. */
|
|
67
|
+
name?: string;
|
|
68
|
+
/** The commands the caller will actually issue. */
|
|
69
|
+
required: readonly string[];
|
|
70
|
+
/** What the caller does with them, for the message that names a gap. */
|
|
71
|
+
what: string;
|
|
72
|
+
/**
|
|
73
|
+
* A second way out, when this package has one.
|
|
74
|
+
*
|
|
75
|
+
* Several of them accept a client object directly, so "pass a client
|
|
76
|
+
* instead of a connection name" is actionable — and it was in each
|
|
77
|
+
* package's own message before this was shared. Dropping it to unify the
|
|
78
|
+
* wording would have made the error strictly less useful.
|
|
79
|
+
*/
|
|
80
|
+
alternative?: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The named connection, checked for the commands the caller needs BEFORE it is
|
|
85
|
+
* handed over — a connection missing one would otherwise fail on the first
|
|
86
|
+
* command, far from the line that asked for it.
|
|
87
|
+
*/
|
|
88
|
+
export async function quasarConnection<T>(
|
|
89
|
+
request: QuasarConnectionRequest,
|
|
90
|
+
): Promise<T> {
|
|
91
|
+
const { pkg, name, required, what, raise, alternative } = request;
|
|
92
|
+
const specifier = "@c9up/quasar/services/main";
|
|
93
|
+
let loaded: unknown;
|
|
94
|
+
try {
|
|
95
|
+
loaded = await import(/* @vite-ignore */ specifier);
|
|
96
|
+
} catch (cause) {
|
|
97
|
+
throw raise(
|
|
98
|
+
"quasar-missing",
|
|
99
|
+
`[${pkg}] ${what} asks for the quasar connection "${name ?? "default"}", but @c9up/quasar is not installed.\n` +
|
|
100
|
+
` pnpm add @c9up/quasar${alternative ? `, ${alternative}` : ""}`,
|
|
101
|
+
cause,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const manager = isConnectionSource(loaded)
|
|
106
|
+
? loaded
|
|
107
|
+
: Reflect.get(Object(loaded), "default");
|
|
108
|
+
if (!isConnectionSource(manager)) {
|
|
109
|
+
throw raise(
|
|
110
|
+
"quasar-missing",
|
|
111
|
+
`[${pkg}] @c9up/quasar/services/main did not expose a connection() manager`,
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const connection = manager.connection(name);
|
|
116
|
+
const missing = required.filter(
|
|
117
|
+
(command) => typeof readMember(connection, command) !== "function",
|
|
118
|
+
);
|
|
119
|
+
if (missing.length > 0) {
|
|
120
|
+
throw raise(
|
|
121
|
+
"incomplete-connection",
|
|
122
|
+
`[${pkg}] the quasar connection${name ? ` '${name}'` : ""} is missing ${missing.join(", ")}, which ${what} issues`,
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
// Load-bearing: every member of `required` has just been checked to be a
|
|
126
|
+
// function on this object. The caller names the type it needs because only
|
|
127
|
+
// the caller knows which commands it asked for.
|
|
128
|
+
return connection as T;
|
|
129
|
+
}
|
package/dist/nodeEnv.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reading `NODE_ENV`, with the aliases people actually set.
|
|
3
|
-
*
|
|
4
|
-
* `NODE_ENV=prod` is ordinary in a Dockerfile or a platform dashboard. Read
|
|
5
|
-
* verbatim it answers "not production" — and here that decides whether a queue
|
|
6
|
-
* silently accepts a delivery guarantee weaker than the one it advertises.
|
|
7
|
-
*
|
|
8
|
-
* Duplicated rather than imported: bay depends on no other package in this
|
|
9
|
-
* workspace, and a safety decision that only holds when an optional peer is
|
|
10
|
-
* installed is not a decision.
|
|
11
|
-
*/
|
|
12
|
-
/** The canonical name for whatever `NODE_ENV` holds. */
|
|
13
|
-
export declare function normalizeNodeEnv(value: string | undefined): string;
|
|
14
|
-
/** Whether this process is running in production, under any spelling. */
|
|
15
|
-
export declare function inProduction(): boolean;
|
|
16
|
-
//# sourceMappingURL=nodeEnv.d.ts.map
|
package/dist/nodeEnv.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nodeEnv.d.ts","sourceRoot":"","sources":["../src/nodeEnv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,wDAAwD;AACxD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAOlE;AAED,yEAAyE;AACzE,wBAAgB,YAAY,IAAI,OAAO,CAEtC"}
|
package/dist/nodeEnv.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nodeEnv.js","sourceRoot":"","sources":["../src/nodeEnv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;AACnD,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AACzC,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAEtC,wDAAwD;AACxD,MAAM,UAAU,gBAAgB,CAAC,KAAyB;IACzD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC1D,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAChC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,aAAa,CAAC;IACjD,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,YAAY,CAAC;IACjD,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC;IAC3C,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,YAAY;IAC3B,OAAO,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,YAAY,CAAC;AAChE,CAAC"}
|
package/dist/stores.d.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The queue store factories a config file names — `{ default, stores }`.
|
|
3
|
-
*
|
|
4
|
-
* The shape AdonisJS gives a package with several backends and one selected:
|
|
5
|
-
* a `stores` namespace imported beside `defineConfig`, each entry that
|
|
6
|
-
* namespace's result, and the selection read from the environment. Bay had a
|
|
7
|
-
* single `driver: "memory"` and told everyone else to build the manager by
|
|
8
|
-
* hand, which meant Redis could not be reached from a config file at all.
|
|
9
|
-
*
|
|
10
|
-
* import { defineConfig, stores } from '@c9up/bay'
|
|
11
|
-
*
|
|
12
|
-
* export default defineConfig({
|
|
13
|
-
* default: env.get('QUEUE_STORE'),
|
|
14
|
-
* stores: {
|
|
15
|
-
* memory: stores.memory(),
|
|
16
|
-
* redis: stores.redis({ connection: 'main' }),
|
|
17
|
-
* },
|
|
18
|
-
* })
|
|
19
|
-
*
|
|
20
|
-
* Factories are lazy: only the store an application actually uses is built, so
|
|
21
|
-
* naming a Redis queue in a config that runs in memory opens no connection.
|
|
22
|
-
*/
|
|
23
|
-
import type { RedisClientSource } from "./drivers/RedisDriver.js";
|
|
24
|
-
import type { QueueDriver } from "./QueueManager.js";
|
|
25
|
-
/** A driver, built on first use. */
|
|
26
|
-
export type QueueStoreFactory = () => QueueDriver;
|
|
27
|
-
export declare const stores: {
|
|
28
|
-
/** In memory. Jobs do not survive a restart — for tests and dev. */
|
|
29
|
-
memory(): QueueStoreFactory;
|
|
30
|
-
/**
|
|
31
|
-
* Redis. `connection` takes an ioredis-shaped client, a function answering
|
|
32
|
-
* one, or the NAME of a `@c9up/quasar` connection — the last resolved at
|
|
33
|
-
* first use, without bay importing quasar, which stays an optional peer.
|
|
34
|
-
*/
|
|
35
|
-
redis(options: {
|
|
36
|
-
connection: RedisClientSource | string;
|
|
37
|
-
prefix?: string;
|
|
38
|
-
visibilityTimeoutMs?: number;
|
|
39
|
-
}): QueueStoreFactory;
|
|
40
|
-
};
|
|
41
|
-
//# sourceMappingURL=stores.d.ts.map
|
package/dist/stores.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"stores.d.ts","sourceRoot":"","sources":["../src/stores.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,oCAAoC;AACpC,MAAM,MAAM,iBAAiB,GAAG,MAAM,WAAW,CAAC;AAElD,eAAO,MAAM,MAAM;IAClB,oEAAoE;cAC1D,iBAAiB;IAI3B;;;;OAIG;mBACY;QACd,UAAU,EAAE,iBAAiB,GAAG,MAAM,CAAC;QACvC,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC7B,GAAG,iBAAiB;CAWrB,CAAC"}
|
package/dist/stores.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The queue store factories a config file names — `{ default, stores }`.
|
|
3
|
-
*
|
|
4
|
-
* The shape AdonisJS gives a package with several backends and one selected:
|
|
5
|
-
* a `stores` namespace imported beside `defineConfig`, each entry that
|
|
6
|
-
* namespace's result, and the selection read from the environment. Bay had a
|
|
7
|
-
* single `driver: "memory"` and told everyone else to build the manager by
|
|
8
|
-
* hand, which meant Redis could not be reached from a config file at all.
|
|
9
|
-
*
|
|
10
|
-
* import { defineConfig, stores } from '@c9up/bay'
|
|
11
|
-
*
|
|
12
|
-
* export default defineConfig({
|
|
13
|
-
* default: env.get('QUEUE_STORE'),
|
|
14
|
-
* stores: {
|
|
15
|
-
* memory: stores.memory(),
|
|
16
|
-
* redis: stores.redis({ connection: 'main' }),
|
|
17
|
-
* },
|
|
18
|
-
* })
|
|
19
|
-
*
|
|
20
|
-
* Factories are lazy: only the store an application actually uses is built, so
|
|
21
|
-
* naming a Redis queue in a config that runs in memory opens no connection.
|
|
22
|
-
*/
|
|
23
|
-
import { MemoryDriver } from "./drivers/MemoryDriver.js";
|
|
24
|
-
import { RedisDriver } from "./drivers/RedisDriver.js";
|
|
25
|
-
import { quasarConnection } from "./quasar.js";
|
|
26
|
-
export const stores = {
|
|
27
|
-
/** In memory. Jobs do not survive a restart — for tests and dev. */
|
|
28
|
-
memory() {
|
|
29
|
-
return () => new MemoryDriver();
|
|
30
|
-
},
|
|
31
|
-
/**
|
|
32
|
-
* Redis. `connection` takes an ioredis-shaped client, a function answering
|
|
33
|
-
* one, or the NAME of a `@c9up/quasar` connection — the last resolved at
|
|
34
|
-
* first use, without bay importing quasar, which stays an optional peer.
|
|
35
|
-
*/
|
|
36
|
-
redis(options) {
|
|
37
|
-
const source = typeof options.connection === "string"
|
|
38
|
-
? quasarConnection(options.connection)
|
|
39
|
-
: options.connection;
|
|
40
|
-
return () => new RedisDriver(source, {
|
|
41
|
-
prefix: options.prefix,
|
|
42
|
-
visibilityTimeoutMs: options.visibilityTimeoutMs,
|
|
43
|
-
});
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
//# sourceMappingURL=stores.js.map
|
package/dist/stores.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"stores.js","sourceRoot":"","sources":["../src/stores.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAK/C,MAAM,CAAC,MAAM,MAAM,GAAG;IACrB,oEAAoE;IACpE,MAAM;QACL,OAAO,GAAG,EAAE,CAAC,IAAI,YAAY,EAAE,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,OAIL;QACA,MAAM,MAAM,GACX,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ;YACrC,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,UAAU,CAAC;YACtC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;QACvB,OAAO,GAAG,EAAE,CACX,IAAI,WAAW,CAAC,MAAM,EAAE;YACvB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;SAChD,CAAC,CAAC;IACL,CAAC;CACD,CAAC"}
|
package/src/stores.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The queue store factories a config file names — `{ default, stores }`.
|
|
3
|
-
*
|
|
4
|
-
* The shape AdonisJS gives a package with several backends and one selected:
|
|
5
|
-
* a `stores` namespace imported beside `defineConfig`, each entry that
|
|
6
|
-
* namespace's result, and the selection read from the environment. Bay had a
|
|
7
|
-
* single `driver: "memory"` and told everyone else to build the manager by
|
|
8
|
-
* hand, which meant Redis could not be reached from a config file at all.
|
|
9
|
-
*
|
|
10
|
-
* import { defineConfig, stores } from '@c9up/bay'
|
|
11
|
-
*
|
|
12
|
-
* export default defineConfig({
|
|
13
|
-
* default: env.get('QUEUE_STORE'),
|
|
14
|
-
* stores: {
|
|
15
|
-
* memory: stores.memory(),
|
|
16
|
-
* redis: stores.redis({ connection: 'main' }),
|
|
17
|
-
* },
|
|
18
|
-
* })
|
|
19
|
-
*
|
|
20
|
-
* Factories are lazy: only the store an application actually uses is built, so
|
|
21
|
-
* naming a Redis queue in a config that runs in memory opens no connection.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
import { MemoryDriver } from "./drivers/MemoryDriver.js";
|
|
25
|
-
import type { RedisClientSource } from "./drivers/RedisDriver.js";
|
|
26
|
-
import { RedisDriver } from "./drivers/RedisDriver.js";
|
|
27
|
-
import type { QueueDriver } from "./QueueManager.js";
|
|
28
|
-
import { quasarConnection } from "./quasar.js";
|
|
29
|
-
|
|
30
|
-
/** A driver, built on first use. */
|
|
31
|
-
export type QueueStoreFactory = () => QueueDriver;
|
|
32
|
-
|
|
33
|
-
export const stores = {
|
|
34
|
-
/** In memory. Jobs do not survive a restart — for tests and dev. */
|
|
35
|
-
memory(): QueueStoreFactory {
|
|
36
|
-
return () => new MemoryDriver();
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Redis. `connection` takes an ioredis-shaped client, a function answering
|
|
41
|
-
* one, or the NAME of a `@c9up/quasar` connection — the last resolved at
|
|
42
|
-
* first use, without bay importing quasar, which stays an optional peer.
|
|
43
|
-
*/
|
|
44
|
-
redis(options: {
|
|
45
|
-
connection: RedisClientSource | string;
|
|
46
|
-
prefix?: string;
|
|
47
|
-
visibilityTimeoutMs?: number;
|
|
48
|
-
}): QueueStoreFactory {
|
|
49
|
-
const source: RedisClientSource =
|
|
50
|
-
typeof options.connection === "string"
|
|
51
|
-
? quasarConnection(options.connection)
|
|
52
|
-
: options.connection;
|
|
53
|
-
return () =>
|
|
54
|
-
new RedisDriver(source, {
|
|
55
|
-
prefix: options.prefix,
|
|
56
|
-
visibilityTimeoutMs: options.visibilityTimeoutMs,
|
|
57
|
-
});
|
|
58
|
-
},
|
|
59
|
-
};
|