@objectql/starter-basic 1.6.1

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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +17 -0
  3. package/dist/demo.app.yml +4 -0
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.js +18 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/main.menu.yml +30 -0
  8. package/dist/modules/kitchen-sink/kitchen_sink.data.yml +18 -0
  9. package/dist/modules/kitchen-sink/kitchen_sink.object.yml +154 -0
  10. package/dist/modules/projects/pages/create_project_wizard.page.yml +244 -0
  11. package/dist/modules/projects/pages/project_detail.page.yml +258 -0
  12. package/dist/modules/projects/project_approval.workflow.yml +51 -0
  13. package/dist/modules/projects/project_status.report.yml +39 -0
  14. package/dist/modules/projects/projects.action.d.ts +104 -0
  15. package/dist/modules/projects/projects.action.js +363 -0
  16. package/dist/modules/projects/projects.action.js.map +1 -0
  17. package/dist/modules/projects/projects.data.yml +13 -0
  18. package/dist/modules/projects/projects.form.yml +41 -0
  19. package/dist/modules/projects/projects.hook.d.ts +15 -0
  20. package/dist/modules/projects/projects.hook.js +302 -0
  21. package/dist/modules/projects/projects.hook.js.map +1 -0
  22. package/dist/modules/projects/projects.object.yml +148 -0
  23. package/dist/modules/projects/projects.permission.yml +141 -0
  24. package/dist/modules/projects/projects.validation.yml +37 -0
  25. package/dist/modules/projects/projects.view.yml +35 -0
  26. package/dist/modules/tasks/tasks.data.yml +23 -0
  27. package/dist/modules/tasks/tasks.object.yml +34 -0
  28. package/dist/modules/tasks/tasks.permission.yml +167 -0
  29. package/dist/pages/dashboard.page.yml +206 -0
  30. package/dist/pages/landing.page.yml +275 -0
  31. package/dist/types/index.d.ts +3 -0
  32. package/dist/types/index.js +20 -0
  33. package/dist/types/index.js.map +1 -0
  34. package/dist/types/kitchen_sink.d.ts +99 -0
  35. package/dist/types/kitchen_sink.js +3 -0
  36. package/dist/types/kitchen_sink.js.map +1 -0
  37. package/dist/types/projects.d.ts +47 -0
  38. package/dist/types/projects.js +3 -0
  39. package/dist/types/projects.js.map +1 -0
  40. package/dist/types/tasks.d.ts +31 -0
  41. package/dist/types/tasks.js +3 -0
  42. package/dist/types/tasks.js.map +1 -0
  43. package/package.json +38 -0
@@ -0,0 +1,302 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * Project Hooks - Comprehensive Example
5
+ *
6
+ * This file demonstrates all major hook patterns according to the ObjectQL specification:
7
+ * 1. Data validation and defaulting (beforeCreate)
8
+ * 2. Query modification for security (beforeFind)
9
+ * 3. State transition validation (beforeUpdate)
10
+ * 4. Change tracking and notifications (afterUpdate)
11
+ * 5. Dependency checking (beforeDelete)
12
+ * 6. Side effects and cleanup (afterDelete)
13
+ */
14
+ const hooks = {
15
+ /**
16
+ * beforeCreate - Data Validation & Defaulting
17
+ *
18
+ * Use case:
19
+ * - Set default values
20
+ * - Auto-assign ownership
21
+ * - Validate business rules
22
+ * - Check for duplicates
23
+ */
24
+ beforeCreate: async ({ data, user, api }) => {
25
+ // 1. Auto-assign owner if not specified
26
+ if (data && !data.owner && (user === null || user === void 0 ? void 0 : user.id)) {
27
+ console.log(`[Hook] Projects: Auto-assigning owner ${user.id}`);
28
+ data.owner = String(user.id);
29
+ }
30
+ // 2. Set default status if not provided
31
+ if (data && !data.status) {
32
+ data.status = 'planned';
33
+ }
34
+ // 3. Validate required fields
35
+ if (data && (!data.name || data.name.trim().length === 0)) {
36
+ throw new Error('Project name is required');
37
+ }
38
+ // 4. Validate name length
39
+ if (data && data.name && data.name.length > 100) {
40
+ throw new Error('Project name must be 100 characters or less');
41
+ }
42
+ // 5. Check for duplicate names (using API)
43
+ if (data && data.name) {
44
+ const existing = await api.count('projects', [['name', '=', data.name]]);
45
+ if (existing > 0) {
46
+ throw new Error(`A project named "${data.name}" already exists`);
47
+ }
48
+ }
49
+ // 6. Set initial budget if not provided
50
+ if (data && !data.budget) {
51
+ data.budget = 0;
52
+ }
53
+ },
54
+ /**
55
+ * afterCreate - Side Effects
56
+ *
57
+ * Use case:
58
+ * - Send notifications
59
+ * - Create related records
60
+ * - Log audit trail
61
+ * - Trigger workflows
62
+ */
63
+ afterCreate: async ({ result, user, api, state }) => {
64
+ console.log(`[Hook] Projects: Project created - ${result === null || result === void 0 ? void 0 : result.name} by ${user === null || user === void 0 ? void 0 : user.id}`);
65
+ // Example: Create a default task for new projects
66
+ // Uncomment if tasks object exists
67
+ /*
68
+ if (result) {
69
+ await api.create('tasks', {
70
+ name: 'Setup Project',
71
+ project_id: result._id,
72
+ status: 'pending',
73
+ description: 'Initial project setup task'
74
+ });
75
+ }
76
+ */
77
+ },
78
+ /**
79
+ * beforeFind - Query Filtering for Security
80
+ *
81
+ * Use case:
82
+ * - Enforce multi-tenancy
83
+ * - Apply row-level security
84
+ * - Add default filters
85
+ * - Restrict data access based on user role
86
+ */
87
+ beforeFind: async ({ query, user, api }) => {
88
+ // Example: If not admin, restrict to own projects
89
+ // Uncomment to enable row-level security
90
+ /*
91
+ if (user && !user.isAdmin) {
92
+ // Add filter to only show projects owned by current user
93
+ if (!query.filters) {
94
+ query.filters = [];
95
+ }
96
+ query.filters.push(['owner', '=', user.id]);
97
+ console.log(`[Hook] Projects: Filtering to user ${user.id}'s projects`);
98
+ }
99
+ */
100
+ // Example: Add default sort
101
+ if (!query.sort) {
102
+ query.sort = [{ field: 'created_at', direction: 'desc' }];
103
+ }
104
+ },
105
+ /**
106
+ * afterFind - Result Transformation
107
+ *
108
+ * Use case:
109
+ * - Add computed fields
110
+ * - Mask sensitive data
111
+ * - Enrich data from external sources
112
+ * - Transform dates/formats
113
+ */
114
+ afterFind: async ({ result, user }) => {
115
+ // Example: Add computed progress field based on status
116
+ if (Array.isArray(result)) {
117
+ result.forEach((project) => {
118
+ switch (project.status) {
119
+ case 'planned':
120
+ project.progress = 0;
121
+ break;
122
+ case 'in_progress':
123
+ project.progress = 50;
124
+ break;
125
+ case 'completed':
126
+ project.progress = 100;
127
+ break;
128
+ default:
129
+ project.progress = 0;
130
+ }
131
+ });
132
+ }
133
+ },
134
+ /**
135
+ * beforeUpdate - State Transition Validation
136
+ *
137
+ * Use case:
138
+ * - Validate state machine transitions
139
+ * - Check permissions for specific updates
140
+ * - Validate budget changes
141
+ * - Track modifications
142
+ */
143
+ beforeUpdate: async ({ data, previousData, isModified, user, state }) => {
144
+ // 1. Check budget constraints
145
+ if (isModified('budget')) {
146
+ if (data && data.budget != undefined && data.budget < 0) {
147
+ throw new Error('Budget cannot be negative');
148
+ }
149
+ if (data && data.budget != undefined && previousData && data.budget < (previousData.budget || 0)) {
150
+ console.warn(`[Hook] Projects: Budget reduced from ${previousData.budget} to ${data.budget}`);
151
+ // Optional: Require approval for budget reduction
152
+ /*
153
+ if ((previousData.budget || 0) - data.budget > 10000) {
154
+ throw new Error('Budget reductions over $10,000 require approval');
155
+ }
156
+ */
157
+ }
158
+ }
159
+ // 2. Validate status transitions
160
+ if (isModified('status') && previousData) {
161
+ const oldStatus = previousData.status;
162
+ const newStatus = data === null || data === void 0 ? void 0 : data.status;
163
+ // Define valid transitions
164
+ const validTransitions = {
165
+ 'planned': ['in_progress'],
166
+ 'in_progress': ['completed', 'planned'], // Can go back to planning
167
+ 'completed': [] // Cannot change from completed
168
+ };
169
+ if (oldStatus && newStatus) {
170
+ const allowed = validTransitions[oldStatus] || [];
171
+ if (!allowed.includes(newStatus)) {
172
+ throw new Error(`Invalid status transition: cannot change from "${oldStatus}" to "${newStatus}"`);
173
+ }
174
+ }
175
+ }
176
+ // 3. Require end_date when marking as completed
177
+ if (isModified('status') && (data === null || data === void 0 ? void 0 : data.status) === 'completed') {
178
+ if (!data.end_date && !(previousData === null || previousData === void 0 ? void 0 : previousData.end_date)) {
179
+ throw new Error('End date is required when completing a project');
180
+ }
181
+ }
182
+ // 4. Store change summary in state for afterUpdate hook
183
+ if (isModified('status')) {
184
+ state.statusChanged = true;
185
+ state.oldStatus = previousData === null || previousData === void 0 ? void 0 : previousData.status;
186
+ state.newStatus = data === null || data === void 0 ? void 0 : data.status;
187
+ }
188
+ },
189
+ /**
190
+ * afterUpdate - Change Notifications & Side Effects
191
+ *
192
+ * Use case:
193
+ * - Send notifications based on changes
194
+ * - Update related records
195
+ * - Trigger workflows
196
+ * - Log audit trail
197
+ */
198
+ afterUpdate: async ({ isModified, data, previousData, result, state, api, user }) => {
199
+ // 1. Notify on status change
200
+ if (state.statusChanged) {
201
+ console.log(`[Hook] Projects: Status changed from "${state.oldStatus}" to "${state.newStatus}" by ${user === null || user === void 0 ? void 0 : user.id}`);
202
+ // Example: Create notification record
203
+ /*
204
+ if (data.status === 'completed' && previousData?.owner) {
205
+ await api.create('notifications', {
206
+ user_id: previousData.owner,
207
+ message: `Project "${result?.name}" has been completed!`,
208
+ type: 'project_completed',
209
+ link: `/projects/${result?._id}`
210
+ });
211
+ }
212
+ */
213
+ }
214
+ // 2. Notify on budget changes over threshold
215
+ if (isModified('budget') && previousData) {
216
+ const oldBudget = previousData.budget || 0;
217
+ const newBudget = (data === null || data === void 0 ? void 0 : data.budget) || 0;
218
+ const change = Math.abs(newBudget - oldBudget);
219
+ if (change > 5000) {
220
+ console.log(`[Hook] Projects: Significant budget change detected: ${oldBudget} -> ${newBudget}`);
221
+ }
222
+ }
223
+ // 3. Update related tasks when project is completed
224
+ /*
225
+ if (data.status === 'completed') {
226
+ await api.updateMany('tasks',
227
+ { filters: [['project_id', '=', result._id]] },
228
+ { status: 'completed' }
229
+ );
230
+ }
231
+ */
232
+ },
233
+ /**
234
+ * beforeDelete - Dependency Checking
235
+ *
236
+ * Use case:
237
+ * - Prevent deletion if dependencies exist
238
+ * - Check permissions
239
+ * - Validate business rules
240
+ */
241
+ beforeDelete: async ({ id, previousData, api, user }) => {
242
+ // 1. Prevent deletion of completed projects
243
+ if ((previousData === null || previousData === void 0 ? void 0 : previousData.status) === 'completed') {
244
+ throw new Error('Cannot delete completed projects. Please archive instead.');
245
+ }
246
+ // 2. Check for dependent tasks
247
+ /*
248
+ const taskCount = await api.count('tasks', [['project_id', '=', id]]);
249
+
250
+ if (taskCount > 0) {
251
+ throw new Error(
252
+ `Cannot delete project: ${taskCount} tasks are still associated with it. ` +
253
+ 'Please delete or reassign tasks first.'
254
+ );
255
+ }
256
+ */
257
+ // 3. Require admin permission for deletion
258
+ /*
259
+ if (!user?.isAdmin) {
260
+ throw new Error('Only administrators can delete projects');
261
+ }
262
+ */
263
+ console.log(`[Hook] Projects: Preparing to delete project ${id}`);
264
+ },
265
+ /**
266
+ * afterDelete - Cleanup & Side Effects
267
+ *
268
+ * Use case:
269
+ * - Delete related records (cascade)
270
+ * - Clean up external resources
271
+ * - Send notifications
272
+ * - Log audit trail
273
+ */
274
+ afterDelete: async ({ id, previousData, api, user }) => {
275
+ console.log(`[Hook] Projects: Project deleted - ${previousData === null || previousData === void 0 ? void 0 : previousData.name} by ${user === null || user === void 0 ? void 0 : user.id}`);
276
+ // Example: Clean up related data
277
+ /*
278
+ // Delete associated tasks
279
+ await api.deleteMany('tasks', {
280
+ filters: [['project_id', '=', id]]
281
+ });
282
+
283
+ // Delete associated files from S3
284
+ if (previousData?.attachments) {
285
+ for (const attachment of previousData.attachments) {
286
+ await deleteFromS3(attachment.key);
287
+ }
288
+ }
289
+
290
+ // Create audit log
291
+ await api.create('audit_logs', {
292
+ action: 'project_deleted',
293
+ entity_id: id,
294
+ entity_name: previousData?.name,
295
+ user_id: user?.id,
296
+ timestamp: new Date()
297
+ });
298
+ */
299
+ }
300
+ };
301
+ exports.default = hooks;
302
+ //# sourceMappingURL=projects.hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.hook.js","sourceRoot":"","sources":["../../../src/modules/projects/projects.hook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,148 @@
1
+ label: Project
2
+ icon: building-line
3
+ fields:
4
+ name:
5
+ type: text
6
+ required: true
7
+ index: true # Field-level index
8
+
9
+ status:
10
+ options:
11
+ - planned
12
+ - in_progress
13
+ - completed
14
+ defaultValue: planned
15
+ index: true
16
+
17
+ priority:
18
+ options:
19
+ - low
20
+ - normal
21
+ - high
22
+ defaultValue: normal
23
+
24
+ description:
25
+ type: textarea
26
+
27
+ owner:
28
+ type: text
29
+
30
+ budget:
31
+ type: currency
32
+
33
+ start_date:
34
+ type: date
35
+
36
+ end_date:
37
+ type: date
38
+
39
+ approved_by:
40
+ type: text
41
+
42
+ approved_at:
43
+ type: datetime
44
+
45
+ approval_comment:
46
+ type: textarea
47
+
48
+ indexes:
49
+ # Composite index for reporting
50
+ status_priority_idx:
51
+ fields: [status, priority]
52
+
53
+ ai:
54
+ search:
55
+ enabled: true
56
+ fields: [name, description]
57
+ model: text-embedding-3-small
58
+
59
+ actions:
60
+ # Record Actions (operate on specific records)
61
+ complete:
62
+ type: record
63
+ label: Complete Project
64
+ icon: checkbox-circle-line
65
+ confirm_text: "Are you sure you want to complete this project?"
66
+ params:
67
+ comment:
68
+ type: textarea
69
+ label: Completion Comment
70
+ completion_date:
71
+ type: date
72
+ label: Completion Date
73
+
74
+ approve:
75
+ type: record
76
+ label: Approve Project
77
+ icon: shield-check-line
78
+ confirm_text: "Are you sure you want to approve this project?"
79
+ params:
80
+ comment:
81
+ type: textarea
82
+ required: true
83
+ label: Approval Comment
84
+ help_text: "Provide a reason for approving this project"
85
+
86
+ clone:
87
+ type: record
88
+ label: Clone Project
89
+ icon: file-copy-line
90
+ description: Create a copy of this project
91
+ params:
92
+ new_name:
93
+ type: text
94
+ required: true
95
+ label: New Project Name
96
+ copy_tasks:
97
+ type: checkbox
98
+ label: Copy Associated Tasks
99
+ defaultValue: false
100
+
101
+ # Global Actions (operate on collections)
102
+ import_projects:
103
+ type: global
104
+ label: Import Projects
105
+ icon: download-line
106
+ internal: false
107
+ description: Import multiple projects from various sources
108
+ params:
109
+ source:
110
+ required: true
111
+ label: Import Source
112
+ options:
113
+ - csv
114
+ - json
115
+ - api
116
+ data:
117
+ type: textarea
118
+ label: JSON Data
119
+ help_text: "Paste JSON array of projects (optional if using file_url)"
120
+ file_url:
121
+ type: text
122
+ label: File URL
123
+ help_text: "URL to fetch data from (optional if using data field)"
124
+
125
+ bulk_update_status:
126
+ type: global
127
+ label: Bulk Update Status
128
+ icon: edit-box-line
129
+ description: Update status for multiple projects at once
130
+ params:
131
+ project_ids:
132
+ type: textarea
133
+ required: true
134
+ label: Project IDs
135
+ help_text: "List of project IDs"
136
+ new_status:
137
+ required: true
138
+ label: New Status
139
+ options:
140
+ - planned
141
+ - in_progress
142
+ - completed
143
+
144
+ generate_report:
145
+ type: global
146
+ label: Generate Project Report
147
+ icon: file-chart-line
148
+ description: Generate statistical report of all projects
@@ -0,0 +1,141 @@
1
+ name: projects_permission
2
+ object: projects
3
+ description: "Comprehensive access control rules for Project object"
4
+
5
+ # Roles (defined in demo.app.yml, referenced here)
6
+ # This list documents which system roles have permissions on this object
7
+ roles:
8
+ - admin
9
+ - manager
10
+ - developer
11
+ - user
12
+ - viewer
13
+
14
+ # Object-level permissions (CRUD)
15
+ object_permissions:
16
+ create: [admin, manager]
17
+ read: [admin, manager, developer, user, viewer]
18
+ update: [admin, manager]
19
+ delete: [admin]
20
+ view_all: [admin] # Admins can see all projects
21
+ modify_all: [admin] # Admins can edit all projects
22
+
23
+ # Field-level security
24
+ field_permissions:
25
+ budget:
26
+ read: [admin, manager]
27
+ update: [admin] # Only admin can change budget
28
+
29
+ approved_by:
30
+ read: [admin, manager, user]
31
+ update: [] # Read-only, set by system/workflow
32
+
33
+ approved_at:
34
+ read: [admin, manager, user]
35
+ update: []
36
+
37
+ approval_comment:
38
+ read: [admin, manager, user]
39
+ update: [admin, manager]
40
+
41
+ # Record-level rules for dynamic access control
42
+ record_rules:
43
+ - name: owner_full_access
44
+ priority: 100
45
+ description: Project owner has full access to their projects
46
+ condition:
47
+ type: simple
48
+ field: owner
49
+ operator: "="
50
+ value: $current_user.id
51
+ permissions:
52
+ read: true
53
+ update: true
54
+ delete: true
55
+
56
+ - name: public_read_access
57
+ priority: 10
58
+ description: Completed projects are publicly readable
59
+ condition:
60
+ type: simple
61
+ field: status
62
+ operator: "="
63
+ value: completed
64
+ permissions:
65
+ read: true
66
+ update: false
67
+ delete: false
68
+
69
+ # Sharing rules
70
+ sharing_rules:
71
+ - name: manual_share
72
+ type: manual
73
+ description: Users can manually share projects with team members
74
+ enabled: true
75
+ permissions:
76
+ read: true
77
+ update: false
78
+ delete: false
79
+
80
+ # Action permissions
81
+ action_permissions:
82
+ approve:
83
+ execute: [admin, manager]
84
+ conditions:
85
+ - field: status
86
+ operator: "="
87
+ value: in_progress
88
+
89
+ complete:
90
+ execute: [admin, manager]
91
+
92
+ clone:
93
+ execute: [admin, manager, developer]
94
+
95
+ import_projects:
96
+ execute: [admin]
97
+ rate_limit:
98
+ requests_per_hour: 10
99
+
100
+ bulk_update_status:
101
+ execute: [admin, manager]
102
+
103
+ # View permissions
104
+ view_permissions:
105
+ all_projects:
106
+ access: [admin, manager, developer, user, viewer]
107
+ field_restrictions:
108
+ budget:
109
+ visible_to: [admin, manager]
110
+
111
+ # Row-level security
112
+ row_level_security:
113
+ enabled: true
114
+ default_rule:
115
+ field: owner
116
+ operator: "="
117
+ value: $current_user.id
118
+ exceptions:
119
+ - role: admin
120
+ bypass: true
121
+ - role: manager
122
+ condition:
123
+ type: simple
124
+ field: status
125
+ operator: "!="
126
+ value: completed
127
+
128
+ # Audit trail
129
+ audit:
130
+ enabled: true
131
+ events:
132
+ - permission_grant
133
+ - permission_revoke
134
+ - access_denied
135
+ - sensitive_field_access
136
+ retention_days: 365
137
+ alerts:
138
+ - event: access_denied
139
+ threshold: 5
140
+ window_minutes: 10
141
+ notify: [admin]
@@ -0,0 +1,37 @@
1
+ name: projects_validation
2
+ object: projects
3
+ description: "Validation rules for Projects"
4
+
5
+ rules:
6
+ - name: valid_date_range
7
+ type: cross_field
8
+ ai_context:
9
+ intent: "Ensure project timeline is valid"
10
+ business_rule: "Projects cannot end before they start"
11
+ rule:
12
+ field: end_date
13
+ operator: ">="
14
+ compare_to: start_date
15
+ message: "End Date must be after Start Date"
16
+
17
+ - name: positive_budget
18
+ type: field
19
+ rule:
20
+ field: budget
21
+ operator: ">="
22
+ value: 0
23
+ message: "Budget cannot be negative"
24
+
25
+ - name: comment_required_if_high_budget
26
+ type: conditional
27
+ description: "Description is required for high budget projects"
28
+ ai_context:
29
+ business_rule: "High value projects (>10k) must have a detailed description"
30
+ condition:
31
+ field: budget
32
+ operator: ">"
33
+ value: 10000
34
+ rule:
35
+ field: description
36
+ operator: "not_empty"
37
+ message: "Description is required for high budget projects (> $10,000)"
@@ -0,0 +1,35 @@
1
+ name: all_projects
2
+ label: "Active Projects"
3
+ type: list
4
+ object: projects
5
+ description: "Standard list view of all active projects"
6
+
7
+ config:
8
+ columns:
9
+ - field: name
10
+ width: 250
11
+ - field: status
12
+ width: 120
13
+ - field: priority
14
+ width: 100
15
+ - field: owner
16
+ width: 150
17
+ - field: budget
18
+ width: 120
19
+ - field: end_date
20
+ width: 120
21
+
22
+ sort:
23
+ - field: created_at
24
+ direction: desc
25
+
26
+ filters:
27
+ - field: status
28
+ operator: "!="
29
+ value: "archived"
30
+
31
+ actions:
32
+ - edit
33
+ - delete
34
+ - clone
35
+ - custom: approve
@@ -0,0 +1,23 @@
1
+ - _id: TASK-001
2
+ name: "Design Homepage Mockups"
3
+ project: "PROJ-001"
4
+ due_date: "2024-12-31"
5
+ completed: false
6
+
7
+ - _id: TASK-002
8
+ name: "Setup CI/CD Pipeline"
9
+ project: "PROJ-001"
10
+ due_date: "2024-11-15"
11
+ completed: true
12
+
13
+ - _id: TASK-003
14
+ name: "Draft App Requirements"
15
+ project: "PROJ-002"
16
+ due_date: "2025-01-20"
17
+ completed: false
18
+
19
+ - _id: TASK-004
20
+ name: "Choose Tech Stack"
21
+ project: "PROJ-002"
22
+ due_date: "2025-01-10"
23
+ completed: true