akanjs 2.0.6 → 2.0.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.
Files changed (45) hide show
  1. package/README.ko.md +1 -1
  2. package/README.md +1 -1
  3. package/cli/application/application.command.ts +4 -1
  4. package/cli/application/application.runner.ts +5 -7
  5. package/cli/build.ts +1 -0
  6. package/cli/index.js +114 -74
  7. package/constant/serialize.ts +1 -1
  8. package/devkit/capacitor.base.config.ts +18 -4
  9. package/devkit/capacitorApp.ts +118 -64
  10. package/devkit/mobile/mobileTarget.ts +2 -1
  11. package/devkit/scanInfo.ts +1 -0
  12. package/package.json +1 -1
  13. package/server/akanApp.ts +53 -12
  14. package/server/processMetricsCollector.ts +79 -1
  15. package/server/resolver/database.resolver.ts +82 -31
  16. package/server/resolver/signal.resolver.ts +67 -28
  17. package/service/ipcTypes.ts +5 -0
  18. package/service/predefinedAdaptor/database.adaptor.ts +95 -27
  19. package/service/predefinedAdaptor/solidSqlite.ts +7 -7
  20. package/service/predefinedAdaptor/storage.adaptor.ts +35 -9
  21. package/signal/index.ts +1 -0
  22. package/signal/middleware.ts +5 -1
  23. package/signal/signalContext.ts +85 -31
  24. package/signal/trace.ts +279 -0
  25. package/types/devkit/capacitorApp.d.ts +14 -5
  26. package/types/server/processMetricsCollector.d.ts +2 -0
  27. package/types/service/ipcTypes.d.ts +5 -0
  28. package/types/service/predefinedAdaptor/database.adaptor.d.ts +26 -32
  29. package/types/service/predefinedAdaptor/solidSqlite.d.ts +3 -3
  30. package/types/service/predefinedAdaptor/storage.adaptor.d.ts +8 -2
  31. package/types/signal/index.d.ts +1 -0
  32. package/types/signal/signalContext.d.ts +4 -1
  33. package/types/signal/trace.d.ts +97 -0
  34. package/types/ui/Signal/style.d.ts +15 -0
  35. package/ui/Signal/Arg.tsx +22 -15
  36. package/ui/Signal/Doc.tsx +28 -21
  37. package/ui/Signal/Listener.tsx +15 -39
  38. package/ui/Signal/Message.tsx +32 -50
  39. package/ui/Signal/Object.tsx +16 -13
  40. package/ui/Signal/PubSub.tsx +29 -47
  41. package/ui/Signal/Response.tsx +7 -17
  42. package/ui/Signal/RestApi.tsx +41 -57
  43. package/ui/Signal/WebSocket.tsx +1 -1
  44. package/ui/Signal/style.ts +36 -0
  45. package/webkit/useCsrValues.ts +147 -37
@@ -67,33 +67,20 @@ export interface DocumentStore {
67
67
  modifiedCount: number;
68
68
  upsertedId: string | null;
69
69
  }>;
70
- find(query?: DocumentQuery, options?: {
71
- sort?: SortOption;
72
- skip?: number | null;
73
- limit?: number | null;
74
- sample?: number;
75
- }): Promise<any[]>;
70
+ find(query?: DocumentQuery, options?: FindManyOptions): Promise<any[]>;
76
71
  findIds(query?: DocumentQuery, options?: {
77
72
  sort?: SortOption;
78
73
  skip?: number | null;
79
74
  limit?: number | null;
80
75
  sample?: number;
81
76
  }): Promise<string[]>;
82
- findOne(query?: DocumentQuery, options?: {
83
- sort?: SortOption;
84
- skip?: number | null;
85
- sample?: boolean;
86
- }): Promise<any | null>;
77
+ findOne(query?: DocumentQuery, options?: FindOneOptions): Promise<any | null>;
87
78
  findId(query?: DocumentQuery, options?: {
88
79
  sort?: SortOption;
89
80
  skip?: number | null;
90
81
  sample?: boolean;
91
82
  }): Promise<string | null>;
92
- pickOne(query?: DocumentQuery, options?: {
93
- sort?: SortOption;
94
- skip?: number | null;
95
- sample?: boolean;
96
- }): Promise<any>;
83
+ pickOne(query?: DocumentQuery, options?: FindOneOptions): Promise<any>;
97
84
  pickById(id: string): Promise<any>;
98
85
  exists(query?: DocumentQuery): Promise<string | null>;
99
86
  count(query?: DocumentQuery): Promise<number>;
@@ -128,6 +115,20 @@ type FieldMap = Record<string, {
128
115
  [key: string]: unknown;
129
116
  }>;
130
117
  type SortOption = Record<string, 1 | -1> | null | undefined;
118
+ type ProjectionOption = Partial<Record<string, boolean>> | null | undefined;
119
+ type FindManyOptions = {
120
+ sort?: SortOption;
121
+ skip?: number | null;
122
+ limit?: number | null;
123
+ sample?: number;
124
+ select?: ProjectionOption;
125
+ };
126
+ type FindOneOptions = {
127
+ sort?: SortOption;
128
+ skip?: number | null;
129
+ sample?: boolean;
130
+ select?: ProjectionOption;
131
+ };
131
132
  interface DocumentDatabaseOwner {
132
133
  getConnection(): AkanSqlClient;
133
134
  getMeta(key: string): Promise<string | undefined> | string | undefined;
@@ -214,33 +215,20 @@ export declare class SqliteDocumentStore {
214
215
  modifiedCount: number;
215
216
  upsertedId: string | null;
216
217
  }>;
217
- find(query?: DocumentQuery, options?: {
218
- sort?: SortOption;
219
- skip?: number | null;
220
- limit?: number | null;
221
- sample?: number;
222
- }): Promise<any[]>;
218
+ find(query?: DocumentQuery, options?: FindManyOptions): Promise<any[]>;
223
219
  findIds(query?: DocumentQuery, options?: {
224
220
  sort?: SortOption;
225
221
  skip?: number | null;
226
222
  limit?: number | null;
227
223
  sample?: number;
228
224
  }): Promise<string[]>;
229
- findOne(query?: DocumentQuery, options?: {
230
- sort?: SortOption;
231
- skip?: number | null;
232
- sample?: boolean;
233
- }): Promise<any>;
225
+ findOne(query?: DocumentQuery, options?: FindOneOptions): Promise<any>;
234
226
  findId(query?: DocumentQuery, options?: {
235
227
  sort?: SortOption;
236
228
  skip?: number | null;
237
229
  sample?: boolean;
238
230
  }): Promise<string | null>;
239
- pickOne(query?: DocumentQuery, options?: {
240
- sort?: SortOption;
241
- skip?: number | null;
242
- sample?: boolean;
243
- }): Promise<any>;
231
+ pickOne(query?: DocumentQuery, options?: FindOneOptions): Promise<any>;
244
232
  pickById(id: string): Promise<any>;
245
233
  exists(query?: DocumentQuery): Promise<string | null>;
246
234
  count(query?: DocumentQuery): Promise<number>;
@@ -259,6 +247,11 @@ export declare class SqliteDocumentStore {
259
247
  private applyDocumentUpdate;
260
248
  private toRow;
261
249
  private fromRow;
250
+ private normalizeProjection;
251
+ private projectionSql;
252
+ private projectionAlias;
253
+ private fromProjectedRow;
254
+ private parseProjectedValue;
262
255
  private decodeDocumentPayload;
263
256
  private decodeFieldValue;
264
257
  private decodeMapValue;
@@ -266,6 +259,7 @@ export declare class SqliteDocumentStore {
266
259
  hydrate(data: DocumentRecord, originalData?: DocumentRecord): any;
267
260
  private runHooks;
268
261
  private insertStmt;
262
+ private prepareReadStmt;
269
263
  private assertValidRefName;
270
264
  }
271
265
  declare const SqliteDatabase_base: import("..").AdaptorCls<{}, {
@@ -13,12 +13,12 @@ export interface SolidEnv extends BaseEnv {
13
13
  workspaceRoot?: string;
14
14
  solid?: SolidConfig;
15
15
  }
16
- export type SolidValueType = "string" | "number" | "buffer";
16
+ export type SolidValueType = "string" | "number" | "buffer" | "json";
17
17
  export declare const getSolidConfig: (env: SolidEnv) => Required<SolidConfig>;
18
18
  export declare const openSolidDatabase: (config: Required<SolidConfig>) => Promise<Database>;
19
- export declare const encodeSolidValue: (value: string | number | Buffer) => {
19
+ export declare const encodeSolidValue: (value: unknown) => {
20
20
  type: SolidValueType;
21
21
  value: string | Buffer;
22
22
  };
23
- export declare const decodeSolidValue: <T extends string | number | Buffer>(type: SolidValueType, value: string | Buffer | null) => T | undefined;
23
+ export declare const decodeSolidValue: <T>(type: SolidValueType, value: string | Buffer | null) => T | undefined;
24
24
  export declare const toEpochMs: (value?: Dayjs | number | null) => number | null;
@@ -15,6 +15,7 @@ export interface UploadRequest {
15
15
  };
16
16
  rename?: string;
17
17
  host?: string;
18
+ access?: "public" | "private";
18
19
  }
19
20
  export interface CopyRequest {
20
21
  bucket: string;
@@ -28,6 +29,7 @@ export interface UploadFromStreamRequest {
28
29
  body: ReadableStream;
29
30
  mimetype: string;
30
31
  root?: string;
32
+ access?: "public" | "private";
31
33
  updateProgress: (progress: {
32
34
  loaded?: number;
33
35
  total?: number;
@@ -49,15 +51,18 @@ export interface StorageAdaptor {
49
51
  saveData(request: DownloadRequest): Promise<LocalFilePath>;
50
52
  copyData(request: CopyRequest): Promise<string>;
51
53
  deleteData(url: string): Promise<boolean>;
54
+ deleteDataByPath(path: string): Promise<boolean>;
52
55
  }
53
56
  export interface BlobStorageOptions extends BaseEnv {
54
57
  blobStorage?: {
55
58
  baseDir?: string;
59
+ privateBaseDir?: string;
56
60
  urlPrefix?: string;
57
61
  };
58
62
  }
59
63
  declare const BlobStorage_base: import("..").AdaptorCls<{}, {
60
64
  root: import("..").InjectInfo<"env", string, BlobStorageOptions, never>;
65
+ privateRoot: import("..").InjectInfo<"env", string, BlobStorageOptions, never>;
61
66
  urlPrefix: import("..").InjectInfo<"env", string | undefined, BlobStorageOptions, never>;
62
67
  }>;
63
68
  export declare class BlobStorage extends BlobStorage_base implements StorageAdaptor {
@@ -65,10 +70,11 @@ export declare class BlobStorage extends BlobStorage_base implements StorageAdap
65
70
  readData(path: string): Promise<ReadableStream>;
66
71
  readDataAsJson<T>(path: string): Promise<T>;
67
72
  getDataList(prefix?: string): Promise<string[]>;
68
- uploadDataFromLocal({ path, localPath, meta }: UploadRequest): Promise<string>;
69
- uploadDataFromStream({ path, body, mimetype, updateProgress, uploadSuccess }: UploadFromStreamRequest): Promise<void>;
73
+ uploadDataFromLocal({ path, localPath, meta, access }: UploadRequest): Promise<string>;
74
+ uploadDataFromStream({ path, body, mimetype, updateProgress, uploadSuccess, access, }: UploadFromStreamRequest): Promise<void>;
70
75
  saveData({ path, localPath, renamePath }: DownloadRequest): Promise<LocalFilePath>;
71
76
  copyData({ copyPath, pastePath, host }: CopyRequest): Promise<string>;
77
+ deleteDataByPath(path: string): Promise<boolean>;
72
78
  deleteData(url: string): Promise<boolean>;
73
79
  }
74
80
  export {};
@@ -15,4 +15,5 @@ export * from "./signalContext.d.ts";
15
15
  export * from "./signalRegistry.d.ts";
16
16
  export * from "./slice.d.ts";
17
17
  export * from "./sliceInfo.d.ts";
18
+ export * from "./trace.d.ts";
18
19
  export * from "./types.d.ts";
@@ -3,6 +3,7 @@ import { type ConstantFieldTypeInput } from "akanjs/constant";
3
3
  import type { Adaptor, AdaptorCls, DatabaseService, InjectRegistry, LiveRegistry } from "akanjs/service";
4
4
  import type { Internal, InternalInfo, MiddlewareCls } from ".";
5
5
  import type { EndpointInfo } from "./endpointInfo.d.ts";
6
+ import { SignalTrace } from "./trace.d.ts";
6
7
  export type SignalTransportType = "http" | "websocket";
7
8
  interface WebSocketRequest {
8
9
  ws: Bun.ServerWebSocket<unknown>;
@@ -19,6 +20,7 @@ export declare class SignalContext<Ctx extends HttpExecutionContext | WebSocketE
19
20
  adaptor: Adaptor;
20
21
  args: unknown[];
21
22
  internalArgs: unknown[];
23
+ trace: SignalTrace | null;
22
24
  constructor(key: string, reqOrWsReq: Bun.BunRequest | WebSocketRequest, { endpointInfo, adaptor, registry, env, live, middleware, }: {
23
25
  endpointInfo: EndpointInfo;
24
26
  adaptor: Adaptor;
@@ -48,6 +50,7 @@ export declare class SignalContext<Ctx extends HttpExecutionContext | WebSocketE
48
50
  getEnv(): Env;
49
51
  }
50
52
  export declare class HttpExecutionContext<Appended = unknown> {
53
+ #private;
51
54
  req: Bun.BunRequest & Appended;
52
55
  res: {
53
56
  new (body?: BodyInit | null, init?: ResponseInit): Response;
@@ -56,11 +59,11 @@ export declare class HttpExecutionContext<Appended = unknown> {
56
59
  json(data: any, init?: ResponseInit): Response;
57
60
  redirect(url: string | URL, status?: number): Response;
58
61
  };
59
- url: URL;
60
62
  params: RuntimeRecord;
61
63
  searchParams: RuntimeRecord;
62
64
  body: RuntimeRecord;
63
65
  constructor(req: Bun.BunRequest);
66
+ get url(): URL;
64
67
  getArgs(endpointInfo: EndpointInfo): Promise<unknown[]>;
65
68
  makeResponse(result: unknown, endpointInfo: EndpointInfo): Response;
66
69
  }
@@ -0,0 +1,97 @@
1
+ /** Whether request tracing is enabled. Cached after first read. */
2
+ export declare const isTraceEnabled: () => boolean;
3
+ /** Override the trace flag at runtime (tests / harness control). */
4
+ export declare const setTraceEnabled: (enabled: boolean) => void;
5
+ export interface SpanRecord {
6
+ name: string;
7
+ durationMs: number;
8
+ }
9
+ /** Per-request trace context. Threaded via {@link AsyncLocalStorage}. */
10
+ export declare class SignalTrace {
11
+ #private;
12
+ readonly traceId: string;
13
+ readonly endpointKey: string;
14
+ readonly endpointType: string;
15
+ readonly startedAt: number;
16
+ readonly spans: SpanRecord[];
17
+ dbQueryCount: number;
18
+ dbQueryMs: number;
19
+ cacheHits: number;
20
+ cacheMisses: number;
21
+ dataLoaderBatchCount: number;
22
+ dataLoaderKeyCount: number;
23
+ constructor(endpointKey: string, endpointType: string);
24
+ recordSpan(name: string, durationMs: number): void;
25
+ countDbQuery(durationMs: number): void;
26
+ countCache(hit: boolean): void;
27
+ countDataLoaderBatch(keyCount: number): void;
28
+ finalize(): void;
29
+ }
30
+ export declare const getCurrentTrace: () => SignalTrace | undefined;
31
+ /** Run `fn` with `trace` as the ambient request trace. */
32
+ export declare const runWithTrace: <T>(trace: SignalTrace, fn: () => T) => T;
33
+ /**
34
+ * Time an async stage under the current trace. When tracing is off (or no trace is
35
+ * active) this is a thin passthrough with no measurement overhead.
36
+ */
37
+ export declare const traceSpan: <T>(name: string, fn: () => Promise<T>) => Promise<T>;
38
+ /** Record a DB query duration against the current trace (no-op when untraced). */
39
+ export declare const traceDbQuery: (durationMs: number) => void;
40
+ /** Record a cache hit/miss against the current trace (no-op when untraced). */
41
+ export declare const traceCache: (hit: boolean) => void;
42
+ /** Record a DataLoader batch against the current trace (no-op when untraced). */
43
+ export declare const traceDataLoaderBatch: (keyCount: number) => void;
44
+ /**
45
+ * Process-wide aggregator. Keeps rolling per-endpoint, per-span statistics with a
46
+ * bounded sample ring per span so percentiles stay representative of steady state
47
+ * without unbounded memory growth.
48
+ */
49
+ declare class TraceAggregator {
50
+ #private;
51
+ ingest(trace: SignalTrace): void;
52
+ reset(): void;
53
+ /** Summarized snapshot suitable for JSON exposure on the metrics endpoint. */
54
+ snapshot(): {
55
+ enabled: boolean;
56
+ endpoints: {
57
+ endpoint: string;
58
+ requests: number;
59
+ avgDbQueriesPerRequest: number;
60
+ avgDbQueryMsPerRequest: number;
61
+ cacheHitRatio: number | null;
62
+ avgDataLoaderBatchSize: number | null;
63
+ spans: {
64
+ name: string;
65
+ count: number;
66
+ meanMs: number;
67
+ p50Ms: number;
68
+ p95Ms: number;
69
+ p99Ms: number;
70
+ maxMs: number;
71
+ }[];
72
+ }[];
73
+ };
74
+ }
75
+ export declare const traceAggregator: TraceAggregator;
76
+ /** Snapshot of all aggregated trace stats. Safe to call when tracing is disabled. */
77
+ export declare const getTraceSnapshot: () => {
78
+ enabled: boolean;
79
+ endpoints: {
80
+ endpoint: string;
81
+ requests: number;
82
+ avgDbQueriesPerRequest: number;
83
+ avgDbQueryMsPerRequest: number;
84
+ cacheHitRatio: number | null;
85
+ avgDataLoaderBatchSize: number | null;
86
+ spans: {
87
+ name: string;
88
+ count: number;
89
+ meanMs: number;
90
+ p50Ms: number;
91
+ p95Ms: number;
92
+ p99Ms: number;
93
+ maxMs: number;
94
+ }[];
95
+ }[];
96
+ };
97
+ export {};
@@ -0,0 +1,15 @@
1
+ export declare const signalUi: {
2
+ sectionTitle: string;
3
+ sectionDescription: string;
4
+ sectionPanel: string;
5
+ endpointCard: string;
6
+ endpointContent: string;
7
+ tablePanel: string;
8
+ inputRow: string;
9
+ inputLabel: string;
10
+ codePanel: string;
11
+ };
12
+ export declare const getEndpointBadgeClassName: (type: string) => "badge badge-primary" | "badge badge-secondary";
13
+ export declare const getGuardBadgeClassName: (guard: string) => "badge badge-primary" | "badge badge-secondary" | "badge";
14
+ export declare const getStatusBadgeClassName: (status: string) => "badge badge-outline" | "badge badge-primary" | "badge badge-error";
15
+ export declare const getStatusTextareaClassName: (status: string) => "" | "border-error text-error" | "border-primary" | "textarea-disabled";
package/ui/Signal/Arg.tsx CHANGED
@@ -9,6 +9,7 @@ import { AiOutlineDelete } from "react-icons/ai";
9
9
  import { DatePicker } from "../DatePicker";
10
10
  import { Input } from "../Input";
11
11
  import UiObject from "./Object";
12
+ import { signalUi } from "./style";
12
13
 
13
14
  interface ArgProps {
14
15
  argType: DefaultPrimitiveName;
@@ -55,7 +56,7 @@ const ArgTable = ({ refName, endpointKey, args }: ArgTableProps) => {
55
56
  return (
56
57
  <table className="table">
57
58
  <thead>
58
- <tr className="text-bold">
59
+ <tr>
59
60
  <th>Arg Key</th>
60
61
  <th className="text-center">Type</th>
61
62
  <th className="text-center">Enum</th>
@@ -69,7 +70,9 @@ const ArgTable = ({ refName, endpointKey, args }: ArgTableProps) => {
69
70
  return (
70
71
  <tbody className="font-normal" key={idx}>
71
72
  <tr>
72
- <td>{arg.name}</td>
73
+ <td>
74
+ <div className="font-bold">{arg.name}</div>
75
+ </td>
73
76
  <td className="text-center">
74
77
  <UiObject.Type objRef={argRef as ConstantCls} arrDepth={arg.arrDepth ?? 0} />
75
78
  </td>
@@ -84,7 +87,7 @@ const ArgTable = ({ refName, endpointKey, args }: ArgTableProps) => {
84
87
  onClick={() => {
85
88
  onCopy(opt.toString());
86
89
  }}
87
- className="tooltip tooltip-primary btn btn-secondary btn-xs"
90
+ className="tooltip tooltip-primary btn btn-outline btn-xs"
88
91
  >
89
92
  {opt}
90
93
  </button>
@@ -95,8 +98,12 @@ const ArgTable = ({ refName, endpointKey, args }: ArgTableProps) => {
95
98
  "-"
96
99
  )}
97
100
  </td>
98
- <td className="text-center">{l._(`${refName}.signal.${endpointKey}.arg.${arg.name}`)}</td>
99
- <td className="text-center">{l._(`${refName}.signal.${endpointKey}.arg.${arg.name}.desc`)}</td>
101
+ <td className="text-center text-base-content/70">
102
+ {l._(`${refName}.signal.${endpointKey}.arg.${arg.name}`)}
103
+ </td>
104
+ <td className="text-center text-base-content/70">
105
+ {l._(`${refName}.signal.${endpointKey}.arg.${arg.name}.desc`)}
106
+ </td>
100
107
  </tr>
101
108
  </tbody>
102
109
  );
@@ -118,8 +125,8 @@ const ArgParam = ({ endpointKey, arg, value, onChange }: ArgParamProps) => {
118
125
  else if ((arg.arrDepth ?? 0) > 0) throw new Error(`Param arg - ${endpointKey}/${arg.name} must not be array`);
119
126
  const argType = PrimitiveRegistry.getName(argRef as typeof PrimitiveScalar) as DefaultPrimitiveName;
120
127
  return (
121
- <div className="flex w-full items-center gap-2">
122
- <div className="w-36 pl-2">- {arg.name}</div>
128
+ <div className={signalUi.inputRow}>
129
+ <div className={signalUi.inputLabel}>{arg.name}</div>
123
130
  <div className="w-full">
124
131
  <Arg argType={argType} value={value as string} onChange={onChange} />
125
132
  </div>
@@ -141,8 +148,8 @@ const ArgQuery = ({ endpointKey, arg, value, onChange }: ArgQueryProps) => {
141
148
  throw new Error(`Query arg - ${endpointKey}/${arg.name} must not be more than 2D array`);
142
149
  const argType = PrimitiveRegistry.getName(argRef as typeof PrimitiveScalar) as DefaultPrimitiveName;
143
150
  return (
144
- <div className="flex items-center gap-2">
145
- <div className="w-36 pl-2">- {arg.name}</div>
151
+ <div className={signalUi.inputRow}>
152
+ <div className={signalUi.inputLabel}>{arg.name}</div>
146
153
  <div className="w-full">
147
154
  {(arg.arrDepth ?? 0) > 0 && Array.isArray(value) ? (
148
155
  <div>
@@ -156,7 +163,7 @@ const ArgQuery = ({ endpointKey, arg, value, onChange }: ArgQueryProps) => {
156
163
  }}
157
164
  />
158
165
  <button
159
- className="btn btn-sm btn-square"
166
+ className="btn btn-outline btn-sm btn-square"
160
167
  onClick={() => {
161
168
  onChange([...(value.slice(0, idx) as string[]), ...(value.slice(idx + 1) as string[])]);
162
169
  }}
@@ -166,7 +173,7 @@ const ArgQuery = ({ endpointKey, arg, value, onChange }: ArgQueryProps) => {
166
173
  </div>
167
174
  ))}
168
175
  <button
169
- className="btn btn-sm"
176
+ className="btn btn-outline btn-sm"
170
177
  onClick={() => {
171
178
  onChange([...(value as string[]), arg.example]);
172
179
  }}
@@ -195,8 +202,8 @@ const ArgFormData = ({ endpointKey, arg, value, onChange }: ArgFormDataProps) =>
195
202
  throw new Error(`FormData arg - ${endpointKey}/${arg.name} must be Upload`);
196
203
  else if ((arg.arrDepth ?? 0) < 1) throw new Error(`FormData arg - ${endpointKey}/${arg.name} must be array`);
197
204
  return (
198
- <div className="flex w-full items-center gap-2">
199
- <div className="w-36 pl-2">- {arg.name}</div>
205
+ <div className={signalUi.inputRow}>
206
+ <div className={signalUi.inputLabel}>{arg.name}</div>
200
207
  <div className="w-full">
201
208
  <Arg argType="Upload" value={value as FileList} onChange={onChange} />
202
209
  </div>
@@ -320,7 +327,7 @@ const ArgJson = ({ value, onChange }: ArgJsonProps) => {
320
327
  <Input.TextArea
321
328
  validate={(e) => true}
322
329
  className="w-full"
323
- inputClassName="w-full min-h-[300px]"
330
+ inputClassName="w-full min-h-[300px] rounded-xl border border-base-300 bg-base-100"
324
331
  value={value}
325
332
  onPressEnter={(value) => {
326
333
  onChange(value);
@@ -342,7 +349,7 @@ const ArgUpload = ({ value, onChange }: ArgUploadProps) => {
342
349
  <input
343
350
  type="file"
344
351
  multiple
345
- className="file-input w-full max-w-xs"
352
+ className="file-input file-input-bordered w-full max-w-xs"
346
353
  onChange={(e: ChangeEvent<HTMLInputElement>) => {
347
354
  onChange(new Array(e.target.files?.length).fill(0).map((_, idx) => e.target.files?.[idx]) as any as FileList);
348
355
  }}
package/ui/Signal/Doc.tsx CHANGED
@@ -10,6 +10,7 @@ import { Copy } from "../Copy";
10
10
  import { Input } from "../Input";
11
11
  import { Modal } from "../Modal";
12
12
  import RestApi from "./RestApi";
13
+ import { signalUi } from "./style";
13
14
  import WebSocket from "./WebSocket";
14
15
 
15
16
  export default function Doc() {
@@ -26,7 +27,6 @@ const DocSetting = ({
26
27
  roleTypes = ["Public", "User", "Admin", "SuperAdmin"],
27
28
  roleKeys = { me: "Admin", self: "User" },
28
29
  }: DocSettingProps) => {
29
- const trySignalType = st.use.trySignalType();
30
30
  const tryRoles = st.use.tryRoles();
31
31
  const tryAccount = st.use.tryAccount();
32
32
  useEffect(() => {
@@ -38,9 +38,9 @@ const DocSetting = ({
38
38
  .filter(([key, roleType]) => !!tryAccount[key as keyof typeof tryAccount])
39
39
  .map(([key, roleType]) => roleType);
40
40
  return (
41
- <div className="flex w-full flex-wrap items-center justify-between gap-4">
42
- <div className="flex flex-1 items-center gap-1">
43
- BaseURL:{" "}
41
+ <div className="flex w-full flex-wrap items-center justify-between gap-3 rounded-xl bg-base-200 p-3">
42
+ <div className="flex flex-1 flex-wrap items-center gap-2">
43
+ <span className="font-semibold text-base-content/70 text-sm">BaseURL</span>
44
44
  <Copy text={baseUrl}>
45
45
  <button className="btn btn-outline btn-sm">
46
46
  {baseUrl}
@@ -48,10 +48,10 @@ const DocSetting = ({
48
48
  </button>
49
49
  </Copy>
50
50
  </div>
51
- <div className="flex items-center gap-1">
52
- Mode:
51
+ <div className="flex items-center gap-2">
52
+ <span className="font-semibold text-base-content/70 text-sm">Mode</span>
53
53
  <button
54
- className="btn btn-sm btn-outline"
54
+ className="btn btn-primary btn-sm"
55
55
  onClick={() => {
56
56
  st.do.setTrySignalType("restapi");
57
57
  }}
@@ -60,8 +60,8 @@ const DocSetting = ({
60
60
  Rest API
61
61
  </button>
62
62
  </div>
63
- <div className="flex items-center gap-0.5">
64
- For:
63
+ <div className="flex flex-wrap items-center gap-1">
64
+ <span className="font-semibold text-base-content/70 text-sm">For</span>
65
65
  <button
66
66
  className={`btn btn-secondary btn-sm ${tryRoleForAll ? "" : "btn-outline"}`}
67
67
  onClick={() => {
@@ -84,10 +84,10 @@ const DocSetting = ({
84
84
  </button>
85
85
  ))}
86
86
  </div>
87
- <div className="flex items-center gap-1">
88
- Auth:
87
+ <div className="flex items-center gap-2">
88
+ <span className="font-semibold text-base-content/70 text-sm">Auth</span>
89
89
  <DocAuthModal>
90
- <button className={`btn btn-sm ${currentRoles.length > 0 ? "btn-warning" : "btn-neutral"} `}>
90
+ <button className={`btn btn-sm ${currentRoles.length > 0 ? "btn-primary" : "btn-outline"} `}>
91
91
  <BiLock /> {currentRoles.length > 0 ? currentRoles.join(", ") : "Public"}
92
92
  </button>
93
93
  </DocAuthModal>
@@ -140,11 +140,11 @@ const DocAuthModal = ({ children }: DocAuthModalProps) => {
140
140
  }
141
141
  >
142
142
  <div className="w-full">
143
- <div>Current JWT</div>
143
+ <div className={signalUi.sectionTitle}>Current JWT</div>
144
144
  <Input inputClassName="w-full" value={jwt ?? ""} onChange={setJwt} validate={() => true} />
145
145
  </div>
146
146
  <div className="w-full">
147
- <div className="flex items-center gap-2">Account Decoded</div>
147
+ <div className={signalUi.sectionTitle}>Account Decoded</div>
148
148
  <div className="relative">
149
149
  <Input.TextArea
150
150
  inputClassName="w-full"
@@ -177,10 +177,10 @@ const DocSignals = ({ fetch }: DocSignalsProps) => {
177
177
  const signal = fetch.serializedSignal;
178
178
  const signalEntries = Object.entries(signal).sort(([keyA], [keyB]) => (lowerlize(keyA) > lowerlize(keyB) ? 1 : -1));
179
179
  return (
180
- <div>
180
+ <div className="flex flex-col gap-3">
181
181
  {signalEntries.map(([refName, signal], idx) => {
182
182
  return (
183
- <div className="px-5 pb-5 font-bold text-3xl" key={idx}>
183
+ <div className="font-bold text-3xl" key={idx}>
184
184
  <DocSignal refName={refName} fetch={fetch} />
185
185
  </div>
186
186
  );
@@ -199,8 +199,13 @@ const DocSignal = ({ refName, fetch }: DocSignalProps) => {
199
199
  return (
200
200
  <div className="collapse-arrow collapse bg-base-200">
201
201
  <input type="checkbox" />
202
- <div className="collapse-title font-medium text-xl">{refName}</div>
203
- <div className="collapse-content">
202
+ <div className="collapse-title">
203
+ <div className="flex flex-wrap items-center gap-2">
204
+ <div className="font-bold text-xl">{refName}</div>
205
+ <div className="badge badge-primary">Signal</div>
206
+ </div>
207
+ </div>
208
+ <div className="collapse-content flex flex-col gap-3">
204
209
  <RestApi.Endpoints refName={refName} fetch={fetch} />
205
210
  </div>
206
211
  </div>
@@ -217,10 +222,12 @@ const Zone = ({ refName, fetch, openAll }: ZoneProps) => {
217
222
  const { l } = usePage();
218
223
  return (
219
224
  <div className="flex break-after-page flex-col gap-4">
220
- <div className="font-bold text-3xl">{refName}</div>
221
- <div className="mb-5"> - {l._(`${refName}.modelDesc`)}</div>
222
- <div className="font-bold text-2xl">APIs</div>
225
+ <div>
226
+ <div className="font-bold text-3xl">{refName}</div>
227
+ <div className="text-base-content/70">{l._(`${refName}.modelDesc`)}</div>
228
+ </div>
223
229
  <DocSetting />
230
+ <div className="font-bold text-2xl">APIs</div>
224
231
  <RestApi.Endpoints refName={refName} fetch={fetch} openAll={openAll} />
225
232
  <div className="font-bold text-2xl">Web Socket</div>
226
233
  <WebSocket.Endpoints refName={refName} fetch={fetch} openAll={openAll} />
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
 
3
- import { clsx } from "akanjs/client";
4
3
  import { capitalize } from "akanjs/common";
5
4
  import { useEffect, useRef } from "react";
5
+ import { getStatusBadgeClassName, getStatusTextareaClassName, signalUi } from "./style";
6
6
 
7
7
  export default function Listener() {
8
8
  return <div></div>;
@@ -23,51 +23,27 @@ const ListenerResult = ({ status, data }: ListenerResultProps) => {
23
23
  <div className="relative">
24
24
  <textarea
25
25
  ref={ref}
26
- className={`textarea duration-300 ${
27
- status === "loading"
28
- ? "textarea-disabled"
29
- : status === "error"
30
- ? "textarea-error border-error text-error"
31
- : status === "listening"
32
- ? "textarea-success animate-borderPulse-50 border-3 border-info"
33
- : ""
34
- } min-h-[300px] w-full rounded-md bg-base-100 p-4 font-normal text-sm`}
26
+ className={`${signalUi.codePanel} duration-300 ${
27
+ status === "listening" ? "animate-borderPulse-50 border-2" : ""
28
+ } ${getStatusTextareaClassName(status)}`}
35
29
  value={dataStr}
36
30
  onChange={() => true}
37
31
  />
38
32
 
39
- <div className="absolute top-4 right-4 flex items-center justify-center gap-3 rounded-lg bg-base-200/50 px-2 py-1 font-bold">
40
- {capitalize(status)}
41
-
33
+ <div className="absolute top-4 right-4 flex items-center justify-center gap-2 rounded-lg bg-base-200/80 px-2 py-1 font-bold">
34
+ <span className={getStatusBadgeClassName(status)}>{capitalize(status)}</span>
42
35
  <div
43
- className={clsx("size-[14px] rounded-full", {
44
- "animate-bounce bg-base-300": status === "ready",
45
- "animate-pop-300 bg-success": status === "listening",
46
-
47
- "animate-none bg-error": status === "error",
48
- "animate-ping bg-warning": status === "loading",
49
- })}
36
+ className={`size-[10px] rounded-full ${
37
+ status === "error"
38
+ ? "bg-error"
39
+ : status === "listening"
40
+ ? "animate-pop-300 bg-primary"
41
+ : status === "loading"
42
+ ? "animate-ping bg-secondary"
43
+ : "bg-base-300"
44
+ }`}
50
45
  ></div>
51
46
  </div>
52
- {/* {status === "loading" ? (
53
- <div className="animate-fadeIn absolute inset-0 flex items-center justify-center backdrop-blur-sm">
54
- <span className="loading loading-dots loading-lg"></span>
55
- </div>
56
- ) : status === "idle" ? (
57
- <></>
58
- ) : status === "listening" ? (
59
- <div className="absolute right-4 top-4 w-3 h-3">
60
- <div className="rounded-full w-full h-full animate-bounce bg-success"></div>
61
- </div>
62
- ) : (
63
- <div className="absolute right-4 top-4">
64
- <Copy text={dataStr}>
65
- <button className="btn btn-sm">
66
- <AiOutlineCopy /> Copy
67
- </button>
68
- </Copy>
69
- </div>
70
- )} */}
71
47
  </div>
72
48
  );
73
49
  };