@gostack-framework/react 0.0.0-stage → 0.1.0

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.
Files changed (138) hide show
  1. package/dist/api.d.ts +83 -0
  2. package/dist/api.js +170 -0
  3. package/dist/api.js.map +1 -0
  4. package/dist/auth.d.ts +60 -0
  5. package/dist/auth.js +136 -0
  6. package/dist/auth.js.map +1 -0
  7. package/dist/data.d.ts +25 -0
  8. package/dist/data.js +73 -0
  9. package/dist/data.js.map +1 -0
  10. package/dist/examples.d.ts +6 -0
  11. package/dist/examples.js +47 -0
  12. package/dist/examples.js.map +1 -0
  13. package/dist/hooks.d.ts +58 -0
  14. package/dist/hooks.js +109 -0
  15. package/dist/hooks.js.map +1 -0
  16. package/dist/index.d.ts +20 -0
  17. package/dist/index.js +21 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/layouts.d.ts +6 -0
  20. package/dist/layouts.js +34 -0
  21. package/dist/layouts.js.map +1 -0
  22. package/dist/line-flow/bus.d.ts +13 -0
  23. package/dist/line-flow/bus.js +52 -0
  24. package/dist/line-flow/bus.js.map +1 -0
  25. package/dist/line-flow/derived-line.d.ts +21 -0
  26. package/dist/line-flow/derived-line.js +122 -0
  27. package/dist/line-flow/derived-line.js.map +1 -0
  28. package/dist/line-flow/errors.d.ts +62 -0
  29. package/dist/line-flow/errors.js +91 -0
  30. package/dist/line-flow/errors.js.map +1 -0
  31. package/dist/line-flow/event-line.d.ts +16 -0
  32. package/dist/line-flow/event-line.js +81 -0
  33. package/dist/line-flow/event-line.js.map +1 -0
  34. package/dist/line-flow/index.d.ts +11 -0
  35. package/dist/line-flow/index.js +11 -0
  36. package/dist/line-flow/index.js.map +1 -0
  37. package/dist/line-flow/interchange.d.ts +17 -0
  38. package/dist/line-flow/interchange.js +86 -0
  39. package/dist/line-flow/interchange.js.map +1 -0
  40. package/dist/line-flow/lineflow.d.ts +12 -0
  41. package/dist/line-flow/lineflow.js +15 -0
  42. package/dist/line-flow/lineflow.js.map +1 -0
  43. package/dist/line-flow/network.d.ts +28 -0
  44. package/dist/line-flow/network.js +165 -0
  45. package/dist/line-flow/network.js.map +1 -0
  46. package/dist/line-flow/react/bridge.d.ts +23 -0
  47. package/dist/line-flow/react/bridge.js +40 -0
  48. package/dist/line-flow/react/bridge.js.map +1 -0
  49. package/dist/line-flow/react/hooks.d.ts +29 -0
  50. package/dist/line-flow/react/hooks.js +117 -0
  51. package/dist/line-flow/react/hooks.js.map +1 -0
  52. package/dist/line-flow/react/index.d.ts +3 -0
  53. package/dist/line-flow/react/index.js +4 -0
  54. package/dist/line-flow/react/index.js.map +1 -0
  55. package/dist/line-flow/react/provider.d.ts +15 -0
  56. package/dist/line-flow/react/provider.js +25 -0
  57. package/dist/line-flow/react/provider.js.map +1 -0
  58. package/dist/line-flow/scope.d.ts +21 -0
  59. package/dist/line-flow/scope.js +157 -0
  60. package/dist/line-flow/scope.js.map +1 -0
  61. package/dist/line-flow/state-line.d.ts +21 -0
  62. package/dist/line-flow/state-line.js +106 -0
  63. package/dist/line-flow/state-line.js.map +1 -0
  64. package/dist/line-flow/taxi.d.ts +15 -0
  65. package/dist/line-flow/taxi.js +81 -0
  66. package/dist/line-flow/taxi.js.map +1 -0
  67. package/dist/line-flow/types.d.ts +222 -0
  68. package/dist/line-flow/types.js +2 -0
  69. package/dist/line-flow/types.js.map +1 -0
  70. package/dist/line-flow/utils.d.ts +24 -0
  71. package/dist/line-flow/utils.js +53 -0
  72. package/dist/line-flow/utils.js.map +1 -0
  73. package/dist/paramsSerializer.d.ts +87 -0
  74. package/dist/paramsSerializer.js +138 -0
  75. package/dist/paramsSerializer.js.map +1 -0
  76. package/dist/registry.d.ts +10 -0
  77. package/dist/registry.js +115 -0
  78. package/dist/registry.js.map +1 -0
  79. package/dist/runtime.d.ts +80 -0
  80. package/dist/runtime.js +442 -0
  81. package/dist/runtime.js.map +1 -0
  82. package/dist/schemas.d.ts +88 -0
  83. package/dist/schemas.js +146 -0
  84. package/dist/schemas.js.map +1 -0
  85. package/dist/services.d.ts +35 -0
  86. package/dist/services.js +65 -0
  87. package/dist/services.js.map +1 -0
  88. package/dist/shared-types/file.types.d.ts +12 -0
  89. package/dist/shared-types/file.types.js +2 -0
  90. package/dist/shared-types/file.types.js.map +1 -0
  91. package/dist/shared-types/gallery.types.d.ts +22 -0
  92. package/dist/shared-types/gallery.types.js +2 -0
  93. package/dist/shared-types/gallery.types.js.map +1 -0
  94. package/dist/shared-types/governorates.types.d.ts +12 -0
  95. package/dist/shared-types/governorates.types.js +2 -0
  96. package/dist/shared-types/governorates.types.js.map +1 -0
  97. package/dist/shared-types/grade.types.d.ts +7 -0
  98. package/dist/shared-types/grade.types.js +2 -0
  99. package/dist/shared-types/grade.types.js.map +1 -0
  100. package/dist/shared-types/index.d.ts +13 -0
  101. package/dist/shared-types/index.js +14 -0
  102. package/dist/shared-types/index.js.map +1 -0
  103. package/dist/shared-types/metadata.types.d.ts +61 -0
  104. package/dist/shared-types/metadata.types.js +3 -0
  105. package/dist/shared-types/metadata.types.js.map +1 -0
  106. package/dist/shared-types/table.types.d.ts +33 -0
  107. package/dist/shared-types/table.types.js +2 -0
  108. package/dist/shared-types/table.types.js.map +1 -0
  109. package/dist/shared-types/viewCard.types.d.ts +78 -0
  110. package/dist/shared-types/viewCard.types.js +3 -0
  111. package/dist/shared-types/viewCard.types.js.map +1 -0
  112. package/dist/styles.css +347 -0
  113. package/dist/types.d.ts +126 -0
  114. package/dist/types.js +19 -0
  115. package/dist/types.js.map +1 -0
  116. package/dist/utils/conditionCompiler.d.ts +11 -0
  117. package/dist/utils/conditionCompiler.js +18 -0
  118. package/dist/utils/conditionCompiler.js.map +1 -0
  119. package/dist/utils/fileUtils.d.ts +50 -0
  120. package/dist/utils/fileUtils.js +266 -0
  121. package/dist/utils/fileUtils.js.map +1 -0
  122. package/dist/utils/metadataUtils.d.ts +35 -0
  123. package/dist/utils/metadataUtils.js +176 -0
  124. package/dist/utils/metadataUtils.js.map +1 -0
  125. package/dist/utils/normalizeTime.d.ts +1 -0
  126. package/dist/utils/normalizeTime.js +25 -0
  127. package/dist/utils/normalizeTime.js.map +1 -0
  128. package/dist/utils/tableUtils.d.ts +9 -0
  129. package/dist/utils/tableUtils.js +92 -0
  130. package/dist/utils/tableUtils.js.map +1 -0
  131. package/dist/utils/toFormData.d.ts +152 -0
  132. package/dist/utils/toFormData.js +250 -0
  133. package/dist/utils/toFormData.js.map +1 -0
  134. package/dist/utils/wizard.utils.d.ts +420 -0
  135. package/dist/utils/wizard.utils.js +596 -0
  136. package/dist/utils/wizard.utils.js.map +1 -0
  137. package/package.json +49 -3
  138. package/README.md +0 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taxi.js","sourceRoot":"","sources":["../../src/line-flow/taxi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Supported line kinds.
3
+ */
4
+ export type LineKind = "state" | "event" | "derived";
5
+ /**
6
+ * Equality comparison function.
7
+ */
8
+ export type EqualityFn<T> = (prev: T, next: T) => boolean;
9
+ /**
10
+ * Function invoked to cancel an active subscription or unregister a resource.
11
+ */
12
+ export type Unsubscribe = () => void;
13
+ /**
14
+ * Listener function called with state updates or published events.
15
+ */
16
+ export type Listener<T> = (value: T) => void;
17
+ /**
18
+ * A resource or function that can be disposed of.
19
+ */
20
+ export type Disposable = {
21
+ dispose: () => void;
22
+ } | (() => void);
23
+ /**
24
+ * Base read-only interface implemented by lines that retain a snapshot (StateLine and DerivedLine).
25
+ */
26
+ export interface ReadableLine<T> {
27
+ readonly id: string;
28
+ readonly kind: "state" | "derived";
29
+ getSnapshot(): T;
30
+ subscribe(listener: Listener<T>): Unsubscribe;
31
+ dispose(): void;
32
+ readonly isDisposed: boolean;
33
+ }
34
+ /**
35
+ * A persistent state line.
36
+ */
37
+ export interface StateLine<T> extends ReadableLine<T> {
38
+ readonly kind: "state";
39
+ set(value: T): void;
40
+ update(updater: (prev: T) => T): void;
41
+ }
42
+ /**
43
+ * An ephemeral event line.
44
+ */
45
+ export interface EventLine<T> {
46
+ readonly id: string;
47
+ readonly kind: "event";
48
+ publish(event: T): void;
49
+ subscribe(listener: Listener<T>): Unsubscribe;
50
+ dispose(): void;
51
+ readonly isDisposed: boolean;
52
+ }
53
+ /**
54
+ * Any line that retains a snapshot and allows reading and subscriptions.
55
+ */
56
+ export type AnyStateLine = ReadableLine<any>;
57
+ /**
58
+ * Any line registered in the LineFlow network.
59
+ */
60
+ export type AnyLine = StateLine<any> | EventLine<any> | DerivedLine<any>;
61
+ /**
62
+ * Extracts the snapshot value type from a readable line.
63
+ */
64
+ export type LineSnapshot<TLine> = TLine extends ReadableLine<infer T> ? T : never;
65
+ /**
66
+ * Extracts a tuple of snapshot value types from a tuple/array of readable lines.
67
+ */
68
+ export type LinesSnapshots<TLines extends readonly AnyStateLine[]> = {
69
+ readonly [K in keyof TLines]: LineSnapshot<TLines[K]>;
70
+ };
71
+ /**
72
+ * A read-only derived line whose snapshot is computed from one or more source lines.
73
+ */
74
+ export interface DerivedLine<T> extends ReadableLine<T> {
75
+ readonly kind: "derived";
76
+ readonly sources: readonly AnyStateLine[];
77
+ }
78
+ /**
79
+ * Options for creating a StateLine.
80
+ */
81
+ export interface StateLineOptions<T> {
82
+ id: string;
83
+ initialValue: T;
84
+ equals?: EqualityFn<T> | undefined;
85
+ }
86
+ /**
87
+ * Options for creating an EventLine.
88
+ */
89
+ export interface EventLineOptions<T = void> {
90
+ id: string;
91
+ _phantom?: ((value: T) => void) | undefined;
92
+ }
93
+ /**
94
+ * Options for creating a DerivedLine.
95
+ */
96
+ export interface DeriveLineOptions<T, TDeps extends readonly AnyStateLine[]> {
97
+ id: string;
98
+ sources: TDeps;
99
+ derive: (snapshots: LinesSnapshots<TDeps>) => T;
100
+ equals?: EqualityFn<T> | undefined;
101
+ }
102
+ /**
103
+ * Options for creating an Interchange between two state lines.
104
+ */
105
+ export interface InterchangeOptions<TSource, TTarget> {
106
+ id?: string | undefined;
107
+ from: ReadableLine<TSource>;
108
+ to: StateLine<TTarget>;
109
+ transform: (sourceSnapshot: TSource) => TTarget;
110
+ equals?: EqualityFn<TTarget> | undefined;
111
+ }
112
+ /**
113
+ * Represents an active directional relationship between lines.
114
+ */
115
+ export interface Interchange {
116
+ readonly id: string;
117
+ readonly isDisposed: boolean;
118
+ dispose(): void;
119
+ }
120
+ /**
121
+ * Feature-scoped message bus.
122
+ */
123
+ export interface Bus<TMessageMap extends object = Record<string, unknown>> {
124
+ readonly id: string;
125
+ readonly isDisposed: boolean;
126
+ publish<K extends keyof TMessageMap & string>(channel: K, payload: TMessageMap[K]): void;
127
+ subscribe<K extends keyof TMessageMap & string>(channel: K, listener: (payload: TMessageMap[K]) => void): Unsubscribe;
128
+ dispose(): void;
129
+ }
130
+ /**
131
+ * Options for creating a Bus.
132
+ */
133
+ export interface BusOptions {
134
+ id?: string | undefined;
135
+ }
136
+ /**
137
+ * Handler for a Taxi task.
138
+ */
139
+ export type TaxiHandler<TReq, TRes> = (req: TReq, signal?: AbortSignal | undefined) => Promise<TRes> | TRes;
140
+ /**
141
+ * Single task request/response contract.
142
+ */
143
+ export interface TaskContract<TRequest = any, TResponse = any> {
144
+ request: TRequest;
145
+ response: TResponse;
146
+ }
147
+ /**
148
+ * Taxi task contract map.
149
+ */
150
+ export type TaxiTaskMap = Record<string, TaskContract>;
151
+ /**
152
+ * Typed request/response handler service.
153
+ */
154
+ export interface Taxi<TTaskMap extends {
155
+ [K in keyof TTaskMap]: TaskContract;
156
+ } = TaxiTaskMap> {
157
+ readonly id: string;
158
+ readonly isDisposed: boolean;
159
+ register<K extends keyof TTaskMap & string>(task: K, handler: TaxiHandler<TTaskMap[K]["request"], TTaskMap[K]["response"]>): Unsubscribe;
160
+ request<K extends keyof TTaskMap & string>(task: K, req: TTaskMap[K]["request"], options?: {
161
+ signal?: AbortSignal | undefined;
162
+ } | undefined): Promise<TTaskMap[K]["response"]>;
163
+ hasHandler<K extends keyof TTaskMap & string>(task: K): boolean;
164
+ dispose(): void;
165
+ }
166
+ /**
167
+ * Options for creating a Taxi.
168
+ */
169
+ export interface TaxiOptions {
170
+ id?: string | undefined;
171
+ }
172
+ /**
173
+ * Scoped lifecycle boundary for managing lines and resources.
174
+ */
175
+ export interface Scope {
176
+ readonly id: string;
177
+ readonly isDisposed: boolean;
178
+ registerDisposable(disposable: Disposable): Unsubscribe;
179
+ stateLine<T>(options: StateLineOptions<T>): StateLine<T>;
180
+ eventLine<T = void>(options: EventLineOptions<T>): EventLine<T>;
181
+ deriveLine<T, const TDeps extends readonly AnyStateLine[]>(options: DeriveLineOptions<T, TDeps>): DerivedLine<T>;
182
+ bus<TMessageMap extends object = Record<string, unknown>>(options?: BusOptions): Bus<TMessageMap>;
183
+ taxi<TTaskMap extends {
184
+ [K in keyof TTaskMap]: TaskContract;
185
+ } = TaxiTaskMap>(options?: TaxiOptions): Taxi<TTaskMap>;
186
+ createChildScope(id: string): Scope;
187
+ dispose(): void;
188
+ }
189
+ /**
190
+ * Options for creating a Scope.
191
+ */
192
+ export interface ScopeOptions {
193
+ id?: string | undefined;
194
+ }
195
+ /**
196
+ * Network instance options.
197
+ */
198
+ export interface LineFlowOptions {
199
+ name?: string | undefined;
200
+ }
201
+ /**
202
+ * The runtime LineFlow network owning lines and registries.
203
+ */
204
+ export interface LineFlowNetwork {
205
+ readonly name: string;
206
+ readonly isDisposed: boolean;
207
+ stateLine<T>(options: StateLineOptions<T>): StateLine<T>;
208
+ eventLine<T = void>(options: EventLineOptions<T>): EventLine<T>;
209
+ deriveLine<T, const TDeps extends readonly AnyStateLine[]>(options: DeriveLineOptions<T, TDeps>): DerivedLine<T>;
210
+ createInterchange<TSource, TTarget>(options: InterchangeOptions<TSource, TTarget>): Interchange;
211
+ createScope(options?: ScopeOptions): Scope;
212
+ bus<TMessageMap extends object = Record<string, unknown>>(options?: BusOptions): Bus<TMessageMap>;
213
+ taxi<TTaskMap extends {
214
+ [K in keyof TTaskMap]: TaskContract;
215
+ } = TaxiTaskMap>(options?: TaxiOptions): Taxi<TTaskMap>;
216
+ getLine(id: string): AnyLine | undefined;
217
+ hasLine(id: string): boolean;
218
+ getAllLines(): readonly AnyLine[];
219
+ dispose(): void;
220
+ }
221
+ export type LineflowOptions = LineFlowOptions;
222
+ export type LineflowNetwork = LineFlowNetwork;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/line-flow/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ import type { EqualityFn, Listener } from "./types.js";
2
+ /**
3
+ * Validates that an ID is a non-empty string.
4
+ */
5
+ export declare function validateId(id: unknown, context?: string): string;
6
+ /**
7
+ * Validates that a listener is a function.
8
+ */
9
+ export declare function validateListener(listener: unknown): asserts listener is (arg: any) => void;
10
+ /**
11
+ * Default equality function using Object.is.
12
+ */
13
+ export declare const defaultEquals: EqualityFn<any>;
14
+ /**
15
+ * Safely dispatches a value to a set of listeners.
16
+ *
17
+ * Guarantees:
18
+ * 1. Subscribers receive notifications in order of registration.
19
+ * 2. Unsubscribing a listener during dispatch takes effect immediately for that tick.
20
+ * 3. Adding a new listener during dispatch does not invoke it during the current tick.
21
+ * 4. If any listener throws an error, all other eligible listeners are still executed.
22
+ * 5. All thrown errors are collected and raised in a single LineFlowSubscriberError.
23
+ */
24
+ export declare function notifyListeners<T>(listeners: ReadonlySet<Listener<T>>, value: T, contextDescription: string): void;
@@ -0,0 +1,53 @@
1
+ import { LineFlowSubscriberError, LineFlowValidationError } from "./errors.js";
2
+ /**
3
+ * Validates that an ID is a non-empty string.
4
+ */
5
+ export function validateId(id, context = "line") {
6
+ if (typeof id !== "string" || id.trim().length === 0) {
7
+ throw new LineFlowValidationError(`Invalid ${context} ID: expected a non-empty string, but received ${String(id)}.`);
8
+ }
9
+ return id;
10
+ }
11
+ /**
12
+ * Validates that a listener is a function.
13
+ */
14
+ export function validateListener(listener) {
15
+ if (typeof listener !== "function") {
16
+ throw new LineFlowValidationError(`Invalid listener: expected a function, but received ${typeof listener}.`);
17
+ }
18
+ }
19
+ /**
20
+ * Default equality function using Object.is.
21
+ */
22
+ export const defaultEquals = (a, b) => Object.is(a, b);
23
+ /**
24
+ * Safely dispatches a value to a set of listeners.
25
+ *
26
+ * Guarantees:
27
+ * 1. Subscribers receive notifications in order of registration.
28
+ * 2. Unsubscribing a listener during dispatch takes effect immediately for that tick.
29
+ * 3. Adding a new listener during dispatch does not invoke it during the current tick.
30
+ * 4. If any listener throws an error, all other eligible listeners are still executed.
31
+ * 5. All thrown errors are collected and raised in a single LineFlowSubscriberError.
32
+ */
33
+ export function notifyListeners(listeners, value, contextDescription) {
34
+ if (listeners.size === 0)
35
+ return;
36
+ const errors = [];
37
+ const snapshot = Array.from(listeners);
38
+ for (const listener of snapshot) {
39
+ if (!listeners.has(listener)) {
40
+ continue;
41
+ }
42
+ try {
43
+ listener(value);
44
+ }
45
+ catch (err) {
46
+ errors.push(err);
47
+ }
48
+ }
49
+ if (errors.length > 0) {
50
+ throw new LineFlowSubscriberError(`Error(s) encountered in subscriber(s) during ${contextDescription}`, errors);
51
+ }
52
+ }
53
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/line-flow/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAG/E;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,EAAW,EAAE,OAAO,GAAG,MAAM;IACtD,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,uBAAuB,CAC/B,WAAW,OAAO,kDAAkD,MAAM,CAAC,EAAE,CAAC,GAAG,CAClF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAiB;IAChD,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;QACnC,MAAM,IAAI,uBAAuB,CAC/B,uDAAuD,OAAO,QAAQ,GAAG,CAC1E,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAExE;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,SAAmC,EACnC,KAAQ,EACR,kBAA0B;IAE1B,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO;IAEjC,MAAM,MAAM,GAAc,EAAE,CAAC;IAC7B,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEvC,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;QAChC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,QAAQ,CAAC,KAAK,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,uBAAuB,CAC/B,gDAAgD,kBAAkB,EAAE,EACpE,MAAM,CACP,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Advanced Params Serializer
3
+ *
4
+ * Serializes complex query parameters including:
5
+ * - Nested objects: filters[status]=active
6
+ * - Arrays: ids[]=1&ids[]=2
7
+ * - Sort objects: sort[field]=name&sort[order]=asc
8
+ * - Pagination: page=1&per_page=10
9
+ * - Date ranges: date[from]=2024-01-01&date[to]=2024-12-31
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * serializeParams({
14
+ * page: 1,
15
+ * filters: { status: 'active', types: ['a', 'b'] },
16
+ * sort: { field: 'name', order: 'asc' }
17
+ * });
18
+ * // Returns: "page=1&filters[status]=active&filters[types][]=a&filters[types][]=b&sort[field]=name&sort[order]=asc"
19
+ * ```
20
+ */
21
+ export type ParamValue = string | number | boolean | null | undefined | Date | ParamValue[] | {
22
+ [key: string]: ParamValue;
23
+ };
24
+ export interface SerializerOptions {
25
+ /**
26
+ * Array format: 'brackets' for key[]=value, 'indices' for key[0]=value, 'repeat' for key=value&key=value
27
+ * @default 'brackets'
28
+ */
29
+ arrayFormat?: "brackets" | "indices" | "repeat";
30
+ /**
31
+ * Whether to encode keys and values
32
+ * @default true
33
+ */
34
+ encode?: boolean;
35
+ /**
36
+ * Whether to skip null/undefined values
37
+ * @default true
38
+ */
39
+ skipNull?: boolean;
40
+ /**
41
+ * Whether to skip empty strings
42
+ * @default true
43
+ */
44
+ skipEmpty?: boolean;
45
+ }
46
+ /**
47
+ * Serialize an object of parameters into a query string
48
+ *
49
+ * @param params - The parameters object to serialize
50
+ * @param options - Serialization options
51
+ * @returns The serialized query string (without leading ?)
52
+ */
53
+ export declare const serializeParams: (params?: Record<string, ParamValue>, options?: SerializerOptions) => string;
54
+ /**
55
+ * Create an Axios-compatible params serializer function
56
+ */
57
+ export declare const createParamsSerializer: (options?: SerializerOptions) => (params: Record<string, ParamValue>) => string;
58
+ /**
59
+ * Standard pagination params interface
60
+ */
61
+ export interface PaginationParams {
62
+ page?: number;
63
+ perPage?: number;
64
+ per_page?: number;
65
+ }
66
+ /**
67
+ * Standard sort params interface
68
+ */
69
+ export interface SortParams {
70
+ sortBy?: string;
71
+ sortOrder?: "asc" | "desc";
72
+ sort?: {
73
+ field?: string;
74
+ order?: "asc" | "desc";
75
+ };
76
+ }
77
+ /**
78
+ * Standard filter params interface (generic)
79
+ */
80
+ export interface FilterParams<T = Record<string, ParamValue>> {
81
+ filters?: T;
82
+ search?: string;
83
+ }
84
+ /**
85
+ * Combined query params type for list endpoints
86
+ */
87
+ export type ListQueryParams<TFilters = Record<string, ParamValue>> = PaginationParams & SortParams & FilterParams<TFilters>;
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Advanced Params Serializer
3
+ *
4
+ * Serializes complex query parameters including:
5
+ * - Nested objects: filters[status]=active
6
+ * - Arrays: ids[]=1&ids[]=2
7
+ * - Sort objects: sort[field]=name&sort[order]=asc
8
+ * - Pagination: page=1&per_page=10
9
+ * - Date ranges: date[from]=2024-01-01&date[to]=2024-12-31
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * serializeParams({
14
+ * page: 1,
15
+ * filters: { status: 'active', types: ['a', 'b'] },
16
+ * sort: { field: 'name', order: 'asc' }
17
+ * });
18
+ * // Returns: "page=1&filters[status]=active&filters[types][]=a&filters[types][]=b&sort[field]=name&sort[order]=asc"
19
+ * ```
20
+ */
21
+ const defaultOptions = {
22
+ arrayFormat: "brackets",
23
+ encode: true,
24
+ skipNull: true,
25
+ skipEmpty: true,
26
+ };
27
+ /**
28
+ * Serialize a single value with proper encoding
29
+ */
30
+ const encodeValue = (value, encode) => {
31
+ const stringValue = String(value);
32
+ if (!encode)
33
+ return stringValue;
34
+ return encodeURIComponent(stringValue)
35
+ .replace(/%3D/g, "=")
36
+ .replace(/%3E/g, ">")
37
+ .replace(/%3C/g, "<");
38
+ };
39
+ /**
40
+ * Serialize a key with proper encoding, keeping square brackets unencoded
41
+ */
42
+ const encodeKey = (key, encode) => {
43
+ if (!encode)
44
+ return key;
45
+ return encodeURIComponent(key).replace(/%5B/g, "[").replace(/%5D/g, "]");
46
+ };
47
+ /**
48
+ * Build a nested key path like "filters[status]" or "filters[types][]"
49
+ */
50
+ const buildKey = (prefix, key, isArrayItem, arrayFormat, index) => {
51
+ if (!prefix) {
52
+ return key;
53
+ }
54
+ if (isArrayItem) {
55
+ switch (arrayFormat) {
56
+ case "indices":
57
+ return `${prefix}[${index}]`;
58
+ case "repeat":
59
+ return prefix;
60
+ case "brackets":
61
+ default:
62
+ return `${prefix}[]`;
63
+ }
64
+ }
65
+ return `${prefix}[${key}]`;
66
+ };
67
+ /**
68
+ * Recursively serialize parameters with circular reference protection
69
+ */
70
+ const serializeValue = (key, value, options, parts, seen = new WeakSet()) => {
71
+ // Skip null/undefined
72
+ if (value === null || value === undefined) {
73
+ if (!options.skipNull) {
74
+ parts.push(`${encodeKey(key, options.encode)}=`);
75
+ }
76
+ return;
77
+ }
78
+ // Skip empty strings
79
+ if (value === "" && options.skipEmpty) {
80
+ return;
81
+ }
82
+ // Handle Date objects
83
+ if (value instanceof Date) {
84
+ parts.push(`${encodeKey(key, options.encode)}=${encodeValue(value.toISOString(), options.encode)}`);
85
+ return;
86
+ }
87
+ // Handle arrays
88
+ if (Array.isArray(value)) {
89
+ value.forEach((item, index) => {
90
+ const arrayKey = buildKey(key, "", true, options.arrayFormat, index);
91
+ serializeValue(arrayKey, item, options, parts, seen);
92
+ });
93
+ return;
94
+ }
95
+ // Handle objects (nested params)
96
+ if (typeof value === "object") {
97
+ // Circular reference protection
98
+ if (seen.has(value)) {
99
+ console.warn(`[paramsSerializer] Circular reference detected for key "${key}", skipping`);
100
+ return;
101
+ }
102
+ seen.add(value);
103
+ Object.entries(value).forEach(([nestedKey, nestedValue]) => {
104
+ const fullKey = buildKey(key, nestedKey, false, options.arrayFormat);
105
+ serializeValue(fullKey, nestedValue, options, parts, seen);
106
+ });
107
+ return;
108
+ }
109
+ // Handle primitives (string, number, boolean)
110
+ parts.push(`${encodeKey(key, options.encode)}=${encodeValue(value, options.encode)}`);
111
+ };
112
+ /**
113
+ * Serialize an object of parameters into a query string
114
+ *
115
+ * @param params - The parameters object to serialize
116
+ * @param options - Serialization options
117
+ * @returns The serialized query string (without leading ?)
118
+ */
119
+ export const serializeParams = (params, options) => {
120
+ if (!params || Object.keys(params).length === 0) {
121
+ return "";
122
+ }
123
+ const mergedOptions = { ...defaultOptions, ...options };
124
+ const parts = [];
125
+ Object.entries(params).forEach(([key, value]) => {
126
+ serializeValue(key, value, mergedOptions, parts);
127
+ });
128
+ return parts.join("&");
129
+ };
130
+ /**
131
+ * Create an Axios-compatible params serializer function
132
+ */
133
+ export const createParamsSerializer = (options) => {
134
+ return (params) => {
135
+ return serializeParams(params, options);
136
+ };
137
+ };
138
+ //# sourceMappingURL=paramsSerializer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paramsSerializer.js","sourceRoot":"","sources":["../src/paramsSerializer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Manifest, Registry } from "./types";
2
+ export declare const normalizePath: (value: string) => string;
3
+ export declare const joinPath: (...parts: string[]) => string;
4
+ export declare function createRegistry(manifest: Manifest, layouts: string[]): Registry;
5
+ export declare function createPaths(base: string): {
6
+ main: string;
7
+ create: () => string;
8
+ detail: (id: string | number) => string;
9
+ edit: (id: string | number) => string;
10
+ };
@@ -0,0 +1,115 @@
1
+ export const normalizePath = (value) => "/" + value.split("/").filter(Boolean).join("/");
2
+ export const joinPath = (...parts) => normalizePath(parts.join("/"));
3
+ const ownerDir = (file) => file.replaceAll("\\", "/").replace(/\/navigation\/index\.[jt]sx?$/, "");
4
+ export function createRegistry(manifest, layouts) {
5
+ const modules = [];
6
+ const ids = new Set();
7
+ for (const { file, definition } of manifest.definitions) {
8
+ if (!definition || !["module", "feature"].includes(definition.kind))
9
+ throw new Error(`GoStack: ${file} must default-export defineModule() or defineFeature().`);
10
+ if (definition.kind !== "module")
11
+ continue;
12
+ if (ids.has(definition.id))
13
+ throw new Error(`GoStack: duplicate module "${definition.id}" in ${file}.`);
14
+ ids.add(definition.id);
15
+ if (!layouts.includes(definition.layout))
16
+ throw new Error(`GoStack: unknown layout "${definition.layout}" in ${file}. Available: ${layouts.join(", ")}.`);
17
+ modules.push({ dir: ownerDir(file), definition });
18
+ }
19
+ const features = [];
20
+ const disabledSources = [];
21
+ const featureIds = new Set();
22
+ const routePaths = new Map();
23
+ for (const { file, definition } of manifest.definitions) {
24
+ if (definition.kind !== "feature")
25
+ continue;
26
+ const dir = ownerDir(file);
27
+ const hierarchy = modules
28
+ .filter((m) => dir.startsWith(m.dir + "/"))
29
+ .sort((a, b) => a.dir.length - b.dir.length);
30
+ const parent = hierarchy.at(-1);
31
+ if (!parent)
32
+ throw new Error(`GoStack: feature ${file} has no containing module navigation/index.ts.`);
33
+ const qualifiedId = `${parent.definition.id}/${definition.id}`;
34
+ if (featureIds.has(qualifiedId))
35
+ throw new Error(`GoStack: duplicate feature "${qualifiedId}" in ${file}.`);
36
+ featureIds.add(qualifiedId);
37
+ const layout = definition.layout ?? parent.definition.layout;
38
+ if (!layouts.includes(layout))
39
+ throw new Error(`GoStack: unknown layout "${layout}" in ${file}.`);
40
+ if (definition.enabled === false ||
41
+ hierarchy.some((m) => m.definition.enabled === false)) {
42
+ disabledSources.push(dir);
43
+ continue;
44
+ }
45
+ const base = joinPath(parent.definition.basePath, definition.basePath);
46
+ const visit = (routes, prefix) => {
47
+ for (const route of routes) {
48
+ if (route.index && (route.path !== undefined || route.children))
49
+ throw new Error(`GoStack: index route cannot have path or children in ${file}.`);
50
+ if (route.path?.startsWith("/"))
51
+ throw new Error(`GoStack: feature routes must use relative paths in ${file}.`);
52
+ const full = joinPath(prefix, route.path ?? "");
53
+ if (!route.children?.length || route.index) {
54
+ const signature = full.replace(/:[^/]+/g, ":param").toLowerCase();
55
+ if (routePaths.has(signature))
56
+ throw new Error(`GoStack: conflicting route "${full}" in ${file} and ${routePaths.get(signature)}.`);
57
+ routePaths.set(signature, file);
58
+ }
59
+ if (route.children)
60
+ visit(route.children, full);
61
+ }
62
+ };
63
+ visit(definition.routes, base);
64
+ features.push({
65
+ ...definition,
66
+ module: parent.definition,
67
+ ancestors: hierarchy.slice(0, -1).map((m) => m.definition),
68
+ qualifiedId,
69
+ namespace: qualifiedId.replaceAll("/", "."),
70
+ source: dir,
71
+ });
72
+ }
73
+ const resources = {};
74
+ for (const locale of manifest.locales) {
75
+ const file = locale.file.replaceAll("\\", "/");
76
+ if (disabledSources.some((dir) => file.startsWith(dir + "/")))
77
+ continue;
78
+ const match = file.match(/\/(?:locales|locals)\/([\w-]+)\.json$/);
79
+ if (!match)
80
+ continue;
81
+ const feature = features
82
+ .filter((f) => file.startsWith(f.source + "/"))
83
+ .sort((a, b) => b.source.length - a.source.length)[0];
84
+ const module = modules
85
+ .filter((m) => file.startsWith(m.dir + "/"))
86
+ .sort((a, b) => b.dir.length - a.dir.length)[0];
87
+ const namespace = feature?.namespace ??
88
+ (file.includes("/design-system/")
89
+ ? "designSystem"
90
+ : module
91
+ ? module.definition.id.replaceAll("/", ".")
92
+ : "shared");
93
+ const language = match[1];
94
+ resources[language] ??= {};
95
+ if (resources[language][namespace])
96
+ throw new Error(`GoStack: duplicate translation namespace "${namespace}" for ${language}: ${file}.`);
97
+ resources[language][namespace] = locale.data;
98
+ }
99
+ return {
100
+ modules: modules
101
+ .map((m) => m.definition)
102
+ .filter((m) => m.enabled !== false),
103
+ features,
104
+ resources,
105
+ };
106
+ }
107
+ export function createPaths(base) {
108
+ return {
109
+ main: normalizePath(base),
110
+ create: () => joinPath(base, "create"),
111
+ detail: (id) => joinPath(base, encodeURIComponent(String(id))),
112
+ edit: (id) => joinPath(base, encodeURIComponent(String(id)), "edit"),
113
+ };
114
+ }
115
+ //# sourceMappingURL=registry.js.map