Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Files
**/.esm-cache/**
.vscode
.idea
.DS_Store
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
**/pnpm-lock.yaml
scripts/
**/.esm-cache/*
34 changes: 32 additions & 2 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,46 @@ import tseslint from "typescript-eslint";
const opts = tseslint.config(
eslint.configs.recommended,
// ...tseslint.configs.recommended,
...tseslint.configs.strict,
...tseslint.configs.stylistic,
// ...tseslint.configs.strict,
// ...tseslint.configs.stylistic,
...tseslint.configs.strictTypeChecked,
...tseslint.configs.stylisticTypeChecked,
...tseslint.configs.recommendedTypeChecked,
{
languageOptions: {
parserOptions: {
sourceType: "module",
project: "./tsconfig.json",
// projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
{
ignores: [
"babel.config.cjs",
"prettier.config.js",
"jest.config.js",
"setup.*.js",
"to-esm.js",
"vitest.*.ts",
"**/.esm-cache/**",
"**/dist/",
"dist/**",
"**/pubdir/",
"**/node_modules/",
"**/scripts/",
"**/examples/",
"scripts/",
"coverage/",
"smoke/react/",
"src/missingTypes/lib.deno.d.ts",
],
},
{
files: ["**/*.js", "*.mjs"],
extends: [tseslint.configs.disableTypeChecked],
},
{
rules: {
"no-console": ["warn"],
Expand All @@ -30,6 +54,12 @@ const opts = tseslint.config(
"no-restricted-globals": ["error", "URL", "TextDecoder", "TextEncoder"],
},
},
{
ignores: ["**/*.mjs"],
rules: {
"@typescript-eslint/prefer-readonly": "error",
},
},
);

export default opts;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"@types/node": "^22.10.5",
"@types/randombytes": "^2.0.3",
"@types/react": "^18.3.12",
"@types/semver": "^7.5.8",
"@typescript-eslint/typescript-estree": "^8.19.0",
"@vitest/browser": "^2.1.8",
"@vitest/coverage-v8": "^2.1.8",
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions publish-package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { $ } from "zx";
import { SemVer } from "semver";
import fs from "fs";
import path from "path";
import * as process from "process";

async function main() {
$.verbose = true;
Expand All @@ -13,17 +14,17 @@ async function main() {
}
const tags: string[] = [];
let refVersion;
if (process.env.GITHUB_REF && process.env.GITHUB_REF.startsWith("refs/tags/v")) {
if (process.env.GITHUB_REF?.startsWith("refs/tags/v")) {
refVersion = process.env.GITHUB_REF;
}
if (!refVersion) {
console.error(`No version found in GITHUB_REF(${process.env.GITHUB_REF}) we will not publish`);
console.error(`No version found in GITHUB_REF(${process.env.GITHUB_REF ?? ""}) we will not publish`);
process.exit(1);
}
const version = refVersion.replace(/^.*\/v/, "");
console.log(`Version: ${version} ${refVersion}`);
const semVer = new SemVer(version);
if (semVer.prerelease.find((i) => i.includes("dev"))) {
if (semVer.prerelease.find((i) => i.toString().includes("dev"))) {
tags.push("dev");
}
console.log(`Publishing package: ${packageJsonFile} version ${version} with tags ${tags.join(", ")}`);
Expand Down
2 changes: 1 addition & 1 deletion setup.indexdb.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function gthis() {
function gthis(): Record<string | symbol, unknown> {
return globalThis;
}

Expand Down
6 changes: 4 additions & 2 deletions src/blockstore/commit-queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
type QueueFunction<T = void> = () => Promise<T>;

export class CommitQueue<T = void> {
readonly queue: QueueFunction<void>[] = [];
readonly queue: QueueFunction[] = [];
processing = false;

readonly _waitIdleItems: Set<Future<void>> = new Set<Future<void>>();
Expand All @@ -22,7 +22,7 @@
try {
resolve(await fn());
} catch (e) {
reject(e);

Check failure on line 25 in src/blockstore/commit-queue.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

Expected the Promise rejection reason to be an Error

Check failure on line 25 in src/blockstore/commit-queue.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

Expected the Promise rejection reason to be an Error
} finally {
this.processing = false;
this.processNext();
Expand All @@ -40,7 +40,7 @@
this.processing = true;
const queueFn = this.queue.shift();
if (queueFn) {
queueFn().finally(() => {

Check failure on line 43 in src/blockstore/commit-queue.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator

Check failure on line 43 in src/blockstore/commit-queue.ts

View workflow job for this annotation

GitHub Actions / Quality Checks

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator
/**/
});
}
Expand All @@ -48,7 +48,9 @@
if (this.queue.length === 0 && !this.processing) {
const toResolve = Array.from(this._waitIdleItems);
this._waitIdleItems.clear();
toResolve.map((fn) => fn.resolve());
toResolve.map((fn) => {
fn.resolve();
});
}
}
}
8 changes: 4 additions & 4 deletions src/blockstore/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ export class Loader implements Loadable {
remoteCarStore?: DataStore;
remoteFileStore?: DataStore;

private getBlockCache = new Map<string, AnyBlock>();
private seenMeta = new Set<string>();
private writeLimit = pLimit(1);
private readonly getBlockCache = new Map<string, AnyBlock>();
private readonly seenMeta = new Set<string>();
private readonly writeLimit = pLimit(1);

private readonly _carStore = new ResolveOnce<DataStore>();
async carStore(): Promise<DataStore> {
Expand Down Expand Up @@ -214,7 +214,7 @@ export class Loader implements Loadable {
carHeader.compact.map((c) => c.toString()).forEach(this.seenCompacted.add, this.seenCompacted);
await this.getMoreReaders(carHeader.cars.flat());
this.carLog = [...uniqueCids([meta.cars, ...this.carLog, ...carHeader.cars], this.seenCompacted)];
await this.ebOpts.applyMeta?.(carHeader.meta);
await this.ebOpts.applyMeta(carHeader.meta);
}

// protected async ingestKeyFromMeta(meta: DbMeta): Promise<void> {
Expand Down
28 changes: 18 additions & 10 deletions src/blockstore/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export abstract class BaseStoreImpl {
const res = await this.gateway.start(this._url, this.loader);
if (res.isErr()) {
this.logger.Error().Result("gw-start", res).Msg("started-gateway");
return res as Result<URI>;
return res;
}
this._url = res.Ok();
// add storekey to url
Expand All @@ -126,7 +126,7 @@ export abstract class BaseStoreImpl {
return storeKeyName.join(":");
});
if (skRes.isErr()) {
return skRes as Result<URI>;
return skRes;
}
this._url = skRes.Ok();
const version = guardVersion(this._url);
Expand All @@ -143,7 +143,9 @@ export abstract class BaseStoreImpl {
return ready as Result<URI>;
}
}
this._onStarted.forEach((fn) => fn());
this._onStarted.forEach((fn) => {
fn();
});
this.logger.Debug().Msg("started");
return version;
}
Expand All @@ -154,7 +156,7 @@ export async function createDbMetaEvent(sthis: SuperThis, dbMeta: DbMeta, parent
{
dbMeta: sthis.txt.encode(format(dbMeta)),
},
parents as unknown as Link<EventView<DbMetaBinary>, number, number, 1>[],
parents as unknown as Link<EventView<DbMetaBinary>>[],
);
return {
eventCid: event.cid as CarClockLink,
Expand Down Expand Up @@ -182,7 +184,7 @@ export class MetaStoreImpl extends BaseStoreImpl implements MetaStore {
async ({ payload: dbMetas }: FPEnvelopeMeta) => {
this.logger.Debug().Msg("Received message from gateway");
await Promise.all(
dbMetas.map((dbMeta) => this.loader.taskManager?.handleEvent(dbMeta.eventCid, dbMeta.parents, dbMeta.dbMeta)),
dbMetas.map((dbMeta) => this.loader.taskManager.handleEvent(dbMeta.eventCid, dbMeta.parents, dbMeta.dbMeta)),
);
this.updateParentsFromDbMetas(dbMetas);
},
Expand Down Expand Up @@ -257,7 +259,9 @@ export class MetaStoreImpl extends BaseStoreImpl implements MetaStore {

async close(): Promise<Result<void>> {
await this.gateway.close(this.url(), this.loader);
this._onClosed.forEach((fn) => fn());
this._onClosed.forEach((fn) => {
fn();
});
return Result.Ok(undefined);
}
async destroy(): Promise<Result<void>> {
Expand Down Expand Up @@ -322,7 +326,7 @@ export class DataStoreImpl extends BaseStoreImpl implements DataStore {
if (res.isErr()) {
throw this.logger.Error().Err(res.Err()).Msg("got error from gateway.put").AsError();
}
return res.Ok();
res.Ok();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Return value missing in save method

The save method declares Promise<Result<void>> as its return type but doesn't return the result from res.Ok(). This violates the method's contract and could cause issues for callers expecting a Result object.

🔗 Analysis chain

Verify the save method's behavior change.

The save method now calls res.Ok() without returning it. Please verify if this change is intentional and doesn't affect the method's contract.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the save method's return type is used in the codebase.

# Search for calls to save method
rg -A 5 'save\(' | grep -v 'async save'

Length of output: 7968


Error: No shell scripts found


Script:

#!/bin/bash
# Find the save method implementation in store.ts
ast-grep --pattern $'async save($$$) {
  $$$
}' src/blockstore/store.ts

Length of output: 72


Script:

#!/bin/bash
# Find the save method implementation with context
rg -B 5 -A 10 'async save\(' src/blockstore/store.ts

Length of output: 2221


Script:

#!/bin/bash
# Get more context around the first save method implementation
rg -B 5 -A 20 'async save\(meta: DbMeta' src/blockstore/store.ts

Length of output: 1133

🧰 Tools
🪛 GitHub Actions: CI

[warning] Code style issues found. Run Prettier with --write to fix.

}
async remove(cid: AnyLink): Promise<Result<void>> {
const url = await this.gateway.buildUrl(this.url(), cid.toString(), this.loader);
Expand All @@ -333,7 +337,9 @@ export class DataStoreImpl extends BaseStoreImpl implements DataStore {
}
async close(): Promise<Result<void>> {
await this.gateway.close(this.url(), this.loader);
this._onClosed.forEach((fn) => fn());
this._onClosed.forEach((fn) => {
fn();
});
return Result.Ok(undefined);
}
destroy(): Promise<Result<void>> {
Expand All @@ -352,7 +358,7 @@ export class WALStoreImpl extends BaseStoreImpl implements WALStore {

readonly walState: WALState = { operations: [], noLoaderOps: [], fileOperations: [] };
readonly processing: Promise<void> | undefined = undefined;
readonly processQueue: CommitQueue<void> = new CommitQueue<void>();
readonly processQueue: CommitQueue = new CommitQueue();

constructor(sthis: SuperThis, url: URI, opts: StoreOpts) {
// const my = new URL(url.toString());
Expand Down Expand Up @@ -574,7 +580,9 @@ export class WALStoreImpl extends BaseStoreImpl implements WALStore {

async close() {
await this.gateway.close(this.url(), this.loader);
this._onClosed.forEach((fn) => fn());
this._onClosed.forEach((fn) => {
fn();
});
return Result.Ok(undefined);
}

Expand Down
2 changes: 1 addition & 1 deletion src/blockstore/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export function defaultedBlockstoreRuntime(
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
compact: async (blocks: BlockFetcher) => {
return {} as unknown as TransactionMeta;
return {} as unknown;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider using a more specific type instead of unknown.

The change to return {} as unknown weakens type safety. If this method is expected to return a specific type, consider maintaining that type or documenting why a generic unknown type is necessary.

If the original TransactionMeta type is still valid, consider keeping it:

-      return {} as unknown;
+      return {} as TransactionMeta;

Committable suggestion skipped: line range outside the PR's diff.

},
autoCompact: 100,
public: false,
Expand Down
4 changes: 2 additions & 2 deletions src/blockstore/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface AnyBlock {
}

export interface CIDBlock {
readonly cid: CID<unknown, number, number, Version>;
readonly cid: CID;
readonly bytes: Uint8Array;
}

Expand Down Expand Up @@ -357,7 +357,7 @@ export interface WALStore extends BaseStore {
readonly storeType: "wal";
ready(): Promise<void>;
readonly processing?: Promise<void> | undefined;
readonly processQueue: CommitQueue<void>;
readonly processQueue: CommitQueue;

process(): Promise<void>;
enqueue(dbMeta: DbMeta, opts: CommitOpts): Promise<void>;
Expand Down
12 changes: 9 additions & 3 deletions src/crdt-clock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,19 @@ export class CRDTClock<T extends DocTypes> {
const changes = await clockChangesSince<T>(throwFalsy(this.blockstore), this.head, prevHead, {}, this.logger);
internalUpdates = changes.result;
}
this.zoomers.forEach((fn) => fn());
this.zoomers.forEach((fn) => {
fn();
});
this.notifyWatchers(internalUpdates || []);
}

notifyWatchers(updates: DocUpdate<T>[]) {
this.emptyWatchers.forEach((fn) => fn());
this.watchers.forEach((fn) => fn(updates || []));
this.emptyWatchers.forEach((fn) => {
fn();
});
this.watchers.forEach((fn) => {
fn(updates || []);
});
}

onTick(fn: (updates: DocUpdate<T>[]) => void) {
Expand Down
8 changes: 3 additions & 5 deletions src/crdt-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ async function processFileset(
// let totalSize = 0
for (const filename in files) {
if (File === files[filename].constructor) {
const file = files[filename] as File;
const file = files[filename];

// totalSize += file.size
const { cid, blocks: fileBlocks } = await store.encodeFile(file);
Expand All @@ -148,7 +148,7 @@ async function processFileset(
if (didPut.length) {
const car = await dbBlockstore.loader.commitFiles(
t,
{ files } as unknown as TransactionMeta /* {
{ files } as unknown /* {
public: publicFiles,
} */,
);
Expand Down Expand Up @@ -241,9 +241,7 @@ export async function clockChangesSince<T extends DocTypes>(
opts: ChangesOptions,
logger: Logger,
): Promise<{ result: DocUpdate<T>[]; head: ClockHead }> {
const eventsFetcher = (
opts.dirty ? new DirtyEventFetcher<Operation>(logger, blocks) : new EventFetcher<Operation>(blocks)
) as EventFetcher<Operation>;
const eventsFetcher = opts.dirty ? new DirtyEventFetcher<Operation>(logger, blocks) : new EventFetcher<Operation>(blocks);
const keys = new Set<string>();
const updates = await gatherUpdates<T>(
blocks,
Expand Down
2 changes: 1 addition & 1 deletion src/crdt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,6 @@ export class CRDT<T extends DocTypes> {

async compact(): Promise<void> {
const blocks = this.blockstore as EncryptedBlockstore;
return await blocks.compact();
await blocks.compact();
}
}
Loading
Loading