Skip to content

Commit 278e550

Browse files
committed
Merge remote-tracking branch 'origin/main' into feat-schema-any
2 parents 4b8ab83 + 69146d2 commit 278e550

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+330
-313
lines changed

.release-please-manifest.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"packages/core": "1.1.2",
3-
"packages/react": "1.1.2",
4-
"packages/jotai": "1.1.2"
2+
"packages/core": "1.1.3",
3+
"packages/react": "1.1.3",
4+
"packages/jotai": "1.1.3"
55
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"test": "vitest run",
99
"lint": "oxlint --type-aware",
1010
"format": "prettier --write .",
11-
"typecheck": "pnpm -r typecheck"
11+
"typecheck": "pnpm -r typecheck",
12+
"check": "pnpm build && pnpm test && pnpm lint && pnpm typecheck"
1213
},
1314
"keywords": [
1415
"loro",

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "loro-mirror",
3-
"version": "1.1.2",
3+
"version": "1.1.3",
44
"description": "Type-safe state management synchronized with Loro CRDT via a declarative schema and bidirectional mirroring.",
55
"type": "module",
66
"main": "dist/index.js",

packages/core/packages/core/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## [1.1.3](https://github.com/loro-dev/loro-mirror/compare/loro-mirror-v1.1.2...loro-mirror-v1.1.3) (2025-12-13)
4+
5+
6+
### Bug Fixes
7+
8+
* use explicit .js extensions for ESM-compliant imports ([#58](https://github.com/loro-dev/loro-mirror/issues/58)) ([d6ee6fe](https://github.com/loro-dev/loro-mirror/commit/d6ee6fe6f9e0781b6f8440075115d6315e3c1594))
9+
310
## [1.1.2](https://github.com/loro-dev/loro-mirror/compare/loro-mirror-v1.1.1...loro-mirror-v1.1.2) (2025-12-06)
411

512

packages/core/src/core/diff.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ import {
2121
LoroTreeSchema,
2222
RootSchemaType,
2323
SchemaType,
24-
} from "../schema";
25-
import { ChangeKinds, InferContainerOptions, type Change } from "./mirror";
26-
import { CID_KEY } from "../constants";
24+
type InferContainerOptions,
25+
} from "../schema/index.js";
26+
import { ChangeKinds, type Change } from "./mirror.js";
27+
import { CID_KEY } from "../constants.js";
2728

2829
import {
2930
containerIdToContainerType,
@@ -41,7 +42,7 @@ import {
4142
isArrayLike,
4243
isTreeID,
4344
defineCidProperty,
44-
} from "./utils";
45+
} from "./utils.js";
4546

4647
/**
4748
* Finds the longest increasing subsequence of a sequence of numbers

packages/core/src/core/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
* Core mirroring functionality for syncing application state with Loro CRDT
33
*/
44

5-
export { Mirror, SyncDirection, toNormalizedJson } from "./mirror";
5+
export { Mirror, SyncDirection, toNormalizedJson } from "./mirror.js";
66
export type {
7-
InferContainerOptions,
87
MirrorOptions,
98
SetStateOptions,
109
SubscriberCallback,
1110
UpdateMetadata,
12-
} from "./mirror";
11+
InferContainerOptions
12+
} from "./mirror.js";

packages/core/src/core/loroEventApply.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable unicorn/consistent-function-scoping */
22
import { describe, it, expect } from "vitest";
33
import { LoroDoc, LoroText, LoroList, LoroMap, LoroCounter } from "loro-crdt";
4-
import { applyEventBatchToState } from "./loroEventApply";
4+
import { applyEventBatchToState } from "./loroEventApply.js";
55

66
const commitAndAssert = (doc: LoroDoc, getState: () => unknown) => {
77
doc.commit();

packages/core/src/core/loroEventApply.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
LoroEventBatch,
99
TreeID,
1010
} from "loro-crdt";
11-
import { defineCidProperty, isTreeID } from "./utils";
11+
import { defineCidProperty, isTreeID } from "./utils.js";
1212

1313
// Plain JSON-like value held in Mirror state (no `any`)
1414
type JSONPrimitive = string | number | boolean | null | undefined;

packages/core/src/core/mirror.ts

Lines changed: 53 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ import {
1717
LoroTree,
1818
TreeID,
1919
} from "loro-crdt";
20-
import type { InferContainerOptions } from "../inferOptions";
20+
import type { InferContainerOptions } from "../schema/types.js";
21+
export type { InferContainerOptions } from "../schema/types.js";
2122

22-
import { applyEventBatchToState } from "./loroEventApply";
23+
import { applyEventBatchToState } from "./loroEventApply.js";
2324
import {
2425
ContainerSchemaType,
2526
getDefaultValue,
@@ -37,7 +38,7 @@ import {
3738
RootSchemaType,
3839
SchemaType,
3940
validateSchema,
40-
} from "../schema";
41+
} from "../schema/index.js";
4142
import {
4243
deepEqual,
4344
inferContainerTypeFromValue,
@@ -48,9 +49,9 @@ import {
4849
tryInferContainerType,
4950
getRootContainerByType,
5051
defineCidProperty,
51-
} from "./utils";
52-
import { diffContainer, diffTree } from "./diff";
53-
import { CID_KEY } from "../constants";
52+
} from "./utils.js";
53+
import { diffContainer, diffTree } from "./diff.js";
54+
import { CID_KEY } from "../constants.js";
5455

5556
// Plain JSON-like value used for state snapshots
5657
type JSONPrimitive = string | number | boolean | null | undefined;
@@ -100,7 +101,7 @@ export interface MirrorOptions<S extends SchemaType> {
100101
/**
101102
* Initial state (optional)
102103
*/
103-
initialState?: Partial<import("../schema").InferInputType<S>>;
104+
initialState?: Partial<import("../schema/index.js").InferInputType<S>>;
104105

105106
/**
106107
* Whether to validate state updates against the schema
@@ -134,8 +135,6 @@ export interface MirrorOptions<S extends SchemaType> {
134135
inferOptions?: InferContainerOptions;
135136
}
136137

137-
export type { InferContainerOptions } from "../inferOptions";
138-
139138
export type ChangeKinds = {
140139
set: {
141140
container: ContainerID | "";
@@ -522,11 +521,11 @@ export class Mirror<S extends SchemaType> {
522521
if (parentSchema && isLoroMapSchema(parentSchema)) {
523522
const candidate = this.getSchemaForMapKey(
524523
parentSchema as
525-
| LoroMapSchema<Record<string, SchemaType>>
526-
| LoroMapSchemaWithCatchall<
527-
Record<string, SchemaType>,
528-
SchemaType
529-
>,
524+
| LoroMapSchema<Record<string, SchemaType>>
525+
| LoroMapSchemaWithCatchall<
526+
Record<string, SchemaType>,
527+
SchemaType
528+
>,
530529
key,
531530
);
532531
if (candidate?.type === "any") {
@@ -745,10 +744,7 @@ export class Mirror<S extends SchemaType> {
745744
/**
746745
* Update Loro based on state changes
747746
*/
748-
private updateLoro(
749-
newState: InferType<S>,
750-
options?: SetStateOptions,
751-
) {
747+
private updateLoro(newState: InferType<S>, options?: SetStateOptions) {
752748
if (this.syncing) return;
753749

754750
this.syncing = true;
@@ -928,9 +924,9 @@ export class Mirror<S extends SchemaType> {
928924
const childInfer =
929925
fieldSchema?.type === "any"
930926
? this.getInferOptionsForChild(
931-
container.id,
932-
fieldSchema,
933-
)
927+
container.id,
928+
fieldSchema,
929+
)
934930
: undefined;
935931
const inserted = this.insertContainerIntoMap(
936932
map,
@@ -984,9 +980,9 @@ export class Mirror<S extends SchemaType> {
984980
value,
985981
fieldSchema?.type === "any"
986982
? this.getInferOptionsForChild(
987-
container.id,
988-
fieldSchema,
989-
)
983+
container.id,
984+
fieldSchema,
985+
)
990986
: undefined,
991987
);
992988
} else {
@@ -1031,9 +1027,9 @@ export class Mirror<S extends SchemaType> {
10311027
value,
10321028
fieldSchema?.type === "any"
10331029
? this.getInferOptionsForChild(
1034-
container.id,
1035-
fieldSchema,
1036-
)
1030+
container.id,
1031+
fieldSchema,
1032+
)
10371033
: undefined,
10381034
);
10391035
} else if (kind === "move") {
@@ -1055,12 +1051,12 @@ export class Mirror<S extends SchemaType> {
10551051
const infer =
10561052
fieldSchema?.type === "any"
10571053
? this.getInferOptionsForChild(
1058-
container.id,
1059-
fieldSchema,
1060-
)
1054+
container.id,
1055+
fieldSchema,
1056+
)
10611057
: !schema
1062-
? this.getInferOptionsForContainer(container.id)
1063-
: undefined;
1058+
? this.getInferOptionsForContainer(container.id)
1059+
: undefined;
10641060
const [detachedContainer, _containerType] =
10651061
this.createContainerFromSchema(
10661062
schema,
@@ -1555,9 +1551,9 @@ export class Mirror<S extends SchemaType> {
15551551
const mapSchema = schema as
15561552
| LoroMapSchema<Record<string, SchemaType>>
15571553
| LoroMapSchemaWithCatchall<
1558-
Record<string, SchemaType>,
1559-
SchemaType
1560-
>
1554+
Record<string, SchemaType>,
1555+
SchemaType
1556+
>
15611557
| undefined;
15621558
const baseInfer = this.getInferOptionsForContainer(map.id);
15631559
for (const [key, val] of Object.entries(value)) {
@@ -1866,9 +1862,9 @@ export class Mirror<S extends SchemaType> {
18661862
const mapSchema = schema as
18671863
| LoroMapSchema<Record<string, SchemaType>>
18681864
| LoroMapSchemaWithCatchall<
1869-
Record<string, SchemaType>,
1870-
SchemaType
1871-
>;
1865+
Record<string, SchemaType>,
1866+
SchemaType
1867+
>;
18721868
const fieldSchema = this.getSchemaForMapKey(mapSchema, key);
18731869
if (fieldSchema && fieldSchema.type === "ignore") {
18741870
// Skip ignore fields: they live only in mirrored state
@@ -1942,21 +1938,21 @@ export class Mirror<S extends SchemaType> {
19421938
const newState =
19431939
typeof updater === "function"
19441940
? produce<InferType<S>>(this.state, (draft) => {
1945-
const res = (
1946-
updater as (
1947-
state: InferType<S>,
1948-
) => InferType<S> | void
1949-
)(draft as InferType<S>);
1950-
if (res && res !== (draft as unknown)) {
1951-
// Return a replacement so Immer finalizes it
1952-
return res as unknown as typeof draft;
1953-
}
1954-
})
1941+
const res = (
1942+
updater as (
1943+
state: InferType<S>,
1944+
) => InferType<S> | void
1945+
)(draft as InferType<S>);
1946+
if (res && res !== (draft as unknown)) {
1947+
// Return a replacement so Immer finalizes it
1948+
return res as unknown as typeof draft;
1949+
}
1950+
})
19551951
: (Object.assign(
1956-
{},
1957-
this.state as unknown as Record<string, unknown>,
1958-
updater as Record<string, unknown>,
1959-
) as InferType<S>);
1952+
{},
1953+
this.state as unknown as Record<string, unknown>,
1954+
updater as Record<string, unknown>,
1955+
) as InferType<S>);
19601956

19611957
// Validate state if needed
19621958
if (this.options.validateUpdates) {
@@ -2219,11 +2215,11 @@ export class Mirror<S extends SchemaType> {
22192215
if (isLoroMapSchema(containerSchema)) {
22202216
return this.getSchemaForMapKey(
22212217
containerSchema as
2222-
| LoroMapSchema<Record<string, SchemaType>>
2223-
| LoroMapSchemaWithCatchall<
2224-
Record<string, SchemaType>,
2225-
SchemaType
2226-
>,
2218+
| LoroMapSchema<Record<string, SchemaType>>
2219+
| LoroMapSchemaWithCatchall<
2220+
Record<string, SchemaType>,
2221+
SchemaType
2222+
>,
22272223
String(childKey),
22282224
);
22292225
} else if (

packages/core/src/core/utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
*/
44

55
import { Container, ContainerID, ContainerType, LoroDoc } from "loro-crdt";
6-
import { SchemaType } from "../schema";
7-
import { Change, InferContainerOptions } from "./mirror";
8-
import { CID_KEY } from "../constants";
6+
import { SchemaType } from "../schema/index.js";
7+
import { Change, InferContainerOptions } from "./mirror.js";
8+
import { CID_KEY } from "../constants.js";
99

1010
export function defineCidProperty(target: unknown, cid: ContainerID) {
1111
if (

0 commit comments

Comments
 (0)