@rawdash/core 0.15.0 → 0.17.0

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 CHANGED
@@ -9,7 +9,7 @@ Headless dashboard backend primitives for rawdash. Define connectors, dashboards
9
9
 
10
10
  `@rawdash/core` is the foundation of the rawdash ecosystem. It provides the types and functions (`defineConfig`, `defineDashboard`, `defineMetric`, `defineConnector`, `secret`) that every rawdash setup is built on. It has no framework dependencies and no I/O — it only models your dashboard configuration and the connector interface.
11
11
 
12
- Other packages (`@rawdash/server`, `@rawdash/hono`, `@rawdash/nextjs`, `@rawdash/mcp`) take a config produced by this package and add runtime behavior.
12
+ Other packages (`@rawdash/server`, `@rawdash/hono`, `@rawdash/sdk-nextjs`, `@rawdash/mcp`) take a config produced by this package and add runtime behavior.
13
13
 
14
14
  ## Install
15
15
 
package/dist/index.d.ts CHANGED
@@ -1,16 +1,20 @@
1
- import { RequestObserver, HttpRequest, HttpResponse } from '@rawdash/connector-shared';
1
+ import { RequestObserver, ConnectorLogger, HttpRequest, HttpResponse } from '@rawdash/connector-shared';
2
+ export { ConnectorLogger, ConnectorLoggerOptions, LogFields, createDefaultConnectorLogger, noopConnectorLogger } from '@rawdash/connector-shared';
2
3
  import { z } from 'zod';
3
4
 
4
5
  type Secret = {
5
6
  $secret: string;
6
7
  };
8
+ type SecretRef = Secret;
7
9
  declare function secret(name: string): Secret;
8
10
  declare function isSecret(value: unknown): value is Secret;
11
+ declare const secretRefSchema: z.ZodType<SecretRef>;
12
+ declare function withSecretRef<T extends z.ZodTypeAny>(schema: T): z.ZodUnion<[T, z.ZodType<SecretRef>]>;
9
13
  interface SecretsResolver {
10
- resolve(name: string): string | undefined;
14
+ resolve(name: string): unknown;
11
15
  }
12
16
  declare class EnvSecretsResolver implements SecretsResolver {
13
- resolve(name: string): string | undefined;
17
+ resolve(name: string): unknown;
14
18
  }
15
19
  declare function extractSecretNames(value: unknown): string[];
16
20
  declare function resolveSecrets<T>(obj: T, resolver: SecretsResolver): T;
@@ -154,6 +158,7 @@ interface SyncOptions {
154
158
  mode: 'full' | 'latest';
155
159
  since?: string;
156
160
  cursor?: unknown;
161
+ resources?: ReadonlySet<string>;
157
162
  }
158
163
  interface SyncResult {
159
164
  done: boolean;
@@ -169,6 +174,7 @@ interface Connector {
169
174
  interface ConnectorContext {
170
175
  observer?: RequestObserver;
171
176
  secretsResolver?: SecretsResolver;
177
+ logger?: ConnectorLogger;
172
178
  }
173
179
  interface ConnectorRequestOptions {
174
180
  resource: string;
@@ -187,7 +193,9 @@ declare abstract class BaseConnector<TSettings = unknown, TCreds extends Credent
187
193
  protected creds: InferCredentials<TCreds>;
188
194
  private rawCredInput;
189
195
  private ctx;
196
+ private cachedLogger;
190
197
  constructor(settings: TSettings, creds?: InferCredentialInput<TCreds>, ctx?: ConnectorContext);
198
+ protected get logger(): ConnectorLogger;
191
199
  protected request<T = unknown>(req: HttpRequest, opts: ConnectorRequestOptions): Promise<HttpResponse<T>>;
192
200
  protected get<T = unknown>(url: string, opts: ConnectorRequestOptions & {
193
201
  headers?: Record<string, string>;
@@ -200,6 +208,7 @@ declare abstract class BaseConnector<TSettings = unknown, TCreds extends Credent
200
208
  signal?: AbortSignal;
201
209
  rateLimit?: HttpRequest['rateLimit'];
202
210
  }): Promise<HttpResponse<T>>;
211
+ protected isResourceEnabled<R extends string>(resource: R): boolean;
203
212
  serializeConfig(): Record<string, unknown>;
204
213
  protected sleep(ms: number, signal?: AbortSignal): Promise<void>;
205
214
  protected withRetry<T>(fn: (signal?: AbortSignal) => Promise<{
@@ -227,6 +236,8 @@ interface ChunkedSyncCursor<TPhase extends string, TPage> {
227
236
  phase: TPhase;
228
237
  page: TPage | null;
229
238
  }
239
+ declare function selectActivePhases<R extends string, P extends string>(resourceToPhase: (resource: R) => P, order: readonly P[], enabled: readonly R[] | undefined): P[];
240
+ declare function makeChunkedCursorGuard<TPhase extends string>(phases: readonly TPhase[]): (value: unknown) => value is ChunkedSyncCursor<TPhase, string>;
230
241
  interface FetchPageResult<TPage> {
231
242
  items: unknown[];
232
243
  next: TPage | null;
@@ -237,9 +248,20 @@ interface ChunkedSyncOptions<TPhase extends string, TPage> {
237
248
  signal: AbortSignal | undefined;
238
249
  fetchPage: (phase: TPhase, page: TPage | null, signal: AbortSignal | undefined) => Promise<FetchPageResult<TPage>>;
239
250
  writeBatch: (phase: TPhase, items: unknown[], page: TPage | null) => Promise<void>;
251
+ logger?: ConnectorLogger;
240
252
  }
241
253
  declare function paginateChunked<TPhase extends string, TPage>(opts: ChunkedSyncOptions<TPhase, TPage>): Promise<SyncResult>;
242
254
 
255
+ type FilterOperator = 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'contains';
256
+ interface FilterCondition {
257
+ field: string;
258
+ op: FilterOperator;
259
+ value: string | number | boolean;
260
+ }
261
+ type FilterClause = FilterCondition | {
262
+ or: FilterCondition[];
263
+ };
264
+
243
265
  interface RetentionConfig {
244
266
  maxAge?: number;
245
267
  maxSize?: number;
@@ -1211,15 +1233,6 @@ declare function getWidgetSchema(kind: WidgetKind): z.ZodObject<{
1211
1233
 
1212
1234
  type AggFn = 'count' | 'sum' | 'avg' | 'min' | 'max' | 'latest' | 'first';
1213
1235
  type Shape = 'event' | 'entity' | 'metric' | 'edge' | 'distribution';
1214
- type FilterOperator = 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'contains';
1215
- interface FilterCondition {
1216
- field: string;
1217
- op: FilterOperator;
1218
- value: string | number | boolean;
1219
- }
1220
- type FilterClause = FilterCondition | {
1221
- or: FilterCondition[];
1222
- };
1223
1236
  interface GroupBy {
1224
1237
  field: string;
1225
1238
  granularity: 'hour' | 'day' | 'week' | 'month';
@@ -1315,6 +1328,7 @@ interface CachedWidget<TData = unknown> {
1315
1328
  data: TData | null;
1316
1329
  cachedAt: string | null;
1317
1330
  syncState?: WidgetSyncState;
1331
+ syncIntervalSeconds?: number;
1318
1332
  meta?: Record<string, unknown>;
1319
1333
  }
1320
1334
  interface WidgetsListResponse {
@@ -1345,22 +1359,70 @@ interface ServerDataSource {
1345
1359
  type ConfigFieldsSchema = z.ZodObject<z.ZodRawShape>;
1346
1360
  declare function defineConfigFields<T extends z.ZodRawShape>(schema: z.ZodObject<T>): z.ZodObject<T>;
1347
1361
 
1348
- declare function computeMetric(storage: StorageHandle, metric: ComputedMetric): Promise<unknown>;
1362
+ declare const connectorCategorySchema: z.ZodEnum<{
1363
+ engineering: "engineering";
1364
+ product: "product";
1365
+ analytics: "analytics";
1366
+ marketing: "marketing";
1367
+ sales: "sales";
1368
+ support: "support";
1369
+ finance: "finance";
1370
+ infrastructure: "infrastructure";
1371
+ security: "security";
1372
+ }>;
1373
+ type ConnectorCategory = z.infer<typeof connectorCategorySchema>;
1374
+ declare const connectorDocSchema: z.ZodObject<{
1375
+ displayName: z.ZodString;
1376
+ category: z.ZodEnum<{
1377
+ engineering: "engineering";
1378
+ product: "product";
1379
+ analytics: "analytics";
1380
+ marketing: "marketing";
1381
+ sales: "sales";
1382
+ support: "support";
1383
+ finance: "finance";
1384
+ infrastructure: "infrastructure";
1385
+ security: "security";
1386
+ }>;
1387
+ tagline: z.ZodString;
1388
+ brandColor: z.ZodOptional<z.ZodString>;
1389
+ vendor: z.ZodObject<{
1390
+ name: z.ZodString;
1391
+ apiDocs: z.ZodOptional<z.ZodURL>;
1392
+ website: z.ZodOptional<z.ZodURL>;
1393
+ }, z.core.$strip>;
1394
+ auth: z.ZodObject<{
1395
+ summary: z.ZodString;
1396
+ setup: z.ZodArray<z.ZodString>;
1397
+ }, z.core.$strip>;
1398
+ rateLimit: z.ZodOptional<z.ZodString>;
1399
+ limitations: z.ZodOptional<z.ZodArray<z.ZodString>>;
1400
+ }, z.core.$strip>;
1401
+ type ConnectorDoc = z.infer<typeof connectorDocSchema>;
1402
+ /**
1403
+ * Declare a connector's documentation metadata. Validates the shape at module
1404
+ * load so a malformed `doc` fails fast (and fails the package's tests), and
1405
+ * returns the typed object for the generator to consume.
1406
+ */
1407
+ declare function defineConnectorDoc(doc: ConnectorDoc): ConnectorDoc;
1349
1408
 
1350
- interface GetStorageHandleOptions {
1351
- signal?: AbortSignal;
1352
- }
1353
- interface ServerStorage {
1354
- getStorageHandle(connectorId: string, options?: GetStorageHandleOptions): StorageHandle;
1355
- getSyncState(): Promise<SyncState>;
1356
- markSyncQueued(): Promise<boolean>;
1357
- markSyncRunning(): Promise<boolean>;
1358
- markSyncSucceeded(): Promise<void>;
1359
- markSyncFailed(error: string): Promise<void>;
1409
+ /**
1410
+ * Optional cost signal a connector reports about syncing. Surfaced in the
1411
+ * generated docs as a callout and read by the cloud connector-manager to warn
1412
+ * when a chosen sync interval is more aggressive than recommended. Use it for
1413
+ * connectors where frequent syncs are genuinely expensive (per-query billing,
1414
+ * tight quotas).
1415
+ */
1416
+ interface ConnectorCost {
1417
+ /** Recommended sync interval, e.g. "1 day". */
1418
+ recommendedInterval?: string;
1419
+ /** Minimum sensible sync interval, e.g. "1 hour". */
1420
+ minInterval?: string;
1421
+ /** What a single sync costs upstream, e.g. "2 Cost Explorer queries (~$0.02)". */
1422
+ perSync?: string;
1423
+ /** One-line warning shown next to the frequency control / at the top of docs. */
1424
+ warning?: string;
1360
1425
  }
1361
-
1362
- declare function resolveWidget(widgetId: string, widget: Widget, connectors: readonly string[] | undefined, storage: ServerStorage): Promise<CachedWidget | undefined>;
1363
-
1364
1426
  /**
1365
1427
  * Map of resource name → Zod schema describing the raw API response shape
1366
1428
  * for that resource. Resource names must match the `resource` tag passed to
@@ -1385,9 +1447,102 @@ type ConnectorClass = {
1385
1447
  new (settings: never, creds?: never, ctx?: ConnectorContext): Connector;
1386
1448
  readonly credentials?: CredentialsSchema;
1387
1449
  readonly schemas: ConnectorSchemas;
1450
+ /** Per-resource definitions (shape, docs, and response schemas). */
1451
+ readonly resources?: ResourceDefinitions;
1452
+ /** Optional cost / recommended-frequency signal (see {@link ConnectorCost}). */
1453
+ readonly cost?: ConnectorCost;
1388
1454
  };
1389
1455
  type ConnectorRegistry = Record<string, ConnectorClass>;
1390
- declare function instantiateConnector(entry: ConfiguredConnector, registry: ConnectorRegistry, secretsResolver?: SecretsResolver): Connector;
1456
+ declare function instantiateConnector(entry: ConfiguredConnector, registry: ConnectorRegistry, secretsResolver?: SecretsResolver, logger?: ConnectorLogger): Connector;
1457
+
1458
+ interface ResourceField {
1459
+ name: string;
1460
+ description: string;
1461
+ }
1462
+ interface ResourceDefBase {
1463
+ description: string;
1464
+ endpoint?: string;
1465
+ notes?: string;
1466
+ dynamic?: boolean;
1467
+ responses?: Readonly<Record<string, z.ZodType>>;
1468
+ }
1469
+ type ResourceDefinition = (ResourceDefBase & {
1470
+ shape: 'entity';
1471
+ fields?: ResourceField[];
1472
+ }) | (ResourceDefBase & {
1473
+ shape: 'event';
1474
+ fields?: ResourceField[];
1475
+ }) | (ResourceDefBase & {
1476
+ shape: 'metric';
1477
+ unit?: string;
1478
+ granularity?: string;
1479
+ dimensions?: ResourceField[];
1480
+ }) | (ResourceDefBase & {
1481
+ shape: 'distribution';
1482
+ kind?: 'buckets' | 'quantiles';
1483
+ unit?: string;
1484
+ }) | (ResourceDefBase & {
1485
+ shape: 'edge';
1486
+ from?: string;
1487
+ to?: string;
1488
+ });
1489
+ type ResourceDefinitions = Readonly<Record<string, ResourceDefinition>>;
1490
+ /**
1491
+ * Validate and return a connector's resource definitions. Call it once at
1492
+ * module scope and reference the result from both `static resources` and
1493
+ * `static schemas` on the connector class.
1494
+ */
1495
+ declare function defineResources<const T extends ResourceDefinitions>(defs: T): T;
1496
+ type UnionToIntersection<U> = (U extends unknown ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
1497
+ type ResponsesOf<T extends ResourceDefinitions> = UnionToIntersection<{
1498
+ [K in keyof T]: T[K] extends {
1499
+ responses: infer R;
1500
+ } ? R extends Readonly<Record<string, z.ZodType>> ? R : object : object;
1501
+ }[keyof T]>;
1502
+ /**
1503
+ * Flatten every resource definition's `responses` into the flat
1504
+ * `{ responseTag -> Zod schema }` map that `ConnectorClass.schemas` exposes for
1505
+ * the shape-drift baseline generator and property tests. The return type keeps
1506
+ * the exact per-tag schema types, so `z.infer<typeof schemas.<tag>>` works.
1507
+ */
1508
+ declare function schemasFromResources<const T extends ResourceDefinitions>(defs: T): ResponsesOf<T> & ConnectorSchemas;
1509
+
1510
+ declare function computeMetric(storage: StorageHandle, metric: ComputedMetric): Promise<unknown>;
1511
+
1512
+ interface ResourceBackfill {
1513
+ requiredWindowMs: number | undefined;
1514
+ }
1515
+ type ConnectorBackfill = Map<string, ResourceBackfill>;
1516
+ declare function computeConnectorBackfill(config: DashboardConfig): Map<string, ConnectorBackfill>;
1517
+
1518
+ interface GetStorageHandleOptions {
1519
+ signal?: AbortSignal;
1520
+ }
1521
+ interface ServerStorage {
1522
+ getStorageHandle(connectorId: string, options?: GetStorageHandleOptions): StorageHandle;
1523
+ getSyncState(): Promise<SyncState>;
1524
+ markSyncQueued(): Promise<boolean>;
1525
+ markSyncRunning?(): Promise<boolean>;
1526
+ markSyncSucceeded(): Promise<void>;
1527
+ markSyncFailed(error: string): Promise<void>;
1528
+ }
1529
+
1530
+ declare function resolveWidget(dashboardId: string, widgetId: string, widget: Widget, connectors: readonly string[] | undefined, storage: ServerStorage): Promise<CachedWidget | undefined>;
1531
+
1532
+ /**
1533
+ * Stable 32-bit hex hash of a widget's declarative config. Used as the
1534
+ * config-dependent component of the widget ETag so that a config edit
1535
+ * invalidates the cached ETag even when `lastSyncAt` is unchanged.
1536
+ *
1537
+ * Not cryptographic — collision-resistant enough for cache busting.
1538
+ */
1539
+ declare function hashWidgetConfig(widget: Widget): string;
1540
+ /**
1541
+ * Build the per-widget ETag value (unquoted). Combines the widget's
1542
+ * `lastSyncAt` (the connector's last successful sync timestamp, which is
1543
+ * what `CachedWidget.cachedAt` reflects) and a hash of the widget config.
1544
+ */
1545
+ declare function computeWidgetEtag(lastSyncAt: string | null, widget: Widget): string;
1391
1546
 
1392
1547
  declare function withAbortSignal(handle: StorageHandle, signal: AbortSignal): StorageHandle;
1393
1548
 
@@ -1443,4 +1598,4 @@ type WireDashboard = z.infer<typeof wireDashboardSchema>;
1443
1598
  type WireConfig = z.infer<typeof wireConfigSchema>;
1444
1599
  declare function toWireConfig(config: DashboardConfig): WireConfig;
1445
1600
 
1446
- export { ACTIVE_SYNC_STATUSES, type AggFn, BaseConnector, type CachedWidget, type ChunkedSyncCursor, type ChunkedSyncOptions, type ComputedMetric, type ConfigFieldsSchema, type ConfiguredConnector, type Connector, type ConnectorClass, type ConnectorContext, type ConnectorHealth, type ConnectorRegistry, type ConnectorRequestOptions, type ConnectorSchemas, type CredentialField, type CredentialsSchema, type Dashboard, type DashboardConfig, type DataSource, type Distribution, type DistributionQuery, type DistributionWidget, type Edge, type EdgeQuery, type Entity, type EntityQuery, EnvSecretsResolver, type Event, type EventQuery, type FetchPageResult, type FilterClause, type FilterCondition, type FilterOperator, type GetStorageHandleOptions, type GroupBy, type HealthResponse, InMemoryStorage, type InferCredentialInput, type InferCredentials, type JSONValue, type Metric, type MetricQuery, type MetricSample, type RetentionConfig, type RetentionDeletionPlan, type Secret, type SecretsResolver, type ServerDataSource, type ServerStorage, type Shape, type StatWidget, type StatusWidget, type StorageHandle, type SyncOptions, type SyncResult, type SyncState, type SyncStatus, type TimeseriesWidget, type TriggerSyncResponse, type Widget, type WidgetKind, type WidgetSyncState, type WidgetsListResponse, type WireConfig, type WireConnector, type WireDashboard, aggFnSchema, computeMetric, computeRetention, computedMetricSchema, defineConfig, defineConfigFields, defineConnector, defineDashboard, defineMetric, distributionWidgetSchema, extractSecretNames, filterClauseSchema, filterConditionSchema, filterOperatorSchema, getWidgetSchema, groupBySchema, instantiateConnector, isSecret, isSyncActive, paginateChunked, resolveSecrets, resolveWidget, secret, selectForDeletion, shapeSchema, statWidgetSchema, statusWidgetSchema, timeseriesWidgetSchema, toWireConfig, widgetSchema, widgetSchemas, wireConfigSchema, wireConnectorSchema, wireDashboardSchema, withAbortSignal };
1601
+ export { ACTIVE_SYNC_STATUSES, type AggFn, BaseConnector, type CachedWidget, type ChunkedSyncCursor, type ChunkedSyncOptions, type ComputedMetric, type ConfigFieldsSchema, type ConfiguredConnector, type Connector, type ConnectorBackfill, type ConnectorCategory, type ConnectorClass, type ConnectorContext, type ConnectorCost, type ConnectorDoc, type ConnectorHealth, type ConnectorRegistry, type ConnectorRequestOptions, type ConnectorSchemas, type CredentialField, type CredentialsSchema, type Dashboard, type DashboardConfig, type DataSource, type Distribution, type DistributionQuery, type DistributionWidget, type Edge, type EdgeQuery, type Entity, type EntityQuery, EnvSecretsResolver, type Event, type EventQuery, type FetchPageResult, type FilterClause, type FilterCondition, type FilterOperator, type GetStorageHandleOptions, type GroupBy, type HealthResponse, InMemoryStorage, type InferCredentialInput, type InferCredentials, type JSONValue, type Metric, type MetricQuery, type MetricSample, type ResourceBackfill, type ResourceDefinition, type ResourceDefinitions, type ResourceField, type RetentionConfig, type RetentionDeletionPlan, type Secret, type SecretRef, type SecretsResolver, type ServerDataSource, type ServerStorage, type Shape, type StatWidget, type StatusWidget, type StorageHandle, type SyncOptions, type SyncResult, type SyncState, type SyncStatus, type TimeseriesWidget, type TriggerSyncResponse, type Widget, type WidgetKind, type WidgetSyncState, type WidgetsListResponse, type WireConfig, type WireConnector, type WireDashboard, aggFnSchema, computeConnectorBackfill, computeMetric, computeRetention, computeWidgetEtag, computedMetricSchema, connectorCategorySchema, connectorDocSchema, defineConfig, defineConfigFields, defineConnector, defineConnectorDoc, defineDashboard, defineMetric, defineResources, distributionWidgetSchema, extractSecretNames, filterClauseSchema, filterConditionSchema, filterOperatorSchema, getWidgetSchema, groupBySchema, hashWidgetConfig, instantiateConnector, isSecret, isSyncActive, makeChunkedCursorGuard, paginateChunked, resolveSecrets, resolveWidget, schemasFromResources, secret, secretRefSchema, selectActivePhases, selectForDeletion, shapeSchema, statWidgetSchema, statusWidgetSchema, timeseriesWidgetSchema, toWireConfig, widgetSchema, widgetSchemas, wireConfigSchema, wireConnectorSchema, wireDashboardSchema, withAbortSignal, withSecretRef };