chore(8.0): modernize toolchain + position Bun as a runtime
Consumer-invisible modernization pass — no public API or runtime-behavior
change; dist for the override-only files is byte-identical.
Toolchain:
- CI: GitHub Actions matrix — Node 22/24 (test:unit) + Bun latest (test:bun).
- engines: node ">=22" (was "22.x"), bun ">=1.1.0".
- tsconfig: isolatedModules + noImplicitOverride; add the 33 `override`
modifiers the flag requires across storage/integrations/vfs/transaction.
- deps: @types/node ^22; add prettier; drop dead standard-version,
@rollup/plugin-* and the redundant embedded eslintConfig (flat
eslint.config.js is the active config — verified identical lint output).
paramValidation: replace the top-level `await import('node:os'/'node:fs')`
with static ESM imports. The top-level-await form poisoned the module graph;
static imports also drop the browser/edge fallback branches no supported
runtime reaches (8.0 is Node/Bun/Deno-only).
Bun positioning: recommend Bun as a runtime (`bun add` / `bun run`), which is
green (test:bun 8/8). Drop single-binary `bun build --compile` as a target —
native addons cannot embed into it, and Bun 1.3.10 has a `--compile` codegen
regression around top-level await. Rename the Bun test to bun-runtime-test.ts
and correct docs that overclaimed single-binary support.
Gates: typecheck 0, build 0, test:unit 1743/1743, test:bun 8/8.
This commit is contained in:
parent
ae55d54cb5
commit
ca9129a924
20 changed files with 159 additions and 2330 deletions
|
|
@ -253,7 +253,7 @@ export class ODataIntegration extends IntegrationBase implements HTTPIntegration
|
|||
/**
|
||||
* Get augmentation manifest
|
||||
*/
|
||||
getManifest(): Record<string, any> {
|
||||
override getManifest(): Record<string, any> {
|
||||
return {
|
||||
id: 'odata',
|
||||
name: 'OData Integration',
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ export class GoogleSheetsIntegration
|
|||
/**
|
||||
* Get manifest
|
||||
*/
|
||||
getManifest(): Record<string, any> {
|
||||
override getManifest(): Record<string, any> {
|
||||
return {
|
||||
id: 'sheets',
|
||||
name: 'Google Sheets Integration',
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ export class SSEIntegration
|
|||
/**
|
||||
* Get manifest
|
||||
*/
|
||||
getManifest(): Record<string, any> {
|
||||
override getManifest(): Record<string, any> {
|
||||
return {
|
||||
id: 'sse',
|
||||
name: 'SSE Streaming',
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ export class WebhookIntegration extends IntegrationBase {
|
|||
/**
|
||||
* Get manifest
|
||||
*/
|
||||
getManifest(): Record<string, any> {
|
||||
override getManifest(): Record<string, any> {
|
||||
return {
|
||||
id: 'webhooks',
|
||||
name: 'Webhooks',
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ export class FileSystemStorage extends BaseStorage {
|
|||
*
|
||||
* @returns FileSystem-optimized batch configuration
|
||||
*/
|
||||
public getBatchConfig(): StorageBatchConfig {
|
||||
public override getBatchConfig(): StorageBatchConfig {
|
||||
return {
|
||||
maxBatchSize: 500,
|
||||
batchDelayMs: 0,
|
||||
|
|
@ -180,7 +180,7 @@ export class FileSystemStorage extends BaseStorage {
|
|||
/**
|
||||
* Initialize the storage adapter
|
||||
*/
|
||||
public async init(): Promise<void> {
|
||||
public override async init(): Promise<void> {
|
||||
if (this.isInitialized) {
|
||||
return
|
||||
}
|
||||
|
|
@ -952,7 +952,7 @@ export class FileSystemStorage extends BaseStorage {
|
|||
*
|
||||
* @param prefix - Storage-root-relative directory prefix to remove.
|
||||
*/
|
||||
public async removeRawPrefix(prefix: string): Promise<void> {
|
||||
public override async removeRawPrefix(prefix: string): Promise<void> {
|
||||
await this.ensureInitialized()
|
||||
await fs.promises.rm(path.join(this.rootDir, prefix), { recursive: true, force: true })
|
||||
}
|
||||
|
|
@ -966,7 +966,7 @@ export class FileSystemStorage extends BaseStorage {
|
|||
*
|
||||
* @param paths - Storage-root-relative object paths previously written.
|
||||
*/
|
||||
public async syncRawObjects(paths: string[]): Promise<void> {
|
||||
public override async syncRawObjects(paths: string[]): Promise<void> {
|
||||
await this.ensureInitialized()
|
||||
const parentDirs = new Set<string>()
|
||||
|
||||
|
|
@ -1539,7 +1539,7 @@ export class FileSystemStorage extends BaseStorage {
|
|||
// Removed 10 *_internal method overrides - now inherit from BaseStorage's type-first implementation
|
||||
// Removed 2 pagination methods (getNounsWithPagination, getVerbsWithPagination) - use BaseStorage's implementation
|
||||
|
||||
public supportsMultiProcessLocking(): boolean {
|
||||
public override supportsMultiProcessLocking(): boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -1557,7 +1557,7 @@ export class FileSystemStorage extends BaseStorage {
|
|||
* `lastHeartbeat` is older than `WRITER_STALE_THRESHOLD_MS` (60s).
|
||||
* Stale locks are overwritten with a warning. `force: true` overrides even live locks.
|
||||
*/
|
||||
public async acquireWriterLock(options?: { force?: boolean }): Promise<WriterLockInfo | null> {
|
||||
public override async acquireWriterLock(options?: { force?: boolean }): Promise<WriterLockInfo | null> {
|
||||
await this.ensureInitialized()
|
||||
await this.ensureDirectoryExists(this.lockDir)
|
||||
|
||||
|
|
@ -1639,7 +1639,7 @@ export class FileSystemStorage extends BaseStorage {
|
|||
return info
|
||||
}
|
||||
|
||||
public async releaseWriterLock(): Promise<void> {
|
||||
public override async releaseWriterLock(): Promise<void> {
|
||||
if (this.writerLockHeartbeat) {
|
||||
clearInterval(this.writerLockHeartbeat)
|
||||
this.writerLockHeartbeat = undefined
|
||||
|
|
@ -1664,7 +1664,7 @@ export class FileSystemStorage extends BaseStorage {
|
|||
}
|
||||
}
|
||||
|
||||
public async readWriterLock(): Promise<WriterLockInfo | null> {
|
||||
public override async readWriterLock(): Promise<WriterLockInfo | null> {
|
||||
await this.ensureInitialized()
|
||||
const lockFile = path.join(this.lockDir, FileSystemStorage.WRITER_LOCK_FILE)
|
||||
try {
|
||||
|
|
@ -1749,7 +1749,7 @@ export class FileSystemStorage extends BaseStorage {
|
|||
* `locks/_flush_responses/` with the same request ID. Stale `.req` files
|
||||
* (>FLUSH_REQUEST_TTL_MS) are garbage-collected on every tick.
|
||||
*/
|
||||
public startFlushRequestWatcher(onRequest: () => Promise<void>): void {
|
||||
public override startFlushRequestWatcher(onRequest: () => Promise<void>): void {
|
||||
if (this.flushWatcherInterval) return // already watching
|
||||
this.flushWatcherOnRequest = onRequest
|
||||
|
||||
|
|
@ -1772,7 +1772,7 @@ export class FileSystemStorage extends BaseStorage {
|
|||
}
|
||||
}
|
||||
|
||||
public stopFlushRequestWatcher(): void {
|
||||
public override stopFlushRequestWatcher(): void {
|
||||
if (this.flushWatcherInterval) {
|
||||
clearInterval(this.flushWatcherInterval)
|
||||
this.flushWatcherInterval = undefined
|
||||
|
|
@ -1851,7 +1851,7 @@ export class FileSystemStorage extends BaseStorage {
|
|||
* Inspector side: drop a `.req` file and poll for the corresponding `.ack`.
|
||||
* Returns true if the writer acknowledged in time, false on timeout.
|
||||
*/
|
||||
public async requestFlushOverFilesystem(timeoutMs: number): Promise<boolean> {
|
||||
public override async requestFlushOverFilesystem(timeoutMs: number): Promise<boolean> {
|
||||
await this.ensureInitialized()
|
||||
const reqDir = path.join(this.lockDir, FileSystemStorage.FLUSH_REQUEST_DIR)
|
||||
const ackDir = path.join(this.lockDir, FileSystemStorage.FLUSH_RESPONSE_DIR)
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ export class MemoryStorage extends BaseStorage {
|
|||
*
|
||||
* @returns Memory-optimized batch configuration
|
||||
*/
|
||||
public getBatchConfig(): StorageBatchConfig {
|
||||
public override getBatchConfig(): StorageBatchConfig {
|
||||
return {
|
||||
maxBatchSize: 1000,
|
||||
batchDelayMs: 0,
|
||||
|
|
@ -86,7 +86,7 @@ export class MemoryStorage extends BaseStorage {
|
|||
* Initialize the storage adapter
|
||||
* Calls super.init() to initialize GraphAdjacencyIndex and type statistics
|
||||
*/
|
||||
public async init(): Promise<void> {
|
||||
public override async init(): Promise<void> {
|
||||
await super.init()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1551,7 +1551,7 @@ export abstract class BaseStorage extends BaseStorageAdapter {
|
|||
* - Early termination when offset + limit entities collected
|
||||
* - Memory efficient: Never loads full dataset
|
||||
*/
|
||||
public async getNounsWithPagination(options: {
|
||||
public override async getNounsWithPagination(options: {
|
||||
limit: number
|
||||
offset: number
|
||||
cursor?: string // Opaque resume token from a prior page's nextCursor; when set it supersedes offset (O(N) walk, no re-scan)
|
||||
|
|
@ -1717,7 +1717,7 @@ export abstract class BaseStorage extends BaseStorageAdapter {
|
|||
* - Memory efficient: Never loads full dataset
|
||||
* - Inline filtering for sourceId, targetId, verbType
|
||||
*/
|
||||
public async getVerbsWithPagination(options: {
|
||||
public override async getVerbsWithPagination(options: {
|
||||
limit: number
|
||||
offset: number
|
||||
cursor?: string // Opaque resume token from a prior page's nextCursor; when set it supersedes offset (O(N) walk, no re-scan)
|
||||
|
|
@ -2442,13 +2442,13 @@ export abstract class BaseStorage extends BaseStorageAdapter {
|
|||
* Clear all data from storage
|
||||
* This method should be implemented by each specific adapter
|
||||
*/
|
||||
public abstract clear(): Promise<void>
|
||||
public abstract override clear(): Promise<void>
|
||||
|
||||
/**
|
||||
* Get information about storage usage and capacity
|
||||
* This method should be implemented by each specific adapter
|
||||
*/
|
||||
public abstract getStorageStatus(): Promise<{
|
||||
public abstract override getStorageStatus(): Promise<{
|
||||
type: string
|
||||
used: number
|
||||
quota: number | null
|
||||
|
|
@ -2957,7 +2957,7 @@ export abstract class BaseStorage extends BaseStorageAdapter {
|
|||
*
|
||||
* @public - Inherited from BaseStorageAdapter
|
||||
*/
|
||||
public getBatchConfig(): StorageBatchConfig {
|
||||
public override getBatchConfig(): StorageBatchConfig {
|
||||
// Conservative defaults - adapters should override with their actual limits
|
||||
return {
|
||||
maxBatchSize: 100,
|
||||
|
|
@ -3513,7 +3513,7 @@ export abstract class BaseStorage extends BaseStorageAdapter {
|
|||
* writer flush — the same silent-stale failure mode that once produced
|
||||
* zero counts from `brain.stats()`.
|
||||
*/
|
||||
public async flushCounts(): Promise<void> {
|
||||
public override async flushCounts(): Promise<void> {
|
||||
await super.flushCounts()
|
||||
await this.saveTypeStatistics()
|
||||
await this.saveSubtypeStatistics()
|
||||
|
|
@ -4297,7 +4297,7 @@ export abstract class BaseStorage extends BaseStorageAdapter {
|
|||
* Save statistics data to storage (public interface)
|
||||
* @param statistics The statistics data to save
|
||||
*/
|
||||
public async saveStatistics(statistics: StatisticsData): Promise<void> {
|
||||
public override async saveStatistics(statistics: StatisticsData): Promise<void> {
|
||||
return this.saveStatisticsData(statistics)
|
||||
}
|
||||
|
||||
|
|
@ -4305,7 +4305,7 @@ export abstract class BaseStorage extends BaseStorageAdapter {
|
|||
* Get statistics data from storage (public interface)
|
||||
* @returns Promise that resolves to the statistics data or null if not found
|
||||
*/
|
||||
public async getStatistics(): Promise<StatisticsData | null> {
|
||||
public override async getStatistics(): Promise<StatisticsData | null> {
|
||||
return this.getStatisticsData()
|
||||
}
|
||||
|
||||
|
|
@ -4314,7 +4314,7 @@ export abstract class BaseStorage extends BaseStorageAdapter {
|
|||
* This method should be implemented by each specific adapter
|
||||
* @param statistics The statistics data to save
|
||||
*/
|
||||
protected abstract saveStatisticsData(
|
||||
protected abstract override saveStatisticsData(
|
||||
statistics: StatisticsData
|
||||
): Promise<void>
|
||||
|
||||
|
|
@ -4323,5 +4323,5 @@ export abstract class BaseStorage extends BaseStorageAdapter {
|
|||
* This method should be implemented by each specific adapter
|
||||
* @returns Promise that resolves to the statistics data or null if not found
|
||||
*/
|
||||
protected abstract getStatisticsData(): Promise<StatisticsData | null>
|
||||
protected abstract override getStatisticsData(): Promise<StatisticsData | null>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export class TransactionExecutionError extends TransactionError {
|
|||
message: string,
|
||||
public readonly operationIndex: number,
|
||||
public readonly operationName: string | undefined,
|
||||
public readonly cause: Error
|
||||
public override readonly cause: Error
|
||||
) {
|
||||
super(message, {
|
||||
operationIndex,
|
||||
|
|
|
|||
|
|
@ -10,15 +10,13 @@ import { NounType, VerbType } from '../types/graphTypes.js'
|
|||
import { prodLog } from './logger.js'
|
||||
import { findCallerLocation } from './callerLocation.js'
|
||||
|
||||
// Dynamic import for Node.js os and fs modules
|
||||
let os: any = null
|
||||
let fs: any = null
|
||||
try {
|
||||
os = await import('node:os')
|
||||
fs = await import('node:fs')
|
||||
} catch (e) {
|
||||
// OS/FS modules not available
|
||||
}
|
||||
// 8.0 is Node/Bun/Deno-only (no browser path), so `node:os` / `node:fs` are
|
||||
// always present — static ESM imports instead of a top-level `await import()`.
|
||||
// The TLA form poisoned the module graph with a top-level await, which `bun
|
||||
// build --compile` refuses; the static form also drops the browser/edge
|
||||
// fallback branches that no supported runtime can reach.
|
||||
import * as os from 'node:os'
|
||||
import * as fs from 'node:fs'
|
||||
|
||||
const getSystemMemory = (): number => {
|
||||
if (os) {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export class VFSReadStream extends Readable {
|
|||
this.position = options.start || 0
|
||||
}
|
||||
|
||||
async _read(size: number): Promise<void> {
|
||||
override async _read(size: number): Promise<void> {
|
||||
try {
|
||||
// Lazy load entity
|
||||
if (!this.entity) {
|
||||
|
|
@ -58,7 +58,7 @@ export class VFSReadStream extends Readable {
|
|||
}
|
||||
}
|
||||
|
||||
_destroy(error: Error | null, callback: (error?: Error | null) => void): void {
|
||||
override _destroy(error: Error | null, callback: (error?: Error | null) => void): void {
|
||||
// Clean up resources
|
||||
this.entity = null
|
||||
this.data = null
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export class VFSWriteStream extends Writable {
|
|||
}
|
||||
}
|
||||
|
||||
async _write(
|
||||
override async _write(
|
||||
chunk: any,
|
||||
encoding: BufferEncoding,
|
||||
callback: (error?: Error | null) => void
|
||||
|
|
@ -52,7 +52,7 @@ export class VFSWriteStream extends Writable {
|
|||
}
|
||||
}
|
||||
|
||||
async _final(callback: (error?: Error | null) => void): Promise<void> {
|
||||
override async _final(callback: (error?: Error | null) => void): Promise<void> {
|
||||
try {
|
||||
await this._flush()
|
||||
callback()
|
||||
|
|
@ -78,7 +78,7 @@ export class VFSWriteStream extends Writable {
|
|||
this.chunks = []
|
||||
}
|
||||
|
||||
_destroy(error: Error | null, callback: (error?: Error | null) => void): void {
|
||||
override _destroy(error: Error | null, callback: (error?: Error | null) => void): void {
|
||||
// Clean up resources
|
||||
this.chunks = []
|
||||
this._closed = true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue