Skip to content
Merged
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
54 changes: 54 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Publish json-document prerelease

on:
push:
tags:
- "json-document-v*-rc.*"

permissions:
contents: read
id-token: write

concurrency:
group: npm-json-document-${{ github.ref }}
cancel-in-progress: false

jobs:
publish:
environment: npm-publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Require a tagged main commit
run: |
git fetch origin main
git merge-base --is-ancestor "${GITHUB_SHA}^{commit}" origin/main
- uses: actions/setup-node@v6
with:
node-version: "24"
registry-url: "https://registry.npmjs.org"
package-manager-cache: false
- name: Verify prerelease identity
env:
RELEASE_TAG: ${{ github.ref_name }}
run: |
node --input-type=module --eval '
import { readFileSync } from "node:fs";
const pkg = JSON.parse(readFileSync("packages/json-document/package.json", "utf8"));
const expectedTag = `json-document-v${pkg.version}`;
if (process.env.RELEASE_TAG !== expectedTag) {
throw new Error(`release tag ${process.env.RELEASE_TAG} does not match ${expectedTag}`);
}
if (!/^\d+\.\d+\.\d+-rc\.\d+$/.test(pkg.version)) {
throw new Error(`package version is not an rc prerelease: ${pkg.version}`);
}
if (pkg.publishConfig?.tag !== "next") {
throw new Error("publishConfig.tag must remain next for prereleases");
}
'
- name: Install dependencies
run: npm ci --no-audit --no-fund
- name: Publish prerelease
run: npm publish -w @interactive-os/json-document --tag next --provenance
2 changes: 1 addition & 1 deletion apps/site/src/generated/repo-catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ export const repoCatalog = {
"status": "core",
"private": false,
"publishable": true,
"version": "1.1.0",
"version": "1.1.0-rc.0",
"description": "Headless JSON editing primitives guarded by Zod schemas.",
"license": "MIT",
"summary": "Zod schema로 보호되는 JSON state를 읽고, 바꾸고, 선택하고, 복사하고,\n붙여넣고, 되돌리기 위한 headless document layer입니다.",
Expand Down
26 changes: 23 additions & 3 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@ All notable changes to this project are documented here.

No unreleased changes.

## 1.1.0 - 2026-07-05
## 1.1.0-rc.0 - 2026-07-11

This release adds the next additive public API surface for the core
`@interactive-os/json-document` document facade while keeping 1.x compatibility.
This prerelease lets sibling editors such as `editable` and `canvas` exercise
the next `@interactive-os/json-document` document facade through an explicit
npm opt-in. It is published under the `next` dist-tag while `latest` remains on
`1.0.1`.

The unified mutation success result described below changes the runtime shape
published in `1.0.1`. Treat it as an integration experiment, not a stable 1.x
compatibility promise. Its final shape must be decided before a stable release.

### Added

Expand Down Expand Up @@ -49,6 +55,20 @@ This release adds the next additive public API surface for the core
- Fixed schema introspection traversal through wrapper schemas.
- Fixed `readAt` so non-canonical array indices are rejected.
- Fixed paste-into capability errors for absent targets.
- Replanned prepared insert, paste, cut, and duplicate changes when schema
validation or a custom rekey callback changed the document revision before
publication.
- Preserved atomic guard-test and mutation semantics for overlapping replace
batches and guarded proposed-change acceptance.

### Performance

- Added a copy-on-write sequential replace path for eligible overlapping
parent/child replacements on plain structural schemas.
- Reused that path for history inverse capture and eligible guarded replace
batches, avoiding repeated whole-document cloning while preserving operation
order. Unsupported operations and schemas keep the canonical full-validation
path.

## 1.0.1 - 2026-06-19

Expand Down
2 changes: 1 addition & 1 deletion docs/generated/repo-catalog.json
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@
"status": "core",
"private": false,
"publishable": true,
"version": "1.1.0",
"version": "1.1.0-rc.0",
"description": "Headless JSON editing primitives guarded by Zod schemas.",
"license": "MIT",
"summary": "Zod schema로 보호되는 JSON state를 읽고, 바꾸고, 선택하고, 복사하고,\n붙여넣고, 되돌리기 위한 headless document layer입니다.",
Expand Down
14 changes: 9 additions & 5 deletions docs/public/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,15 +269,19 @@ doc.paste({ after: "/lists/0/cards/0" });

Pointer 배열을 copy/cut하면 clipboard payload도 배열입니다. 여러 source를 담은 clipboard buffer는 array 삽입 target에 기본으로 펼쳐집니다.

성공 result shape는 method family별로 다릅니다.
성공 result shape는 method family별로 다릅니다. 아래 `EditOk` shape는
`1.1.0-rc.0` 통합 후보이며 npm `latest`의 `1.0.1` shape와 다릅니다. RC
소비자는 exact version으로 opt in하고 stable 승격 전에 최종 계약을 다시
확인해야 합니다.

| Method | 성공 result |
| --- | --- |
| `insert`, `replace`, `delete`, `move`, `patch`, `commit` | `{ ok: true }`; 실제 patch는 `doc.lastPatch`, subscriber, history에 기록 |
| `insert`, `replace`, `delete`, `move` | `{ ok: true, value, applied, target }` (`EditOk`) |
| `patch`, `commit` | `{ ok: true }`; 실제 patch는 `doc.lastPatch`, subscriber, history에 기록 |
| `copy` | `{ ok: true, payload, source, sources }` |
| `cut` | `{ ok: true, value, applied, payload, source, sources }` |
| `paste` | `{ ok: true, value, applied }` |
| `duplicate` | `{ ok: true, value, applied, duplicatedTo }` |
| `cut` | `EditOk` + `{ payload, source, sources }` (`target: null`) |
| `paste` | `EditOk` |
| `duplicate` | `EditOk` + `{ duplicatedTo }` (`target`과 같은 값) |

`applied`는 이미 commit된 JSON Patch입니다. 다시 `commit`하지 않습니다. 실패
result는 `reason` 문구가 아니라 stable `code`로 분기합니다.
Expand Down
11 changes: 10 additions & 1 deletion docs/standard/result-contract.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Result and Error Code Contract

상태: 1.0 semantic freeze 기준.
상태: 1.0 stable baseline과 1.1.0-rc.0 통합 후보를 함께 기록.

이 문서는 public API가 반환하는 성공, 실패, error code, diagnostic shape를
고정한다. 문서의 목적은 앱이 실패를 문자열로 추측하지 않고, 안정적인 코드와
Expand All @@ -14,6 +14,10 @@
동일하게 유지해야 한다. 새 error code 추가는 minor일 수 있지만, 기존 code
제거, 의미 변경, 성공/실패 discriminant 변경은 breaking change다.

`1.1.0-rc.0` 후보라고 표시한 shape는 sibling editor의 통합 압력을 받기 위한
opt-in prerelease다. npm `latest`의 1.0 stable 계약을 대체하지 않으며, stable
승격 전에 호환성 또는 다음 major 계약으로 다시 판정해야 한다.

## 공통 Result Shape

공개 Result family는 `ok` discriminant를 가져야 한다.
Expand Down Expand Up @@ -143,6 +147,10 @@ Clipboard와 structural command result는 `ok` discriminant를 공유하지만 A
Mutation verb의 성공은 통일 `EditOk` shape를 따른다. "duplicate는 새
객체(위치)를 반환한다"는 정본을 전 verb로 일반화한 것이다.

> `1.1.0-rc.0` 후보: 이 shape는 `1.0.1`의 성공 result에 필수 field를
> 추가한다. prerelease 소비자는 exact version으로 opt in해야 하며 stable
> 1.x 호환 shape로 간주하면 안 된다.

```ts
type JSONDocumentEditOk<T> = {
ok: true;
Expand Down Expand Up @@ -224,6 +232,7 @@ throw 여부가 아니라 result contract의 `code`로 실패를 분류해야
- `violations[].path`를 JSON Pointer가 아닌 형식으로 변경.
- `schema-slot`과 `document-result` violation path 기준 변경.
- 성공 mutation result에서 `applied` 의미를 실제 commit patch가 아닌 것으로 변경.
- 기존 성공 result의 필수 field 또는 exact key shape 변경.

다음 변경은 호환 가능한 확장일 수 있다.

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"standard:check": "node scripts/evaluate-standardization.mjs && npm test -w @interactive-os/json-document -- standard-conformance",
"verify": "npm run typecheck && npm test && npm run build && npm run smoke:package && npm run build && npm run extensions:verify && npm run labs:extensions:verify && npm run docs:evaluate && npm run playground:typecheck && npm run playground:test && npm run playground:build && npm run site:evaluate && npm run site:verify:pages && npm run browser:test",
"pack:library": "npm pack -w @interactive-os/json-document --cache ./.npm-cache",
"publish": "npm publish -w @interactive-os/json-document",
"publish": "npm publish -w @interactive-os/json-document --tag next",
"playground:dev": "npm run dev -w @interactive-os/json-document-site",
"playground:build": "node scripts/run-workspace-scripts.mjs apps build --if-present",
"playground:typecheck": "node scripts/run-workspace-scripts.mjs apps typecheck",
Expand Down
10 changes: 10 additions & 0 deletions packages/json-document/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ schema -> document -> pointer/query -> can* -> change -> result
- 공식 사이트: https://developer-1px.github.io/json-document/
- GitHub Wiki: https://github.com/developer-1px/json-document/wiki

> `1.1.0-rc.0`은 `editable`, `canvas` 같은 sibling editor에서 통합 압력을
> 확인하기 위한 prerelease입니다. npm `latest`는 계속 `1.0.1`을 가리킵니다.
> 이 RC는 document mutation 성공을 `{ ok, value, applied, target }` 후보로
> 통일하지만 low-level `patch`/`commit`은 `{ ok: true }`를 유지합니다. 이 shape는
> stable 승격 전에 바뀔 수 있으므로 아래처럼 exact version으로 opt in합니다.
>
> ```sh
> npm install @interactive-os/json-document@1.1.0-rc.0 zod
> ```

## 왜 json-document인가

JSON을 단순 data blob으로만 다루면 값 하나를 바꾸는 일은 쉽습니다. 하지만 실제
Expand Down
5 changes: 3 additions & 2 deletions packages/json-document/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@interactive-os/json-document",
"version": "1.1.0",
"version": "1.1.0-rc.0",
"description": "Headless JSON editing primitives guarded by Zod schemas.",
"type": "module",
"license": "MIT",
Expand All @@ -18,7 +18,8 @@
},
"publishConfig": {
"access": "public",
"provenance": true
"provenance": true,
"tag": "next"
},
"keywords": [
"zod",
Expand Down