@antseed/cli 0.1.196 → 0.1.198
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/commands/buyer/start.d.ts.map +1 -1
- package/dist/cli/commands/buyer/start.js +1 -0
- package/dist/cli/commands/buyer/start.js.map +1 -1
- package/dist/cli/commands/gateway/activity.d.ts.map +1 -1
- package/dist/cli/commands/gateway/activity.js +26 -5
- package/dist/cli/commands/gateway/activity.js.map +1 -1
- package/dist/config/types.d.ts +2 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/gateway/accounting.d.ts +118 -6
- package/dist/gateway/accounting.d.ts.map +1 -1
- package/dist/gateway/accounting.js +319 -21
- package/dist/gateway/accounting.js.map +1 -1
- package/dist/gateway/console-api/handlers/favorites.d.ts +9 -0
- package/dist/gateway/console-api/handlers/favorites.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/favorites.js +44 -0
- package/dist/gateway/console-api/handlers/favorites.js.map +1 -0
- package/dist/gateway/console-api/handlers/favorites.test.d.ts +2 -0
- package/dist/gateway/console-api/handlers/favorites.test.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/favorites.test.js +41 -0
- package/dist/gateway/console-api/handlers/favorites.test.js.map +1 -0
- package/dist/gateway/console-api/handlers/index.d.ts.map +1 -1
- package/dist/gateway/console-api/handlers/index.js +2 -0
- package/dist/gateway/console-api/handlers/index.js.map +1 -1
- package/dist/gateway/console-api/handlers/network-mapping.d.ts +7 -1
- package/dist/gateway/console-api/handlers/network-mapping.d.ts.map +1 -1
- package/dist/gateway/console-api/handlers/network-mapping.js +46 -0
- package/dist/gateway/console-api/handlers/network-mapping.js.map +1 -1
- package/dist/gateway/console-api/handlers/network.d.ts.map +1 -1
- package/dist/gateway/console-api/handlers/network.js +19 -3
- package/dist/gateway/console-api/handlers/network.js.map +1 -1
- package/dist/gateway/console-api/handlers/network.test.js +70 -8
- package/dist/gateway/console-api/handlers/network.test.js.map +1 -1
- package/dist/gateway/console-api/handlers/usage.d.ts.map +1 -1
- package/dist/gateway/console-api/handlers/usage.js +2 -1
- package/dist/gateway/console-api/handlers/usage.js.map +1 -1
- package/dist/gateway/console-api/types.d.ts +75 -1
- package/dist/gateway/console-api/types.d.ts.map +1 -1
- package/dist/gateway/console-api/types.js.map +1 -1
- package/dist/gateway/gateway.test.js +829 -3
- package/dist/gateway/gateway.test.js.map +1 -1
- package/dist/gateway/request-errors.test.js +30 -0
- package/dist/gateway/request-errors.test.js.map +1 -1
- package/dist/gateway/routing-through-gateway.test.js +120 -4
- package/dist/gateway/routing-through-gateway.test.js.map +1 -1
- package/dist/gateway/runtime.d.ts.map +1 -1
- package/dist/gateway/runtime.js +4 -0
- package/dist/gateway/runtime.js.map +1 -1
- package/dist/gateway/server.d.ts +20 -0
- package/dist/gateway/server.d.ts.map +1 -1
- package/dist/gateway/server.js +181 -25
- package/dist/gateway/server.js.map +1 -1
- package/dist/gateway/services/network.d.ts +6 -1
- package/dist/gateway/services/network.d.ts.map +1 -1
- package/dist/gateway/services/network.js +12 -1
- package/dist/gateway/services/network.js.map +1 -1
- package/dist/gateway/services/usage.d.ts +2 -0
- package/dist/gateway/services/usage.d.ts.map +1 -1
- package/dist/gateway/services/usage.js +19 -5
- package/dist/gateway/services/usage.js.map +1 -1
- package/dist/gateway/spend-feed.d.ts +4 -1
- package/dist/gateway/spend-feed.d.ts.map +1 -1
- package/dist/gateway/spend-feed.js +7 -0
- package/dist/gateway/spend-feed.js.map +1 -1
- package/dist/gateway/store-data.test.js +1 -1
- package/dist/gateway/store-data.test.js.map +1 -1
- package/dist/gateway/store-migrations.d.ts.map +1 -1
- package/dist/gateway/store-migrations.js +40 -0
- package/dist/gateway/store-migrations.js.map +1 -1
- package/dist/gateway/store.d.ts +63 -1
- package/dist/gateway/store.d.ts.map +1 -1
- package/dist/gateway/store.js +142 -21
- package/dist/gateway/store.js.map +1 -1
- package/dist/gateway/video-jobs.d.ts +12 -0
- package/dist/gateway/video-jobs.d.ts.map +1 -0
- package/dist/gateway/video-jobs.js +24 -0
- package/dist/gateway/video-jobs.js.map +1 -0
- package/dist/proxy/buyer-proxy.d.ts +15 -0
- package/dist/proxy/buyer-proxy.d.ts.map +1 -1
- package/dist/proxy/buyer-proxy.js +166 -19
- package/dist/proxy/buyer-proxy.js.map +1 -1
- package/dist/proxy/buyer-proxy.test.js +158 -1
- package/dist/proxy/buyer-proxy.test.js.map +1 -1
- package/dist/proxy/gateway-policy.test.js +75 -1
- package/dist/proxy/gateway-policy.test.js.map +1 -1
- package/dist/proxy/request-utils.d.ts +4 -0
- package/dist/proxy/request-utils.d.ts.map +1 -1
- package/dist/proxy/request-utils.js +4 -0
- package/dist/proxy/request-utils.js.map +1 -1
- package/dist/proxy/resource-routes.d.ts +2 -0
- package/dist/proxy/resource-routes.d.ts.map +1 -1
- package/dist/proxy/resource-routes.js +4 -0
- package/dist/proxy/resource-routes.js.map +1 -1
- package/dist/proxy/route-selection.d.ts +79 -0
- package/dist/proxy/route-selection.d.ts.map +1 -0
- package/dist/proxy/route-selection.js +79 -0
- package/dist/proxy/route-selection.js.map +1 -0
- package/dist/proxy/spend-attribution.d.ts +17 -1
- package/dist/proxy/spend-attribution.d.ts.map +1 -1
- package/dist/proxy/spend-attribution.js +45 -10
- package/dist/proxy/spend-attribution.js.map +1 -1
- package/dist/proxy/spend-attribution.test.d.ts +2 -0
- package/dist/proxy/spend-attribution.test.d.ts.map +1 -0
- package/dist/proxy/spend-attribution.test.js +63 -0
- package/dist/proxy/spend-attribution.test.js.map +1 -0
- package/dist/proxy/telemetry.d.ts +15 -0
- package/dist/proxy/telemetry.d.ts.map +1 -1
- package/dist/proxy/telemetry.js +26 -3
- package/dist/proxy/telemetry.js.map +1 -1
- package/dist/proxy/video-download.d.ts +9 -1
- package/dist/proxy/video-download.d.ts.map +1 -1
- package/dist/proxy/video-download.js +41 -6
- package/dist/proxy/video-download.js.map +1 -1
- package/dist/proxy/video-download.test.js +33 -3
- package/dist/proxy/video-download.test.js.map +1 -1
- package/package.json +7 -7
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { BUDGET_PERIODS, cappedPeriods, findLimitBreach, hasSpendLimits } from './limits.js';
|
|
3
3
|
import { parseBaseUnits } from './money.js';
|
|
4
|
+
import { isVideoReservationKey, videoReservationKey } from './video-jobs.js';
|
|
5
|
+
export { videoJobKey } from './video-jobs.js';
|
|
4
6
|
/** The key's cap per period: the lower of the admins' and the owner's. */
|
|
5
7
|
export function effectiveKeyLimits(key) {
|
|
6
8
|
const result = {};
|
|
@@ -11,6 +13,21 @@ export function effectiveKeyLimits(key) {
|
|
|
11
13
|
}
|
|
12
14
|
/** Spend can be signed after the response ends (seller-initiated auth). */
|
|
13
15
|
const DEFAULT_SETTLE_GRACE_MS = 60_000;
|
|
16
|
+
/**
|
|
17
|
+
* An accepted video nobody downloads stops counting against the caps after
|
|
18
|
+
* this long: as long as the buyer keeps the job's route and billing (30 days),
|
|
19
|
+
* so a video that can still be delivered and charged is never forgotten first.
|
|
20
|
+
*/
|
|
21
|
+
const DEFAULT_VIDEO_COMMITMENT_MS = 30 * 24 * 60 * 60_000;
|
|
22
|
+
/**
|
|
23
|
+
* A delivered video is charged right after its file is received; if no charge
|
|
24
|
+
* has arrived this long after a complete delivery, none will (the buyer had no
|
|
25
|
+
* billing for the job, or the seller did not bill it), and the job stops
|
|
26
|
+
* holding its price.
|
|
27
|
+
*/
|
|
28
|
+
const DELIVERY_CHARGE_WAIT_MS = 60 * 60_000;
|
|
29
|
+
/** The buyer's default limit for one video ($5), when its config sets none. */
|
|
30
|
+
export const DEFAULT_MAX_VIDEO_REQUEST_USDC = 5_000_000;
|
|
14
31
|
export function newRequestTag() {
|
|
15
32
|
return `gw_${randomUUID()}`;
|
|
16
33
|
}
|
|
@@ -24,44 +41,274 @@ export class GatewayAccounting {
|
|
|
24
41
|
_store;
|
|
25
42
|
_options;
|
|
26
43
|
_holds = new Map();
|
|
44
|
+
/** Accepted video jobs, by `videoJobKey`: their price counts against the caps until delivered, failed or expired. */
|
|
45
|
+
_videoCommitments = new Map();
|
|
46
|
+
/**
|
|
47
|
+
* Commitment writes that failed, retried before admitting a capped request
|
|
48
|
+
* (null: a delete). A job's write also removes its create's reservation
|
|
49
|
+
* (`replaces`), in the same transaction.
|
|
50
|
+
*/
|
|
51
|
+
_pendingVideoWrites = new Map();
|
|
52
|
+
/** Whether the stored commitments were read; until then a capped request cannot be admitted safely. */
|
|
53
|
+
_videoCommitmentsLoaded = false;
|
|
27
54
|
_settleGraceMs;
|
|
55
|
+
_videoCommitmentMs;
|
|
56
|
+
_maxVideoRequestUsdc;
|
|
28
57
|
_now;
|
|
29
58
|
constructor(_store, _options) {
|
|
30
59
|
this._store = _store;
|
|
31
60
|
this._options = _options;
|
|
32
61
|
this._settleGraceMs = _options.settleGraceMs ?? DEFAULT_SETTLE_GRACE_MS;
|
|
62
|
+
this._videoCommitmentMs = _options.videoCommitmentMs ?? DEFAULT_VIDEO_COMMITMENT_MS;
|
|
63
|
+
this._maxVideoRequestUsdc = _options.maxVideoRequestUsdc ?? DEFAULT_MAX_VIDEO_REQUEST_USDC;
|
|
33
64
|
this._now = _options.now ?? (() => Date.now());
|
|
65
|
+
this._loadVideoCommitments();
|
|
34
66
|
}
|
|
35
|
-
|
|
36
|
-
|
|
67
|
+
/** In-flight holds plus accepted videos not yet charged, optionally leaving one video job out. */
|
|
68
|
+
heldUsdc(keyId, excludeVideoJob, withoutVideoCreates = false) {
|
|
69
|
+
return this._held((hold) => hold.keyId === keyId, excludeVideoJob, withoutVideoCreates);
|
|
37
70
|
}
|
|
38
71
|
/** Holds in flight for every key a member owns. */
|
|
39
|
-
heldForMember(memberId) {
|
|
40
|
-
return this._held((hold) => hold.memberId === memberId);
|
|
72
|
+
heldForMember(memberId, excludeVideoJob, withoutVideoCreates = false) {
|
|
73
|
+
return this._held((hold) => hold.memberId === memberId, excludeVideoJob, withoutVideoCreates);
|
|
41
74
|
}
|
|
42
|
-
heldForWorkspace(workspaceId) {
|
|
43
|
-
return this._held((hold) => hold.workspaceId === workspaceId);
|
|
75
|
+
heldForWorkspace(workspaceId, excludeVideoJob, withoutVideoCreates = false) {
|
|
76
|
+
return this._held((hold) => hold.workspaceId === workspaceId, excludeVideoJob, withoutVideoCreates);
|
|
44
77
|
}
|
|
45
|
-
_held(match) {
|
|
78
|
+
_held(match, excludeVideoJob, withoutVideoCreates = false) {
|
|
46
79
|
let held = 0;
|
|
47
80
|
for (const hold of this._holds.values())
|
|
48
|
-
if (match(hold))
|
|
81
|
+
if (match(hold) && !(withoutVideoCreates && hold.videoCreate))
|
|
49
82
|
held += hold.amountUsdc;
|
|
83
|
+
const now = this._now();
|
|
84
|
+
// A revoked key cannot retrieve its jobs any more (only the creating key may), so they are never charged:
|
|
85
|
+
// unless a retrieve admitted before the revocation is still running, or a delivery's charge is still to come.
|
|
86
|
+
let retrieving = null;
|
|
87
|
+
const chargeable = (job, commitment) => {
|
|
88
|
+
if (commitment.deliveredAt !== null)
|
|
89
|
+
return true;
|
|
90
|
+
retrieving ??= new Set([...this._holds.values()].flatMap((hold) => hold.videoJob ? [hold.videoJob] : []));
|
|
91
|
+
return retrieving.has(job);
|
|
92
|
+
};
|
|
93
|
+
const active = new Map();
|
|
94
|
+
const isActive = (keyId) => {
|
|
95
|
+
let result = active.get(keyId);
|
|
96
|
+
if (result === undefined) {
|
|
97
|
+
try {
|
|
98
|
+
result = this._store.getKey(keyId)?.status !== 'revoked';
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// Unreadable: keep counting it, the safe side.
|
|
102
|
+
result = true;
|
|
103
|
+
}
|
|
104
|
+
active.set(keyId, result);
|
|
105
|
+
}
|
|
106
|
+
return result;
|
|
107
|
+
};
|
|
108
|
+
for (const [job, commitment] of this._videoCommitments) {
|
|
109
|
+
if (commitment.expiresAt <= now) {
|
|
110
|
+
this._forgetVideo(job);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (commitment.amountUsdc > 0 && commitment.deliveredAt !== null && now - commitment.deliveredAt >= DELIVERY_CHARGE_WAIT_MS) {
|
|
114
|
+
this._setVideoHeld(job, commitment, 0);
|
|
115
|
+
}
|
|
116
|
+
if (commitment.amountUsdc > 0 && job !== excludeVideoJob && match(commitment) && (isActive(commitment.keyId) || chargeable(job, commitment)))
|
|
117
|
+
held += commitment.amountUsdc;
|
|
118
|
+
}
|
|
50
119
|
return held;
|
|
51
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* A video create was accepted: remember which key owns the job (only that
|
|
123
|
+
* key may retrieve it) and keep `amountUsdc` counted against the caps of the
|
|
124
|
+
* key, member and workspace the create was admitted for until the buyer's
|
|
125
|
+
* charge for its delivery arrives, the buyer retires the job, or the record
|
|
126
|
+
* expires. A key without caps records the price too, so caps added later
|
|
127
|
+
* count the job.
|
|
128
|
+
*
|
|
129
|
+
* Part of the price may already be spent by the create itself (a one-off
|
|
130
|
+
* channel's opening fee counts toward the video): what is already in the
|
|
131
|
+
* ledger is not held again, and a charge on the create that arrives later
|
|
132
|
+
* lowers the commitment like any other charge of the job (see `ingest`).
|
|
133
|
+
*/
|
|
134
|
+
commitVideo(tag, job, amountUsdc) {
|
|
135
|
+
const hold = this._holds.get(tag);
|
|
136
|
+
if (!hold)
|
|
137
|
+
return;
|
|
138
|
+
const existing = this._videoCommitments.get(job);
|
|
139
|
+
if (existing && existing.keyId !== hold.keyId && existing.expiresAt > this._now()) {
|
|
140
|
+
// Another key's job by the same ID: it keeps its owner and commitment. This create's job cannot be
|
|
141
|
+
// retrieved by its key (only the owner may), so it is never charged to it.
|
|
142
|
+
this._options.onLog?.('gateway ignored a video job ID that another key already owns');
|
|
143
|
+
this.videoNotAccepted(tag);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
let spent = 0;
|
|
147
|
+
try {
|
|
148
|
+
spent = this._store.spendForRequest(tag);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// Unreadable now: hold the whole price, never less than the job can still be charged.
|
|
152
|
+
}
|
|
153
|
+
const commitment = {
|
|
154
|
+
keyId: hold.keyId,
|
|
155
|
+
memberId: hold.memberId,
|
|
156
|
+
workspaceId: hold.workspaceId,
|
|
157
|
+
amountUsdc: Math.max(0, Math.floor(amountUsdc) - spent),
|
|
158
|
+
expiresAt: this._now() + this._videoCommitmentMs,
|
|
159
|
+
deliveredAt: null,
|
|
160
|
+
};
|
|
161
|
+
this._videoCommitments.set(job, commitment);
|
|
162
|
+
this._storeVideo(job, { job, ...commitment }, hold.reserved ? videoReservationKey(tag) : undefined);
|
|
163
|
+
hold.reserved = false;
|
|
164
|
+
hold.videoCreate = false;
|
|
165
|
+
}
|
|
166
|
+
/** A video create ended without an accepted job: its reservation goes. */
|
|
167
|
+
videoNotAccepted(tag) {
|
|
168
|
+
const hold = this._holds.get(tag);
|
|
169
|
+
if (!hold?.reserved)
|
|
170
|
+
return;
|
|
171
|
+
hold.reserved = false;
|
|
172
|
+
hold.videoCreate = false;
|
|
173
|
+
this._storeVideo(videoReservationKey(tag), null);
|
|
174
|
+
}
|
|
175
|
+
/** The key that created a video job through this gateway, if it is still remembered. */
|
|
176
|
+
videoJobOwner(job) {
|
|
177
|
+
const commitment = this._videoCommitments.get(job);
|
|
178
|
+
return commitment && commitment.expiresAt > this._now() ? commitment.keyId : null;
|
|
179
|
+
}
|
|
180
|
+
/** What a video job still holds against the caps (0 once charged, or for an uncapped key). */
|
|
181
|
+
videoJobHeldUsdc(job) {
|
|
182
|
+
return this._videoCommitments.get(job)?.amountUsdc ?? 0;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* The buyer retired the job: it failed, its seller no longer has it, or the
|
|
186
|
+
* buyer has no record of it. It can never be delivered or charged.
|
|
187
|
+
*/
|
|
188
|
+
dropVideo(job) {
|
|
189
|
+
if (this._videoCommitments.has(job))
|
|
190
|
+
this._forgetVideo(job);
|
|
191
|
+
}
|
|
192
|
+
/** A retrieve streamed the job's whole file: its charge should follow (see DELIVERY_CHARGE_WAIT_MS). */
|
|
193
|
+
videoDelivered(job) {
|
|
194
|
+
const commitment = this._videoCommitments.get(job);
|
|
195
|
+
if (!commitment || commitment.deliveredAt !== null)
|
|
196
|
+
return;
|
|
197
|
+
commitment.deliveredAt = this._now();
|
|
198
|
+
this._storeVideo(job, { job, ...commitment });
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* The buyer charged `amountUsdc` for the job's delivery: that much is in the
|
|
202
|
+
* ledger now, so the job holds that much less. Spend plus what the job still
|
|
203
|
+
* holds stays the same, whatever request the charge names. Ownership stays,
|
|
204
|
+
* so its owner can download it again (the buyer does not charge twice).
|
|
205
|
+
*/
|
|
206
|
+
_videoCharged(job, amountUsdc) {
|
|
207
|
+
const commitment = this._videoCommitments.get(job);
|
|
208
|
+
if (!commitment || commitment.amountUsdc === 0)
|
|
209
|
+
return;
|
|
210
|
+
this._setVideoHeld(job, commitment, Math.max(0, commitment.amountUsdc - amountUsdc));
|
|
211
|
+
}
|
|
212
|
+
_setVideoHeld(job, commitment, amountUsdc) {
|
|
213
|
+
commitment.amountUsdc = amountUsdc;
|
|
214
|
+
this._storeVideo(job, { job, ...commitment });
|
|
215
|
+
}
|
|
216
|
+
_forgetVideo(job) {
|
|
217
|
+
this._videoCommitments.delete(job);
|
|
218
|
+
this._storeVideo(job, null);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Commitments live in memory first and are stored so a restart keeps them.
|
|
222
|
+
* A failed write (for example another process holding the database lock)
|
|
223
|
+
* does not fail the request that caused it; it is retried, and until it
|
|
224
|
+
* succeeds capped requests are refused (see `videoCommitmentsReady`).
|
|
225
|
+
* A restart before the retry still keeps the job counted: its create's
|
|
226
|
+
* reservation, stored before the create was sent, is only removed in the
|
|
227
|
+
* same transaction that stores the job (see `_loadVideoCommitments`).
|
|
228
|
+
*/
|
|
229
|
+
_storeVideo(job, record, replaces) {
|
|
230
|
+
this._pendingVideoWrites.delete(job);
|
|
231
|
+
try {
|
|
232
|
+
if (record)
|
|
233
|
+
this._store.saveVideoCommitment(record, replaces);
|
|
234
|
+
else
|
|
235
|
+
this._store.deleteVideoCommitment(job);
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
this._pendingVideoWrites.set(job, { record, ...(replaces !== undefined ? { replaces } : {}) });
|
|
239
|
+
this._options.onLog?.(`gateway could not store a video commitment: ${error instanceof Error ? error.message : String(error)}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Reads the stored commitments. A create's reservation still stored was
|
|
244
|
+
* left by a gateway that stopped before storing the create's job: when the
|
|
245
|
+
* request log names the job, the reservation becomes that job's commitment
|
|
246
|
+
* (the whole room the create was told about, less what it already spent),
|
|
247
|
+
* since its key can still retrieve it and be charged; otherwise the create
|
|
248
|
+
* was not accepted, or its job cannot be retrieved through this gateway
|
|
249
|
+
* (no record names its owner), so it is never charged and the reservation
|
|
250
|
+
* goes.
|
|
251
|
+
*/
|
|
252
|
+
_loadVideoCommitments() {
|
|
253
|
+
try {
|
|
254
|
+
const rows = this._store.listVideoCommitments(this._now());
|
|
255
|
+
const stored = new Set(rows.map((row) => row.job));
|
|
256
|
+
for (const { job, ...commitment } of rows) {
|
|
257
|
+
if (!isVideoReservationKey(job)) {
|
|
258
|
+
if (!this._videoCommitments.has(job) && !this._pendingVideoWrites.has(job))
|
|
259
|
+
this._videoCommitments.set(job, commitment);
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
const tag = job.slice(videoReservationKey('').length);
|
|
263
|
+
const created = this._store.videoCreateJob(tag);
|
|
264
|
+
if (!created || stored.has(created) || this._videoCommitments.has(created)) {
|
|
265
|
+
this._store.deleteVideoCommitment(job);
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
// Everything already charged for the job (its create, polls and delivery) is spend, not held again; a
|
|
269
|
+
// delivered job gets the same hour for its charge as any other.
|
|
270
|
+
const jobId = created.slice(created.indexOf('\n') + 1);
|
|
271
|
+
const delivery = this._store.videoJobDeliveredAt(commitment.keyId, jobId);
|
|
272
|
+
const recovered = {
|
|
273
|
+
...commitment,
|
|
274
|
+
amountUsdc: Math.max(0, commitment.amountUsdc - this._store.videoJobSpend(commitment.keyId, jobId)),
|
|
275
|
+
deliveredAt: delivery,
|
|
276
|
+
};
|
|
277
|
+
this._store.saveVideoCommitment({ job: created, ...recovered }, job);
|
|
278
|
+
stored.add(created);
|
|
279
|
+
this._videoCommitments.set(created, recovered);
|
|
280
|
+
}
|
|
281
|
+
this._videoCommitmentsLoaded = true;
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
this._options.onLog?.(`gateway could not load video commitments: ${error instanceof Error ? error.message : String(error)}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Whether every video commitment is read and stored, so caps can be applied:
|
|
289
|
+
* retries a failed load and failed writes first. A delete that still fails
|
|
290
|
+
* only over-counts after a restart (the safe side) and does not block.
|
|
291
|
+
*/
|
|
292
|
+
videoCommitmentsReady() {
|
|
293
|
+
if (!this._videoCommitmentsLoaded)
|
|
294
|
+
this._loadVideoCommitments();
|
|
295
|
+
for (const [job, { record, replaces }] of [...this._pendingVideoWrites])
|
|
296
|
+
this._storeVideo(job, record, replaces);
|
|
297
|
+
return this._videoCommitmentsLoaded && [...this._pendingVideoWrites.values()].every(({ record }) => record === null);
|
|
298
|
+
}
|
|
52
299
|
/** Whether any level above or at the key caps spend (so admission depends on the spend feed). */
|
|
53
300
|
hasBudgets(key, context = this._context(key)) {
|
|
54
301
|
return this._budgetChecks(key, context).some(({ limits }) => hasSpendLimits(limits));
|
|
55
302
|
}
|
|
56
303
|
/** The key (the lower of its admin and owner caps), the member who owns it and its workspace. */
|
|
57
|
-
_budgetChecks(key, { member, workspace }) {
|
|
304
|
+
_budgetChecks(key, { member, workspace }, excludeVideoJob) {
|
|
58
305
|
const checks = [
|
|
59
|
-
{ level: 'key', limits: effectiveKeyLimits(key), scope: { keyId: key.id }, held: () => this.heldUsdc(key.id) },
|
|
306
|
+
{ level: 'key', limits: effectiveKeyLimits(key), scope: { keyId: key.id }, held: (without) => this.heldUsdc(key.id, excludeVideoJob, without) },
|
|
60
307
|
];
|
|
61
308
|
if (member)
|
|
62
|
-
checks.push({ level: 'member', limits: member.limits, scope: { memberId: member.id }, held: () => this.heldForMember(member.id) });
|
|
309
|
+
checks.push({ level: 'member', limits: member.limits, scope: { memberId: member.id }, held: (without) => this.heldForMember(member.id, excludeVideoJob, without) });
|
|
63
310
|
if (workspace)
|
|
64
|
-
checks.push({ level: 'workspace', limits: workspace.limits, scope: { workspaceId: workspace.id }, held: () => this.heldForWorkspace(workspace.id) });
|
|
311
|
+
checks.push({ level: 'workspace', limits: workspace.limits, scope: { workspaceId: workspace.id }, held: (without) => this.heldForWorkspace(workspace.id, excludeVideoJob, without) });
|
|
65
312
|
return checks;
|
|
66
313
|
}
|
|
67
314
|
_context(key) {
|
|
@@ -76,28 +323,72 @@ export class GatewayAccounting {
|
|
|
76
323
|
* Member and workspace spend is the ledger as attributed at request time,
|
|
77
324
|
* so a member who revokes a key and creates a new one still counts
|
|
78
325
|
* everything spent before against the member's caps. Levels and periods
|
|
79
|
-
* without a cap cost no query.
|
|
326
|
+
* without a cap cost no query. A video job's own polls and delivery are
|
|
327
|
+
* admitted without its own commitment (`videoJob`), which they would
|
|
328
|
+
* otherwise count twice.
|
|
80
329
|
*/
|
|
81
|
-
admit(key, context = this._context(key)) {
|
|
330
|
+
admit(key, context = this._context(key), { videoCreate = false, videoJob } = {}) {
|
|
82
331
|
const now = this._now();
|
|
83
|
-
|
|
332
|
+
// A job that still holds its price already covers its delivery's charge, and one that holds nothing (free,
|
|
333
|
+
// or already charged: the buyer charges a job once) has none to come: its own polls and download are
|
|
334
|
+
// admitted even when other spend has filled the caps since, so the job can always finish (or be retired).
|
|
335
|
+
const own = videoJob ? this._videoCommitments.get(videoJob) : undefined;
|
|
336
|
+
if (own && own.keyId === key.id && own.expiresAt > now) {
|
|
337
|
+
const tag = newRequestTag();
|
|
338
|
+
this._holds.set(tag, { keyId: key.id, memberId: key.ownerMemberId, workspaceId: key.workspaceId, amountUsdc: 0, finished: false, timer: null, videoJob });
|
|
339
|
+
return { ok: true, tag, remainingUsdc: null };
|
|
340
|
+
}
|
|
341
|
+
let remainingUsdc = null;
|
|
342
|
+
for (const { level, limits, scope, held } of this._budgetChecks(key, context, videoJob)) {
|
|
84
343
|
const periods = cappedPeriods(limits);
|
|
85
344
|
if (periods.length === 0)
|
|
86
345
|
continue;
|
|
87
|
-
const
|
|
88
|
-
|
|
346
|
+
const spent = this._store.spendByPeriod(scope, now, periods);
|
|
347
|
+
const heldUsdc = held();
|
|
348
|
+
const breach = findLimitBreach(limits, spent, heldUsdc, now);
|
|
349
|
+
if (breach) {
|
|
350
|
+
// Room a create holds while it is priced comes back in seconds: say so, rather than that the cap is reached.
|
|
351
|
+
if (findLimitBreach(limits, spent, held(true), now) === null)
|
|
352
|
+
return { ok: false, breach: null, reason: 'video_pricing' };
|
|
89
353
|
return { ok: false, breach: { ...breach, level } };
|
|
354
|
+
}
|
|
355
|
+
for (const period of periods) {
|
|
356
|
+
const room = (limits[period] ?? 0) - (spent[period] ?? 0) - heldUsdc;
|
|
357
|
+
remainingUsdc = remainingUsdc === null ? room : Math.min(remainingUsdc, room);
|
|
358
|
+
}
|
|
90
359
|
}
|
|
360
|
+
// A video create may start a job worth up to the room it is told about, so it
|
|
361
|
+
// holds all of that until the buyer reports the price: two creates in flight
|
|
362
|
+
// at once cannot both be told the same room.
|
|
363
|
+
if (videoCreate && remainingUsdc !== null)
|
|
364
|
+
remainingUsdc = Math.min(remainingUsdc, this._maxVideoRequestUsdc);
|
|
91
365
|
const tag = newRequestTag();
|
|
92
|
-
|
|
366
|
+
const hold = {
|
|
93
367
|
keyId: key.id,
|
|
94
368
|
memberId: key.ownerMemberId,
|
|
95
369
|
workspaceId: key.workspaceId,
|
|
96
|
-
amountUsdc: this._options.holdUsdc,
|
|
370
|
+
amountUsdc: videoCreate && remainingUsdc !== null ? remainingUsdc : this._options.holdUsdc,
|
|
97
371
|
finished: false,
|
|
98
372
|
timer: null,
|
|
99
|
-
}
|
|
100
|
-
|
|
373
|
+
};
|
|
374
|
+
if (videoCreate && remainingUsdc !== null) {
|
|
375
|
+
// Stored before the create is sent, so a job the buyer accepts is never lost from the caps, even when
|
|
376
|
+
// its own commitment cannot be stored and the gateway restarts (see `_loadVideoCommitments`).
|
|
377
|
+
try {
|
|
378
|
+
this._store.saveVideoCommitment({
|
|
379
|
+
job: videoReservationKey(tag), keyId: hold.keyId, memberId: hold.memberId, workspaceId: hold.workspaceId,
|
|
380
|
+
amountUsdc: remainingUsdc, expiresAt: now + this._videoCommitmentMs, deliveredAt: null,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
catch (error) {
|
|
384
|
+
this._options.onLog?.(`gateway could not store a video reservation: ${error instanceof Error ? error.message : String(error)}`);
|
|
385
|
+
return { ok: false, breach: null, reason: 'video_storage' };
|
|
386
|
+
}
|
|
387
|
+
hold.reserved = true;
|
|
388
|
+
hold.videoCreate = true;
|
|
389
|
+
}
|
|
390
|
+
this._holds.set(tag, hold);
|
|
391
|
+
return { ok: true, tag, remainingUsdc };
|
|
101
392
|
}
|
|
102
393
|
/** Drops a hold at once, for a request that never reached the buyer. */
|
|
103
394
|
release(tag) {
|
|
@@ -142,10 +433,15 @@ export class GatewayAccounting {
|
|
|
142
433
|
memberId: request.memberId,
|
|
143
434
|
model: request.model,
|
|
144
435
|
endUser: request.endUser,
|
|
436
|
+
routingFee: event.purpose === 'routing',
|
|
145
437
|
});
|
|
146
438
|
if (!inserted)
|
|
147
439
|
continue;
|
|
148
440
|
recorded += 1;
|
|
441
|
+
// A charge of a video job (its create's opening fee, a poll or its delivery): that much of its commitment is now spend.
|
|
442
|
+
// Spend without a request ID is only attributed to the seller's latest request, so it may not be the job's.
|
|
443
|
+
if (request.videoJob && event.requestId !== null)
|
|
444
|
+
this._videoCharged(request.videoJob, parseBaseUnits(event.amountUsdc));
|
|
149
445
|
// Settled spend replaces that much of the request's worst-case hold.
|
|
150
446
|
// The rest stays until the grace period ends: one request can sign
|
|
151
447
|
// several deltas, and later ones still need to be covered.
|
|
@@ -160,6 +456,8 @@ export class GatewayAccounting {
|
|
|
160
456
|
if (hold.timer)
|
|
161
457
|
clearTimeout(hold.timer);
|
|
162
458
|
this._holds.clear();
|
|
459
|
+
// Commitments stay stored: the next gateway reloads them.
|
|
460
|
+
this._videoCommitments.clear();
|
|
163
461
|
}
|
|
164
462
|
}
|
|
165
463
|
/** The stricter of two caps; null is no cap. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accounting.js","sourceRoot":"","sources":["../../src/gateway/accounting.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"accounting.js","sourceRoot":"","sources":["../../src/gateway/accounting.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ConsoleDeps } from '../deps.js';
|
|
2
|
+
import { type ConsoleRouter } from '../router.js';
|
|
3
|
+
/**
|
|
4
|
+
* Starred models and routers (`/favorites`), per member (or API-key
|
|
5
|
+
* session), so they follow the person across browsers. Ids are the Models
|
|
6
|
+
* page's: a model id, or a router's `<peerId>@<serviceId>`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function registerFavoriteRoutes(router: ConsoleRouter, deps: ConsoleDeps): void;
|
|
9
|
+
//# sourceMappingURL=favorites.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"favorites.d.ts","sourceRoot":"","sources":["../../../../src/gateway/console-api/handlers/favorites.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,EAA8C,KAAK,aAAa,EAAE,MAAM,cAAc,CAAA;AAqB7F;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CAqBrF"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ConsoleError, respond } from '../router.js';
|
|
2
|
+
/** Most models one owner can star. */
|
|
3
|
+
const MAX_FAVORITES = 500;
|
|
4
|
+
const MAX_MODEL_ID = 300;
|
|
5
|
+
/** Favorites belong to the signed-in member, or to the API key of a key session; admin tokens have none. */
|
|
6
|
+
function favoriteOwner(request) {
|
|
7
|
+
const { principal } = request;
|
|
8
|
+
if (principal?.kind === 'member')
|
|
9
|
+
return { kind: 'member', id: principal.memberId };
|
|
10
|
+
if (principal?.kind === 'key')
|
|
11
|
+
return { kind: 'key', id: principal.keyId };
|
|
12
|
+
throw new ConsoleError(403, 'forbidden', 'Sign in to the console to star models');
|
|
13
|
+
}
|
|
14
|
+
function modelParam(request) {
|
|
15
|
+
const model = (request.params['model'] ?? '').trim();
|
|
16
|
+
if (!model || model.length > MAX_MODEL_ID)
|
|
17
|
+
throw new ConsoleError(400, 'invalid_model', `Name a model id of at most ${MAX_MODEL_ID} characters`);
|
|
18
|
+
return model;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Starred models and routers (`/favorites`), per member (or API-key
|
|
22
|
+
* session), so they follow the person across browsers. Ids are the Models
|
|
23
|
+
* page's: a model id, or a router's `<peerId>@<serviceId>`.
|
|
24
|
+
*/
|
|
25
|
+
export function registerFavoriteRoutes(router, deps) {
|
|
26
|
+
const allow = { allow: ['member', 'key'] };
|
|
27
|
+
router.add('GET', '/favorites', async (request) => ({
|
|
28
|
+
models: deps.store.listFavoriteModels(favoriteOwner(request)),
|
|
29
|
+
}), allow);
|
|
30
|
+
router.add('PUT', '/favorites/:model', async (request) => {
|
|
31
|
+
const owner = favoriteOwner(request);
|
|
32
|
+
const model = modelParam(request);
|
|
33
|
+
if (deps.store.countFavoriteModels(owner) >= MAX_FAVORITES && !deps.store.listFavoriteModels(owner).includes(model)) {
|
|
34
|
+
throw new ConsoleError(409, 'too_many_favorites', `You can star at most ${MAX_FAVORITES} models`);
|
|
35
|
+
}
|
|
36
|
+
deps.store.setFavoriteModel(owner, model, true);
|
|
37
|
+
return respond(204);
|
|
38
|
+
}, allow);
|
|
39
|
+
router.add('DELETE', '/favorites/:model', async (request) => {
|
|
40
|
+
deps.store.setFavoriteModel(favoriteOwner(request), modelParam(request), false);
|
|
41
|
+
return respond(204);
|
|
42
|
+
}, allow);
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=favorites.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"favorites.js","sourceRoot":"","sources":["../../../../src/gateway/console-api/handlers/favorites.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,OAAO,EAA2C,MAAM,cAAc,CAAA;AAG7F,sCAAsC;AACtC,MAAM,aAAa,GAAG,GAAG,CAAA;AACzB,MAAM,YAAY,GAAG,GAAG,CAAA;AAExB,4GAA4G;AAC5G,SAAS,aAAa,CAAC,OAAuB;IAC5C,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;IAC7B,IAAI,SAAS,EAAE,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAA;IACnF,IAAI,SAAS,EAAE,IAAI,KAAK,KAAK;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,CAAC,KAAK,EAAE,CAAA;IAC1E,MAAM,IAAI,YAAY,CAAC,GAAG,EAAE,WAAW,EAAE,uCAAuC,CAAC,CAAA;AACnF,CAAC;AAED,SAAS,UAAU,CAAC,OAAuB;IACzC,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IACpD,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,YAAY;QAAE,MAAM,IAAI,YAAY,CAAC,GAAG,EAAE,eAAe,EAAE,8BAA8B,YAAY,aAAa,CAAC,CAAA;IAChJ,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAqB,EAAE,IAAiB;IAC7E,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAU,EAAE,CAAA;IAEnD,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAA2B,EAAE,CAAC,CAAC;QAC3E,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;KAC9D,CAAC,EAAE,KAAK,CAAC,CAAA;IAEV,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QACvD,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;QACpC,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAA;QACjC,IAAI,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,aAAa,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACpH,MAAM,IAAI,YAAY,CAAC,GAAG,EAAE,oBAAoB,EAAE,wBAAwB,aAAa,SAAS,CAAC,CAAA;QACnG,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;QAC/C,OAAO,OAAO,CAAC,GAAG,CAAC,CAAA;IACrB,CAAC,EAAE,KAAK,CAAC,CAAA;IAET,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,mBAAmB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAC1D,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,CAAA;QAC/E,OAAO,OAAO,CAAC,GAAG,CAAC,CAAA;IACrB,CAAC,EAAE,KAAK,CAAC,CAAA;AACX,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"favorites.test.d.ts","sourceRoot":"","sources":["../../../../src/gateway/console-api/handlers/favorites.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { test } from 'node:test';
|
|
3
|
+
import { FakeConsoleAuth, addActiveMember, call, memberPrincipal, startConsole, tempDataDir, testDeps } from '../test-support.js';
|
|
4
|
+
import { coreConsoleRegistrars } from './index.js';
|
|
5
|
+
const NO_LIMITS = { daily: null, weekly: null, monthly: null, total: null };
|
|
6
|
+
const ROUTER = `${'aa'.repeat(20)}@fake-route`;
|
|
7
|
+
async function harness() {
|
|
8
|
+
const { dir, store, cleanup } = tempDataDir();
|
|
9
|
+
const auth = new FakeConsoleAuth();
|
|
10
|
+
const owner = store.createOwner({ label: 'Owner', email: 'owner@example.test' });
|
|
11
|
+
const ws = store.createWorkspace({ name: 'Alpha', buyerIdentity: 'ws-alpha' });
|
|
12
|
+
const member = addActiveMember(store, 'Member', { workspaces: [{ workspaceId: ws.id, role: 'member' }], createdBy: owner.id });
|
|
13
|
+
const { key } = store.createKey({ label: 'Mine', workspaceId: ws.id, ownerMemberId: member.id, limits: NO_LIMITS, expiresAt: null });
|
|
14
|
+
auth.as('owner', memberPrincipal(store, owner.id));
|
|
15
|
+
auth.as('member', memberPrincipal(store, member.id));
|
|
16
|
+
auth.as('key', { kind: 'key', keyId: key.id, sessionId: 'ks' });
|
|
17
|
+
auth.as('token', { kind: 'token', tokenId: 'tok', scope: 'admin' });
|
|
18
|
+
const server = await startConsole(testDeps(store, dir), auth, coreConsoleRegistrars);
|
|
19
|
+
const as = (who, method, path) => call(server.port, method, `/console/api${path}`, { who });
|
|
20
|
+
return { as, close: async () => { await server.close(); cleanup(); } };
|
|
21
|
+
}
|
|
22
|
+
test('each member and key session keeps its own starred models and routers', async () => {
|
|
23
|
+
const h = await harness();
|
|
24
|
+
try {
|
|
25
|
+
assert.deepEqual((await h.as('member', 'GET', '/favorites')).body, { models: [] });
|
|
26
|
+
assert.equal((await h.as('member', 'PUT', `/favorites/${encodeURIComponent('vendor/open-model-a')}`)).status, 204);
|
|
27
|
+
assert.equal((await h.as('member', 'PUT', `/favorites/${encodeURIComponent(ROUTER)}`)).status, 204);
|
|
28
|
+
assert.equal((await h.as('member', 'PUT', `/favorites/${encodeURIComponent(ROUTER)}`)).status, 204, 'starring twice is fine');
|
|
29
|
+
assert.deepEqual((await h.as('member', 'GET', '/favorites')).body, { models: ['vendor/open-model-a', ROUTER] });
|
|
30
|
+
assert.deepEqual((await h.as('owner', 'GET', '/favorites')).body, { models: [] }, 'another member has their own');
|
|
31
|
+
assert.equal((await h.as('key', 'PUT', '/favorites/open-model-b')).status, 204);
|
|
32
|
+
assert.deepEqual((await h.as('key', 'GET', '/favorites')).body, { models: ['open-model-b'] }, 'a key session too');
|
|
33
|
+
assert.equal((await h.as('member', 'DELETE', `/favorites/${encodeURIComponent('vendor/open-model-a')}`)).status, 204);
|
|
34
|
+
assert.deepEqual((await h.as('member', 'GET', '/favorites')).body, { models: [ROUTER] });
|
|
35
|
+
assert.equal((await h.as('token', 'GET', '/favorites')).status, 403, 'admin tokens have no favorites');
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
await h.close();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
//# sourceMappingURL=favorites.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"favorites.test.js","sourceRoot":"","sources":["../../../../src/gateway/console-api/handlers/favorites.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/gateway/console-api/handlers/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/gateway/console-api/handlers/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAcpD,iGAAiG;AACjG,eAAO,MAAM,qBAAqB,EAAE,gBAAgB,EAanD,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { registerAdminTokenRoutes } from './admin-tokens.js';
|
|
2
|
+
import { registerFavoriteRoutes } from './favorites.js';
|
|
2
3
|
import { registerKeyRoutes } from './keys.js';
|
|
3
4
|
import { registerOrgRoutes } from './org.js';
|
|
4
5
|
import { registerPeerListRoutes } from './peer-lists.js';
|
|
@@ -22,5 +23,6 @@ export const coreConsoleRegistrars = [
|
|
|
22
23
|
registerSettingsRoutes,
|
|
23
24
|
registerStatusRoutes,
|
|
24
25
|
registerUpdateRoutes,
|
|
26
|
+
registerFavoriteRoutes,
|
|
25
27
|
];
|
|
26
28
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/gateway/console-api/handlers/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAEzD,iGAAiG;AACjG,MAAM,CAAC,MAAM,qBAAqB,GAAuB;IACvD,iBAAiB;IACjB,uBAAuB;IACvB,iBAAiB;IACjB,wBAAwB;IACxB,mBAAmB;IACnB,sBAAsB;IACtB,oBAAoB;IACpB,qBAAqB;IACrB,sBAAsB;IACtB,oBAAoB;IACpB,oBAAoB;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/gateway/console-api/handlers/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAEzD,iGAAiG;AACjG,MAAM,CAAC,MAAM,qBAAqB,GAAuB;IACvD,iBAAiB;IACjB,uBAAuB;IACvB,iBAAiB;IACjB,wBAAwB;IACxB,mBAAmB;IACnB,sBAAsB;IACtB,oBAAoB;IACpB,qBAAqB;IACrB,sBAAsB;IACtB,oBAAoB;IACpB,oBAAoB;IACpB,sBAAsB;CACvB,CAAA"}
|