@hasna/hooks 0.4.0 → 0.4.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/bin/index.js +48 -303
- package/hooks/codewith-native-common.test.ts +364 -12
- package/hooks/codewith-native-common.ts +412 -24
- package/hooks/worktree-guard/README.md +44 -0
- package/hooks/worktree-guard/src/hook.ts +50 -8
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -6270,7 +6270,6 @@ var init_http = () => {};
|
|
|
6270
6270
|
|
|
6271
6271
|
// node_modules/@hasna/events/dist/commander.js
|
|
6272
6272
|
import { chmod, mkdir, readFile, rename, writeFile } from "fs/promises";
|
|
6273
|
-
import { Buffer as Buffer2 } from "buffer";
|
|
6274
6273
|
import { existsSync } from "fs";
|
|
6275
6274
|
import { homedir } from "os";
|
|
6276
6275
|
import { join } from "path";
|
|
@@ -6375,9 +6374,6 @@ function channelMatchesEvent(channel, event) {
|
|
|
6375
6374
|
}
|
|
6376
6375
|
var HASNA_EVENTS_DIR_ENV = "HASNA_EVENTS_DIR";
|
|
6377
6376
|
var HASNA_EVENTS_HOME_ENV = "HASNA_EVENTS_HOME";
|
|
6378
|
-
var LOCAL_JSON_EVENT_CURSOR_PREFIX = "local-json-v1:";
|
|
6379
|
-
var DEFAULT_EVENT_PAGE_LIMIT = 100;
|
|
6380
|
-
var MAX_EVENT_PAGE_LIMIT = 1000;
|
|
6381
6377
|
function getEventsDataDir(override) {
|
|
6382
6378
|
return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join(homedir(), ".hasna", "events");
|
|
6383
6379
|
}
|
|
@@ -6391,13 +6387,11 @@ function getActiveEventsDirEnv() {
|
|
|
6391
6387
|
|
|
6392
6388
|
class JsonEventsStore {
|
|
6393
6389
|
dataDir;
|
|
6394
|
-
runtime;
|
|
6395
6390
|
channelsPath;
|
|
6396
6391
|
eventsPath;
|
|
6397
6392
|
deliveriesPath;
|
|
6398
6393
|
constructor(dataDir = getEventsDataDir()) {
|
|
6399
6394
|
this.dataDir = dataDir;
|
|
6400
|
-
this.runtime = localJsonRuntime(dataDir);
|
|
6401
6395
|
this.channelsPath = join(dataDir, "channels.json");
|
|
6402
6396
|
this.eventsPath = join(dataDir, "events.json");
|
|
6403
6397
|
this.deliveriesPath = join(dataDir, "deliveries.json");
|
|
@@ -6445,58 +6439,13 @@ class JsonEventsStore {
|
|
|
6445
6439
|
await this.writeJson(this.eventsPath, events);
|
|
6446
6440
|
return event;
|
|
6447
6441
|
}
|
|
6448
|
-
async
|
|
6442
|
+
async listEvents() {
|
|
6449
6443
|
await this.init();
|
|
6450
|
-
|
|
6451
|
-
const dedupe = options.dedupe !== false;
|
|
6452
|
-
if (dedupe) {
|
|
6453
|
-
const existing = findEventByIdentity(events, { id: event.id, dedupeKey: event.dedupeKey });
|
|
6454
|
-
if (existing) {
|
|
6455
|
-
return {
|
|
6456
|
-
event: existing,
|
|
6457
|
-
stored: false,
|
|
6458
|
-
deduped: true,
|
|
6459
|
-
identity: { id: existing.id, dedupeKey: existing.dedupeKey }
|
|
6460
|
-
};
|
|
6461
|
-
}
|
|
6462
|
-
}
|
|
6463
|
-
events.push(event);
|
|
6464
|
-
await this.writeJson(this.eventsPath, events);
|
|
6465
|
-
return {
|
|
6466
|
-
event,
|
|
6467
|
-
stored: true,
|
|
6468
|
-
deduped: false,
|
|
6469
|
-
identity: { id: event.id, dedupeKey: event.dedupeKey }
|
|
6470
|
-
};
|
|
6471
|
-
}
|
|
6472
|
-
async listEvents(options = {}) {
|
|
6473
|
-
await this.init();
|
|
6474
|
-
const events = await this.readJson(this.eventsPath, []);
|
|
6475
|
-
return queryEvents(events, options);
|
|
6476
|
-
}
|
|
6477
|
-
async listEventsPage(options = {}) {
|
|
6478
|
-
await this.init();
|
|
6479
|
-
const events = await this.readJson(this.eventsPath, []);
|
|
6480
|
-
const queried = queryEvents(events, {
|
|
6481
|
-
eventId: options.eventId,
|
|
6482
|
-
source: options.source,
|
|
6483
|
-
type: options.type
|
|
6484
|
-
});
|
|
6485
|
-
const offset = decodeLocalJsonEventCursor(options.cursor, options);
|
|
6486
|
-
const limit = normalizeEventPageLimit(options.limit);
|
|
6487
|
-
const pageEvents = queried.slice(offset, offset + limit);
|
|
6488
|
-
const nextOffset = offset + pageEvents.length;
|
|
6489
|
-
const hasMore = nextOffset < queried.length;
|
|
6490
|
-
return {
|
|
6491
|
-
events: pageEvents,
|
|
6492
|
-
cursor: options.cursor,
|
|
6493
|
-
nextCursor: hasMore ? encodeLocalJsonEventCursor(nextOffset, options) : undefined,
|
|
6494
|
-
hasMore
|
|
6495
|
-
};
|
|
6444
|
+
return this.readJson(this.eventsPath, []);
|
|
6496
6445
|
}
|
|
6497
6446
|
async findEventByIdentity(identity) {
|
|
6498
6447
|
const events = await this.listEvents();
|
|
6499
|
-
return
|
|
6448
|
+
return events.find((event) => identity.id !== undefined && event.id === identity.id || identity.dedupeKey !== undefined && event.dedupeKey === identity.dedupeKey);
|
|
6500
6449
|
}
|
|
6501
6450
|
async appendDelivery(result) {
|
|
6502
6451
|
await this.init();
|
|
@@ -6547,83 +6496,6 @@ class JsonEventsStore {
|
|
|
6547
6496
|
});
|
|
6548
6497
|
}
|
|
6549
6498
|
}
|
|
6550
|
-
function localJsonRuntime(dataDir = getEventsDataDir()) {
|
|
6551
|
-
return {
|
|
6552
|
-
mode: "local-files",
|
|
6553
|
-
name: "json-events-store",
|
|
6554
|
-
remote: false,
|
|
6555
|
-
localFiles: true,
|
|
6556
|
-
localSqlite: false,
|
|
6557
|
-
postgres: false,
|
|
6558
|
-
s3: false,
|
|
6559
|
-
aws: false,
|
|
6560
|
-
durable: true,
|
|
6561
|
-
idempotency: "best-effort-local",
|
|
6562
|
-
replayCursors: true,
|
|
6563
|
-
description: `Local JSON files in ${dataDir}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`
|
|
6564
|
-
};
|
|
6565
|
-
}
|
|
6566
|
-
function encodeLocalJsonEventCursor(offset, options = {}) {
|
|
6567
|
-
if (!Number.isInteger(offset) || offset < 0)
|
|
6568
|
-
throw new Error(`Invalid event cursor offset: ${offset}`);
|
|
6569
|
-
const payload = {
|
|
6570
|
-
offset,
|
|
6571
|
-
eventId: options.eventId,
|
|
6572
|
-
source: options.source,
|
|
6573
|
-
type: options.type
|
|
6574
|
-
};
|
|
6575
|
-
return `${LOCAL_JSON_EVENT_CURSOR_PREFIX}${Buffer2.from(JSON.stringify(payload), "utf-8").toString("base64url")}`;
|
|
6576
|
-
}
|
|
6577
|
-
function decodeLocalJsonEventCursor(cursor, options = {}) {
|
|
6578
|
-
if (!cursor)
|
|
6579
|
-
return 0;
|
|
6580
|
-
if (!cursor.startsWith(LOCAL_JSON_EVENT_CURSOR_PREFIX))
|
|
6581
|
-
throw new Error(`Invalid local JSON event cursor: ${cursor}`);
|
|
6582
|
-
const rawPayload = cursor.slice(LOCAL_JSON_EVENT_CURSOR_PREFIX.length);
|
|
6583
|
-
let payload;
|
|
6584
|
-
try {
|
|
6585
|
-
payload = JSON.parse(Buffer2.from(rawPayload, "base64url").toString("utf-8"));
|
|
6586
|
-
} catch {
|
|
6587
|
-
throw new Error(`Invalid local JSON event cursor: ${cursor}`);
|
|
6588
|
-
}
|
|
6589
|
-
const offset = payload.offset;
|
|
6590
|
-
if (!Number.isInteger(offset) || offset < 0)
|
|
6591
|
-
throw new Error(`Invalid local JSON event cursor: ${cursor}`);
|
|
6592
|
-
assertCursorFilter("eventId", payload.eventId, options.eventId);
|
|
6593
|
-
assertCursorFilter("source", payload.source, options.source);
|
|
6594
|
-
assertCursorFilter("type", payload.type, options.type);
|
|
6595
|
-
return offset;
|
|
6596
|
-
}
|
|
6597
|
-
function normalizeEventPageLimit(limit) {
|
|
6598
|
-
if (limit === undefined)
|
|
6599
|
-
return DEFAULT_EVENT_PAGE_LIMIT;
|
|
6600
|
-
if (!Number.isInteger(limit) || limit < 1)
|
|
6601
|
-
throw new Error(`Event page limit must be a positive integer, got ${limit}`);
|
|
6602
|
-
return Math.min(limit, MAX_EVENT_PAGE_LIMIT);
|
|
6603
|
-
}
|
|
6604
|
-
function queryEvents(events, options) {
|
|
6605
|
-
let rows = events;
|
|
6606
|
-
if (options.eventId)
|
|
6607
|
-
rows = rows.filter((event) => event.id === options.eventId);
|
|
6608
|
-
if (options.source)
|
|
6609
|
-
rows = rows.filter((event) => event.source === options.source);
|
|
6610
|
-
if (options.type)
|
|
6611
|
-
rows = rows.filter((event) => event.type === options.type);
|
|
6612
|
-
if (options.cursor) {
|
|
6613
|
-
const offset = decodeLocalJsonEventCursor(options.cursor, options);
|
|
6614
|
-
rows = rows.slice(offset);
|
|
6615
|
-
}
|
|
6616
|
-
if (options.limit !== undefined)
|
|
6617
|
-
rows = rows.slice(0, normalizeEventPageLimit(options.limit));
|
|
6618
|
-
return rows;
|
|
6619
|
-
}
|
|
6620
|
-
function assertCursorFilter(name, cursorValue, optionValue) {
|
|
6621
|
-
if (cursorValue !== optionValue)
|
|
6622
|
-
throw new Error(`Local JSON event cursor ${name} filter mismatch`);
|
|
6623
|
-
}
|
|
6624
|
-
function findEventByIdentity(events, identity) {
|
|
6625
|
-
return events.find((event) => identity.id !== undefined && event.id === identity.id || identity.dedupeKey !== undefined && event.dedupeKey === identity.dedupeKey);
|
|
6626
|
-
}
|
|
6627
6499
|
async function getEventsStatus(dataDir) {
|
|
6628
6500
|
const store = new JsonEventsStore(dataDir);
|
|
6629
6501
|
await store.init();
|
|
@@ -6640,7 +6512,6 @@ async function getEventsStatus(dataDir) {
|
|
|
6640
6512
|
service: "events",
|
|
6641
6513
|
schemaVersion: "1.0",
|
|
6642
6514
|
dataDir: store.dataDir,
|
|
6643
|
-
storage: store.runtime,
|
|
6644
6515
|
env: {
|
|
6645
6516
|
primary: HASNA_EVENTS_DIR_ENV,
|
|
6646
6517
|
fallback: HASNA_EVENTS_HOME_ENV,
|
|
@@ -6827,51 +6698,6 @@ function createDeliveryResult(event, channel, attempts) {
|
|
|
6827
6698
|
completedAt: attempts.at(-1)?.completedAt ?? now()
|
|
6828
6699
|
};
|
|
6829
6700
|
}
|
|
6830
|
-
|
|
6831
|
-
class EventValidationError extends Error {
|
|
6832
|
-
eventType;
|
|
6833
|
-
issues;
|
|
6834
|
-
constructor(eventType, issues) {
|
|
6835
|
-
const detail = issues.map((issue) => `${issue.path || "<root>"}: ${issue.message}`).join("; ");
|
|
6836
|
-
super(`Event validation failed for type "${eventType}": ${detail}`);
|
|
6837
|
-
this.name = "EventValidationError";
|
|
6838
|
-
this.eventType = eventType;
|
|
6839
|
-
this.issues = issues;
|
|
6840
|
-
}
|
|
6841
|
-
}
|
|
6842
|
-
|
|
6843
|
-
class EventTypeCatalog {
|
|
6844
|
-
definitions = new Map;
|
|
6845
|
-
register(definition) {
|
|
6846
|
-
this.definitions.set(definition.type, definition);
|
|
6847
|
-
return this;
|
|
6848
|
-
}
|
|
6849
|
-
unregister(type) {
|
|
6850
|
-
return this.definitions.delete(type);
|
|
6851
|
-
}
|
|
6852
|
-
has(type) {
|
|
6853
|
-
return this.definitions.has(type);
|
|
6854
|
-
}
|
|
6855
|
-
get(type) {
|
|
6856
|
-
return this.definitions.get(type);
|
|
6857
|
-
}
|
|
6858
|
-
list() {
|
|
6859
|
-
return [...this.definitions.values()];
|
|
6860
|
-
}
|
|
6861
|
-
validateEvent(event) {
|
|
6862
|
-
const definition = this.definitions.get(event.type);
|
|
6863
|
-
if (!definition)
|
|
6864
|
-
return { ok: true };
|
|
6865
|
-
return definition.validate(event.data, event);
|
|
6866
|
-
}
|
|
6867
|
-
assertEventValid(event) {
|
|
6868
|
-
const result = this.validateEvent(event);
|
|
6869
|
-
if (!result.ok) {
|
|
6870
|
-
throw new EventValidationError(event.type, result.issues);
|
|
6871
|
-
}
|
|
6872
|
-
}
|
|
6873
|
-
}
|
|
6874
|
-
var defaultEventTypeCatalog = new EventTypeCatalog;
|
|
6875
6701
|
function createEvent(input) {
|
|
6876
6702
|
return {
|
|
6877
6703
|
id: input.id ?? randomUUID2(),
|
|
@@ -6892,14 +6718,10 @@ class EventsClient {
|
|
|
6892
6718
|
store;
|
|
6893
6719
|
redactors;
|
|
6894
6720
|
transportOptions;
|
|
6895
|
-
catalog;
|
|
6896
|
-
validateCatalogTypes;
|
|
6897
6721
|
constructor(options = {}) {
|
|
6898
6722
|
this.store = options.store ?? new JsonEventsStore(options.dataDir);
|
|
6899
6723
|
this.redactors = options.redactors ?? [];
|
|
6900
6724
|
this.transportOptions = { fetchImpl: options.fetchImpl };
|
|
6901
|
-
this.catalog = options.catalog ?? defaultEventTypeCatalog;
|
|
6902
|
-
this.validateCatalogTypes = options.validateCatalogTypes ?? false;
|
|
6903
6725
|
}
|
|
6904
6726
|
async addChannel(input) {
|
|
6905
6727
|
const timestamp = new Date().toISOString();
|
|
@@ -6917,40 +6739,18 @@ class EventsClient {
|
|
|
6917
6739
|
}
|
|
6918
6740
|
async emit(input, options = {}) {
|
|
6919
6741
|
const event = options.redactSensitiveData === false ? createEvent(input) : redactSensitiveKeys(createEvent(input));
|
|
6920
|
-
if (options.
|
|
6921
|
-
this.
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
|
|
6927
|
-
const deliveries = options.deliver === false ? [] : await this.deliver(
|
|
6928
|
-
return { event
|
|
6929
|
-
}
|
|
6930
|
-
async listEvents(
|
|
6931
|
-
|
|
6932
|
-
return this.store.listEvents();
|
|
6933
|
-
return queryClientEvents(await this.store.listEvents(), options);
|
|
6934
|
-
}
|
|
6935
|
-
async listEventsPage(options = {}) {
|
|
6936
|
-
if (this.store.listEventsPage)
|
|
6937
|
-
return this.store.listEventsPage(options);
|
|
6938
|
-
const events = queryClientEvents(await this.store.listEvents(), {
|
|
6939
|
-
eventId: options.eventId,
|
|
6940
|
-
source: options.source,
|
|
6941
|
-
type: options.type
|
|
6942
|
-
});
|
|
6943
|
-
const offset = decodeLocalJsonEventCursor(options.cursor, options);
|
|
6944
|
-
const limit = normalizeEventPageLimit(options.limit);
|
|
6945
|
-
const pageEvents = events.slice(offset, offset + limit);
|
|
6946
|
-
const nextOffset = offset + pageEvents.length;
|
|
6947
|
-
const hasMore = nextOffset < events.length;
|
|
6948
|
-
return {
|
|
6949
|
-
events: pageEvents,
|
|
6950
|
-
cursor: options.cursor,
|
|
6951
|
-
nextCursor: hasMore ? encodeLocalJsonEventCursor(nextOffset, options) : undefined,
|
|
6952
|
-
hasMore
|
|
6953
|
-
};
|
|
6742
|
+
if (options.dedupe !== false) {
|
|
6743
|
+
const existing = await this.store.findEventByIdentity({ id: input.id, dedupeKey: event.dedupeKey });
|
|
6744
|
+
if (existing) {
|
|
6745
|
+
return { event: existing, deliveries: [], deduped: true };
|
|
6746
|
+
}
|
|
6747
|
+
}
|
|
6748
|
+
await this.store.appendEvent(event);
|
|
6749
|
+
const deliveries = options.deliver === false ? [] : await this.deliver(event);
|
|
6750
|
+
return { event, deliveries, deduped: false };
|
|
6751
|
+
}
|
|
6752
|
+
async listEvents() {
|
|
6753
|
+
return this.store.listEvents();
|
|
6954
6754
|
}
|
|
6955
6755
|
async listDeliveries() {
|
|
6956
6756
|
return this.store.listDeliveries();
|
|
@@ -7018,37 +6818,22 @@ class EventsClient {
|
|
|
7018
6818
|
return result;
|
|
7019
6819
|
}
|
|
7020
6820
|
async replay(options = {}) {
|
|
7021
|
-
const
|
|
6821
|
+
const events = (await this.store.listEvents()).filter((event) => {
|
|
6822
|
+
if (options.eventId && event.id !== options.eventId)
|
|
6823
|
+
return false;
|
|
6824
|
+
if (options.source && event.source !== options.source)
|
|
6825
|
+
return false;
|
|
6826
|
+
if (options.type && event.type !== options.type)
|
|
6827
|
+
return false;
|
|
6828
|
+
return true;
|
|
6829
|
+
});
|
|
7022
6830
|
if (options.dryRun)
|
|
7023
|
-
return { events
|
|
6831
|
+
return { events, deliveries: [] };
|
|
7024
6832
|
const deliveries = [];
|
|
7025
|
-
for (const event of
|
|
6833
|
+
for (const event of events) {
|
|
7026
6834
|
deliveries.push(...await this.deliver(event));
|
|
7027
6835
|
}
|
|
7028
|
-
return { events
|
|
7029
|
-
}
|
|
7030
|
-
async appendEvent(event, options) {
|
|
7031
|
-
if (this.store.appendEventOnce) {
|
|
7032
|
-
return this.store.appendEventOnce(event, { dedupe: options.dedupe });
|
|
7033
|
-
}
|
|
7034
|
-
if (options.dedupe) {
|
|
7035
|
-
const existing = await this.store.findEventByIdentity({ id: event.id, dedupeKey: event.dedupeKey });
|
|
7036
|
-
if (existing) {
|
|
7037
|
-
return {
|
|
7038
|
-
event: existing,
|
|
7039
|
-
stored: false,
|
|
7040
|
-
deduped: true,
|
|
7041
|
-
identity: { id: existing.id, dedupeKey: existing.dedupeKey }
|
|
7042
|
-
};
|
|
7043
|
-
}
|
|
7044
|
-
}
|
|
7045
|
-
const stored = await this.store.appendEvent(event);
|
|
7046
|
-
return {
|
|
7047
|
-
event: stored,
|
|
7048
|
-
stored: true,
|
|
7049
|
-
deduped: false,
|
|
7050
|
-
identity: { id: stored.id, dedupeKey: stored.dedupeKey }
|
|
7051
|
-
};
|
|
6836
|
+
return { events, deliveries };
|
|
7052
6837
|
}
|
|
7053
6838
|
async applyRedaction(event, channel) {
|
|
7054
6839
|
let next = redactPaths(event, channel.redact?.paths ?? [], channel.redact?.replacement ?? "[REDACTED]");
|
|
@@ -7125,20 +6910,6 @@ function setPath(input, path, replacement) {
|
|
|
7125
6910
|
if (last && last in cursor)
|
|
7126
6911
|
cursor[last] = replacement;
|
|
7127
6912
|
}
|
|
7128
|
-
function queryClientEvents(events, options) {
|
|
7129
|
-
let rows = events;
|
|
7130
|
-
if (options.eventId)
|
|
7131
|
-
rows = rows.filter((event) => event.id === options.eventId);
|
|
7132
|
-
if (options.source)
|
|
7133
|
-
rows = rows.filter((event) => event.source === options.source);
|
|
7134
|
-
if (options.type)
|
|
7135
|
-
rows = rows.filter((event) => event.type === options.type);
|
|
7136
|
-
if (options.cursor)
|
|
7137
|
-
rows = rows.slice(decodeLocalJsonEventCursor(options.cursor, options));
|
|
7138
|
-
if (options.limit !== undefined)
|
|
7139
|
-
rows = rows.slice(0, normalizeEventPageLimit(options.limit));
|
|
7140
|
-
return rows;
|
|
7141
|
-
}
|
|
7142
6913
|
function normalizeTime(value) {
|
|
7143
6914
|
if (!value)
|
|
7144
6915
|
return new Date().toISOString();
|
|
@@ -7221,7 +6992,6 @@ function parseMatcherExpression(value, label) {
|
|
|
7221
6992
|
negated: false
|
|
7222
6993
|
};
|
|
7223
6994
|
}
|
|
7224
|
-
var DEFAULT_EVENT_LIST_LIMIT = 100;
|
|
7225
6995
|
function parseJsonObject(value, fallback) {
|
|
7226
6996
|
if (!value)
|
|
7227
6997
|
return fallback;
|
|
@@ -7254,14 +7024,6 @@ function print(value, json, text) {
|
|
|
7254
7024
|
else
|
|
7255
7025
|
console.log(text);
|
|
7256
7026
|
}
|
|
7257
|
-
function fail(error, json) {
|
|
7258
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
7259
|
-
if (json)
|
|
7260
|
-
console.log(JSON.stringify({ error: message }, null, 2));
|
|
7261
|
-
else
|
|
7262
|
-
console.error(message);
|
|
7263
|
-
process.exitCode = 1;
|
|
7264
|
-
}
|
|
7265
7027
|
function hasJsonOption(options) {
|
|
7266
7028
|
return Boolean(options?.json || options?.opts?.().json || options?.optsWithGlobals?.().json || options?.parent?.opts?.().json || options?.parent?.optsWithGlobals?.().json);
|
|
7267
7029
|
}
|
|
@@ -7316,36 +7078,26 @@ function registerChannelCommands(program, options) {
|
|
|
7316
7078
|
print({ removed }, wantsJson(actionOptions, command), removed ? `Removed ${id}` : `Channel not found: ${id}`);
|
|
7317
7079
|
});
|
|
7318
7080
|
channels.command("test").description("Send a test event to one channel").argument("<id>", "Channel identifier").option("--source <source>", "Event source override").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--honor-filters", "Skip delivery when the sample event does not match channel filters", false).option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
|
|
7319
|
-
const
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
}, { honorFilters: actionOptions.honorFilters });
|
|
7329
|
-
print(result, json, `${result.status}: ${result.channelId}`);
|
|
7330
|
-
} catch (error) {
|
|
7331
|
-
fail(error, json);
|
|
7332
|
-
}
|
|
7081
|
+
const result = await createClient(options).testChannel(id, {
|
|
7082
|
+
source: actionOptions.source ?? options.source,
|
|
7083
|
+
type: actionOptions.type,
|
|
7084
|
+
subject: actionOptions.subject ?? id,
|
|
7085
|
+
message: actionOptions.message,
|
|
7086
|
+
data: parseJsonObject(actionOptions.data, { test: true }),
|
|
7087
|
+
metadata: parseJsonObject(actionOptions.metadata, {})
|
|
7088
|
+
}, { honorFilters: actionOptions.honorFilters });
|
|
7089
|
+
print(result, wantsJson(actionOptions, command), `${result.status}: ${result.channelId}`);
|
|
7333
7090
|
});
|
|
7334
7091
|
channels.command("match").description("Check whether a sample event matches one channel without delivering").argument("<id>", "Channel identifier").option("--source <source>", "Event source override").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events match preview").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
|
|
7335
|
-
const
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
});
|
|
7345
|
-
print(result, json, `${result.matched ? "matched" : "skipped"}: ${result.channelId}`);
|
|
7346
|
-
} catch (error) {
|
|
7347
|
-
fail(error, json);
|
|
7348
|
-
}
|
|
7092
|
+
const result = await createClient(options).matchChannel(id, {
|
|
7093
|
+
source: actionOptions.source ?? options.source,
|
|
7094
|
+
type: actionOptions.type,
|
|
7095
|
+
subject: actionOptions.subject ?? id,
|
|
7096
|
+
message: actionOptions.message,
|
|
7097
|
+
data: parseJsonObject(actionOptions.data, { test: true }),
|
|
7098
|
+
metadata: parseJsonObject(actionOptions.metadata, {})
|
|
7099
|
+
});
|
|
7100
|
+
print(result, wantsJson(actionOptions, command), `${result.matched ? "matched" : "skipped"}: ${result.channelId}`);
|
|
7349
7101
|
});
|
|
7350
7102
|
return channels;
|
|
7351
7103
|
}
|
|
@@ -7364,8 +7116,7 @@ function registerEventCommands(program, options) {
|
|
|
7364
7116
|
}, { deliver: actionOptions.deliver, dedupe: actionOptions.dedupe });
|
|
7365
7117
|
print(result, wantsJson(actionOptions, command), `${result.deduped ? "Deduped" : "Emitted"} ${result.event.id} to ${result.deliveries.length} channel(s)`);
|
|
7366
7118
|
});
|
|
7367
|
-
|
|
7368
|
-
events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", `Limit to the most recent <n> events (default ${defaultListLimit}; use 0 for all)`, parseNumber, defaultListLimit).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
|
|
7119
|
+
events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
|
|
7369
7120
|
let rows = await createClient(options).listEvents();
|
|
7370
7121
|
if (actionOptions.source)
|
|
7371
7122
|
rows = rows.filter((event) => event.source === actionOptions.source);
|
|
@@ -7384,16 +7135,14 @@ function registerEventCommands(program, options) {
|
|
|
7384
7135
|
for (const event of rows)
|
|
7385
7136
|
console.log(`${event.time} ${event.id} ${event.source} ${event.type} ${event.severity}`);
|
|
7386
7137
|
});
|
|
7387
|
-
events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--
|
|
7138
|
+
events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
|
|
7388
7139
|
const result = await createClient(options).replay({
|
|
7389
7140
|
eventId: actionOptions.id,
|
|
7390
7141
|
source: actionOptions.source,
|
|
7391
7142
|
type: actionOptions.type,
|
|
7392
|
-
cursor: actionOptions.cursor,
|
|
7393
|
-
limit: actionOptions.limit,
|
|
7394
7143
|
dryRun: actionOptions.dryRun
|
|
7395
7144
|
});
|
|
7396
|
-
print(result, wantsJson(actionOptions, command),
|
|
7145
|
+
print(result, wantsJson(actionOptions, command), `Replayed ${result.events.length} event(s), ${result.deliveries.length} delivery result(s)`);
|
|
7397
7146
|
});
|
|
7398
7147
|
return events;
|
|
7399
7148
|
}
|
|
@@ -7411,10 +7160,6 @@ function collectValues(value, previous) {
|
|
|
7411
7160
|
previous.push(value);
|
|
7412
7161
|
return previous;
|
|
7413
7162
|
}
|
|
7414
|
-
function replaySummary(events, deliveries, nextCursor) {
|
|
7415
|
-
const suffix = nextCursor ? `, next cursor: ${nextCursor}` : "";
|
|
7416
|
-
return `Replayed ${events} event(s), ${deliveries} delivery result(s)${suffix}`;
|
|
7417
|
-
}
|
|
7418
7163
|
|
|
7419
7164
|
// src/cli/index.tsx
|
|
7420
7165
|
import { render } from "ink";
|