web_plsql 0.18.0 → 1.2.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 (74) hide show
  1. package/README.md +29 -9
  2. package/package.json +17 -7
  3. package/src/admin/client/charts.ts +598 -0
  4. package/src/admin/client/main.js +3 -0
  5. package/src/admin/client/tailwind.css +41 -0
  6. package/src/admin/favicon.svg +3 -0
  7. package/src/admin/index.html +529 -0
  8. package/src/admin/js/api.ts +170 -0
  9. package/src/admin/js/app.ts +614 -0
  10. package/src/admin/js/eslint.config.js +74 -0
  11. package/src/admin/js/schemas.ts +215 -0
  12. package/src/admin/js/templates/config.ts +147 -0
  13. package/src/admin/js/templates/errorRow.ts +21 -0
  14. package/src/admin/js/templates/index.ts +4 -0
  15. package/src/admin/js/templates/poolCard.ts +61 -0
  16. package/src/admin/js/templates/traceRow.ts +24 -0
  17. package/src/admin/js/tsconfig.json +24 -0
  18. package/src/admin/js/types.ts +336 -0
  19. package/src/admin/js/ui/components.ts +44 -0
  20. package/src/admin/js/ui/table.ts +173 -0
  21. package/src/admin/js/ui/theme.ts +93 -0
  22. package/src/admin/js/ui/views.ts +427 -0
  23. package/src/admin/js/util/format.ts +46 -0
  24. package/src/admin/js/util/metrics.ts +24 -0
  25. package/src/admin/lib/chart.bundle.css +1 -0
  26. package/src/admin/lib/chart.bundle.js +146 -0
  27. package/src/admin/style.css +1437 -0
  28. package/src/bin/load-test.js +202 -0
  29. package/src/handler/handlerAdmin.js +293 -0
  30. package/src/handler/plsql/cgi.js +1 -1
  31. package/src/handler/plsql/errorPage.js +31 -6
  32. package/src/handler/plsql/handlerPlSql.js +32 -6
  33. package/src/handler/plsql/owaPageStream.js +93 -0
  34. package/src/handler/plsql/parsePage.js +7 -3
  35. package/src/handler/plsql/procedure.js +221 -105
  36. package/src/handler/plsql/procedureNamed.js +34 -49
  37. package/src/handler/plsql/procedureSanitize.js +120 -45
  38. package/src/handler/plsql/procedureVariable.js +4 -2
  39. package/src/handler/plsql/request.js +8 -3
  40. package/src/handler/plsql/sendResponse.js +43 -5
  41. package/src/index.js +0 -1
  42. package/src/server/adminContext.js +23 -0
  43. package/src/server/config.js +1 -0
  44. package/src/server/server.js +130 -9
  45. package/src/types.js +7 -1
  46. package/src/util/cache.js +123 -0
  47. package/src/util/jsonLogger.js +47 -0
  48. package/src/util/shutdown.js +6 -2
  49. package/src/util/statsManager.js +368 -0
  50. package/src/util/trace.js +7 -6
  51. package/src/util/traceManager.js +68 -0
  52. package/src/version.js +1 -1
  53. package/types/admin/js/schemas.d.ts +384 -0
  54. package/types/admin/js/types.d.ts +312 -0
  55. package/types/handler/handlerAdmin.d.ts +79 -0
  56. package/types/handler/plsql/errorPage.d.ts +1 -0
  57. package/types/handler/plsql/handlerPlSql.d.ts +6 -1
  58. package/types/handler/plsql/owaPageStream.d.ts +28 -0
  59. package/types/handler/plsql/procedure.d.ts +4 -1
  60. package/types/handler/plsql/procedureNamed.d.ts +2 -5
  61. package/types/handler/plsql/procedureSanitize.d.ts +2 -5
  62. package/types/handler/plsql/procedureVariable.d.ts +1 -1
  63. package/types/handler/plsql/request.d.ts +3 -1
  64. package/types/handler/plsql/sendResponse.d.ts +1 -1
  65. package/types/index.d.ts +0 -1
  66. package/types/server/adminContext.d.ts +17 -0
  67. package/types/server/server.d.ts +5 -0
  68. package/types/types.d.ts +19 -1
  69. package/types/util/cache.d.ts +69 -0
  70. package/types/util/jsonLogger.d.ts +45 -0
  71. package/types/util/statsManager.d.ts +395 -0
  72. package/types/util/traceManager.d.ts +35 -0
  73. package/src/handler/handlerMetrics.js +0 -68
  74. package/types/handler/handlerMetrics.d.ts +0 -25
@@ -0,0 +1,170 @@
1
+ import {z} from 'zod';
2
+ import {
3
+ statusSchema,
4
+ errorLogSchema,
5
+ accessLogResponseSchema,
6
+ traceEntrySchema,
7
+ type StatusResponse,
8
+ type ErrorLogResponse,
9
+ type AccessLogResponse,
10
+ } from './schemas.js';
11
+ import type {TraceEntry} from './types.js';
12
+
13
+ /**
14
+ * Validates response data against a Zod schema.
15
+ *
16
+ * @param data - The data to validate.
17
+ * @param schema - The Zod schema to validate against.
18
+ * @param path - The API path for error messages.
19
+ * @returns The validated data.
20
+ */
21
+ function validate<T>(data: unknown, schema: z.ZodType<T>, path: string): T {
22
+ const result = schema.safeParse(data);
23
+ if (!result.success) {
24
+ throw new Error(`Validation failed for ${path}: ${result.error.message}`);
25
+ }
26
+ return result.data;
27
+ }
28
+
29
+ /**
30
+ * Fetch with retry logic.
31
+ *
32
+ * @param url - The URL to fetch.
33
+ * @param options - Fetch options.
34
+ * @param retries - Number of retries (default 2).
35
+ * @param delay - Delay between retries in ms (default 500).
36
+ * @returns The response.
37
+ */
38
+ async function fetchWithRetry(url: string, options?: RequestInit, retries = 2, delay = 500): Promise<Response> {
39
+ for (let i = 0; i <= retries; i++) {
40
+ try {
41
+ const res = await fetch(url, options);
42
+ return res;
43
+ } catch (err) {
44
+ if (i === retries) throw err;
45
+ await new Promise((resolve) => setTimeout(resolve, delay));
46
+ }
47
+ }
48
+ throw new Error('Unreachable');
49
+ }
50
+
51
+ /**
52
+ * Typed API client with Zod validation.
53
+ */
54
+ export const typedApi = {
55
+ /**
56
+ * Get server status with validation.
57
+ *
58
+ * @returns The validated status response.
59
+ */
60
+ async getStatus(): Promise<StatusResponse> {
61
+ const res = await fetchWithRetry('api/status');
62
+ if (!res.ok) throw new Error(`GET api/status failed: ${res.statusText}`);
63
+ const data: unknown = await res.json();
64
+ return validate(data, statusSchema, 'api/status');
65
+ },
66
+
67
+ /**
68
+ * Get error logs with validation.
69
+ *
70
+ * @param limit - Max number of entries.
71
+ * @param filter - Optional filter string.
72
+ * @returns The validated error log response.
73
+ */
74
+ async getErrorLogs(limit = 100, filter = ''): Promise<ErrorLogResponse[]> {
75
+ const query = new URLSearchParams({
76
+ limit: limit.toString(),
77
+ filter,
78
+ });
79
+ const res = await fetchWithRetry(`api/logs/error?${query.toString()}`);
80
+ if (!res.ok) throw new Error(`GET api/logs/error failed: ${res.statusText}`);
81
+ const data: unknown = await res.json();
82
+ return validate(data, z.array(errorLogSchema), 'api/logs/error');
83
+ },
84
+
85
+ /**
86
+ * Get access logs with validation.
87
+ *
88
+ * @param limit - Max number of entries.
89
+ * @param filter - Optional filter string.
90
+ * @returns The validated access log response.
91
+ */
92
+ async getAccessLogs(limit = 100, filter = ''): Promise<AccessLogResponse> {
93
+ const query = new URLSearchParams({
94
+ limit: limit.toString(),
95
+ filter,
96
+ });
97
+ const res = await fetchWithRetry(`api/logs/access?${query.toString()}`);
98
+ if (!res.ok) throw new Error(`GET api/logs/access failed: ${res.statusText}`);
99
+ const data: unknown = await res.json();
100
+ return validate(data, accessLogResponseSchema, 'api/logs/access');
101
+ },
102
+
103
+ /**
104
+ * Get trace logs with validation.
105
+ *
106
+ * @param limit - Max number of entries.
107
+ * @param filter - Optional filter string.
108
+ * @returns The validated trace log response.
109
+ */
110
+ async getTraceLogs(limit = 100, filter = ''): Promise<TraceEntry[]> {
111
+ const query = new URLSearchParams({
112
+ limit: limit.toString(),
113
+ filter,
114
+ });
115
+ const res = await fetchWithRetry(`api/trace/logs?${query.toString()}`);
116
+ if (!res.ok) throw new Error(`GET api/trace/logs failed: ${res.statusText}`);
117
+ const data: unknown = await res.json();
118
+ return validate(data, z.array(traceEntrySchema), 'api/trace/logs');
119
+ },
120
+
121
+ /**
122
+ * Get trace status.
123
+ *
124
+ * @returns Trace status.
125
+ */
126
+ async getTraceStatus(): Promise<{enabled: boolean}> {
127
+ const res = await fetchWithRetry('api/trace/status');
128
+ if (!res.ok) throw new Error(`GET api/trace/status failed: ${res.statusText}`);
129
+ return (await res.json()) as {enabled: boolean};
130
+ },
131
+
132
+ /**
133
+ * Toggle trace status.
134
+ *
135
+ * @param enabled - Enable or disable.
136
+ * @returns New status.
137
+ */
138
+ async toggleTrace(enabled: boolean): Promise<{enabled: boolean}> {
139
+ const res = await fetchWithRetry('api/trace/toggle', {
140
+ method: 'POST',
141
+ headers: {'Content-Type': 'application/json'},
142
+ body: JSON.stringify({enabled}),
143
+ });
144
+ if (!res.ok) throw new Error(`POST api/trace/toggle failed: ${res.statusText}`);
145
+ return (await res.json()) as {enabled: boolean};
146
+ },
147
+
148
+ /**
149
+ * Clear trace logs.
150
+ */
151
+ async clearTraces(): Promise<void> {
152
+ const res = await fetchWithRetry('api/trace/clear', {method: 'POST'});
153
+ if (!res.ok) throw new Error(`POST api/trace/clear failed: ${res.statusText}`);
154
+ },
155
+
156
+ /**
157
+ * POST to an endpoint without response validation.
158
+ *
159
+ * @param path - The API path.
160
+ * @param body - The request body.
161
+ */
162
+ async post(path: string, body: object = {}): Promise<void> {
163
+ const res = await fetchWithRetry(path, {
164
+ method: 'POST',
165
+ headers: {'Content-Type': 'application/json'},
166
+ body: JSON.stringify(body),
167
+ });
168
+ if (!res.ok) throw new Error(`POST ${path} failed: ${res.statusText}`);
169
+ },
170
+ };