@fluojs/serialization 1.0.1 → 1.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/README.ko.md CHANGED
@@ -103,7 +103,7 @@ class UsersController {
103
103
 
104
104
  ### 순환 참조 처리
105
105
 
106
- fluo의 직렬화 엔진은 활성 순환 참조를 자동으로 감지하고 `undefined`로 절단하여 무한 루프와 스택 오버플로를 방지합니다. 이미 직렬화가 끝난 공유 참조는 삭제하지 않고 직렬화된 그래프 안에서 재사용합니다. 예를 들어 두 sibling 필드가 같은 원본 객체를 가리키면 두 직렬화 결과도 같은 직렬화 객체를 가리키며, 현재 직렬화 중인 객체를 다시 만나는 활성 cycle만 `undefined`로 절단됩니다.
106
+ fluo의 직렬화 엔진은 활성 순환 참조를 자동으로 감지하고 `undefined`로 절단하여 무한 루프와 스택 오버플로를 방지합니다. 같은 reference tracker가 class instance, plain object, 배열, mixed object-array graph 전체에서 공유됩니다. 자기 자신을 참조하는 배열과 object-array cycle은 활성 back edge에서 절단되고, 이미 직렬화가 끝난 공유 참조는 삭제하지 않고 직렬화된 그래프 안에서 재사용합니다. 예를 들어 두 sibling 필드 또는 객체 필드와 배열 항목이 같은 원본 객체를 가리키면 두 직렬화 결과도 같은 직렬화 객체를 가리키며, 현재 직렬화 중인 값을 다시 만나는 활성 cycle만 `undefined`로 절단됩니다.
107
107
 
108
108
  ### 상속된 데코레이터 계약
109
109
 
@@ -124,8 +124,8 @@ Decorated metadata가 없는 class instance도 재귀적으로 순회하므로,
124
124
  ## 공개 API 개요
125
125
 
126
126
  - **데코레이터**: `Expose`, `Exclude`, `Transform`
127
- - **엔진**: `serialize(value)`
128
- - **HTTP 통합**: `SerializerInterceptor`
127
+ - **엔진**: `serialize(value)`는 class instance, 배열, plain object, mixed graph를 재귀적으로 순회하며, 직접 transform하지 않은 opaque built-in 및 non-JSON leaf 값은 보존합니다.
128
+ - **HTTP 통합**: `SerializerInterceptor`는 아직 commit되지 않은 handler 결과를 직렬화하고, response가 이미 commit된 뒤에는 handler 소유 값을 그대로 반환합니다.
129
129
 
130
130
  `Expose`는 class와 field에 적용할 수 있습니다. `Exclude`와 `Transform`은 field에 적용합니다.
131
131
 
package/README.md CHANGED
@@ -103,7 +103,7 @@ class UsersController {
103
103
 
104
104
  ### Cycle-safe serialization
105
105
 
106
- The serializer cuts active cyclic references safely instead of recursing forever, so complex object graphs can still be turned into plain response-shaped objects without unbounded recursion. Completed shared references are reused in the serialized graph rather than dropped: if two sibling fields point at the same source object, both serialized fields point at the same serialized object. Only an object that is encountered again while it is already being serialized is cut to `undefined`.
106
+ The serializer cuts active cyclic references safely instead of recursing forever, so complex object graphs can still be turned into plain response-shaped objects without unbounded recursion. The same reference tracker is shared across class instances, plain objects, arrays, and mixed object-array graphs. Self-referential arrays and object-array cycles are cut at the active back edge, while completed shared references are reused in the serialized graph rather than dropped: if two sibling fields, or an object field and an array entry, point at the same source object, both serialized fields point at the same serialized object. Only a value that is encountered again while it is already being serialized is cut to `undefined`.
107
107
 
108
108
  ### Inherited decorator contracts
109
109
 
@@ -124,8 +124,8 @@ Undecorated class instances are still traversed recursively, so decorated nested
124
124
  ## Public API Overview
125
125
 
126
126
  - **Decorators**: `Expose`, `Exclude`, `Transform`
127
- - **Engine**: `serialize(value)`
128
- - **HTTP integration**: `SerializerInterceptor`
127
+ - **Engine**: `serialize(value)` recursively walks class instances, arrays, plain objects, and mixed graphs while preserving opaque built-ins and non-JSON leaf values unless you transform them
128
+ - **HTTP integration**: `SerializerInterceptor` serializes uncommitted handler results and returns handler-owned values unchanged after the response has already been committed
129
129
 
130
130
  `Expose` can be applied to classes and fields. `Exclude` and `Transform` apply to fields.
131
131
 
@@ -1,8 +1,11 @@
1
1
  /**
2
- * Serializes class instances and object graphs into plain response-shaped values.
2
+ * Serializes class instances, arrays, plain records, and mixed object graphs
3
+ * into plain response-shaped values.
3
4
  *
4
5
  * Serialization honors `@Expose()`, `@Exclude()`, and `@Transform()` metadata.
5
- * Cycles and repeated references are handled without unbounded recursion.
6
+ * Cycles and repeated references are handled without unbounded recursion across
7
+ * both object and array boundaries. Active cycles are cut to `undefined`, while
8
+ * completed shared references reuse the previously serialized value.
6
9
  * Opaque built-ins and non-JSON leaf values such as `Date`, `Map`, `Set`, `URL`, `Error`, `bigint`, functions, and symbols pass through unchanged unless you normalize them before or during serialization.
7
10
  *
8
11
  * @typeParam T Input value type.
@@ -1 +1 @@
1
- {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../src/serialize.ts"],"names":[],"mappings":"AAwQA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAOxD"}
1
+ {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../src/serialize.ts"],"names":[],"mappings":"AAwQA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAOxD"}
package/dist/serialize.js CHANGED
@@ -166,10 +166,13 @@ function serializeInternal(value, context) {
166
166
  }
167
167
 
168
168
  /**
169
- * Serializes class instances and object graphs into plain response-shaped values.
169
+ * Serializes class instances, arrays, plain records, and mixed object graphs
170
+ * into plain response-shaped values.
170
171
  *
171
172
  * Serialization honors `@Expose()`, `@Exclude()`, and `@Transform()` metadata.
172
- * Cycles and repeated references are handled without unbounded recursion.
173
+ * Cycles and repeated references are handled without unbounded recursion across
174
+ * both object and array boundaries. Active cycles are cut to `undefined`, while
175
+ * completed shared references reuse the previously serialized value.
173
176
  * Opaque built-ins and non-JSON leaf values such as `Date`, `Map`, `Set`, `URL`, `Error`, `bigint`, functions, and symbols pass through unchanged unless you normalize them before or during serialization.
174
177
  *
175
178
  * @typeParam T Input value type.
@@ -5,7 +5,9 @@ import type { CallHandler, Interceptor, InterceptorContext } from '@fluojs/http'
5
5
  * @remarks
6
6
  * Use this at the controller or route level when handlers return class instances
7
7
  * and you want `@Expose()`, `@Exclude()`, and `@Transform()` metadata applied
8
- * automatically.
8
+ * automatically. If the handler already committed `RequestContext.response`,
9
+ * the interceptor returns the handler-owned value unchanged so streaming and
10
+ * manually written responses keep their response ownership.
9
11
  */
10
12
  export declare class SerializerInterceptor implements Interceptor {
11
13
  intercept(context: InterceptorContext, next: CallHandler): Promise<unknown>;
@@ -1 +1 @@
1
- {"version":3,"file":"serializer-interceptor.d.ts","sourceRoot":"","sources":["../src/serializer-interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAIjF;;;;;;;GAOG;AACH,qBAAa,qBAAsB,YAAW,WAAW;IACjD,SAAS,CAAC,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;CASlF"}
1
+ {"version":3,"file":"serializer-interceptor.d.ts","sourceRoot":"","sources":["../src/serializer-interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAIjF;;;;;;;;;GASG;AACH,qBAAa,qBAAsB,YAAW,WAAW;IACjD,SAAS,CAAC,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;CASlF"}
@@ -6,7 +6,9 @@ import { serialize } from './serialize.js';
6
6
  * @remarks
7
7
  * Use this at the controller or route level when handlers return class instances
8
8
  * and you want `@Expose()`, `@Exclude()`, and `@Transform()` metadata applied
9
- * automatically.
9
+ * automatically. If the handler already committed `RequestContext.response`,
10
+ * the interceptor returns the handler-owned value unchanged so streaming and
11
+ * manually written responses keep their response ownership.
10
12
  */
11
13
  export class SerializerInterceptor {
12
14
  async intercept(context, next) {
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "output",
10
10
  "transform"
11
11
  ],
12
- "version": "1.0.1",
12
+ "version": "1.0.3",
13
13
  "private": false,
14
14
  "license": "MIT",
15
15
  "repository": {
@@ -36,8 +36,8 @@
36
36
  "dist"
37
37
  ],
38
38
  "dependencies": {
39
- "@fluojs/core": "^1.0.1",
40
- "@fluojs/http": "^1.0.0"
39
+ "@fluojs/core": "^1.0.3",
40
+ "@fluojs/http": "^1.1.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "vitest": "^3.2.4"