divhunt 2.0.6 → 2.0.9

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 (39) hide show
  1. package/addons/core/commands/back/functions/expose.js +14 -0
  2. package/addons/core/commands/back/functions/find.js +1 -1
  3. package/addons/core/commands/back/functions/grpc/client.js +1 -1
  4. package/addons/core/commands/back/functions/grpc/server.js +1 -1
  5. package/addons/core/commands/back/functions/hide.js +14 -0
  6. package/addons/core/commands/back/functions/http/server.js +1 -1
  7. package/addons/core/commands/back/items/{many.js → self/many.js} +2 -4
  8. package/addons/core/commands/back/items/{one.js → self/one.js} +2 -4
  9. package/addons/core/commands/back/items/{run.js → self/run.js} +3 -7
  10. package/addons/core/commands/core/functions/run.js +13 -0
  11. package/addons/core/commands/{back → core}/item/functions/run.js +1 -1
  12. package/addons/core/commands/core/load.js +25 -0
  13. package/addons/core/commands/front/directives/run.js +84 -0
  14. package/addons/core/commands/front/directives/submit.js +150 -0
  15. package/addons/core/commands/front/functions/api.js +30 -0
  16. package/addons/render/assets/back/functions/import.js +1 -1
  17. package/examples/basic-front/back/assets.js +11 -0
  18. package/examples/basic-front/back/index.js +13 -0
  19. package/examples/basic-front/back/items/commands/html.js +14 -0
  20. package/examples/basic-front/back/items/commands/test.js +19 -0
  21. package/examples/basic-front/back/items/html/fonts.js +12 -0
  22. package/examples/basic-front/front/pages/home.js +16 -0
  23. package/examples/basic-front/front/styles/main.css +31 -0
  24. package/examples/basic-front/front/test.js +7 -0
  25. package/examples/basic-front/package.json +7 -0
  26. package/lib/src/divhunt.js +2 -0
  27. package/lib/src/mixins/form.js +67 -0
  28. package/package.json +3 -3
  29. package/test/front/test.js +31 -0
  30. package/test.js +52 -0
  31. package/addons/core/commands/LICENSE.txt +0 -40
  32. package/addons/core/commands/README.md +0 -294
  33. package/addons/core/commands/back/load.js +0 -18
  34. package/addons/core/commands/front/#register/addon.js +0 -9
  35. package/addons/core/commands/front/functions/find.js +0 -22
  36. package/addons/core/commands/front/item/functions/run.js +0 -96
  37. package/addons/core/commands/front/items/elements/table/table.css +0 -18
  38. package/addons/core/commands/front/items/elements/table/table.js +0 -254
  39. /package/addons/core/commands/{back → core}/addon.js +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "divhunt",
3
- "version": "2.0.6",
3
+ "version": "2.0.9",
4
4
  "description": "Full-stack isomorphic JavaScript framework built from scratch. One addon abstraction powers databases, servers, commands, pages, directives, queues, and more.",
5
5
  "type": "module",
6
6
  "main": "lib/load.js",
@@ -13,7 +13,7 @@
13
13
  "./servers/http": "./addons/core/servers/back/http/load.js",
14
14
  "./clients/grpc": "./addons/core/clients/back/grpc/load.js",
15
15
  "./clients/http": "./addons/core/clients/back/http/load.js",
16
- "./commands": "./addons/core/commands/back/load.js",
16
+ "./commands": "./addons/core/commands/core/load.js",
17
17
  "./queue": "./addons/core/queue/back/load.js",
18
18
  "./assets": "./addons/render/assets/back/load.js",
19
19
  "./html": "./addons/render/html/load.js",
@@ -26,7 +26,7 @@
26
26
  "#database/*": "./addons/core/database/back/*",
27
27
  "#servers/*": "./addons/core/servers/back/*",
28
28
  "#clients/*": "./addons/core/clients/back/*",
29
- "#commands/*": "./addons/core/commands/back/*",
29
+ "#commands/*": "./addons/core/commands/*",
30
30
  "#queue/*": "./addons/core/queue/back/*",
31
31
  "#assets/*": "./addons/render/assets/back/*",
32
32
  "#html/*": "./addons/render/html/*",
@@ -0,0 +1,31 @@
1
+ pages.Item({
2
+ id: 'home',
3
+ route: '/',
4
+ title: 'dh-command test',
5
+ grid: {
6
+ template: '"content"',
7
+ columns: '1fr',
8
+ rows: '1fr'
9
+ },
10
+ areas: {
11
+ content: function()
12
+ {
13
+ return `
14
+ {{ name }}
15
+ <h1>dh-command test</h1>
16
+
17
+ <dh-command command="test" :api="true" bind="test2" :data='{"name": "dejan"}'>
18
+ <p dh-if="test.loading">Loading...</p>
19
+ <p dh-if="test.error">Error: {{test.error}}</p>
20
+ <p dh-if="test.response">{{test.response.message}}</p>
21
+ </dh-command>
22
+
23
+ <dh-command command="test" :api="true" bind="test" :data='{"name": "dejan"}'>
24
+ <p dh-if="test.loading">Loading...</p>
25
+ <p dh-if="test.error">Error: {{test.error}}</p>
26
+ <p dh-if="test.response">{{test.response.message}}</p>
27
+ </dh-command>
28
+ `;
29
+ }
30
+ }
31
+ });
package/test.js ADDED
@@ -0,0 +1,52 @@
1
+ import { dirname, resolve } from 'path';
2
+ import { fileURLToPath } from 'url';
3
+
4
+ const root = resolve(dirname(fileURLToPath(import.meta.url)));
5
+
6
+ import assets from './addons/render/assets/back/load.js';
7
+ import commands from './addons/core/commands/core/load.js';
8
+ import html from './addons/render/html/load.js';
9
+
10
+ assets.Fn('import', ['framework', 'directives', 'commands', 'pages']);
11
+ assets.Item({ type: 'js', order: 10, path: resolve(root, 'test/front') });
12
+ assets.Item({ type: 'css', order: 10, path: resolve(root, 'test/front') });
13
+
14
+ commands.Item({
15
+ id: 'html',
16
+ exposed: true,
17
+ method: 'GET',
18
+ endpoint: '*',
19
+ type: 'HTML',
20
+ callback: async function(properties, resolve)
21
+ {
22
+ resolve(html.Fn('render'));
23
+ }
24
+ });
25
+
26
+ commands.Item({
27
+ id: 'test',
28
+ exposed: true,
29
+ method: 'POST',
30
+ endpoint: '/api/test',
31
+ type: 'JSON',
32
+ in: {
33
+ name: ['string', 'World']
34
+ },
35
+ out: {
36
+ message: ['string']
37
+ },
38
+ callback: async function(properties, resolve)
39
+ {
40
+ resolve({ message: 'Hello, ' + properties.name + '!' });
41
+ }
42
+ });
43
+
44
+
45
+ commands.Fn('expose', 'commands:run', '/api/commands/run');
46
+
47
+ await commands.Fn('http.server', 3000, {
48
+ onStart: () =>
49
+ {
50
+ console.log('test server running on http://localhost:3000');
51
+ }
52
+ });
@@ -1,40 +0,0 @@
1
- Copyright © 2025 Divhunt GmbH
2
-
3
- This License governs use of the Divhunt framework (the "Software"). By accessing or using the Software, you agree to be bound by the terms of this License.
4
-
5
- 1. GRANT OF LICENSE
6
- You are granted a limited, non-exclusive, non-transferable, non-sublicensable license to use the Software solely for:
7
- - personal projects;
8
- - internal business purposes;
9
- - client work, provided the client is not reselling or redistributing the Software.
10
-
11
- 2. ATTRIBUTION AND BRANDING
12
- a. All uses of the Software must retain visible attribution to “Divhunt”.
13
- b. You must not remove, obscure, alter, or suppress any branding, notices, or credits related to Divhunt.
14
- c. Any public project using the Software must clearly state that it uses the “Divhunt Framework”.
15
-
16
- 3. PROHIBITED USES
17
- The following are strictly prohibited:
18
- a. Rebranding, renaming, or representing the Software as your own work;
19
- b. Creating derivative frameworks or similar software tools based on the Software with the intent of distribution;
20
- c. Redistributing, sublicensing, or selling the Software or any modified version thereof;
21
- d. Using the Software in any commercial product, service, or offering without explicit, written permission from Divhunt GmbH.
22
-
23
- 4. MODIFICATIONS
24
- You may modify the Software for personal or internal use only. Modified versions may not be:
25
- - redistributed;
26
- - rebranded or marketed as original work;
27
- - offered as a service or product.
28
-
29
- 5. ENFORCEMENT AND TERMINATION
30
- Any violation of this License will result in the immediate termination of all rights granted herein. Divhunt GmbH reserves the right to pursue legal remedies including but not limited to damages, injunctions, and recovery of profits obtained through unauthorized use.
31
-
32
- 6. NO WARRANTY
33
- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. IN NO EVENT SHALL JOVANAT GMBH BE LIABLE FOR ANY DAMAGES ARISING FROM THE USE OR INABILITY TO USE THE SOFTWARE.
34
-
35
- 7. GOVERNING LAW
36
- This License shall be governed by and construed in accordance with the laws of Switzerland. All disputes shall be subject to the exclusive jurisdiction of the courts of Zug, Switzerland.
37
-
38
- ---
39
-
40
- For commercial licensing or other questions, please contact: **dejan@divhunt.com**
@@ -1,294 +0,0 @@
1
- ## Built with the Divhunt Framework – non-commercial use only. For commercial use, contact dejan@divhunt.com.
2
-
3
- # Commands Addon
4
-
5
- The Commands addon provides a structured way to define and manage API endpoints with automatic validation, routing, and response formatting.
6
-
7
- ## Basic Usage
8
-
9
- ### Creating a Command
10
-
11
- ```javascript
12
- import commands from '#commands/load.js';
13
-
14
- commands.Item({
15
- id: 'users:create',
16
- method: 'POST',
17
- endpoint: '/api/users',
18
- type: 'JSON',
19
- description: 'Create a new user',
20
- in: {
21
- name: ['string', null, true],
22
- email: ['string', null, true],
23
- age: ['number']
24
- },
25
- out: {
26
- user: {
27
- type: 'object',
28
- config: {
29
- id: ['string'],
30
- name: ['string'],
31
- email: ['string']
32
- }
33
- }
34
- },
35
- callback: async function(properties, resolve) {
36
- // Your logic here
37
- const user = createUser(properties);
38
- resolve({user});
39
- }
40
- });
41
- ```
42
-
43
- ## Command Properties
44
-
45
- ### Required Fields
46
-
47
- - **id** - Unique identifier for the command
48
- - **callback** - Function that executes the command logic
49
-
50
- ### Optional Fields
51
-
52
- - **method** - HTTP method (`GET`, `POST`, `PUT`, `DELETE`). Default: `GET`
53
- - **endpoint** - URL pattern (supports route parameters with `:param`)
54
- - **type** - Response type (`JSON`, `HTML`, `CSS`, `JSS`). Default: `JSON`
55
- - **description** - Human-readable description
56
- - **in** - Input validation schema
57
- - **out** - Output validation schema
58
-
59
- ## Route Parameters
60
-
61
- Use `:parameter` syntax in endpoints to capture URL segments:
62
-
63
- ```javascript
64
- commands.Item({
65
- id: 'users:get:one',
66
- method: 'GET',
67
- endpoint: '/api/users/:id',
68
- in: {
69
- id: ['string', null, true]
70
- },
71
- callback: async function(properties, resolve) {
72
- // properties.id contains the URL parameter
73
- const user = await findUser(properties.id);
74
- resolve({user});
75
- }
76
- });
77
- ```
78
-
79
- ## Input Validation
80
-
81
- Define input schemas to automatically validate request data:
82
-
83
- ```javascript
84
- // Simple validation
85
- in: {
86
- name: ['string', null, true], // required string
87
- age: ['number', 18], // optional number, default 18
88
- active: ['boolean', true] // optional boolean, default true
89
- }
90
-
91
- // Complex validation
92
- in: {
93
- user: {
94
- type: 'object',
95
- config: {
96
- profile: {
97
- type: 'object',
98
- config: {
99
- name: ['string', null, true],
100
- contacts: {
101
- type: 'array',
102
- each: {
103
- type: 'object',
104
- config: {
105
- type: ['string'],
106
- value: ['string']
107
- }
108
- }
109
- }
110
- }
111
- }
112
- }
113
- }
114
- }
115
-
116
- // Using predefined schemas
117
- in: 'user --skip=id --skip=created_at'
118
- ```
119
-
120
- ## Output Validation
121
-
122
- Define output schemas to validate and format responses:
123
-
124
- ```javascript
125
- out: {
126
- users: {
127
- type: 'array',
128
- each: {
129
- type: 'object',
130
- config: {
131
- id: ['string'],
132
- name: ['string'],
133
- email: ['string']
134
- }
135
- }
136
- },
137
- total: ['number', null, true],
138
- page: ['number', null, true]
139
- }
140
- ```
141
-
142
- ## Callback Function
143
-
144
- The callback receives two parameters:
145
-
146
- ```javascript
147
- callback: async function(properties, resolve) {
148
- // properties - validated input data
149
- // resolve(data, message, code) - response function
150
-
151
- try {
152
- const result = await doSomething(properties);
153
- resolve(result); // Success with default message and 200 code
154
- } catch (error) {
155
- resolve(null, 'Error occurred', 500);
156
- }
157
- }
158
- ```
159
-
160
- ### Resolve Function
161
-
162
- ```javascript
163
- resolve(data, message, code)
164
- ```
165
-
166
- - **data** - Response data (will be validated against `out` schema)
167
- - **message** - Response message (optional, has default)
168
- - **code** - HTTP status code (optional, default: 200)
169
-
170
- ## Finding Commands
171
-
172
- ### Find by Method and Path
173
-
174
- ```javascript
175
- const command = commands.Fn('find', 'GET', '/api/users/123');
176
- ```
177
-
178
- ## Running Commands
179
-
180
- ```javascript
181
- const command = commands.ItemGet('users:create');
182
- const result = await command.Fn('run', inputData, context);
183
-
184
- // Returns:
185
- // {
186
- // data: {...}, // Validated output
187
- // message: "...", // Success/error message
188
- // code: 200 // HTTP status code
189
- // }
190
- ```
191
-
192
- ## Response Types
193
-
194
- ### JSON (Default)
195
-
196
- ```javascript
197
- type: 'JSON' // Returns application/json
198
- ```
199
-
200
- ### HTML
201
-
202
- ```javascript
203
- type: 'HTML' // Returns text/html
204
- ```
205
-
206
- ### CSS
207
-
208
- ```javascript
209
- type: 'CSS' // Returns text/css
210
- ```
211
-
212
- ### JavaScript
213
-
214
- ```javascript
215
- type: 'JSS' // Returns application/javascript
216
- ```
217
-
218
- ## Built-in Commands
219
-
220
- The addon includes two built-in commands:
221
-
222
- ### List All Commands
223
-
224
- ```
225
- GET /api/commands
226
- ```
227
-
228
- Returns all registered commands with their metadata.
229
-
230
- ### Get Single Command
231
-
232
- ```
233
- GET /api/commands/:id
234
- ```
235
-
236
- Returns details for a specific command.
237
-
238
- ## Data Type Hints
239
-
240
- Use type hints in property names for automatic conversion:
241
-
242
- ```javascript
243
- // URL: /api/users?age:number=25&active:boolean=true&tags:array=tag1,tag2
244
-
245
- // Converts to:
246
- // {
247
- // age: 25, // number
248
- // active: true, // boolean
249
- // tags: ['tag1', 'tag2'] // array
250
- // }
251
- ```
252
-
253
- Available hints:
254
- - `:number` - Convert to number
255
- - `:string` - Convert to string
256
- - `:boolean` - Convert to boolean (`true`, `1`, `false`, `0`)
257
- - `:array` - Convert to array (comma-separated or JSON)
258
- - `:object` - Convert to object (JSON)
259
-
260
- ## Error Handling
261
-
262
- Commands automatically handle validation errors and return appropriate error responses:
263
-
264
- ```javascript
265
- // Input validation error
266
- {
267
- data: "Error message",
268
- message: "Request contains invalid parameters.",
269
- code: 400
270
- }
271
-
272
- // Command not found
273
- {
274
- data: {},
275
- message: "Command does not exist.",
276
- code: 404
277
- }
278
-
279
- // Server error
280
- {
281
- data: {},
282
- message: "Command could not be completed.",
283
- code: 500
284
- }
285
- ```
286
-
287
- ## Best Practices
288
-
289
- 1. **Use descriptive IDs** - Follow pattern `resource:action` or `resource:action:modifier`
290
- 2. **Validate inputs** - Always define `in` schema for data integrity
291
- 3. **Handle errors gracefully** - Use try/catch and appropriate error codes
292
- 4. **Use route parameters** - Prefer `/users/:id` over query parameters for resources
293
- 5. **Document commands** - Add meaningful descriptions
294
- 6. **Consistent responses** - Use standard response format across commands# commands
@@ -1,18 +0,0 @@
1
- import commands from './addon.js';
2
-
3
- import './functions/find.js';
4
- import './item/functions/run.js';
5
-
6
- /* gRPC */
7
- import './functions/grpc/server.js';
8
- import './functions/grpc/client.js';
9
-
10
- /* HTTP */
11
- import './functions/http/server.js';
12
-
13
- /* Items */
14
- import './items/one.js';
15
- import './items/many.js';
16
- import './items/run.js';
17
-
18
- export default commands;
@@ -1,9 +0,0 @@
1
- const commands = divhunt.Addon('commands', (addon) =>
2
- {
3
- addon.Field('id', ['string']);
4
- addon.Field('type', ['string', 'JSON']);
5
- addon.Field('description', ['string']);
6
- addon.Field('in', ['object|string']);
7
- addon.Field('out', ['object|string']);
8
- addon.Field('callback', ['function']);
9
- });
@@ -1,22 +0,0 @@
1
- commands.Fn('find', function(method, pathname)
2
- {
3
- const items = Object.values(this.Items());
4
-
5
- for (const item of items)
6
- {
7
- if (item.Get('method') !== method)
8
- {
9
- continue;
10
- }
11
-
12
- const endpoint = item.Get('endpoint');
13
- const result = divhunt.RouteMatch(endpoint, pathname);
14
-
15
- if (result.match)
16
- {
17
- return item;
18
- }
19
- }
20
-
21
- return null;
22
- });
@@ -1,96 +0,0 @@
1
- commands.Fn('item.run', function(item, properties = {}, context = {})
2
- {
3
- this.methods.resolve = null;
4
- this.methods.reject = null;
5
-
6
- this.methods.init = async (resolve, reject) =>
7
- {
8
- this.methods.resolve = resolve;
9
- this.methods.reject = reject;
10
-
11
- if(item.Get('in'))
12
- {
13
- try
14
- {
15
- properties = divhunt.DataDefine(properties, item.Get('in'));
16
- }
17
- catch(error)
18
- {
19
- return this.methods.resolve({data: error.message, message: 'Request contains invalid parameters.', code: 400});
20
- }
21
- }
22
-
23
- if(item.Get('callback'))
24
- {
25
- await item.Get('callback').call(context, properties, {callback: this.methods.callback});
26
- }
27
- else
28
- {
29
- const options = {
30
- method: 'POST',
31
- headers: {
32
- 'Content-Type': 'application/json'
33
- },
34
- body: JSON.stringify({
35
- id: item.Get('id'),
36
- in: properties
37
- })
38
- };
39
-
40
- try
41
- {
42
- const response = await fetch('/api/commands/run', options);
43
- const result = await response.json();
44
-
45
- if(result.code !== 200)
46
- {
47
- throw new Error(result.message);
48
- }
49
-
50
- return this.methods.callback(result.data.data, result.data.message, result.data.code);
51
- }
52
- catch(error)
53
- {
54
- return this.methods.callback(null, error.message, 500);
55
- }
56
- }
57
- };
58
-
59
- this.methods.callback = (data, message = "Command '{{command}}' executed successfully.", code = 200) =>
60
- {
61
- if(message === null && code === 404)
62
- {
63
- message = 'The requested resource cannot be found.';
64
- }
65
-
66
- if(code >= 200 && code < 300 && item.Get('out'))
67
- {
68
- try
69
- {
70
- data = divhunt.DataDefine(data, item.Get('out'));
71
- }
72
- catch(error)
73
- {
74
- throw new Error('Command OUT Error. ' + error.message);
75
- }
76
- }
77
- else if(code < 200 || code >= 300)
78
- {
79
- data = {};
80
- }
81
-
82
- this.methods.resolve({data, message: message?.replace('{{command}}', item.Get('id')), code});
83
- };
84
-
85
- return new Promise((resolve, reject) =>
86
- {
87
- try
88
- {
89
- this.methods.init(resolve, reject);
90
- }
91
- catch(error)
92
- {
93
- this.methods.resolve({data: error.message, message: 'Internal server error.', code: 500});
94
- }
95
- });
96
- });
@@ -1,18 +0,0 @@
1
- /* Base */
2
- .e-cmd-table > .holder
3
- {
4
- display: flex;
5
- flex-direction: column;
6
- }
7
-
8
- .e-cmd-table > .holder > .error
9
- {
10
- display: flex;
11
- align-items: center;
12
- justify-content: center;
13
- padding: var(--dh-spacing-l);
14
- color: var(--dh-red);
15
- font-size: var(--dh-size-m);
16
- background: var(--dh-red-opacity);
17
- border-radius: var(--dh-radius-m);
18
- }