@zoneflow/core 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 GROOBEE
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,133 @@
1
+ # @zoneflow/core
2
+
3
+ `@zoneflow/core`는 Zoneflow의 도메인 레이어입니다.
4
+
5
+ 이 패키지는 다음 역할을 담당합니다.
6
+
7
+ - `UniverseModel`, `UniverseLayoutModel` 타입
8
+ - zone / path 생성, 수정, 삭제 mutation
9
+ - lookup / validation 유틸
10
+ - layout 유틸
11
+ - zoneflow 문서 import / export
12
+
13
+ 일반적으로 `@zoneflow/react`와 함께 사용합니다.
14
+
15
+ ## 설치
16
+
17
+ ```bash
18
+ pnpm add @zoneflow/core
19
+ ```
20
+
21
+ ## 포함 기능
22
+
23
+ - 모델 타입
24
+ - `UniverseModel`
25
+ - `UniverseLayoutModel`
26
+ - `Zone`
27
+ - `Path`
28
+ - mutation
29
+ - `createZone`
30
+ - `updateZone`
31
+ - `removeZone`
32
+ - `addPath`
33
+ - `updatePath`
34
+ - `removePath`
35
+ - layout
36
+ - `createUniverseLayoutModel`
37
+ - `createZoneLayout`
38
+ - `getZoneLayout`
39
+ - `updateZoneLayout`
40
+ - 문서 포맷
41
+ - `createZoneflowDocument`
42
+ - `serializeZoneflowDocument`
43
+ - `parseZoneflowDocument`
44
+
45
+ ## 최소 예제
46
+
47
+ ```ts
48
+ import {
49
+ createUniverseId,
50
+ createUniverseLayoutModel,
51
+ createZone,
52
+ createZoneLayout,
53
+ serializeZoneflowDocument,
54
+ } from "@zoneflow/core";
55
+
56
+ const universeId = createUniverseId();
57
+
58
+ let model = {
59
+ version: "1.0.0",
60
+ universeId,
61
+ rootZoneIds: [],
62
+ zonesById: {},
63
+ };
64
+
65
+ let layoutModel = createUniverseLayoutModel({
66
+ universeId,
67
+ version: "1.0.0",
68
+ });
69
+
70
+ model = createZone(model, {
71
+ name: "Start",
72
+ zoneType: "action",
73
+ parentZoneId: null,
74
+ });
75
+
76
+ const rootZoneId = model.rootZoneIds[0];
77
+
78
+ layoutModel = {
79
+ ...layoutModel,
80
+ zoneLayoutsById: {
81
+ ...layoutModel.zoneLayoutsById,
82
+ [rootZoneId]: createZoneLayout({
83
+ x: 120,
84
+ y: 100,
85
+ width: 220,
86
+ height: 140,
87
+ }),
88
+ },
89
+ };
90
+
91
+ const json = serializeZoneflowDocument({
92
+ model,
93
+ layoutModel,
94
+ });
95
+ ```
96
+
97
+ ## 문서 저장 / 불러오기
98
+
99
+ Zoneflow 문서 포맷은 다음 함수를 사용합니다.
100
+
101
+ ```ts
102
+ import {
103
+ serializeZoneflowDocument,
104
+ parseZoneflowDocument,
105
+ } from "@zoneflow/core";
106
+
107
+ const json = serializeZoneflowDocument({
108
+ model,
109
+ layoutModel,
110
+ });
111
+
112
+ const documentBundle = parseZoneflowDocument(json);
113
+ ```
114
+
115
+ 문서 형식:
116
+
117
+ ```json
118
+ {
119
+ "kind": "zoneflow/universe",
120
+ "formatVersion": 1,
121
+ "exportedAt": "2026-03-31T12:00:00.000Z",
122
+ "model": {},
123
+ "layoutModel": {}
124
+ }
125
+ ```
126
+
127
+ 레거시 호환을 위해 raw `{ "model": ..., "layoutModel": ... }` 형태도 읽을 수 있습니다.
128
+
129
+ ## 함께 쓰는 패키지
130
+
131
+ - 렌더링/에디팅 UI까지 필요하면 `@zoneflow/react`
132
+
133
+ 레포지토리: [github.com/groobee/zoneflow](https://github.com/groobee/zoneflow)
@@ -0,0 +1,22 @@
1
+ import type { UniverseLayoutModel, UniverseModel } from "./types";
2
+ export declare const ZONEFLOW_DOCUMENT_KIND = "zoneflow/universe";
3
+ export declare const ZONEFLOW_DOCUMENT_VERSION = 1;
4
+ export type ZoneflowDocument = {
5
+ kind: typeof ZONEFLOW_DOCUMENT_KIND;
6
+ formatVersion: typeof ZONEFLOW_DOCUMENT_VERSION;
7
+ exportedAt: string;
8
+ model: UniverseModel;
9
+ layoutModel: UniverseLayoutModel;
10
+ };
11
+ export declare function createZoneflowDocument(params: {
12
+ model: UniverseModel;
13
+ layoutModel: UniverseLayoutModel;
14
+ exportedAt?: string;
15
+ }): ZoneflowDocument;
16
+ export declare function serializeZoneflowDocument(params: {
17
+ model: UniverseModel;
18
+ layoutModel: UniverseLayoutModel;
19
+ exportedAt?: string;
20
+ }, space?: number): string;
21
+ export declare function readZoneflowDocument(input: unknown): ZoneflowDocument;
22
+ export declare function parseZoneflowDocument(json: string): ZoneflowDocument;
@@ -0,0 +1,83 @@
1
+ import { validateUniverseModel } from "./validation";
2
+ export const ZONEFLOW_DOCUMENT_KIND = "zoneflow/universe";
3
+ export const ZONEFLOW_DOCUMENT_VERSION = 1;
4
+ function isRecord(value) {
5
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6
+ }
7
+ function assertUniverseShape(value, key) {
8
+ if (!isRecord(value)) {
9
+ throw new Error(`Invalid zoneflow document: "${key}" must be an object.`);
10
+ }
11
+ if (typeof value.universeId !== "string" || typeof value.version !== "string") {
12
+ throw new Error(`Invalid zoneflow document: "${key}" must include string "universeId" and "version".`);
13
+ }
14
+ }
15
+ function validateLayoutModel(layoutModel) {
16
+ const errors = [];
17
+ if (!isRecord(layoutModel.zoneLayoutsById)) {
18
+ errors.push(`layoutModel.zoneLayoutsById must be an object`);
19
+ }
20
+ if (!isRecord(layoutModel.pathLayoutsById)) {
21
+ errors.push(`layoutModel.pathLayoutsById must be an object`);
22
+ }
23
+ return errors;
24
+ }
25
+ export function createZoneflowDocument(params) {
26
+ return {
27
+ kind: ZONEFLOW_DOCUMENT_KIND,
28
+ formatVersion: ZONEFLOW_DOCUMENT_VERSION,
29
+ exportedAt: params.exportedAt ?? new Date().toISOString(),
30
+ model: structuredClone(params.model),
31
+ layoutModel: structuredClone(params.layoutModel),
32
+ };
33
+ }
34
+ export function serializeZoneflowDocument(params, space = 2) {
35
+ return JSON.stringify(createZoneflowDocument(params), null, space);
36
+ }
37
+ export function readZoneflowDocument(input) {
38
+ if (!isRecord(input)) {
39
+ throw new Error("Invalid zoneflow document: root must be an object.");
40
+ }
41
+ const isLegacyBundle = !("kind" in input) &&
42
+ "model" in input &&
43
+ "layoutModel" in input;
44
+ if (!isLegacyBundle) {
45
+ if (input.kind !== ZONEFLOW_DOCUMENT_KIND) {
46
+ throw new Error(`Invalid zoneflow document: "kind" must be "${ZONEFLOW_DOCUMENT_KIND}".`);
47
+ }
48
+ if (input.formatVersion !== ZONEFLOW_DOCUMENT_VERSION) {
49
+ throw new Error(`Unsupported zoneflow document version: "${String(input.formatVersion)}".`);
50
+ }
51
+ }
52
+ assertUniverseShape(input.model, "model");
53
+ assertUniverseShape(input.layoutModel, "layoutModel");
54
+ const model = structuredClone(input.model);
55
+ const layoutModel = structuredClone(input.layoutModel);
56
+ if (layoutModel.universeId !== model.universeId) {
57
+ throw new Error("Invalid zoneflow document: model.universeId and layoutModel.universeId must match.");
58
+ }
59
+ const modelErrors = validateUniverseModel(model);
60
+ const layoutErrors = validateLayoutModel(layoutModel);
61
+ const errors = [...modelErrors, ...layoutErrors];
62
+ if (errors.length > 0) {
63
+ throw new Error(`Invalid zoneflow document:\\n- ${errors.join("\\n- ")}`);
64
+ }
65
+ return {
66
+ kind: ZONEFLOW_DOCUMENT_KIND,
67
+ formatVersion: ZONEFLOW_DOCUMENT_VERSION,
68
+ exportedAt: typeof input.exportedAt === "string" ? input.exportedAt : new Date().toISOString(),
69
+ model,
70
+ layoutModel,
71
+ };
72
+ }
73
+ export function parseZoneflowDocument(json) {
74
+ let parsed;
75
+ try {
76
+ parsed = JSON.parse(json);
77
+ }
78
+ catch (error) {
79
+ const message = error instanceof Error ? error.message : "Unknown JSON parse error";
80
+ throw new Error(`Failed to parse zoneflow document JSON: ${message}`);
81
+ }
82
+ return readZoneflowDocument(parsed);
83
+ }
package/dist/ids.d.ts CHANGED
@@ -1,3 +1,4 @@
1
- import type { ZoneId, PathId } from "./types";
1
+ import type { UniverseId, ZoneId, PathId } from "./types";
2
+ export declare function createUniverseId(): UniverseId;
2
3
  export declare function createZoneId(): ZoneId;
3
4
  export declare function createPathId(): PathId;
package/dist/ids.js CHANGED
@@ -1,4 +1,7 @@
1
1
  import { v7 as uuidv7 } from "uuid";
2
+ export function createUniverseId() {
3
+ return `universe_${uuidv7()}`;
4
+ }
2
5
  export function createZoneId() {
3
6
  return `zone_${uuidv7()}`;
4
7
  }
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export * from "./traversal";
7
7
  export * from "./validation";
8
8
  export * from "./mutation";
9
9
  export * from "./layout";
10
+ export * from "./document";
10
11
  export * from "./ids";
11
12
  export * from "./remap";
12
13
  export * from "./clone";
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ export * from "./traversal";
7
7
  export * from "./validation";
8
8
  export * from "./mutation";
9
9
  export * from "./layout";
10
+ export * from "./document";
10
11
  export * from "./ids";
11
12
  export * from "./remap";
12
13
  export * from "./clone";
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@zoneflow/core",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
+ "description": "Zoneflow core model, layout, mutation, validation, and document utilities.",
4
5
  "type": "module",
5
6
  "main": "dist/index.js",
6
7
  "types": "dist/index.d.ts",
8
+ "homepage": "https://github.com/groobee/zoneflow",
7
9
  "repository": {
8
10
  "type": "git",
9
- "url": "git@github-groobee:groobee/zoneflow.git",
11
+ "url": "https://github.com/groobee/zoneflow.git",
10
12
  "directory": "packages/core"
11
13
  },
12
14
  "publishConfig": {
@@ -15,11 +17,11 @@
15
17
  "files": [
16
18
  "dist"
17
19
  ],
20
+ "dependencies": {
21
+ "uuid": "^13.0.0"
22
+ },
18
23
  "scripts": {
19
24
  "build": "tsc -p tsconfig.json",
20
25
  "type-check": "tsc -p tsconfig.json --noEmit"
21
- },
22
- "dependencies": {
23
- "uuid": "^13.0.0"
24
26
  }
25
- }
27
+ }