Skip to content

Commit

Permalink
Improve docs, add prettier-plugin-jsdoc
Browse files Browse the repository at this point in the history
  • Loading branch information
steida committed Nov 26, 2023
1 parent 5cb2825 commit 633b2d4
Show file tree
Hide file tree
Showing 18 changed files with 370 additions and 186 deletions.
4 changes: 3 additions & 1 deletion .prettierrc.json
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
{}
{
"plugins": ["./node_modules/prettier-plugin-jsdoc/dist/index.js"]
}
4 changes: 2 additions & 2 deletions examples/electron-app/webpack.main.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { rules } from "./webpack.rules";

export const mainConfig: Configuration = {
/**
* This is the main entry point for your application, it's the first file
* that runs in the main process.
* This is the main entry point for your application, it's the first file that
* runs in the main process.
*/
entry: "./src/index.ts",
// Put your normal webpack config below here
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"eslint": "^8.54.0",
"eslint-config-evolu": "workspace:*",
"prettier": "^3.1.0",
"prettier-plugin-jsdoc": "^1.1.1",
"turbo": "^1.10.16"
},
"packageManager": "[email protected]",
Expand Down
12 changes: 6 additions & 6 deletions packages/eslint-config-evolu/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,22 @@ module.exports = {
"any",
{
startLines: 1,
tags: { returns: { lines: "always" }, param: { lines: "never" } },
tags: { param: { lines: "never" } },
},
],
},
parser: "@typescript-eslint/parser",

// https://github.com/facebook/react-native/issues/28549#issuecomment-1464986589
settings: {
"import/ignore": ["react-native"],
},

parserOptions: {
babelOptions: {
presets: [require.resolve("next/babel")],
},
project: ["./apps/*/tsconfig.json", "./packages/*/tsconfig.json"],
tsconfigRootDir: __dirname,
},

// https://github.com/facebook/react-native/issues/28549#issuecomment-1464986589
settings: {
"import/ignore": ["react-native"],
},
};
30 changes: 14 additions & 16 deletions packages/evolu-common-react/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ export interface EvoluCommonReact<S extends Schema = Schema> {
readonly createQuery: Evolu<S>["createQuery"];

/**
* TODO: Docs
* Loading promises are released on mutation by default, so loading the same
* query will be suspended again, which is undesirable if we already have such
* a query on a page. Luckily, subscribeQuery tracks subscribed queries to be
* automatically updated on mutation while unsubscribed queries are released.
* TODO: Docs Loading promises are released on mutation by default, so loading
* the same query will be suspended again, which is undesirable if we already
* have such a query on a page. Luckily, subscribeQuery tracks subscribed
* queries to be automatically updated on mutation while unsubscribed queries
* are released.
*/
readonly useQuerySubscription: <R extends Row>(
query: Query<R>,
Expand All @@ -70,13 +70,11 @@ export interface EvoluCommonReact<S extends Schema = Schema> {
) => QueryResult<R>;

/**
* TODO: Docs
* For more than one query, always use useQueries Hook to avoid loading waterfalls
* and to cache loading promises.
* This is possible of course:
* const foo = use(useEvolu().loadQuery(todos))
* but it will not cache loading promise nor subscribe updates.
* That's why we have useQuery and useQueries.
* TODO: Docs For more than one query, always use useQueries Hook to avoid
* loading waterfalls and to cache loading promises. This is possible of
* course: const foo = use(useEvolu().loadQuery(todos)) but it will not cache
* loading promise nor subscribe updates. That's why we have useQuery and
* useQueries.
*/
readonly useQueries: <
R extends Row,
Expand Down Expand Up @@ -108,10 +106,10 @@ export interface EvoluCommonReact<S extends Schema = Schema> {
readonly useSyncState: () => SyncState;

/**
* The default value of EvoluContext is an Evolu instance, so we don't have
* to use EvoluProvider by default. However, EvoluProvider is helpful for
* testing, as we can inject memory-only Evolu.
* Yep, it's OK to use React Context without a provider:
* The default value of EvoluContext is an Evolu instance, so we don't have to
* use EvoluProvider by default. However, EvoluProvider is helpful for
* testing, as we can inject memory-only Evolu. Yep, it's OK to use React
* Context without a provider:
* https://react.dev/learn/passing-data-deeply-with-context
*/
readonly EvoluProvider: FC<{
Expand Down
12 changes: 5 additions & 7 deletions packages/evolu-common/src/Config.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { Context, Layer } from "effect";

export interface Config {
/**
* Alternate URL to Evolu sync&backup server.
*/
/** Alternate URL to Evolu sync and backup server. */
readonly syncUrl: string;

/**
* Alternate URL to reload browser tabs after `Owner` reset or restore.
* The default value is `/`.
* Alternate URL to reload browser tabs after `Owner` reset or restore. The
* default value is `/`.
*/
readonly reloadUrl: string;

/**
* Maximum physical clock drift allowed in ms.
* The default value is 5 * 60 * 1000 (5 minutes).
* Maximum physical clock drift allowed in ms. The default value is 5 * 60 *
* 1000 (5 minutes).
*/
readonly maxDrift: number;
}
Expand Down
15 changes: 8 additions & 7 deletions packages/evolu-common/src/Crdt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ export const AllowedTimeRange = {
};

/**
* Millis represents a time that is valid for usage with the Merkle tree.
* It must be between Apr 13, 1997, and Nov 05, 2051, to ensure MinutesBase3
* length equals 16. We can find diff for two Merkle trees only within this range.
* If the device clock is out of range, Evolu will not store data until it's fixed.
* Millis represents a time that is valid for usage with the Merkle tree. It
* must be between Apr 13, 1997, and Nov 05, 2051, to ensure MinutesBase3 length
* equals 16. We can find diff for two Merkle trees only within this range. If
* the device clock is out of range, Evolu will not store data until it's
* fixed.
*/
export const Millis = S.number.pipe(
S.greaterThan(AllowedTimeRange.greaterThan),
Expand Down Expand Up @@ -118,9 +119,9 @@ export const TimeLive = Layer.succeed(
);

/**
* The TimestampError type represents all Timestamp-related errors. If such
* an error happens, the device clock is skewed and should be set to the
* current time.
* The TimestampError type represents all Timestamp-related errors. If such an
* error happens, the device clock is skewed and should be set to the current
* time.
*/
export type TimestampError =
| TimestampDriftError
Expand Down
10 changes: 4 additions & 6 deletions packages/evolu-common/src/Crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ export interface InvalidMnemonicError {
/**
* Mnemonic is a password generated by Evolu in BIP39 format.
*
* A mnemonic, also known as a "seed phrase," is a set of 12 words in a
* specific order chosen from a predefined list. The purpose of the BIP39
* mnemonic is to provide a human-readable way of storing a private key.
* A mnemonic, also known as a "seed phrase," is a set of 12 words in a specific
* order chosen from a predefined list. The purpose of the BIP39 mnemonic is to
* provide a human-readable way of storing a private key.
*/
export type Mnemonic = string & Brand.Brand<"Mnemonic">;

Expand Down Expand Up @@ -74,9 +74,7 @@ export const slip21Derive = (
return m.slice(32, 64);
});

/**
* Alias to xsalsa20poly1305, for compatibility with libsodium / nacl
*/
/** Alias to xsalsa20poly1305, for compatibility with libsodium / nacl */
export interface SecretBox {
readonly seal: (
key: Uint8Array,
Expand Down
8 changes: 3 additions & 5 deletions packages/evolu-common/src/Db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,12 @@ export const emptyRows = <R extends Row>(): ReadonlyArray<R> =>
_emptyRows as ReadonlyArray<R>;

export interface QueryResult<R extends Row = Row> {
/**
* An array containing all the rows returned by the query.
*/
/** An array containing all the rows returned by the query. */
readonly rows: ReadonlyArray<Readonly<Kysely.Simplify<R>>>;

/**
* The first row returned by the query, or null if no rows were returned.
* This property is useful for queries that are expected to return a single row.
* The first row returned by the query, or null if no rows were returned. This
* property is useful for queries that are expected to return a single row.
*/
readonly row: Readonly<Kysely.Simplify<R>> | null;
}
Expand Down
20 changes: 9 additions & 11 deletions packages/evolu-common/src/ErrorStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,20 @@ import { Effect } from "effect";
import { TimestampError } from "./Crdt.js";
import { Store, makeStore } from "./Store.js";

export type ErrorStore = Store<ErrorStoreValue>;
export type ErrorStore = Store<EvoluError | null>;

export const makeErrorStore = makeStore<ErrorStoreValue>(null);

type ErrorStoreValue = EvoluError | null;
export const makeErrorStore = makeStore<EvoluError | null>(null);

/**
* The EvoluError type is used to represent errors that can occur in Evolu.
* It is a union type that includes UnexpectedError and TimestampError.
* The EvoluError type is used to represent errors that can occur in Evolu. It
* is a union type that includes UnexpectedError and TimestampError.
*/
export type EvoluError = UnexpectedError | TimestampError;

/**
* The UnexpectedError interface is designed to represent errors that can
* occur unexpectedly anywhere, even in third-party libraries, because
* Evolu uses Effect to track all errors.
* The UnexpectedError interface is designed to represent errors that can occur
* unexpectedly anywhere, even in third-party libraries, because Evolu uses
* Effect to track all errors.
*/
export interface UnexpectedError {
readonly _tag: "UnexpectedError";
Expand All @@ -40,8 +38,8 @@ export const makeUnexpectedError = (

/**
* We can't use the whole error because of WebWorker postMessage DataCloneError
* in Safari and Firefox.
* TODO: https://discord.com/channels/795981131316985866/795983589644304396/1096736473396564079
* in Safari and Firefox. TODO:
* https://discord.com/channels/795981131316985866/795983589644304396/1096736473396564079
*/
interface TransferableError {
readonly message: string;
Expand Down
54 changes: 34 additions & 20 deletions packages/evolu-common/src/Evolu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,33 @@ import { Store, Unsubscribe, makeStore } from "./Store.js";
import { SyncState } from "./SyncWorker.js";

export interface Evolu<T extends Schema = Schema> {
/** TODO: Docs */
/**
* Subscribe EvoluError.
*
* @example
* const unsubscribe = evolu.subscribeError(() => {
* const error = evolu.getError();
* console.log(error);
* });
*/
readonly subscribeError: ErrorStore["subscribe"];

/** TODO: Docs */
/** Get EvoluError. */
readonly getError: ErrorStore["getState"];

/** TODO: Docs */
/**
* Create type-safe SQL query.
*
* @example
* const allTodos = evolu.createQuery((db) =>
* db.selectFrom("todo").selectAll(),
* );
*
* const todoById = (id: TodoId) =>
* evolu.createQuery((db) =>
* db.selectFrom("todo").selectAll().where("id", "=", id),
* );
*/
readonly createQuery: CreateQuery<T>;

/** TODO: Docs */
Expand Down Expand Up @@ -81,24 +101,18 @@ export interface Evolu<T extends Schema = Schema> {
update: Mutate<T, "update">;

/**
* Delete all local data from the current device.
* After the deletion, Evolu reloads all browser tabs that use Evolu.
* Delete all local data from the current device. After the deletion, Evolu
* reloads all browser tabs that use Evolu.
*/
readonly resetOwner: () => void;

/**
* TODO:
*/
/** TODO: */
readonly parseMnemonic: Bip39["parse"];

/**
* Restore `Owner` with synced data from different devices.
*/
/** Restore `Owner` with synced data from different devices. */
readonly restoreOwner: (mnemonic: Mnemonic) => void;

/**
* Ensure database tables and columns exist.
*/
/** Ensure database tables and columns exist. */
readonly ensureSchema: <From, To extends T>(
schema: S.Schema<From, To>,
) => void;
Expand Down Expand Up @@ -176,8 +190,8 @@ export interface LoadingPromises {
) => void;

/**
* Release all unsubscribed queries on mutation because only subscribed queries
* are automatically updated.
* Release all unsubscribed queries on mutation because only subscribed
* queries are automatically updated.
*/
readonly release: () => void;
}
Expand Down Expand Up @@ -403,11 +417,11 @@ type PartialForNullable<
> = { [K in keyof NP]: NP[K] };

/**
* SQLite doesn't support Date nor Boolean types, so Evolu emulates them
* with {@link SqliteBoolean} and {@link SqliteDate}.
* SQLite doesn't support Date nor Boolean types, so Evolu emulates them with
* {@link SqliteBoolean} and {@link SqliteDate}.
*
* For {@link SqliteBoolean}, you can use JavaScript boolean.
* For {@link SqliteDate}, you can use JavaScript Date.
* For {@link SqliteBoolean}, you can use JavaScript boolean. For
* {@link SqliteDate}, you can use JavaScript Date.
*/
type Castable<T> = {
readonly [K in keyof T]: T[K] extends SqliteBoolean
Expand Down
Loading

0 comments on commit 633b2d4

Please sign in to comment.