@feltdb/core 0.2.0 → 0.3.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.
Files changed (95) hide show
  1. package/LICENSE +19 -0
  2. package/dist/analytics-backend.d.ts +39 -0
  3. package/dist/analytics-backend.d.ts.map +1 -0
  4. package/dist/analytics-backend.js +152 -0
  5. package/dist/application-contract.d.ts +49 -0
  6. package/dist/application-contract.d.ts.map +1 -0
  7. package/dist/application-contract.js +13 -0
  8. package/dist/application-manifest.d.ts +305 -0
  9. package/dist/application-manifest.d.ts.map +1 -0
  10. package/dist/application-manifest.js +26 -0
  11. package/dist/artifact.d.ts +73 -0
  12. package/dist/artifact.d.ts.map +1 -0
  13. package/dist/artifact.js +21 -0
  14. package/dist/authorization.d.ts +99 -0
  15. package/dist/authorization.d.ts.map +1 -0
  16. package/dist/authorization.js +15 -0
  17. package/dist/bundle.d.ts +55 -0
  18. package/dist/bundle.d.ts.map +1 -0
  19. package/dist/bundle.js +13 -0
  20. package/dist/collection.d.ts +28 -0
  21. package/dist/collection.d.ts.map +1 -1
  22. package/dist/collection.js +83 -0
  23. package/dist/db.d.ts +18 -0
  24. package/dist/db.d.ts.map +1 -1
  25. package/dist/db.js +20 -8
  26. package/dist/distributed-indexing.d.ts +170 -0
  27. package/dist/distributed-indexing.d.ts.map +1 -0
  28. package/dist/distributed-indexing.js +260 -0
  29. package/dist/flowspec.d.ts +4 -0
  30. package/dist/flowspec.d.ts.map +1 -1
  31. package/dist/flowspec.js +8 -0
  32. package/dist/http-client.d.ts +35 -0
  33. package/dist/http-client.d.ts.map +1 -0
  34. package/dist/http-client.js +70 -0
  35. package/dist/identity.d.ts +40 -0
  36. package/dist/identity.d.ts.map +1 -0
  37. package/dist/identity.js +10 -0
  38. package/dist/index-analytics.d.ts +121 -0
  39. package/dist/index-analytics.d.ts.map +1 -0
  40. package/dist/index-analytics.js +279 -0
  41. package/dist/index-backend.d.ts +26 -0
  42. package/dist/index-backend.d.ts.map +1 -0
  43. package/dist/index-backend.js +115 -0
  44. package/dist/index-dashboard.d.ts +114 -0
  45. package/dist/index-dashboard.d.ts.map +1 -0
  46. package/dist/index-dashboard.js +256 -0
  47. package/dist/index-manager.d.ts +18 -0
  48. package/dist/index-manager.d.ts.map +1 -0
  49. package/dist/index-manager.js +333 -0
  50. package/dist/index-monitoring.d.ts +133 -0
  51. package/dist/index-monitoring.d.ts.map +1 -0
  52. package/dist/index-monitoring.js +218 -0
  53. package/dist/index-recovery.d.ts +57 -0
  54. package/dist/index-recovery.d.ts.map +1 -0
  55. package/dist/index-recovery.js +117 -0
  56. package/dist/index-store.d.ts +62 -0
  57. package/dist/index-store.d.ts.map +1 -0
  58. package/dist/index-store.js +141 -0
  59. package/dist/index-types.d.ts +70 -0
  60. package/dist/index-types.d.ts.map +1 -0
  61. package/dist/index-types.js +6 -0
  62. package/dist/index.d.ts +26 -0
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +26 -0
  65. package/dist/observe.d.ts +51 -0
  66. package/dist/observe.d.ts.map +1 -0
  67. package/dist/observe.js +14 -0
  68. package/dist/protocol.d.ts +25 -0
  69. package/dist/protocol.d.ts.map +1 -0
  70. package/dist/protocol.js +18 -0
  71. package/dist/provider.d.ts +61 -0
  72. package/dist/provider.d.ts.map +1 -0
  73. package/dist/provider.js +17 -0
  74. package/dist/query-planner.d.ts +69 -0
  75. package/dist/query-planner.d.ts.map +1 -0
  76. package/dist/query-planner.js +184 -0
  77. package/dist/release.d.ts +60 -0
  78. package/dist/release.d.ts.map +1 -0
  79. package/dist/release.js +18 -0
  80. package/dist/sharding.d.ts +159 -0
  81. package/dist/sharding.d.ts.map +1 -0
  82. package/dist/sharding.js +317 -0
  83. package/dist/state-contract.d.ts +173 -0
  84. package/dist/state-contract.d.ts.map +1 -0
  85. package/dist/state-contract.js +24 -0
  86. package/dist/sync-contract.d.ts +101 -0
  87. package/dist/sync-contract.d.ts.map +1 -0
  88. package/dist/sync-contract.js +90 -0
  89. package/dist/worker.d.ts +90 -0
  90. package/dist/worker.d.ts.map +1 -0
  91. package/dist/worker.js +26 -0
  92. package/dist/workload.d.ts +102 -0
  93. package/dist/workload.d.ts.map +1 -0
  94. package/dist/workload.js +23 -0
  95. package/package.json +17 -5
@@ -0,0 +1,90 @@
1
+ class StatusSignal {
2
+ constructor(value = 'offline') {
3
+ this.value = value;
4
+ this.listeners = new Set();
5
+ }
6
+ subscribe(listener) { this.listeners.add(listener); listener(this.value); return () => this.listeners.delete(listener); }
7
+ set(value) { this.value = value; for (const listener of this.listeners)
8
+ listener(value); }
9
+ get() { return this.value; }
10
+ }
11
+ export class SyncController {
12
+ constructor(config) {
13
+ this.config = config;
14
+ this.status = new StatusSignal();
15
+ this.fetcher = config.fetcher || fetch;
16
+ this.restore();
17
+ }
18
+ key() { return `feltdb:sync:v1:${this.config.device.application_id}:${this.config.device.device_id}`; }
19
+ restore() { if (typeof localStorage === 'undefined')
20
+ return; try {
21
+ const value = JSON.parse(localStorage.getItem(this.key()) || '{}');
22
+ this.sessionId = value.sessionId;
23
+ this.cursor = value.cursor;
24
+ this.error = value.error;
25
+ }
26
+ catch { } }
27
+ persist() { if (typeof localStorage !== 'undefined')
28
+ localStorage.setItem(this.key(), JSON.stringify({ sessionId: this.sessionId, cursor: this.cursor, error: this.error, outbox: this.readOutbox() })); }
29
+ readOutbox() { if (typeof localStorage === 'undefined')
30
+ return []; try {
31
+ return JSON.parse(localStorage.getItem(`${this.key()}:outbox`) || '[]');
32
+ }
33
+ catch {
34
+ return [];
35
+ } }
36
+ writeOutbox(value) { if (typeof localStorage !== 'undefined')
37
+ localStorage.setItem(`${this.key()}:outbox`, JSON.stringify(value)); }
38
+ async request(path, body) { const response = await this.fetcher(`${this.config.endpoint || ''}/v1/sync/${path}`, { method: 'POST', credentials: 'include', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body) }); const value = await response.json().catch(() => ({})); if (!response.ok)
39
+ throw new Error(value.error || `sync ${path} failed (${response.status})`); return value; }
40
+ async start() { this.status.set('connecting'); try {
41
+ if (!this.sessionId) {
42
+ const scope = { resources: this.config.scope.resources || this.config.scope.collections?.map(v => `flow://${this.config.device.application_id}/${v}/*`) || [], fields: this.config.scope.fields || {} };
43
+ const session = await this.request('session', { device: { ...this.config.device, created_at: Math.floor(Date.now() / 1000) }, scope, offline_grant: this.config.offlineGrant });
44
+ this.sessionId = session.session_id;
45
+ this.cursor = session.cursor;
46
+ this.persist();
47
+ }
48
+ await this.flush();
49
+ this.timer = setInterval(() => void this.flush(), 5000);
50
+ return this;
51
+ }
52
+ catch (error) {
53
+ this.error = String(error);
54
+ this.status.set('degraded');
55
+ this.persist();
56
+ throw error;
57
+ } }
58
+ async stop() { if (this.timer)
59
+ clearInterval(this.timer); if (this.sessionId)
60
+ await this.request('close', { session_id: this.sessionId }); this.status.set('offline'); }
61
+ enqueue(operation) { const outbox = this.readOutbox(); if (!outbox.some(v => v.operation_id === operation.operation_id)) {
62
+ outbox.push(operation);
63
+ this.writeOutbox(outbox);
64
+ } return operation.operation_id; }
65
+ async flush() { if (!this.sessionId || !this.cursor)
66
+ return; this.status.set('syncing'); try {
67
+ const pending = this.readOutbox();
68
+ if (pending.length) {
69
+ const result = await this.request('push', { session_id: this.sessionId, operations: pending });
70
+ const terminal = new Set([...result.acknowledgements.map(v => v.operation_id), ...result.rejections.filter(v => !v.retryable).map(v => v.operation_id)]);
71
+ this.writeOutbox(pending.filter(v => !terminal.has(v.operation_id)));
72
+ this.cursor = result.cursor;
73
+ }
74
+ const pulled = await this.request('pull', { session_id: this.sessionId, cursor: this.cursor, limit: 250 });
75
+ this.cursor = pulled.cursor;
76
+ await this.request('ack', { session_id: this.sessionId, cursor: this.cursor });
77
+ this.error = undefined;
78
+ this.status.set('synced');
79
+ this.persist();
80
+ }
81
+ catch (error) {
82
+ this.error = String(error);
83
+ this.status.set(typeof navigator !== 'undefined' && !navigator.onLine ? 'offline' : 'degraded');
84
+ this.persist();
85
+ } }
86
+ pending() { return this.readOutbox(); }
87
+ conflicts() { return this.readOutbox().filter((v) => v.status === 'CONFLICTED'); }
88
+ lastCursor() { return this.cursor; }
89
+ lastError() { return this.error; }
90
+ }
@@ -0,0 +1,90 @@
1
+ import type { SignedGrant, AuthorizationSubject } from './authorization.js';
2
+ export type WorkerLifecycle = 'REGISTERED' | 'READY' | 'BUSY' | 'DRAINING' | 'OFFLINE' | 'RECOVERING';
3
+ export type WorkerHealth = 'HEALTHY' | 'DEGRADED' | 'UNHEALTHY' | 'UNKNOWN';
4
+ export interface WorkerRegistration {
5
+ tenant_id: string;
6
+ application_id: string;
7
+ name: string;
8
+ runtime: 'wasm' | 'process' | 'container' | 'browser' | 'remote' | 'hosted' | 'edge' | 'customer';
9
+ version: string;
10
+ capabilities: string[];
11
+ workload_kinds?: string[];
12
+ resource_profile?: Record<string, number>;
13
+ labels?: Record<string, string>;
14
+ capacity: {
15
+ concurrency: number;
16
+ active?: number;
17
+ };
18
+ authorization_grant: SignedGrant;
19
+ registered_by: AuthorizationSubject;
20
+ registered_at?: number;
21
+ }
22
+ export interface Worker {
23
+ worker_id: string;
24
+ tenant_id: string;
25
+ application_id: string;
26
+ name: string;
27
+ runtime: string;
28
+ version: string;
29
+ declared_capabilities: string[];
30
+ granted_capabilities: string[];
31
+ workload_kinds: string[];
32
+ labels: Record<string, string>;
33
+ capacity: {
34
+ concurrency: number;
35
+ active: number;
36
+ };
37
+ health: WorkerHealth;
38
+ lifecycle: WorkerLifecycle;
39
+ last_seen: number;
40
+ capability_version: number;
41
+ claims: string[];
42
+ }
43
+ export interface WorkerPool {
44
+ pool_id: string;
45
+ tenant_id: string;
46
+ application_id?: string;
47
+ name: string;
48
+ capabilities: string[];
49
+ required_labels?: Record<string, string>;
50
+ worker_ids: string[];
51
+ max_concurrency?: number;
52
+ created_at: number;
53
+ }
54
+ declare class MeshTransport {
55
+ protected baseUrl: string;
56
+ protected fetcher: typeof fetch;
57
+ constructor(baseUrl?: string, fetcher?: typeof fetch);
58
+ protected json<T>(path: string, init?: RequestInit): Promise<T>;
59
+ }
60
+ export declare class WorkerClient extends MeshTransport {
61
+ register(input: WorkerRegistration): Promise<Worker>;
62
+ list(applicationId: string): Promise<{
63
+ workers: Worker[];
64
+ }>;
65
+ inspect(id: string): Promise<Worker>;
66
+ heartbeat(id: string, heartbeat: unknown, grant: SignedGrant): Promise<Worker>;
67
+ drain(id: string, grant: SignedGrant): Promise<Worker>;
68
+ recover(id: string, grant: SignedGrant): Promise<Worker>;
69
+ reconcile(id: string, reconciliation: unknown, grant: SignedGrant): Promise<unknown>;
70
+ }
71
+ export declare class WorkerPoolClient extends MeshTransport {
72
+ list(applicationId: string): Promise<{
73
+ pools: WorkerPool[];
74
+ }>;
75
+ create(pool: WorkerPool, grant: SignedGrant): Promise<WorkerPool>;
76
+ inspect(id: string): Promise<WorkerPool>;
77
+ }
78
+ export declare class MeshClient extends MeshTransport {
79
+ status(applicationId: string): Promise<{
80
+ workers: Worker[];
81
+ pools: WorkerPool[];
82
+ ready: number;
83
+ busy: number;
84
+ }>;
85
+ eligibleWorkers(workloadId: string): Promise<{
86
+ eligible_workers: string[];
87
+ }>;
88
+ }
89
+ export {};
90
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"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"}
package/dist/worker.js ADDED
@@ -0,0 +1,26 @@
1
+ class MeshTransport {
2
+ constructor(baseUrl = '', fetcher = fetch) {
3
+ this.baseUrl = baseUrl;
4
+ this.fetcher = fetcher;
5
+ }
6
+ async json(path, init) { const response = await this.fetcher(`${this.baseUrl}${path}`, { credentials: 'include', headers: { 'content-type': 'application/json', ...(init?.headers || {}) }, ...init }); const value = response.status === 204 ? undefined : await response.json(); if (!response.ok)
7
+ throw new Error(value?.error || `Mesh request failed (${response.status})`); return value; }
8
+ }
9
+ export class WorkerClient extends MeshTransport {
10
+ register(input) { return this.json('/v1/workers/register', { method: 'POST', body: JSON.stringify({ ...input, registered_at: input.registered_at || Math.floor(Date.now() / 1000) }) }); }
11
+ list(applicationId) { return this.json(`/v1/workers?application_id=${encodeURIComponent(applicationId)}`); }
12
+ inspect(id) { return this.json(`/v1/workers/${encodeURIComponent(id)}`); }
13
+ heartbeat(id, heartbeat, grant) { return this.json(`/v1/workers/${encodeURIComponent(id)}/heartbeat`, { method: 'POST', body: JSON.stringify({ heartbeat, grant }) }); }
14
+ drain(id, grant) { return this.json(`/v1/workers/${encodeURIComponent(id)}/drain`, { method: 'POST', body: JSON.stringify({ grant }) }); }
15
+ recover(id, grant) { return this.json(`/v1/workers/${encodeURIComponent(id)}/recover`, { method: 'POST', body: JSON.stringify({ grant }) }); }
16
+ reconcile(id, reconciliation, grant) { return this.json(`/v1/workers/${encodeURIComponent(id)}/reconcile`, { method: 'POST', body: JSON.stringify({ reconciliation, grant }) }); }
17
+ }
18
+ export class WorkerPoolClient extends MeshTransport {
19
+ list(applicationId) { return this.json(`/v1/worker-pools?application_id=${encodeURIComponent(applicationId)}`); }
20
+ create(pool, grant) { return this.json('/v1/worker-pools', { method: 'POST', body: JSON.stringify({ pool, grant }) }); }
21
+ inspect(id) { return this.json(`/v1/worker-pools/${encodeURIComponent(id)}`); }
22
+ }
23
+ export class MeshClient extends MeshTransport {
24
+ async status(applicationId) { const [workers, pools] = await Promise.all([new WorkerClient(this.baseUrl, this.fetcher).list(applicationId), new WorkerPoolClient(this.baseUrl, this.fetcher).list(applicationId)]); return { workers: workers.workers, pools: pools.pools, ready: workers.workers.filter(v => v.lifecycle === 'READY').length, busy: workers.workers.filter(v => v.lifecycle === 'BUSY').length }; }
25
+ eligibleWorkers(workloadId) { return this.json(`/v1/workloads/${encodeURIComponent(workloadId)}/eligible-workers`); }
26
+ }
@@ -0,0 +1,102 @@
1
+ import type { AuthorizationSubject, SignedGrant } from './authorization.js';
2
+ export type WorkloadState = 'CREATED' | 'READY' | 'CLAIMED' | 'RUNNING' | 'CHECKPOINTED' | 'RECOVERING' | 'CANCELLATION_REQUESTED' | 'SUCCEEDED' | 'FAILED' | 'CANCELLED' | 'TIMED_OUT' | 'DEAD_LETTER';
3
+ export interface WorkloadRetryPolicy {
4
+ max_attempts: number;
5
+ initial_delay_ms: number;
6
+ max_delay_ms: number;
7
+ backoff: 'fixed' | 'exponential';
8
+ retry_on: string[];
9
+ }
10
+ export interface CreateWorkloadInput {
11
+ tenant_id: string;
12
+ application_id: string;
13
+ environment: string;
14
+ definition_id: string;
15
+ definition_revision: string;
16
+ trigger: string;
17
+ input: unknown;
18
+ requested_by: AuthorizationSubject;
19
+ authorization_snapshot: SignedGrant;
20
+ capability_snapshot: string[];
21
+ connection_scopes?: string[];
22
+ priority?: number;
23
+ idempotency_key: string;
24
+ retry_policy?: WorkloadRetryPolicy;
25
+ timeouts?: Record<string, number>;
26
+ dependencies?: Array<{
27
+ workload_id: string;
28
+ required_state?: WorkloadState;
29
+ }>;
30
+ created_at?: number;
31
+ }
32
+ export interface Workload {
33
+ workload_id: string;
34
+ tenant_id: string;
35
+ application_id: string;
36
+ definition_id: string;
37
+ input: unknown;
38
+ input_hash: string;
39
+ priority: number;
40
+ state: WorkloadState;
41
+ attempt_count: number;
42
+ retry_count: number;
43
+ next_attempt_at?: number;
44
+ last_failure?: string;
45
+ current_claim?: WorkloadClaim;
46
+ execution_history: unknown[];
47
+ attempts: unknown[];
48
+ checkpoints: unknown[];
49
+ result?: WorkloadResult;
50
+ }
51
+ export interface WorkloadClaim {
52
+ claim_id: string;
53
+ workload_id: string;
54
+ worker_id: string;
55
+ lease_id: string;
56
+ fencing_token: number;
57
+ claimed_at: number;
58
+ expires_at: number;
59
+ }
60
+ export interface WorkloadResult {
61
+ result_id: string;
62
+ workload_id: string;
63
+ attempt_id: string;
64
+ status: string;
65
+ output: unknown;
66
+ output_hash: string;
67
+ artifacts: string[];
68
+ produced_by: string;
69
+ created_at: number;
70
+ }
71
+ export declare class WorkloadClient {
72
+ private baseUrl;
73
+ private fetcher;
74
+ constructor(baseUrl?: string, fetcher?: typeof fetch);
75
+ private json;
76
+ create(input: CreateWorkloadInput): Promise<Workload>;
77
+ list(applicationId: string): Promise<{
78
+ workloads: Workload[];
79
+ }>;
80
+ inspect(id: string): Promise<Workload>;
81
+ claim(id: string, input: {
82
+ worker_id: string;
83
+ lease_ms: number;
84
+ grant: SignedGrant;
85
+ }): Promise<WorkloadClaim>;
86
+ start(id: string, fence: unknown): Promise<void>;
87
+ heartbeat(id: string, input: unknown): Promise<WorkloadClaim>;
88
+ checkpoint(id: string, input: unknown): Promise<unknown>;
89
+ complete(id: string, input: unknown): Promise<WorkloadResult>;
90
+ fail(id: string, input: unknown): Promise<{
91
+ state: WorkloadState;
92
+ }>;
93
+ confirmCancelled(id: string, fence: unknown): Promise<void>;
94
+ executionContext(id: string, input: unknown): Promise<unknown>;
95
+ cancel(id: string, grant: SignedGrant): Promise<{
96
+ state: WorkloadState;
97
+ }>;
98
+ retry(id: string, grant: SignedGrant): Promise<void>;
99
+ history(id: string): Promise<unknown>;
100
+ result(id: string): Promise<WorkloadResult | undefined>;
101
+ }
102
+ //# sourceMappingURL=workload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workload.d.ts","sourceRoot":"","sources":["../src/workload.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export class WorkloadClient {
2
+ constructor(baseUrl = '', fetcher = fetch) {
3
+ this.baseUrl = baseUrl;
4
+ this.fetcher = fetcher;
5
+ }
6
+ async json(path, init) { const response = await this.fetcher(`${this.baseUrl}${path}`, { credentials: 'include', headers: { 'content-type': 'application/json', ...(init?.headers || {}) }, ...init }); const value = response.status === 204 ? undefined : await response.json(); if (!response.ok)
7
+ throw new Error(value?.error || `Workload request failed (${response.status})`); return value; }
8
+ create(input) { return this.json('/v1/workloads', { method: 'POST', body: JSON.stringify({ ...input, created_at: input.created_at || Math.floor(Date.now() / 1000) }) }); }
9
+ list(applicationId) { return this.json(`/v1/workloads?application_id=${encodeURIComponent(applicationId)}`); }
10
+ inspect(id) { return this.json(`/v1/workloads/${encodeURIComponent(id)}`); }
11
+ claim(id, input) { return this.json(`/v1/workloads/${encodeURIComponent(id)}/claim`, { method: 'POST', body: JSON.stringify(input) }); }
12
+ start(id, fence) { return this.json(`/v1/workloads/${encodeURIComponent(id)}/start`, { method: 'POST', body: JSON.stringify(fence) }); }
13
+ heartbeat(id, input) { return this.json(`/v1/workloads/${encodeURIComponent(id)}/heartbeat`, { method: 'POST', body: JSON.stringify(input) }); }
14
+ checkpoint(id, input) { return this.json(`/v1/workloads/${encodeURIComponent(id)}/checkpoint`, { method: 'POST', body: JSON.stringify(input) }); }
15
+ complete(id, input) { return this.json(`/v1/workloads/${encodeURIComponent(id)}/complete`, { method: 'POST', body: JSON.stringify(input) }); }
16
+ fail(id, input) { return this.json(`/v1/workloads/${encodeURIComponent(id)}/fail`, { method: 'POST', body: JSON.stringify(input) }); }
17
+ confirmCancelled(id, fence) { return this.json(`/v1/workloads/${encodeURIComponent(id)}/cancelled`, { method: 'POST', body: JSON.stringify(fence) }); }
18
+ executionContext(id, input) { return this.json(`/v1/workloads/${encodeURIComponent(id)}/context`, { method: 'POST', body: JSON.stringify(input) }); }
19
+ cancel(id, grant) { return this.json(`/v1/workloads/${encodeURIComponent(id)}/cancel`, { method: 'POST', body: JSON.stringify({ grant }) }); }
20
+ retry(id, grant) { return this.json(`/v1/workloads/${encodeURIComponent(id)}/retry`, { method: 'POST', body: JSON.stringify({ grant }) }); }
21
+ history(id) { return this.json(`/v1/workloads/${encodeURIComponent(id)}/history`); }
22
+ result(id) { return this.json(`/v1/workloads/${encodeURIComponent(id)}/result`); }
23
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@feltdb/core",
3
- "version": "0.2.0",
4
- "description": "FeltDB Core - The application-facing database API",
3
+ "version": "0.3.0",
4
+ "description": "FeltDB Core - Application-facing database API with state-first reactivity",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
@@ -19,14 +19,26 @@
19
19
  }
20
20
  },
21
21
  "files": [
22
- "dist/"
22
+ "dist/",
23
+ "README.md"
23
24
  ],
24
25
  "scripts": {
25
26
  "build": "rm -rf dist && tsc",
26
- "test": "node ../../test-runner.ts"
27
+ "test": "node ../../test-runner.ts",
28
+ "type-check": "tsc --noEmit"
27
29
  },
30
+ "keywords": [
31
+ "feltdb",
32
+ "database",
33
+ "reactive",
34
+ "state-first",
35
+ "collections",
36
+ "workflows",
37
+ "sync"
38
+ ],
39
+ "author": "FeltDB Contributors",
28
40
  "dependencies": {
29
- "@feltdb/wasm": "^0.2.0"
41
+ "@feltdb/wasm": "^0.3.0"
30
42
  },
31
43
  "devDependencies": {
32
44
  "typescript": "^5.0.0",