akanjs 2.3.5-rc.6 → 2.3.5-rc.7

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
@@ -2,12 +2,12 @@
2
2
 
3
3
  [English](https://unpkg.com/akanjs@latest/README.md) | [Docs](https://akanjs.com/docs) | [npm](https://www.npmjs.com/package/akanjs)
4
4
 
5
- **코드가 아니라, 비즈니스를 씁니다.**
6
- **Write the business, not the plumbing.**
5
+ **한 줄의 비즈니스 코드로 웹·iOS·Android·서버·DB를 한 번에.**
6
+ **One line of business code ships web, iOS, Android, server, and database together.**
7
7
 
8
- Akan.js는 비즈니스 정의가 애플리케이션이 되도록 설계된 Bun-first 풀스택 TypeScript
9
- 프레임워크입니다. 하나의 코드베이스에서 SEO 웹, iOS/Android 앱 화면, 서버, 데이터베이스 계약,
10
- 인프라 산출물, 문서화까지 이어갑니다.
8
+ 프레임워크 조립, 중복 선언, 플랫폼별 재작성은 이제 그만. Akan.js는 비즈니스 의도를 곳에 쓰면
9
+ SEO 웹, iOS/Android 앱 패키지, 서버, 데이터베이스 계약, 인프라 산출물, 문서화까지 함께 이어지는
10
+ Bun-first 풀스택 TypeScript 프레임워크입니다.
11
11
 
12
12
  ```bash
13
13
  bunx create-akan-workspace@latest
@@ -15,14 +15,14 @@ bunx create-akan-workspace@latest
15
15
 
16
16
  ## 왜 Akan인가
17
17
 
18
- Akan은 기술 계층마다 같은 의도를 다시 쓰는 대신, 비즈니스가 무엇을 하는지 또렷하게 선언하도록
19
- 돕습니다. 도메인을 한 번 정의하면 schema, API, fetch client, store, UI, server, deployment
20
- artifact, generated reference가 같은 의도에서 이어집니다.
18
+ Akan은 기술 계층을 손으로 배선하는 대신 비즈니스를 먼저 출시하도록 돕습니다. 도메인을
19
+ 정의하면 schema, API, fetch client, store, UI, server, app packaging, deployment artifact,
20
+ generated reference가 같은 의도에서 이어집니다.
21
21
 
22
- - **Agents write**: 비즈니스 정의가 코드의 원천입니다. 반복적인 프레임워크 코드는 생성과 규칙이 맡습니다.
23
- - **Keep it minimal**: 줄의 의도가 웹, 앱, 서버, 데이터베이스, 배포까지 이어집니다.
24
- - **Always readable**: 적은 파일, 엄격한 규칙, 예측 가능한 선언 방식으로 6개월 뒤에도 읽히는 코드를 만듭니다.
25
- - **Nice to review**: 군더더기 없는 도메인 변경은 확인하기 쉽고, 리뷰가 빠르며, 곧장 배포하기 좋습니다.
22
+ - **웹 개발자**: 같은 비즈니스 코드가 SEO 웹과 네이티브 느낌의 iOS/Android 화면까지 이어집니다.
23
+ - **앱 개발자**: Bun 서버, SQLite, API 계약, 검증이 손배선 없이 따라옵니다.
24
+ - **1인 창업가 / 소규모 팀**: 풀스택 1명이 5개 표면을 책임집니다. 사람 명, 코드 1/4.
25
+ - **AI 에이전트도 일관되게**: 엄격한 규칙이 파일 위치, 이름, 구조, 선언 방식을 읽기 좋게 유지합니다.
26
26
 
27
27
  ## 요구사항
28
28
 
@@ -104,12 +104,39 @@ flowchart LR
104
104
  하나의 모델과 하나의 계약이 DB, 서버, API, 상태관리, UI까지 이어지기 때문에 계층마다 의도를
105
105
  반복해서 작성할 필요가 줄어듭니다.
106
106
 
107
+ ## 8 in 1
108
+
109
+ 필드 하나. 8개 레이어가 따라옵니다.
110
+
111
+ 기존 풀스택 앱에서 비즈니스 필드 하나를 추가하려면 보통 이만큼을 직접 손으로 해야 합니다.
112
+
113
+ 1. DB 스키마 정의.
114
+ 2. 쿼리 필드 추가.
115
+ 3. 서비스 로직 추가.
116
+ 4. API 필드 추가.
117
+ 5. fetch 필드 추가.
118
+ 6. 클라이언트 타입 선언.
119
+ 7. 상태관리 선언.
120
+ 8. UI prop 선언.
121
+
122
+ 한 곳만 바뀌어도 8곳을 따라 고쳐야 하고, 한 곳을 빠뜨리면 타입이 깨지거나 런타임에서 터집니다.
123
+ Akan에서는 비즈니스 필드가 코드의 원천입니다.
124
+
125
+ ```ts
126
+ export class ProductInput extends via((field) => ({
127
+ name: field(String),
128
+ })) {}
129
+ ```
130
+
131
+ 이 선언 하나로 스키마와 타입이 동시에 정의됩니다. 주변 레이어는 같은 의도에서 생성되므로 스택이
132
+ 흩어져 스파게티가 되는 일을 줄입니다.
133
+
107
134
  ## Akan이 만드는 것
108
135
 
109
136
  Akan은 보통 여러 프로젝트로 흩어지는 것들을 하나의 프레임워크로 묶습니다.
110
137
 
111
138
  - SEO에 최적화된 server-side rendered web surface.
112
- - 아름다운 페이지 전환을 가진 iOS/Android 친화 client-side rendered app surface.
139
+ - 컴파일된 surface를 앱으로 패키징한 iOS/Android surface와 네이티브 수준의 built-in 화면 전환.
113
140
  - Bun 기반 HTTP/WebSocket server.
114
141
  - SQLite-first 단순 서버 경로와 더 큰 시스템을 위한 Postgres/Redis 확장 경로.
115
142
  - Schema validation, error handling, security helper, middleware.
@@ -121,6 +148,10 @@ Akan은 보통 여러 프로젝트로 흩어지는 것들을 하나의 프레임
121
148
  배포와 문서 작성에 하루를 쓰고 있다면 뭔가 잘못된 것입니다. Akan은 schema와 endpoint 정의가
122
149
  table reference, runtime contract, API docs, testable endpoint reference가 되도록 설계됩니다.
123
150
 
151
+ 일반적인 앱 패키징은 감싼 웹사이트처럼 느껴지기 쉽습니다. Akan의 client runtime은 목록-상세 흐름,
152
+ 오버레이, 맥락 전환을 위한 transition preset을 제공하므로 별도 UI 재작성 없이도 앱 패키징된 웹에서
153
+ 네이티브 수준의 사용자 경험을 만들 수 있습니다.
154
+
124
155
  ## 하나의 패키지, 여러 경계
125
156
 
126
157
  Akan은 하나의 npm package인 `akanjs`로 배포됩니다.
package/README.md CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  [한국어](https://unpkg.com/akanjs@latest/README.ko.md) | [Docs](https://akanjs.com/docs) | [npm](https://www.npmjs.com/package/akanjs)
4
4
 
5
- **Write the business, not the plumbing.**
5
+ **One line of business code ships web, iOS, Android, server, and database together.**
6
6
 
7
- Akan.js is a Bun-first full-stack TypeScript framework for teams that want business definitions to be the
8
- application. One cohesive codebase can produce SEO web surfaces, iOS and Android app surfaces, servers,
9
- database contracts, infrastructure artifacts, and documentation.
7
+ No more framework assembly, duplicated declarations, or per-platform rewrites. Akan.js is a Bun-first
8
+ full-stack TypeScript framework where business intent is written once, then compiled into SEO web surfaces,
9
+ iOS and Android app packages, servers, database contracts, infrastructure artifacts, and documentation.
10
10
 
11
11
  ```bash
12
12
  bunx create-akan-workspace@latest
@@ -14,14 +14,14 @@ bunx create-akan-workspace@latest
14
14
 
15
15
  ## Why Akan
16
16
 
17
- Akan is designed for teams and solo builders who would rather describe what the business does than keep
18
- rewriting the same intent for each technical layer. Define the domain once, then let the framework connect
19
- the schema, API, fetch client, store, UI, server, deployment artifacts, and generated references.
17
+ Akan is designed for teams and solo builders who would rather ship the business than keep wiring technical
18
+ layers by hand. Define the domain once, then let the framework connect schema, API, fetch client, store, UI,
19
+ server, app packaging, deployment artifacts, and generated references.
20
20
 
21
- - **Agents write**: business definitions are the source of truth; generation handles repetitive framework code.
22
- - **Keep it minimal**: one line of intent can flow across web, app, server, database, and deployment.
23
- - **Always readable**: fewer files, strict conventions, and predictable declarations keep code clear months later.
24
- - **Nice to review**: focused domain changes are easier to inspect, approve, and ship.
21
+ - **Web devs**: the same business code becomes SEO-ready web and native-feeling iOS/Android screens.
22
+ - **App devs**: Bun server, SQLite, API contracts, and validation follow without hand-wiring.
23
+ - **Solo and small teams**: one full-stack developer can own all five surfaces with a quarter of the code.
24
+ - **Agents stay consistent**: strict conventions keep file paths, names, structures, and declarations readable.
25
25
 
26
26
  ## Requirements
27
27
 
@@ -102,12 +102,39 @@ flowchart LR
102
102
  This structure lets one model and one contract flow through the database, server, API, state management,
103
103
  and UI without duplicating intent across layers.
104
104
 
105
+ ## 8 in 1
106
+
107
+ One field. Eight layers follow.
108
+
109
+ Adding a single business field in a traditional full-stack app usually means changing all of this by hand:
110
+
111
+ 1. Define the DB schema.
112
+ 2. Add the query field.
113
+ 3. Add the service logic.
114
+ 4. Add the API field.
115
+ 5. Add the fetch field.
116
+ 6. Declare the client type.
117
+ 7. Declare the state management.
118
+ 8. Declare the UI prop.
119
+
120
+ Change one place, chase eight. Miss one, and types break, or it fails at runtime. In Akan, the business field is
121
+ the source of truth:
122
+
123
+ ```ts
124
+ export class ProductInput extends via((field) => ({
125
+ name: field(String),
126
+ })) {}
127
+ ```
128
+
129
+ That one declaration defines schema and type together. The surrounding layers are generated from the same
130
+ intent, so the stack stays connected instead of turning into spaghetti.
131
+
105
132
  ## What Akan Builds
106
133
 
107
134
  Akan is one framework for the pieces that normally become separate projects:
108
135
 
109
136
  - SEO-optimized server-side rendered web surfaces.
110
- - iOS and Android friendly client-side rendered app surfaces with page transitions.
137
+ - iOS and Android app packages from compiled web surfaces, with native-level built-in screen transitions.
111
138
  - Bun-powered HTTP and WebSocket servers.
112
139
  - SQLite-first simple server paths, with Postgres and Redis expansion paths for larger systems.
113
140
  - Schema validation, error handling, security helpers, and middleware.
@@ -119,6 +146,10 @@ Akan is one framework for the pieces that normally become separate projects:
119
146
  Deployment and documentation should not consume a day of work. Akan is built so schema and endpoint
120
147
  definitions can also become table references, runtime contracts, API docs, and testable endpoint references.
121
148
 
149
+ Unlike ordinary app packaging that can feel like a wrapped website, Akan's client runtime includes transition
150
+ presets for list-detail flows, overlays, and context changes. Packaged web surfaces can deliver a native-level
151
+ user experience without a separate UI rewrite.
152
+
122
153
  ## One Package, Many Boundaries
123
154
 
124
155
  Akan is published as a single npm package: `akanjs`.
@@ -273,15 +273,26 @@ export class ConstantRegistry {
273
273
  }
274
274
  }
275
275
 
276
- export interface ConstantCore<
276
+ export interface ConstantModel<
277
277
  T extends string = string,
278
- Input = unknown,
279
- Obj = unknown,
280
- Full = unknown,
281
- Light = unknown,
282
- Insight = unknown,
278
+ Input = any,
279
+ Obj = any,
280
+ Full = any,
281
+ Light = any,
282
+ Insight = any,
283
283
  FullFieldObj extends FieldObject = FieldObject,
284
284
  _CapitalizedRefName extends string = Capitalize<T>,
285
+ _Default = DefaultOf<Full>,
286
+ _DefaultInput = DefaultOf<Input>,
287
+ _DefaultState = GetStateObject<Full>,
288
+ _DefaultStateInput = GetStateObject<Input>,
289
+ _DefaultInsight = DefaultOf<Insight>,
290
+ _PurifiedInput = PurifiedModel<Input>,
291
+ _Doc = DocumentModel<Full>,
292
+ _DocInput = DocumentModel<Input>,
293
+ _QueryOfDoc = QueryOf<_Doc>,
294
+ _StateLight = GetStateObject<Light>,
295
+ _StateInsight = GetStateObject<Insight>,
285
296
  > {
286
297
  refName: T;
287
298
  input: ConstantCls<Input>;
@@ -295,25 +306,6 @@ export interface ConstantCore<
295
306
  _Full: Full;
296
307
  _Light: Light;
297
308
  _Insight: Insight;
298
- }
299
-
300
- export interface ConstantDerived<
301
- Input = unknown,
302
- Full = unknown,
303
- Light = unknown,
304
- Insight = unknown,
305
- _Default = DefaultOf<Full>,
306
- _DefaultInput = DefaultOf<Input>,
307
- _DefaultState = GetStateObject<Full>,
308
- _DefaultStateInput = GetStateObject<Input>,
309
- _DefaultInsight = DefaultOf<Insight>,
310
- _PurifiedInput = PurifiedModel<Input>,
311
- _Doc = DocumentModel<Full>,
312
- _DocInput = DocumentModel<Input>,
313
- _QueryOfDoc = QueryOf<_Doc>,
314
- _StateLight = GetStateObject<Light>,
315
- _StateInsight = GetStateObject<Insight>,
316
- > {
317
309
  _Default: _Default;
318
310
  _DefaultInput: _DefaultInput;
319
311
  _DefaultState: _DefaultState;
@@ -327,109 +319,6 @@ export interface ConstantDerived<
327
319
  _StateInsight: _StateInsight;
328
320
  }
329
321
 
330
- export interface ConstantModel<
331
- T extends string = string,
332
- Input = any,
333
- Obj = any,
334
- Full = any,
335
- Light = any,
336
- Insight = any,
337
- FullFieldObj extends FieldObject = FieldObject,
338
- _CapitalizedRefName extends string = Capitalize<T>,
339
- _Default = DefaultOf<Full>,
340
- _DefaultInput = DefaultOf<Input>,
341
- _DefaultState = GetStateObject<Full>,
342
- _DefaultStateInput = GetStateObject<Input>,
343
- _DefaultInsight = DefaultOf<Insight>,
344
- _PurifiedInput = PurifiedModel<Input>,
345
- _Doc = DocumentModel<Full>,
346
- _DocInput = DocumentModel<Input>,
347
- _QueryOfDoc = QueryOf<_Doc>,
348
- _StateLight = GetStateObject<Light>,
349
- _StateInsight = GetStateObject<Insight>,
350
- > extends ConstantCore<T, Input, Obj, Full, Light, Insight, FullFieldObj, _CapitalizedRefName>,
351
- ConstantDerived<
352
- Input,
353
- Full,
354
- Light,
355
- Insight,
356
- _Default,
357
- _DefaultInput,
358
- _DefaultState,
359
- _DefaultStateInput,
360
- _DefaultInsight,
361
- _PurifiedInput,
362
- _Doc,
363
- _DocInput,
364
- _QueryOfDoc,
365
- _StateLight,
366
- _StateInsight
367
- > {}
368
-
369
- export type ConstantReturnView<Full = unknown, Light = unknown, Insight = unknown> = {
370
- full: Full;
371
- light: Light;
372
- insight: Insight;
373
- };
374
-
375
- export type ConstantReturnViewOf<Cnst> = Cnst extends {
376
- _Full: infer Full;
377
- _Light: infer Light;
378
- _Insight: infer Insight;
379
- }
380
- ? ConstantReturnView<Full, Light, Insight>
381
- : never;
382
-
383
- export type ConstantFetchView<
384
- RefName extends string = string,
385
- CapRefName extends string = Capitalize<RefName>,
386
- Input = unknown,
387
- Full = unknown,
388
- Light = unknown,
389
- Insight = unknown,
390
- PurifiedInput = unknown,
391
- DefaultInput = unknown,
392
- StateLight = unknown,
393
- StateInsight = unknown,
394
- > = {
395
- refName: RefName;
396
- capRefName: CapRefName;
397
- input: Input;
398
- full: Full;
399
- light: Light;
400
- insight: Insight;
401
- purifiedInput: PurifiedInput;
402
- defaultInput: DefaultInput;
403
- stateLight: StateLight;
404
- stateInsight: StateInsight;
405
- };
406
-
407
- export type ConstantFetchViewOf<Cnst> = Cnst extends {
408
- refName: infer RefName extends string;
409
- _CapitalizedRefName: infer CapRefName extends string;
410
- _Input: infer Input;
411
- _Full: infer Full;
412
- _Light: infer Light;
413
- _Insight: infer Insight;
414
- _PurifiedInput: infer PurifiedInput;
415
- _DefaultInput: infer DefaultInput;
416
- _StateLight: infer StateLight;
417
- _StateInsight: infer StateInsight;
418
- }
419
- ? ConstantFetchView<
420
- RefName,
421
- CapRefName,
422
- Input,
423
- Full,
424
- Light,
425
- Insight,
426
- PurifiedInput,
427
- DefaultInput,
428
- StateLight,
429
- StateInsight
430
- >
431
- : never;
432
-
433
322
  export interface ScalarConstantModel<
434
323
  T extends string = string,
435
324
  Model = any,
@@ -1,5 +1,4 @@
1
- import type { Assign } from "akanjs/base";
2
- import type { DatabaseSignal, SerializedSignal, ServiceSignal } from "akanjs/signal";
1
+ import type { DatabaseSignal, EndpointCls, SerializedSignal, ServiceSignal, SliceCls } from "akanjs/signal";
3
2
  import type { FetchProxy } from "../client";
4
3
  import type { GetSliceMetaObjFromDatabaseSignals } from "../types";
5
4
  import type { SliceMeta } from "./appliedReturn.type";
@@ -18,31 +17,36 @@ export type FetchProxySignalInput<
18
17
 
19
18
  export type FetchSignalInput = FetchProxySignalInput | DatabaseSignal | ServiceSignal;
20
19
 
21
- export type IsAny<Type> = 0 extends 1 & Type ? true : false;
22
- export type SafeFetchPart<Type, Fallback = unknown> = IsAny<Type> extends true ? Fallback : Type;
23
-
24
- type MergeFetchParts<First, Second> = [First] extends [never]
25
- ? Second
26
- : [Second] extends [never]
27
- ? First
28
- : Assign<First, Second>;
29
-
30
20
  export type FetchTypeOfSignal<Signal extends FetchSignalInput> = Signal extends { _FetchType: infer FetchType }
31
21
  ? FetchType
32
- : Signal extends DatabaseSignal<infer _IntlCls, infer EndpCls, infer SlceCls, infer _SrvrCls>
33
- ? MergeFetchParts<GetFetchTypeFromEndpoint<EndpCls, SlceCls>, GetFetchTypeFromSlice<SlceCls>>
34
- : Signal extends ServiceSignal<infer _IntlCls, infer EndpCls, infer _SrvrCls>
22
+ : Signal extends { endpoint: infer EndpCls extends EndpointCls; slice: infer SlceCls extends SliceCls }
23
+ ? GetFetchTypeFromEndpoint<EndpCls, SlceCls> & GetFetchTypeFromSlice<SlceCls>
24
+ : Signal extends { endpoint: infer EndpCls extends EndpointCls }
35
25
  ? GetFetchTypeFromEndpoint<EndpCls>
36
26
  : unknown;
37
27
 
38
- type MergeProxyFetchTypes<
28
+ type FetchKeysOfProxySignal<Signal> = Signal extends { _FetchType: infer FetchType } ? keyof FetchType : never;
29
+ type FetchKeysOfProxySignals<Signals extends readonly FetchSignalInput[]> = FetchKeysOfProxySignal<Signals[number]>;
30
+
31
+ type LastProxyFetchValue<
39
32
  Signals extends readonly FetchSignalInput[],
40
- Acc = Record<never, never>,
33
+ Key extends PropertyKey,
34
+ Current = never,
41
35
  > = Signals extends readonly [infer First extends FetchSignalInput, ...infer Rest extends readonly FetchSignalInput[]]
42
36
  ? First extends { _FetchType: infer FetchType }
43
- ? MergeProxyFetchTypes<Rest, Assign<Acc, FetchType>>
44
- : MergeProxyFetchTypes<Rest, Acc>
45
- : Acc;
37
+ ? Key extends keyof FetchType
38
+ ? LastProxyFetchValue<Rest, Key, FetchType[Key]>
39
+ : LastProxyFetchValue<Rest, Key, Current>
40
+ : LastProxyFetchValue<Rest, Key, Current>
41
+ : Current;
42
+
43
+ type MergeProxyFetchTypes<Signals extends readonly FetchSignalInput[]> = [FetchKeysOfProxySignals<Signals>] extends [
44
+ never,
45
+ ]
46
+ ? Record<never, never>
47
+ : {
48
+ [Key in FetchKeysOfProxySignals<Signals>]: LastProxyFetchValue<Signals, Key>;
49
+ };
46
50
 
47
51
  type MergeDirectFetchTypes<
48
52
  Signals extends readonly FetchSignalInput[],
@@ -50,13 +54,13 @@ type MergeDirectFetchTypes<
50
54
  > = Signals extends readonly [infer First extends FetchSignalInput, ...infer Rest extends readonly FetchSignalInput[]]
51
55
  ? First extends { _FetchType: unknown }
52
56
  ? MergeDirectFetchTypes<Rest, Acc>
53
- : MergeDirectFetchTypes<Rest, MergeFetchParts<Acc, FetchTypeOfSignal<First>>>
57
+ : MergeDirectFetchTypes<Rest, Acc & FetchTypeOfSignal<First>>
54
58
  : Acc;
55
59
 
56
60
  export type MergeAllFetchTypes<Signals extends readonly FetchSignalInput[]> =
57
61
  MergeProxyFetchTypes<Signals> extends infer ProxyFetch
58
62
  ? MergeDirectFetchTypes<Signals> extends infer DirectFetch
59
- ? Assign<ProxyFetch, DirectFetch>
63
+ ? Omit<ProxyFetch, keyof DirectFetch> & DirectFetch
60
64
  : never
61
65
  : never;
62
66
 
@@ -1,6 +1,5 @@
1
1
  import type { ENDPOINT_META, PromiseOrObject } from "akanjs/base";
2
2
  import type { FetchPolicy } from "akanjs/common";
3
- import type { ConstantReturnViewOf } from "akanjs/constant";
4
3
  import type {
5
4
  EndpInfoArgs,
6
5
  EndpInfoClientReturns,
@@ -11,112 +10,81 @@ import type {
11
10
  SliceCls,
12
11
  } from "akanjs/signal";
13
12
 
14
- export type EndpointReturnContext<Full = unknown, Light = unknown, Insight = unknown> = {
15
- full: Full;
16
- light: Light;
17
- insight: Insight;
18
- };
19
-
20
- type EndpointReturnContextOf<SlceCls extends SliceCls | never> = [SlceCls] extends [never]
21
- ? never
22
- : SlceCls extends SliceCls
23
- ? ConstantReturnViewOf<SlceCls["srv"]["cnst"]>
24
- : never;
25
-
26
- type ExtendedEndpointReturn<ClientReturns, Context> = ClientReturns extends (infer R)[]
27
- ? ExtendedEndpointReturn<R, Context>[]
28
- : Context extends EndpointReturnContext<infer Full, infer Light, infer Insight>
29
- ? Full extends ClientReturns
30
- ? Full
31
- : Light extends ClientReturns
32
- ? Light
33
- : Insight extends ClientReturns
34
- ? Insight
35
- : ClientReturns
36
- : ClientReturns;
37
-
38
- type EndpointClientReturns<E, Context> = [Context] extends [never]
13
+ type ExtendedEndpointReturn<ClientReturns, Full, Light, Insight> = ClientReturns extends (infer R)[]
14
+ ? ExtendedEndpointReturn<R, Full, Light, Insight>[]
15
+ : Full extends ClientReturns
16
+ ? Full
17
+ : Light extends ClientReturns
18
+ ? Light
19
+ : Insight extends ClientReturns
20
+ ? Insight
21
+ : ClientReturns;
22
+
23
+ type EndpointClientReturns<E, SlceCls extends SliceCls | never> = [SlceCls] extends [never]
39
24
  ? EndpInfoClientReturns<E>
40
- : ExtendedEndpointReturn<EndpInfoClientReturns<E>, Context>;
41
-
42
- type EndpInfoReturns<E, Context> =
43
- | EndpointClientReturns<E, Context>
25
+ : ExtendedEndpointReturn<
26
+ EndpInfoClientReturns<E>,
27
+ SlceCls["srv"]["cnst"]["_Full"],
28
+ SlceCls["srv"]["cnst"]["_Light"],
29
+ SlceCls["srv"]["cnst"]["_Insight"]
30
+ >;
31
+
32
+ type EndpInfoReturns<E, SlceCls extends SliceCls | never> =
33
+ | EndpointClientReturns<E, SlceCls>
44
34
  | (EndpInfoNullable<E> extends true ? null : never);
45
35
 
46
- type QueryOrMutationFetchFn<E, Context> = (
36
+ type QueryOrMutationFetchFn<E, SlceCls extends SliceCls | never> = (
47
37
  ...args: [...EndpInfoArgs<E>, fetchPolicy?: FetchPolicy]
48
- ) => Promise<EndpInfoReturns<E, Context>>;
38
+ ) => Promise<EndpInfoReturns<E, SlceCls>>;
49
39
 
50
- type MessageEmitFn<E, Context> = (...args: EndpInfoArgs<E>) => EndpInfoReturns<E, Context>;
40
+ type MessageEmitFn<E, SlceCls extends SliceCls | never> = (...args: EndpInfoArgs<E>) => EndpInfoReturns<E, SlceCls>;
51
41
 
52
- type MessageListenFn<E, Context> = (
53
- handleEvent: (data: EndpInfoReturns<E, Context>) => PromiseOrObject<void>,
42
+ type MessageListenFn<E, SlceCls extends SliceCls | never> = (
43
+ handleEvent: (data: EndpInfoReturns<E, SlceCls>) => PromiseOrObject<void>,
54
44
  options?: FetchPolicy,
55
45
  ) => () => void;
56
46
 
57
- type PubsubSubscribeFn<E, Context> = (
47
+ type PubsubSubscribeFn<E, SlceCls extends SliceCls | never> = (
58
48
  ...args: [
59
49
  ...EndpInfoArgs<E>,
60
- handleEvent: (data: EndpInfoReturns<E, Context>) => PromiseOrObject<void>,
50
+ handleEvent: (data: EndpInfoReturns<E, SlceCls>) => PromiseOrObject<void>,
61
51
  options?: FetchPolicy,
62
52
  ]
63
53
  ) => () => void;
64
54
 
65
- type PrimaryFetchFn<E, Context, ReqType = EndpInfoReqType<E>> = ReqType extends "query" | "mutation"
66
- ? QueryOrMutationFetchFn<E, Context>
67
- : ReqType extends "message"
68
- ? MessageEmitFn<E, Context>
69
- : never;
70
-
71
- type UploadLikeArg = FileList | File | File[];
72
- type HasUploadLikeArg<Args extends readonly unknown[]> =
73
- Extract<Args[number], UploadLikeArg> extends never ? false : true;
74
- type RestApiArg<Arg> = Arg extends FileList ? FileList : Arg extends File | File[] ? FileList : Arg;
75
- type RestApiArgs<Args extends readonly unknown[]> = {
76
- [K in keyof Args]: RestApiArg<Args[K]>;
77
- };
78
- type UploadRestApiFetchFn<E, Context> = (
79
- ...args: [...RestApiArgs<EndpInfoArgs<E>>, fetchPolicy?: FetchPolicy]
80
- ) => Promise<EndpInfoReturns<E, Context>>;
81
-
82
- type PrimaryFetchType<EInfoObj extends { [key: string]: EndpointInfo }, Context> = {
83
- [K in keyof EInfoObj as Extract<EndpInfoReqType<EInfoObj[K]>, "query" | "mutation" | "message"> extends never
84
- ? never
85
- : K]: PrimaryFetchFn<EInfoObj[K], Context>;
86
- };
87
-
88
- type UploadRestApiFetchType<EInfoObj extends { [key: string]: EndpointInfo }, Context> = {
89
- [K in keyof EInfoObj as Extract<EndpInfoReqType<EInfoObj[K]>, "mutation"> extends never
90
- ? never
91
- : HasUploadLikeArg<EndpInfoArgs<EInfoObj[K]>> extends true
92
- ? K extends string
93
- ? `${K}RestApi`
94
- : never
95
- : never]: UploadRestApiFetchFn<EInfoObj[K], Context>;
55
+ type PrimaryFetchFn<E, SlceCls extends SliceCls | never> =
56
+ EndpInfoReqType<E> extends "query" | "mutation"
57
+ ? QueryOrMutationFetchFn<E, SlceCls>
58
+ : EndpInfoReqType<E> extends "message"
59
+ ? MessageEmitFn<E, SlceCls>
60
+ : never;
61
+
62
+ type PrimaryFetchType<EInfoObj extends { [key: string]: EndpointInfo }, SlceCls extends SliceCls | never> = {
63
+ [K in keyof EInfoObj as EndpInfoReqType<EInfoObj[K]> extends "query" | "mutation" | "message"
64
+ ? K
65
+ : never]: PrimaryFetchFn<EInfoObj[K], SlceCls>;
96
66
  };
97
67
 
98
- type PubsubFetchType<EInfoObj extends { [key: string]: EndpointInfo }, Context> = {
99
- [K in keyof EInfoObj as Extract<EndpInfoReqType<EInfoObj[K]>, "pubsub"> extends never
100
- ? never
101
- : K extends string
68
+ type PubsubFetchType<EInfoObj extends { [key: string]: EndpointInfo }, SlceCls extends SliceCls | never> = {
69
+ [K in keyof EInfoObj as EndpInfoReqType<EInfoObj[K]> extends "pubsub"
70
+ ? K extends string
102
71
  ? `subscribe${Capitalize<K>}`
103
- : never]: PubsubSubscribeFn<EInfoObj[K], Context>;
72
+ : never
73
+ : never]: PubsubSubscribeFn<EInfoObj[K], SlceCls>;
104
74
  };
105
75
 
106
- type MessageListenFetchType<EInfoObj extends { [key: string]: EndpointInfo }, Context> = {
107
- [K in keyof EInfoObj as Extract<EndpInfoReqType<EInfoObj[K]>, "message"> extends never
108
- ? never
109
- : K extends string
76
+ type MessageListenFetchType<EInfoObj extends { [key: string]: EndpointInfo }, SlceCls extends SliceCls | never> = {
77
+ [K in keyof EInfoObj as EndpInfoReqType<EInfoObj[K]> extends "message"
78
+ ? K extends string
110
79
  ? `listen${Capitalize<K>}`
111
- : never]: MessageListenFn<EInfoObj[K], Context>;
80
+ : never
81
+ : never]: MessageListenFn<EInfoObj[K], SlceCls>;
112
82
  };
113
83
 
114
84
  export type GetFetchTypeFromEndpoint<
115
85
  EndpCls extends EndpointCls,
116
86
  SlceCls extends SliceCls | never = never,
117
87
  _EndpointInfoObj extends { [key: string]: EndpointInfo } = EndpCls[typeof ENDPOINT_META],
118
- _ReturnContext = EndpointReturnContextOf<SlceCls>,
119
- > = PrimaryFetchType<_EndpointInfoObj, _ReturnContext> &
120
- UploadRestApiFetchType<_EndpointInfoObj, _ReturnContext> &
121
- PubsubFetchType<_EndpointInfoObj, _ReturnContext> &
122
- MessageListenFetchType<_EndpointInfoObj, _ReturnContext>;
88
+ > = PrimaryFetchType<_EndpointInfoObj, SlceCls> &
89
+ PubsubFetchType<_EndpointInfoObj, SlceCls> &
90
+ MessageListenFetchType<_EndpointInfoObj, SlceCls>;