Skip to content

Commit 273121b

Browse files
authored
Merge pull request #354 from objectstack-ai/copilot/q3-edge-runtime-offline-sync
2 parents 318301d + e63760c commit 273121b

7 files changed

Lines changed: 1057 additions & 0 deletions

File tree

docs/WORK_PLAN_2026_Q1_P2.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,8 @@ export class MultiTenancyPlugin implements RuntimePlugin {
344344
## Q3 — Edge Runtime & Offline Sync
345345

346346
> Status: **Planned** | Target: 2026-07 — 2026-09
347+
> 📄 **Detailed Work Plan: [WORK_PLAN_2026_Q3.md](./WORK_PLAN_2026_Q3.md)**
348+
> 🧩 **Type Contracts Defined:** `@objectql/types``sync.ts`, `edge.ts`
347349
348350
### Part A: Edge Runtime Support (4 weeks)
349351

docs/WORK_PLAN_2026_Q3.md

Lines changed: 652 additions & 0 deletions
Large diffs are not rendered by default.

packages/foundation/types/src/driver.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ export interface DriverCapabilities {
131131
readonly connectionPooling?: boolean;
132132
readonly preparedStatements?: boolean;
133133
readonly queryCache?: boolean;
134+
135+
// Sync support (Q3 — Offline-First Sync Protocol)
136+
/** Driver can record mutations to an append-only log for offline sync */
137+
readonly mutationLog?: boolean;
138+
/** Driver supports checkpoint-based change tracking */
139+
readonly changeTracking?: boolean;
134140
}
135141

136142
/**
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/**
2+
* ObjectQL
3+
* Copyright (c) 2026-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
// ============================================================================
10+
// Edge Runtime Types
11+
// ============================================================================
12+
13+
/**
14+
* Supported edge runtime environments.
15+
*/
16+
export type EdgeRuntime =
17+
| 'cloudflare-workers'
18+
| 'deno-deploy'
19+
| 'vercel-edge'
20+
| 'bun'
21+
| 'node';
22+
23+
/**
24+
* Edge-specific driver binding.
25+
*
26+
* Maps an ObjectQL driver to an edge-platform-native storage primitive.
27+
* For example, Cloudflare Workers binds `driver-sqlite-wasm` to D1.
28+
*/
29+
export interface EdgeDriverBinding {
30+
/**
31+
* The ObjectQL driver package name.
32+
* e.g., `'@objectql/driver-memory'`, `'@objectql/driver-sqlite-wasm'`
33+
*/
34+
readonly driver: string;
35+
36+
/**
37+
* Edge-platform binding name (environment variable or resource identifier).
38+
* e.g., `'D1_DATABASE'` for Cloudflare D1, `'POSTGRES_URL'` for Deno Postgres.
39+
*/
40+
readonly binding?: string;
41+
42+
/**
43+
* Driver-specific configuration overrides for the edge environment.
44+
*/
45+
readonly config?: Record<string, unknown>;
46+
}
47+
48+
/**
49+
* Edge runtime adapter configuration.
50+
*
51+
* Declares how ObjectQL should adapt to a specific edge runtime.
52+
* Used by the edge adapter packages (e.g., `@objectql/adapter-cloudflare`).
53+
*/
54+
export interface EdgeAdapterConfig {
55+
/** Target edge runtime */
56+
readonly runtime: EdgeRuntime;
57+
58+
/**
59+
* Driver bindings for this edge environment.
60+
* Maps datasource names to edge-specific driver bindings.
61+
*/
62+
readonly bindings?: Record<string, EdgeDriverBinding>;
63+
64+
/**
65+
* Maximum execution time in milliseconds.
66+
* Edge runtimes impose strict CPU time limits.
67+
* Default varies by runtime (e.g., 30000 for Cloudflare Workers).
68+
*/
69+
readonly maxExecutionTime?: number;
70+
71+
/**
72+
* Enable request-scoped driver connections.
73+
* Edge runtimes are stateless; connections are created per-request.
74+
* Default: true
75+
*/
76+
readonly requestScoped?: boolean;
77+
}
78+
79+
/**
80+
* Edge runtime environment capabilities.
81+
*
82+
* Declares what platform APIs are available in the target edge runtime.
83+
* Used by ObjectQL to select compatible code paths.
84+
*/
85+
export interface EdgeCapabilities {
86+
/** WebAssembly support */
87+
readonly wasm: boolean;
88+
89+
/** Persistent storage available (OPFS, KV, D1, etc.) */
90+
readonly persistentStorage: boolean;
91+
92+
/** WebSocket support for real-time sync */
93+
readonly webSocket: boolean;
94+
95+
/** Cron/scheduled trigger support */
96+
readonly scheduledTriggers: boolean;
97+
98+
/** Maximum request body size in bytes */
99+
readonly maxRequestBodySize?: number;
100+
101+
/** Maximum execution time in milliseconds */
102+
readonly maxExecutionTime?: number;
103+
104+
/** Available storage primitives */
105+
readonly storagePrimitives: readonly string[];
106+
}
107+
108+
/**
109+
* Predefined edge capability profiles for known runtimes.
110+
*/
111+
export const EDGE_CAPABILITIES: Readonly<Record<EdgeRuntime, EdgeCapabilities>> = {
112+
'cloudflare-workers': {
113+
wasm: true,
114+
persistentStorage: true,
115+
webSocket: true,
116+
scheduledTriggers: true,
117+
maxRequestBodySize: 100 * 1024 * 1024, // 100MB
118+
maxExecutionTime: 30_000,
119+
storagePrimitives: ['D1', 'KV', 'R2', 'Durable Objects'],
120+
},
121+
'deno-deploy': {
122+
wasm: true,
123+
persistentStorage: true,
124+
webSocket: true,
125+
scheduledTriggers: true,
126+
maxRequestBodySize: 512 * 1024, // 512KB
127+
maxExecutionTime: 50_000,
128+
storagePrimitives: ['Deno KV', 'Deno Postgres'],
129+
},
130+
'vercel-edge': {
131+
wasm: true,
132+
persistentStorage: false,
133+
webSocket: false,
134+
scheduledTriggers: false,
135+
maxRequestBodySize: 4 * 1024 * 1024, // 4MB
136+
maxExecutionTime: 25_000,
137+
storagePrimitives: ['KV (via Vercel KV)', 'Postgres (via Vercel Postgres)'],
138+
},
139+
'bun': {
140+
wasm: true,
141+
persistentStorage: true,
142+
webSocket: true,
143+
scheduledTriggers: false,
144+
maxRequestBodySize: Infinity,
145+
maxExecutionTime: Infinity,
146+
storagePrimitives: ['SQLite (bun:sqlite)', 'File System'],
147+
},
148+
'node': {
149+
wasm: true,
150+
persistentStorage: true,
151+
webSocket: true,
152+
scheduledTriggers: false,
153+
maxRequestBodySize: Infinity,
154+
maxExecutionTime: Infinity,
155+
storagePrimitives: ['All drivers'],
156+
},
157+
};

packages/foundation/types/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,5 @@ export * from './plugin';
3636
export * from './gateway';
3737
export * from './logger';
3838
export * from './ai';
39+
export * from './sync';
40+
export * from './edge';

packages/foundation/types/src/object.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { z } from 'zod';
1111
import { FieldConfig } from './field';
1212
import { ActionConfig } from './action';
1313
import { AnyValidationRule } from './validation';
14+
import { SyncConfig } from './sync';
1415

1516
/**
1617
* Re-export Protocol Types from @objectstack/spec 1.1.0
@@ -170,6 +171,20 @@ export interface ObjectConfig {
170171
validation_strategy?: string;
171172
};
172173
};
174+
175+
/**
176+
* Offline-First Sync configuration (RUNTIME ONLY).
177+
* Opt-in per object. See {@link SyncConfig} for details.
178+
*
179+
* @example
180+
* ```yaml
181+
* sync:
182+
* enabled: true
183+
* strategy: last-write-wins
184+
* conflict_fields: [status]
185+
* ```
186+
*/
187+
sync?: SyncConfig;
173188
}
174189

175190
/**

0 commit comments

Comments
 (0)