kimu-core 0.4.1 → 0.5.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 (75) hide show
  1. package/.editorconfig +116 -30
  2. package/.gitattributes +81 -11
  3. package/.github/FUNDING.yml +8 -8
  4. package/.github/kimu-copilot-instructions.md +3779 -3779
  5. package/.github/workflows/deploy-demo.yml +39 -39
  6. package/.nvmrc +1 -0
  7. package/.prettierignore +44 -0
  8. package/.prettierrc +16 -0
  9. package/FUNDING.md +31 -31
  10. package/icon.svg +10 -10
  11. package/kimu-core-0.5.0.tgz +0 -0
  12. package/package.json +10 -3
  13. package/scripts/minify-css-assets.js +82 -82
  14. package/src/core/index.ts +47 -47
  15. package/src/core/kimu-global-styles.ts +136 -136
  16. package/src/core/kimu-reactive.ts +196 -196
  17. package/src/extensions/{kimu-home → app-root}/component.ts +5 -5
  18. package/src/extensions/extensions-manifest.json +4 -4
  19. package/src/main.ts +3 -3
  20. package/src/modules-repository/api-axios/CHANGELOG.md +48 -48
  21. package/src/modules-repository/api-axios/QUICK-REFERENCE.md +178 -178
  22. package/src/modules-repository/api-axios/README.md +304 -304
  23. package/src/modules-repository/api-axios/api-axios-service.ts +355 -355
  24. package/src/modules-repository/api-axios/examples.ts +293 -293
  25. package/src/modules-repository/api-axios/index.ts +19 -19
  26. package/src/modules-repository/api-axios/interfaces.ts +71 -71
  27. package/src/modules-repository/api-axios/module.ts +41 -41
  28. package/src/modules-repository/api-core/CHANGELOG.md +42 -42
  29. package/src/modules-repository/api-core/QUICK-REFERENCE.md +192 -192
  30. package/src/modules-repository/api-core/README.md +435 -435
  31. package/src/modules-repository/api-core/api-core-service.ts +289 -289
  32. package/src/modules-repository/api-core/examples.ts +432 -432
  33. package/src/modules-repository/api-core/index.ts +8 -8
  34. package/src/modules-repository/api-core/interfaces.ts +83 -83
  35. package/src/modules-repository/api-core/module.ts +30 -30
  36. package/src/modules-repository/event-bus/README.md +273 -273
  37. package/src/modules-repository/event-bus/event-bus-service.ts +176 -176
  38. package/src/modules-repository/event-bus/module.ts +30 -30
  39. package/src/modules-repository/notification/README.md +423 -423
  40. package/src/modules-repository/notification/module.ts +30 -30
  41. package/src/modules-repository/notification/notification-service.ts +436 -436
  42. package/src/modules-repository/router/README.it.md +61 -10
  43. package/src/modules-repository/router/README.md +61 -10
  44. package/src/modules-repository/router/router-config.ts.example +61 -0
  45. package/src/modules-repository/router/router.ts +18 -0
  46. package/src/modules-repository/state/README.md +409 -409
  47. package/src/modules-repository/state/module.ts +30 -30
  48. package/src/modules-repository/state/state-service.ts +296 -296
  49. package/src/modules-repository/theme/README.md +311 -267
  50. package/src/modules-repository/theme/module.ts +30 -30
  51. package/src/modules-repository/theme/pre-build.js +40 -40
  52. package/src/modules-repository/theme/theme-service.ts +411 -389
  53. package/src/modules-repository/theme/themes/theme-cherry-blossom.css +78 -78
  54. package/src/modules-repository/theme/themes/theme-cozy.css +111 -111
  55. package/src/modules-repository/theme/themes/theme-cyberpunk.css +150 -150
  56. package/src/modules-repository/theme/themes/theme-dark.css +79 -79
  57. package/src/modules-repository/theme/themes/theme-forest.css +171 -171
  58. package/src/modules-repository/theme/themes/theme-gold.css +100 -100
  59. package/src/modules-repository/theme/themes/theme-high-contrast.css +126 -126
  60. package/src/modules-repository/theme/themes/theme-lava.css +101 -101
  61. package/src/modules-repository/theme/themes/theme-lavender.css +90 -90
  62. package/src/modules-repository/theme/themes/theme-light.css +79 -79
  63. package/src/modules-repository/theme/themes/theme-matrix.css +103 -103
  64. package/src/modules-repository/theme/themes/theme-midnight.css +81 -81
  65. package/src/modules-repository/theme/themes/theme-nord.css +94 -94
  66. package/src/modules-repository/theme/themes/theme-ocean.css +84 -84
  67. package/src/modules-repository/theme/themes/theme-retro80s.css +343 -343
  68. package/src/modules-repository/theme/themes/theme-sunset.css +62 -62
  69. package/src/modules-repository/theme/themes-config-default.json +19 -0
  70. package/src/modules-repository/theme/themes-config.d.ts +27 -27
  71. package/src/modules-repository/theme/{themes-config.json → themes-config.json.example} +223 -213
  72. /package/src/extensions/{kimu-home → app-root}/lang/en.json +0 -0
  73. /package/src/extensions/{kimu-home → app-root}/lang/it.json +0 -0
  74. /package/src/extensions/{kimu-home → app-root}/style.css +0 -0
  75. /package/src/extensions/{kimu-home → app-root}/view.html +0 -0
@@ -1,289 +1,289 @@
1
- /**
2
- * KIMU API Core Service
3
- * Lightweight HTTP client based on native fetch API
4
- * Zero dependencies, Promise-based, TypeScript-first
5
- */
6
-
7
- import {
8
- ApiRequestOptions,
9
- ApiResponse,
10
- ApiError,
11
- ApiConfig
12
- } from './interfaces';
13
-
14
- /**
15
- * Main API service class for making HTTP requests
16
- */
17
- export class ApiCoreService {
18
- private config: ApiConfig = {};
19
-
20
- /**
21
- * Configure the API service with global settings
22
- * @param config - Global configuration options
23
- */
24
- configure(config: ApiConfig): void {
25
- this.config = { ...this.config, ...config };
26
- }
27
-
28
- /**
29
- * Make a GET request
30
- * @param url - Request URL (relative to baseURL if configured)
31
- * @param options - Request options
32
- * @returns Promise with response data
33
- */
34
- async get<T = any>(url: string, options?: ApiRequestOptions): Promise<ApiResponse<T>> {
35
- return this.request<T>(url, { ...options, method: 'GET' });
36
- }
37
-
38
- /**
39
- * Make a POST request
40
- * @param url - Request URL
41
- * @param data - Request body data
42
- * @param options - Request options
43
- * @returns Promise with response data
44
- */
45
- async post<T = any>(url: string, data?: any, options?: ApiRequestOptions): Promise<ApiResponse<T>> {
46
- return this.request<T>(url, { ...options, method: 'POST', body: data });
47
- }
48
-
49
- /**
50
- * Make a PUT request
51
- * @param url - Request URL
52
- * @param data - Request body data
53
- * @param options - Request options
54
- * @returns Promise with response data
55
- */
56
- async put<T = any>(url: string, data?: any, options?: ApiRequestOptions): Promise<ApiResponse<T>> {
57
- return this.request<T>(url, { ...options, method: 'PUT', body: data });
58
- }
59
-
60
- /**
61
- * Make a PATCH request
62
- * @param url - Request URL
63
- * @param data - Request body data
64
- * @param options - Request options
65
- * @returns Promise with response data
66
- */
67
- async patch<T = any>(url: string, data?: any, options?: ApiRequestOptions): Promise<ApiResponse<T>> {
68
- return this.request<T>(url, { ...options, method: 'PATCH', body: data });
69
- }
70
-
71
- /**
72
- * Make a DELETE request
73
- * @param url - Request URL
74
- * @param options - Request options
75
- * @returns Promise with response data
76
- */
77
- async delete<T = any>(url: string, options?: ApiRequestOptions): Promise<ApiResponse<T>> {
78
- return this.request<T>(url, { ...options, method: 'DELETE' });
79
- }
80
-
81
- /**
82
- * Make a generic HTTP request
83
- * @param url - Request URL
84
- * @param options - Request options
85
- * @returns Promise with response data
86
- */
87
- async request<T = any>(url: string, options: ApiRequestOptions = {}): Promise<ApiResponse<T>> {
88
- try {
89
- // Apply request interceptor if configured
90
- let finalOptions = options;
91
- if (this.config.requestInterceptor) {
92
- finalOptions = await this.config.requestInterceptor(options);
93
- }
94
-
95
- // Build final URL with baseURL and query params
96
- const finalUrl = this.buildUrl(url, finalOptions.params);
97
-
98
- // Build headers
99
- const headers = this.buildHeaders(finalOptions);
100
-
101
- // Build request body
102
- const body = this.buildBody(finalOptions.body, headers);
103
-
104
- // Setup timeout if specified
105
- const controller = new AbortController();
106
- const signal = finalOptions.signal || controller.signal;
107
- const timeout = finalOptions.timeout || this.config.timeout;
108
-
109
- let timeoutId: NodeJS.Timeout | undefined;
110
- if (timeout) {
111
- timeoutId = setTimeout(() => controller.abort(), timeout);
112
- }
113
-
114
- // Make fetch request
115
- const response = await fetch(finalUrl, {
116
- method: finalOptions.method || 'GET',
117
- headers,
118
- body,
119
- credentials: finalOptions.credentials,
120
- cache: finalOptions.cache,
121
- signal
122
- });
123
-
124
- // Clear timeout
125
- if (timeoutId) {
126
- clearTimeout(timeoutId);
127
- }
128
-
129
- // Parse response
130
- const responseData = await this.parseResponse<T>(response, finalOptions.responseType);
131
-
132
- // Build API response object
133
- let apiResponse: ApiResponse<T> = {
134
- data: responseData,
135
- status: response.status,
136
- statusText: response.statusText,
137
- headers: response.headers,
138
- raw: response
139
- };
140
-
141
- // Apply response interceptor if configured
142
- if (this.config.responseInterceptor) {
143
- apiResponse = await this.config.responseInterceptor(apiResponse);
144
- }
145
-
146
- // Check if response is ok
147
- if (!response.ok) {
148
- throw this.createError(
149
- `HTTP Error ${response.status}: ${response.statusText}`,
150
- response.status,
151
- response.statusText,
152
- responseData
153
- );
154
- }
155
-
156
- return apiResponse;
157
-
158
- } catch (error: any) {
159
- // Create API error
160
- let apiError: ApiError;
161
-
162
- if (error.name === 'AbortError') {
163
- apiError = this.createError('Request timeout', undefined, undefined, undefined, error);
164
- } else if (error.message?.includes('HTTP Error')) {
165
- apiError = error;
166
- } else {
167
- apiError = this.createError(
168
- error.message || 'Network error',
169
- undefined,
170
- undefined,
171
- undefined,
172
- error
173
- );
174
- }
175
-
176
- // Apply error interceptor if configured
177
- if (this.config.errorInterceptor) {
178
- apiError = await this.config.errorInterceptor(apiError);
179
- }
180
-
181
- throw apiError;
182
- }
183
- }
184
-
185
- /**
186
- * Build final URL with baseURL and query parameters
187
- */
188
- private buildUrl(url: string, params?: Record<string, string | number | boolean>): string {
189
- let finalUrl = url;
190
-
191
- // Add baseURL if configured and URL is relative
192
- if (this.config.baseURL && !url.startsWith('http')) {
193
- finalUrl = `${this.config.baseURL.replace(/\/$/, '')}/${url.replace(/^\//, '')}`;
194
- }
195
-
196
- // Add query parameters
197
- if (params) {
198
- const queryString = Object.entries(params)
199
- .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
200
- .join('&');
201
-
202
- finalUrl += (finalUrl.includes('?') ? '&' : '?') + queryString;
203
- }
204
-
205
- return finalUrl;
206
- }
207
-
208
- /**
209
- * Build request headers
210
- */
211
- private buildHeaders(options: ApiRequestOptions): HeadersInit {
212
- const headers: Record<string, string> = {
213
- ...this.config.headers,
214
- ...options.headers
215
- };
216
-
217
- // Auto-add Content-Type for JSON body if not specified
218
- if (options.body && typeof options.body === 'object' && !headers['Content-Type']) {
219
- headers['Content-Type'] = 'application/json';
220
- }
221
-
222
- return headers;
223
- }
224
-
225
- /**
226
- * Build request body
227
- */
228
- private buildBody(body: any, _headers: HeadersInit): BodyInit | undefined {
229
- if (!body) {
230
- return undefined;
231
- }
232
-
233
- // If body is already a string, FormData, Blob, etc., return as-is
234
- if (typeof body === 'string' || body instanceof FormData || body instanceof Blob) {
235
- return body;
236
- }
237
-
238
- // Otherwise, stringify as JSON
239
- return JSON.stringify(body);
240
- }
241
-
242
- /**
243
- * Parse response based on response type
244
- */
245
- private async parseResponse<T>(response: Response, responseType?: string): Promise<T> {
246
- const type = responseType || 'json';
247
-
248
- switch (type) {
249
- case 'json':
250
- try {
251
- return await response.json();
252
- } catch {
253
- return null as T;
254
- }
255
- case 'text':
256
- return await response.text() as T;
257
- case 'blob':
258
- return await response.blob() as T;
259
- case 'arraybuffer':
260
- return await response.arrayBuffer() as T;
261
- default:
262
- return await response.json();
263
- }
264
- }
265
-
266
- /**
267
- * Create an API error object
268
- */
269
- private createError(
270
- message: string,
271
- status?: number,
272
- statusText?: string,
273
- data?: any,
274
- originalError?: Error
275
- ): ApiError {
276
- return {
277
- message,
278
- status,
279
- statusText,
280
- data,
281
- originalError: originalError || new Error(message)
282
- };
283
- }
284
- }
285
-
286
- /**
287
- * Singleton instance of API Core Service
288
- */
289
- export const apiCoreService = new ApiCoreService();
1
+ /**
2
+ * KIMU API Core Service
3
+ * Lightweight HTTP client based on native fetch API
4
+ * Zero dependencies, Promise-based, TypeScript-first
5
+ */
6
+
7
+ import {
8
+ ApiRequestOptions,
9
+ ApiResponse,
10
+ ApiError,
11
+ ApiConfig
12
+ } from './interfaces';
13
+
14
+ /**
15
+ * Main API service class for making HTTP requests
16
+ */
17
+ export class ApiCoreService {
18
+ private config: ApiConfig = {};
19
+
20
+ /**
21
+ * Configure the API service with global settings
22
+ * @param config - Global configuration options
23
+ */
24
+ configure(config: ApiConfig): void {
25
+ this.config = { ...this.config, ...config };
26
+ }
27
+
28
+ /**
29
+ * Make a GET request
30
+ * @param url - Request URL (relative to baseURL if configured)
31
+ * @param options - Request options
32
+ * @returns Promise with response data
33
+ */
34
+ async get<T = any>(url: string, options?: ApiRequestOptions): Promise<ApiResponse<T>> {
35
+ return this.request<T>(url, { ...options, method: 'GET' });
36
+ }
37
+
38
+ /**
39
+ * Make a POST request
40
+ * @param url - Request URL
41
+ * @param data - Request body data
42
+ * @param options - Request options
43
+ * @returns Promise with response data
44
+ */
45
+ async post<T = any>(url: string, data?: any, options?: ApiRequestOptions): Promise<ApiResponse<T>> {
46
+ return this.request<T>(url, { ...options, method: 'POST', body: data });
47
+ }
48
+
49
+ /**
50
+ * Make a PUT request
51
+ * @param url - Request URL
52
+ * @param data - Request body data
53
+ * @param options - Request options
54
+ * @returns Promise with response data
55
+ */
56
+ async put<T = any>(url: string, data?: any, options?: ApiRequestOptions): Promise<ApiResponse<T>> {
57
+ return this.request<T>(url, { ...options, method: 'PUT', body: data });
58
+ }
59
+
60
+ /**
61
+ * Make a PATCH request
62
+ * @param url - Request URL
63
+ * @param data - Request body data
64
+ * @param options - Request options
65
+ * @returns Promise with response data
66
+ */
67
+ async patch<T = any>(url: string, data?: any, options?: ApiRequestOptions): Promise<ApiResponse<T>> {
68
+ return this.request<T>(url, { ...options, method: 'PATCH', body: data });
69
+ }
70
+
71
+ /**
72
+ * Make a DELETE request
73
+ * @param url - Request URL
74
+ * @param options - Request options
75
+ * @returns Promise with response data
76
+ */
77
+ async delete<T = any>(url: string, options?: ApiRequestOptions): Promise<ApiResponse<T>> {
78
+ return this.request<T>(url, { ...options, method: 'DELETE' });
79
+ }
80
+
81
+ /**
82
+ * Make a generic HTTP request
83
+ * @param url - Request URL
84
+ * @param options - Request options
85
+ * @returns Promise with response data
86
+ */
87
+ async request<T = any>(url: string, options: ApiRequestOptions = {}): Promise<ApiResponse<T>> {
88
+ try {
89
+ // Apply request interceptor if configured
90
+ let finalOptions = options;
91
+ if (this.config.requestInterceptor) {
92
+ finalOptions = await this.config.requestInterceptor(options);
93
+ }
94
+
95
+ // Build final URL with baseURL and query params
96
+ const finalUrl = this.buildUrl(url, finalOptions.params);
97
+
98
+ // Build headers
99
+ const headers = this.buildHeaders(finalOptions);
100
+
101
+ // Build request body
102
+ const body = this.buildBody(finalOptions.body, headers);
103
+
104
+ // Setup timeout if specified
105
+ const controller = new AbortController();
106
+ const signal = finalOptions.signal || controller.signal;
107
+ const timeout = finalOptions.timeout || this.config.timeout;
108
+
109
+ let timeoutId: NodeJS.Timeout | undefined;
110
+ if (timeout) {
111
+ timeoutId = setTimeout(() => controller.abort(), timeout);
112
+ }
113
+
114
+ // Make fetch request
115
+ const response = await fetch(finalUrl, {
116
+ method: finalOptions.method || 'GET',
117
+ headers,
118
+ body,
119
+ credentials: finalOptions.credentials,
120
+ cache: finalOptions.cache,
121
+ signal
122
+ });
123
+
124
+ // Clear timeout
125
+ if (timeoutId) {
126
+ clearTimeout(timeoutId);
127
+ }
128
+
129
+ // Parse response
130
+ const responseData = await this.parseResponse<T>(response, finalOptions.responseType);
131
+
132
+ // Build API response object
133
+ let apiResponse: ApiResponse<T> = {
134
+ data: responseData,
135
+ status: response.status,
136
+ statusText: response.statusText,
137
+ headers: response.headers,
138
+ raw: response
139
+ };
140
+
141
+ // Apply response interceptor if configured
142
+ if (this.config.responseInterceptor) {
143
+ apiResponse = await this.config.responseInterceptor(apiResponse);
144
+ }
145
+
146
+ // Check if response is ok
147
+ if (!response.ok) {
148
+ throw this.createError(
149
+ `HTTP Error ${response.status}: ${response.statusText}`,
150
+ response.status,
151
+ response.statusText,
152
+ responseData
153
+ );
154
+ }
155
+
156
+ return apiResponse;
157
+
158
+ } catch (error: any) {
159
+ // Create API error
160
+ let apiError: ApiError;
161
+
162
+ if (error.name === 'AbortError') {
163
+ apiError = this.createError('Request timeout', undefined, undefined, undefined, error);
164
+ } else if (error.message?.includes('HTTP Error')) {
165
+ apiError = error;
166
+ } else {
167
+ apiError = this.createError(
168
+ error.message || 'Network error',
169
+ undefined,
170
+ undefined,
171
+ undefined,
172
+ error
173
+ );
174
+ }
175
+
176
+ // Apply error interceptor if configured
177
+ if (this.config.errorInterceptor) {
178
+ apiError = await this.config.errorInterceptor(apiError);
179
+ }
180
+
181
+ throw apiError;
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Build final URL with baseURL and query parameters
187
+ */
188
+ private buildUrl(url: string, params?: Record<string, string | number | boolean>): string {
189
+ let finalUrl = url;
190
+
191
+ // Add baseURL if configured and URL is relative
192
+ if (this.config.baseURL && !url.startsWith('http')) {
193
+ finalUrl = `${this.config.baseURL.replace(/\/$/, '')}/${url.replace(/^\//, '')}`;
194
+ }
195
+
196
+ // Add query parameters
197
+ if (params) {
198
+ const queryString = Object.entries(params)
199
+ .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
200
+ .join('&');
201
+
202
+ finalUrl += (finalUrl.includes('?') ? '&' : '?') + queryString;
203
+ }
204
+
205
+ return finalUrl;
206
+ }
207
+
208
+ /**
209
+ * Build request headers
210
+ */
211
+ private buildHeaders(options: ApiRequestOptions): HeadersInit {
212
+ const headers: Record<string, string> = {
213
+ ...this.config.headers,
214
+ ...options.headers
215
+ };
216
+
217
+ // Auto-add Content-Type for JSON body if not specified
218
+ if (options.body && typeof options.body === 'object' && !headers['Content-Type']) {
219
+ headers['Content-Type'] = 'application/json';
220
+ }
221
+
222
+ return headers;
223
+ }
224
+
225
+ /**
226
+ * Build request body
227
+ */
228
+ private buildBody(body: any, _headers: HeadersInit): BodyInit | undefined {
229
+ if (!body) {
230
+ return undefined;
231
+ }
232
+
233
+ // If body is already a string, FormData, Blob, etc., return as-is
234
+ if (typeof body === 'string' || body instanceof FormData || body instanceof Blob) {
235
+ return body;
236
+ }
237
+
238
+ // Otherwise, stringify as JSON
239
+ return JSON.stringify(body);
240
+ }
241
+
242
+ /**
243
+ * Parse response based on response type
244
+ */
245
+ private async parseResponse<T>(response: Response, responseType?: string): Promise<T> {
246
+ const type = responseType || 'json';
247
+
248
+ switch (type) {
249
+ case 'json':
250
+ try {
251
+ return await response.json();
252
+ } catch {
253
+ return null as T;
254
+ }
255
+ case 'text':
256
+ return await response.text() as T;
257
+ case 'blob':
258
+ return await response.blob() as T;
259
+ case 'arraybuffer':
260
+ return await response.arrayBuffer() as T;
261
+ default:
262
+ return await response.json();
263
+ }
264
+ }
265
+
266
+ /**
267
+ * Create an API error object
268
+ */
269
+ private createError(
270
+ message: string,
271
+ status?: number,
272
+ statusText?: string,
273
+ data?: any,
274
+ originalError?: Error
275
+ ): ApiError {
276
+ return {
277
+ message,
278
+ status,
279
+ statusText,
280
+ data,
281
+ originalError: originalError || new Error(message)
282
+ };
283
+ }
284
+ }
285
+
286
+ /**
287
+ * Singleton instance of API Core Service
288
+ */
289
+ export const apiCoreService = new ApiCoreService();