@cloudstreamsoftware/claude-tools 1.0.0 → 1.1.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.
- package/README.md +152 -37
- package/agents/INDEX.md +183 -0
- package/agents/architect.md +247 -0
- package/agents/build-error-resolver.md +555 -0
- package/agents/catalyst-deployer.md +132 -0
- package/agents/code-reviewer.md +121 -0
- package/agents/compliance-auditor.md +148 -0
- package/agents/creator-architect.md +395 -0
- package/agents/deluge-reviewer.md +98 -0
- package/agents/doc-updater.md +471 -0
- package/agents/e2e-runner.md +711 -0
- package/agents/planner.md +122 -0
- package/agents/refactor-cleaner.md +309 -0
- package/agents/security-reviewer.md +582 -0
- package/agents/tdd-guide.md +302 -0
- package/config/versions.json +63 -0
- package/dist/hooks/hooks.json +209 -0
- package/dist/index.js +47 -0
- package/dist/lib/asset-value.js +609 -0
- package/dist/lib/client-manager.js +300 -0
- package/dist/lib/command-matcher.js +242 -0
- package/dist/lib/cross-session-patterns.js +754 -0
- package/dist/lib/intent-classifier.js +1075 -0
- package/dist/lib/package-manager.js +374 -0
- package/dist/lib/recommendation-engine.js +597 -0
- package/dist/lib/session-memory.js +489 -0
- package/dist/lib/skill-effectiveness.js +486 -0
- package/dist/lib/skill-matcher.js +595 -0
- package/dist/lib/tutorial-metrics.js +242 -0
- package/dist/lib/tutorial-progress.js +209 -0
- package/dist/lib/tutorial-renderer.js +431 -0
- package/dist/lib/utils.js +380 -0
- package/dist/lib/verify-formatter.js +143 -0
- package/dist/lib/workflow-state.js +249 -0
- package/hooks/hooks.json +209 -0
- package/package.json +5 -1
- package/scripts/aggregate-sessions.js +290 -0
- package/scripts/branch-name-validator.js +291 -0
- package/scripts/build.js +101 -0
- package/scripts/commands/client-switch.js +231 -0
- package/scripts/deprecate-skill.js +610 -0
- package/scripts/diagnose.js +324 -0
- package/scripts/doc-freshness.js +168 -0
- package/scripts/generate-weekly-digest.js +393 -0
- package/scripts/health-check.js +270 -0
- package/scripts/hooks/credential-check.js +101 -0
- package/scripts/hooks/evaluate-session.js +81 -0
- package/scripts/hooks/pre-compact.js +66 -0
- package/scripts/hooks/prompt-analyzer.js +276 -0
- package/scripts/hooks/prompt-router.js +422 -0
- package/scripts/hooks/quality-gate-enforcer.js +371 -0
- package/scripts/hooks/session-end.js +156 -0
- package/scripts/hooks/session-start.js +195 -0
- package/scripts/hooks/skill-injector.js +333 -0
- package/scripts/hooks/suggest-compact.js +58 -0
- package/scripts/lib/asset-value.js +609 -0
- package/scripts/lib/client-manager.js +300 -0
- package/scripts/lib/command-matcher.js +242 -0
- package/scripts/lib/cross-session-patterns.js +754 -0
- package/scripts/lib/intent-classifier.js +1075 -0
- package/scripts/lib/package-manager.js +374 -0
- package/scripts/lib/recommendation-engine.js +597 -0
- package/scripts/lib/session-memory.js +489 -0
- package/scripts/lib/skill-effectiveness.js +486 -0
- package/scripts/lib/skill-matcher.js +595 -0
- package/scripts/lib/tutorial-metrics.js +242 -0
- package/scripts/lib/tutorial-progress.js +209 -0
- package/scripts/lib/tutorial-renderer.js +431 -0
- package/scripts/lib/utils.js +380 -0
- package/scripts/lib/verify-formatter.js +143 -0
- package/scripts/lib/workflow-state.js +249 -0
- package/scripts/onboard.js +363 -0
- package/scripts/quarterly-report.js +692 -0
- package/scripts/setup-package-manager.js +204 -0
- package/scripts/sync-upstream.js +391 -0
- package/scripts/test.js +108 -0
- package/scripts/tutorial-runner.js +351 -0
- package/scripts/validate-all.js +201 -0
- package/scripts/verifiers/agents.js +245 -0
- package/scripts/verifiers/config.js +186 -0
- package/scripts/verifiers/environment.js +123 -0
- package/scripts/verifiers/hooks.js +188 -0
- package/scripts/verifiers/index.js +38 -0
- package/scripts/verifiers/persistence.js +140 -0
- package/scripts/verifiers/plugin.js +215 -0
- package/scripts/verifiers/skills.js +209 -0
- package/scripts/verify-setup.js +164 -0
- package/skills/INDEX.md +157 -0
- package/skills/backend-patterns/SKILL.md +586 -0
- package/skills/backend-patterns/catalyst-patterns.md +128 -0
- package/skills/bigquery-patterns/SKILL.md +27 -0
- package/skills/bigquery-patterns/performance-optimization.md +518 -0
- package/skills/bigquery-patterns/query-patterns.md +372 -0
- package/skills/bigquery-patterns/schema-design.md +78 -0
- package/skills/cloudstream-project-template/SKILL.md +20 -0
- package/skills/cloudstream-project-template/structure.md +65 -0
- package/skills/coding-standards/SKILL.md +524 -0
- package/skills/coding-standards/deluge-standards.md +83 -0
- package/skills/compliance-patterns/SKILL.md +28 -0
- package/skills/compliance-patterns/hipaa/audit-requirements.md +251 -0
- package/skills/compliance-patterns/hipaa/baa-process.md +298 -0
- package/skills/compliance-patterns/hipaa/data-archival-strategy.md +387 -0
- package/skills/compliance-patterns/hipaa/phi-handling.md +52 -0
- package/skills/compliance-patterns/pci-dss/saq-a-requirements.md +307 -0
- package/skills/compliance-patterns/pci-dss/tokenization-patterns.md +382 -0
- package/skills/compliance-patterns/pci-dss/zoho-checkout-patterns.md +56 -0
- package/skills/compliance-patterns/soc2/access-controls.md +344 -0
- package/skills/compliance-patterns/soc2/audit-logging.md +458 -0
- package/skills/compliance-patterns/soc2/change-management.md +403 -0
- package/skills/compliance-patterns/soc2/deluge-execution-logging.md +407 -0
- package/skills/consultancy-workflows/SKILL.md +19 -0
- package/skills/consultancy-workflows/client-isolation.md +21 -0
- package/skills/consultancy-workflows/documentation-automation.md +454 -0
- package/skills/consultancy-workflows/handoff-procedures.md +257 -0
- package/skills/consultancy-workflows/knowledge-capture.md +513 -0
- package/skills/consultancy-workflows/time-tracking.md +26 -0
- package/skills/continuous-learning/SKILL.md +84 -0
- package/skills/continuous-learning/config.json +18 -0
- package/skills/continuous-learning/evaluate-session.sh +60 -0
- package/skills/continuous-learning-v2/SKILL.md +126 -0
- package/skills/continuous-learning-v2/config.json +61 -0
- package/skills/frontend-patterns/SKILL.md +635 -0
- package/skills/frontend-patterns/zoho-widget-patterns.md +103 -0
- package/skills/gcp-data-engineering/SKILL.md +36 -0
- package/skills/gcp-data-engineering/bigquery/performance-optimization.md +337 -0
- package/skills/gcp-data-engineering/dataflow/error-handling.md +496 -0
- package/skills/gcp-data-engineering/dataflow/pipeline-patterns.md +444 -0
- package/skills/gcp-data-engineering/dbt/model-organization.md +63 -0
- package/skills/gcp-data-engineering/dbt/testing-patterns.md +503 -0
- package/skills/gcp-data-engineering/medallion-architecture/bronze-layer.md +60 -0
- package/skills/gcp-data-engineering/medallion-architecture/gold-layer.md +311 -0
- package/skills/gcp-data-engineering/medallion-architecture/layer-transitions.md +517 -0
- package/skills/gcp-data-engineering/medallion-architecture/silver-layer.md +305 -0
- package/skills/gcp-data-engineering/zoho-to-gcp/data-extraction.md +543 -0
- package/skills/gcp-data-engineering/zoho-to-gcp/real-time-vs-batch.md +337 -0
- package/skills/security-review/SKILL.md +498 -0
- package/skills/security-review/compliance-checklist.md +53 -0
- package/skills/strategic-compact/SKILL.md +67 -0
- package/skills/tdd-workflow/SKILL.md +413 -0
- package/skills/tdd-workflow/zoho-testing.md +124 -0
- package/skills/tutorial/SKILL.md +249 -0
- package/skills/tutorial/docs/ACCESSIBILITY.md +169 -0
- package/skills/tutorial/lessons/00-philosophy-and-workflow.md +198 -0
- package/skills/tutorial/lessons/01-basics.md +81 -0
- package/skills/tutorial/lessons/02-training.md +86 -0
- package/skills/tutorial/lessons/03-commands.md +109 -0
- package/skills/tutorial/lessons/04-workflows.md +115 -0
- package/skills/tutorial/lessons/05-compliance.md +116 -0
- package/skills/tutorial/lessons/06-zoho.md +121 -0
- package/skills/tutorial/lessons/07-hooks-system.md +277 -0
- package/skills/tutorial/lessons/08-mcp-servers.md +316 -0
- package/skills/tutorial/lessons/09-client-management.md +215 -0
- package/skills/tutorial/lessons/10-testing-e2e.md +260 -0
- package/skills/tutorial/lessons/11-skills-deep-dive.md +272 -0
- package/skills/tutorial/lessons/12-rules-system.md +326 -0
- package/skills/tutorial/lessons/13-golden-standard-graduation.md +213 -0
- package/skills/tutorial/lessons/14-fork-setup-and-sync.md +312 -0
- package/skills/tutorial/lessons/15-living-examples-system.md +221 -0
- package/skills/tutorial/tracks/accelerated/README.md +134 -0
- package/skills/tutorial/tracks/accelerated/assessment/checkpoint-1.md +161 -0
- package/skills/tutorial/tracks/accelerated/assessment/checkpoint-2.md +175 -0
- package/skills/tutorial/tracks/accelerated/day-1-core-concepts.md +234 -0
- package/skills/tutorial/tracks/accelerated/day-2-essential-commands.md +270 -0
- package/skills/tutorial/tracks/accelerated/day-3-workflow-mastery.md +305 -0
- package/skills/tutorial/tracks/accelerated/day-4-compliance-zoho.md +304 -0
- package/skills/tutorial/tracks/accelerated/day-5-hooks-skills.md +344 -0
- package/skills/tutorial/tracks/accelerated/day-6-client-testing.md +386 -0
- package/skills/tutorial/tracks/accelerated/day-7-graduation.md +369 -0
- package/skills/zoho-patterns/CHANGELOG.md +108 -0
- package/skills/zoho-patterns/SKILL.md +446 -0
- package/skills/zoho-patterns/analytics/dashboard-patterns.md +352 -0
- package/skills/zoho-patterns/analytics/zoho-to-bigquery-pipeline.md +427 -0
- package/skills/zoho-patterns/catalyst/appsail-deployment.md +349 -0
- package/skills/zoho-patterns/catalyst/context-close-patterns.md +354 -0
- package/skills/zoho-patterns/catalyst/cron-batch-processing.md +374 -0
- package/skills/zoho-patterns/catalyst/function-patterns.md +439 -0
- package/skills/zoho-patterns/creator/form-design.md +304 -0
- package/skills/zoho-patterns/creator/publish-api-patterns.md +313 -0
- package/skills/zoho-patterns/creator/widget-integration.md +306 -0
- package/skills/zoho-patterns/creator/workflow-automation.md +253 -0
- package/skills/zoho-patterns/deluge/api-patterns.md +468 -0
- package/skills/zoho-patterns/deluge/batch-processing.md +403 -0
- package/skills/zoho-patterns/deluge/cross-app-integration.md +356 -0
- package/skills/zoho-patterns/deluge/error-handling.md +423 -0
- package/skills/zoho-patterns/deluge/syntax-reference.md +65 -0
- package/skills/zoho-patterns/integration/cors-proxy-architecture.md +426 -0
- package/skills/zoho-patterns/integration/crm-books-native-sync.md +277 -0
- package/skills/zoho-patterns/integration/oauth-token-management.md +461 -0
- package/skills/zoho-patterns/integration/zoho-flow-patterns.md +334 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# Creator Form Design Patterns
|
|
2
|
+
|
|
3
|
+
## Form Hierarchy
|
|
4
|
+
|
|
5
|
+
| Level | Purpose | Example | Relationship |
|
|
6
|
+
|-------|---------|---------|--------------|
|
|
7
|
+
| Parent form | Core entity | Customers, Projects | Standalone |
|
|
8
|
+
| Child form | Related record | Invoices (via Lookup to Customer) | Lookup field |
|
|
9
|
+
| Subform | Inline 1:N data | Invoice Line Items (max 200 rows) | Embedded in parent |
|
|
10
|
+
|
|
11
|
+
### When to Use Subforms vs. Separate Forms
|
|
12
|
+
|
|
13
|
+
| Use Subform | Use Separate Form |
|
|
14
|
+
|-------------|-------------------|
|
|
15
|
+
| Items always viewed/edited with parent | Records accessed independently |
|
|
16
|
+
| Under 50 rows typical (200 max) | Could grow to thousands of records |
|
|
17
|
+
| No complex workflows on child items | Needs its own workflows/blueprints |
|
|
18
|
+
| Line items, addresses, phone numbers | Invoices, tickets, projects |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Field Types and When to Use Each
|
|
23
|
+
|
|
24
|
+
| Field Type | Use For | Avoid When |
|
|
25
|
+
|-----------|---------|-----------|
|
|
26
|
+
| **Single Line** | Names, short labels, IDs | Content exceeds 255 chars |
|
|
27
|
+
| **Multi Line** | Notes, descriptions, logs | Need rich formatting |
|
|
28
|
+
| **Rich Text** | Formatted content, templates | Simple text (heavy on storage) |
|
|
29
|
+
| **Email** | Email addresses | Already using Single Line (lose validation) |
|
|
30
|
+
| **Number** | Integers, quantities, IDs | Decimal values needed |
|
|
31
|
+
| **Decimal** | Currency, measurements, rates | Integer-only values |
|
|
32
|
+
| **Currency** | Monetary values | Non-monetary decimals |
|
|
33
|
+
| **Date** | Dates without time | Need time component |
|
|
34
|
+
| **DateTime** | Timestamps, audit events | Date-only values |
|
|
35
|
+
| **Decision Box** | Boolean yes/no values | Need multiple options |
|
|
36
|
+
| **Picklist** | Fixed set of options (up to ~50) | Values change frequently |
|
|
37
|
+
| **Multi-Select** | Multiple options from fixed set | Single selection needed |
|
|
38
|
+
| **Lookup** | Relationship to another form | Storing IDs as text |
|
|
39
|
+
| **Formula** | Computed values | Value needs user editing |
|
|
40
|
+
| **Auto-number** | Sequential IDs, reference numbers | User-supplied IDs |
|
|
41
|
+
| **File Upload** | Documents, images (50 MB max) | Storing file paths as text |
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Validation Rules
|
|
46
|
+
|
|
47
|
+
### Built-in Validation
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
Field: Customer_Email
|
|
51
|
+
Type: Email
|
|
52
|
+
Required: YES
|
|
53
|
+
Unique: YES (prevents duplicate customers)
|
|
54
|
+
|
|
55
|
+
Field: Phone_Number
|
|
56
|
+
Type: Single Line
|
|
57
|
+
Regex: ^\+?[1-9]\d{1,14}$
|
|
58
|
+
Error: "Enter a valid phone number with country code"
|
|
59
|
+
|
|
60
|
+
Field: Invoice_Amount
|
|
61
|
+
Type: Currency
|
|
62
|
+
Min Value: 0.01
|
|
63
|
+
Max Value: 999999.99
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Deluge Validation (on Form Submit)
|
|
67
|
+
|
|
68
|
+
```deluge
|
|
69
|
+
// Custom validation rules in "on validate" workflow
|
|
70
|
+
errors = List();
|
|
71
|
+
|
|
72
|
+
// Cross-field validation
|
|
73
|
+
if (input.End_Date < input.Start_Date)
|
|
74
|
+
{
|
|
75
|
+
errors.add("End date must be after start date");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Business rule validation
|
|
79
|
+
if (input.Discount_Percent > 30 && input.Approved_By == "")
|
|
80
|
+
{
|
|
81
|
+
errors.add("Discounts over 30% require manager approval");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Conditional required fields
|
|
85
|
+
if (input.Payment_Method == "ACH" && input.Routing_Number == "")
|
|
86
|
+
{
|
|
87
|
+
errors.add("Routing number is required for ACH payments");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (errors.size() > 0)
|
|
91
|
+
{
|
|
92
|
+
cancel submit;
|
|
93
|
+
alert errors.toString("\n");
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Formula Fields
|
|
100
|
+
|
|
101
|
+
### Common Patterns
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
// Full name from first + last
|
|
105
|
+
Field: Full_Name
|
|
106
|
+
Formula: First_Name + " " + Last_Name
|
|
107
|
+
|
|
108
|
+
// Age from date of birth
|
|
109
|
+
Field: Age
|
|
110
|
+
Formula: ((zoho.currentdate - Date_of_Birth) / 365).floor()
|
|
111
|
+
|
|
112
|
+
// Days since last contact
|
|
113
|
+
Field: Days_Since_Contact
|
|
114
|
+
Formula: if(Last_Contact_Date != null, (zoho.currentdate - Last_Contact_Date), -1)
|
|
115
|
+
|
|
116
|
+
// Total from subform
|
|
117
|
+
Field: Invoice_Total
|
|
118
|
+
Formula: sum(Line_Items.Amount)
|
|
119
|
+
|
|
120
|
+
// Status based on date
|
|
121
|
+
Field: Overdue_Status
|
|
122
|
+
Formula: if(Due_Date < zoho.currentdate && Status != "Paid", "OVERDUE", "OK")
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Conditional Visibility (Page Rules)
|
|
128
|
+
|
|
129
|
+
Use page rules to show/hide fields based on other field values:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
Rule: Show HIPAA Fields
|
|
133
|
+
Condition: Compliance_Mode == "hipaa"
|
|
134
|
+
Show: PHI_Consent_Date, BAA_Status, Encryption_Level
|
|
135
|
+
|
|
136
|
+
Rule: Show Payment Details
|
|
137
|
+
Condition: Payment_Method == "Credit Card"
|
|
138
|
+
Show: Card_Last_Four, Expiry_Month, Token_ID
|
|
139
|
+
|
|
140
|
+
Rule: Show Approval Section
|
|
141
|
+
Condition: Amount > 10000
|
|
142
|
+
Show: Approver, Approval_Date, Approval_Notes
|
|
143
|
+
Make Required: Approver
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Subform Patterns
|
|
149
|
+
|
|
150
|
+
### Line Items Subform
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
Parent Form: Invoices
|
|
154
|
+
Subform: Line_Items
|
|
155
|
+
|
|
156
|
+
Fields:
|
|
157
|
+
- Item_Name (Single Line, required)
|
|
158
|
+
- Description (Multi Line)
|
|
159
|
+
- Quantity (Number, required, min: 1)
|
|
160
|
+
- Unit_Price (Currency, required)
|
|
161
|
+
- Discount_Percent (Decimal, default: 0)
|
|
162
|
+
- Line_Total (Formula: Quantity * Unit_Price * (1 - Discount_Percent / 100))
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Performance Guidelines for Subforms
|
|
166
|
+
|
|
167
|
+
- Keep row count under 50 for responsive UI
|
|
168
|
+
- Avoid lookup fields in subforms (each triggers a query)
|
|
169
|
+
- Use formula fields over workflow calculations
|
|
170
|
+
- Don't put subforms inside subforms (not supported)
|
|
171
|
+
- Consider a separate form if rows exceed 100 regularly
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## HIPAA-Compliant Form Design
|
|
176
|
+
|
|
177
|
+
When compliance mode is `hipaa`, apply these rules to any form containing ePHI:
|
|
178
|
+
|
|
179
|
+
### Field Marking
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
Field: Patient_Name [PHI]
|
|
183
|
+
- Help Text: "[PHI] Patient's full legal name"
|
|
184
|
+
- Encryption: ENABLED
|
|
185
|
+
- Access: Roles [Doctor, Nurse, Admin]
|
|
186
|
+
- Audit: ON (log all reads and writes)
|
|
187
|
+
- Reports: HIDDEN by default
|
|
188
|
+
|
|
189
|
+
Field: Diagnosis_Code [PHI]
|
|
190
|
+
- Help Text: "[PHI] ICD-10 code"
|
|
191
|
+
- Encryption: ENABLED
|
|
192
|
+
- Access: Roles [Doctor]
|
|
193
|
+
- Audit: ON
|
|
194
|
+
- Reports: Aggregates only (never individual values)
|
|
195
|
+
|
|
196
|
+
Field: SSN [PHI]
|
|
197
|
+
- Help Text: "[PHI] Social Security Number"
|
|
198
|
+
- Encryption: ENABLED
|
|
199
|
+
- Display Mask: ***-**-{last4}
|
|
200
|
+
- Access: Roles [Admin] only
|
|
201
|
+
- Audit: ON
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### HIPAA Form Rules
|
|
205
|
+
|
|
206
|
+
1. Add `[PHI]` prefix to help text of every ePHI field
|
|
207
|
+
2. Enable field-level encryption for all ePHI fields
|
|
208
|
+
3. Set field permissions to minimum necessary roles
|
|
209
|
+
4. Hide ePHI fields from all reports by default
|
|
210
|
+
5. Add audit trigger on form `on load` to log reads
|
|
211
|
+
6. Never include ePHI in email notifications
|
|
212
|
+
7. Implement "break-glass" access pattern for emergencies
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Field Permissions
|
|
217
|
+
|
|
218
|
+
### Role-Based Access Matrix
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
Form: Patient_Records
|
|
222
|
+
| View | Edit | Delete |
|
|
223
|
+
Admin | ALL | ALL | YES |
|
|
224
|
+
Doctor | ALL | Medical fields | NO |
|
|
225
|
+
Nurse | Non-sensitive | Vitals only | NO |
|
|
226
|
+
Billing | Name, Insurance | Billing fields | NO |
|
|
227
|
+
Front Desk | Name, Phone, Appt | Contact info | NO |
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Field-Level Permissions in Creator
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
Field: Annual_Revenue
|
|
234
|
+
View: Manager, Director, Admin
|
|
235
|
+
Edit: Director, Admin
|
|
236
|
+
|
|
237
|
+
Field: Internal_Notes
|
|
238
|
+
View: All internal roles
|
|
239
|
+
Edit: All internal roles
|
|
240
|
+
HIDDEN from: Client portal users
|
|
241
|
+
|
|
242
|
+
Field: Commission_Rate
|
|
243
|
+
View: HR, Finance
|
|
244
|
+
Edit: HR only
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Lookup Relationships
|
|
250
|
+
|
|
251
|
+
### One-to-Many (Lookup)
|
|
252
|
+
|
|
253
|
+
```
|
|
254
|
+
Form: Projects
|
|
255
|
+
Field: Client (Lookup → Clients form)
|
|
256
|
+
Display: Client.Company_Name
|
|
257
|
+
Filter: Client.Status == "Active"
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Many-to-Many (Junction Form)
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
Form: Project_Team_Members (junction form)
|
|
264
|
+
Field: Project (Lookup → Projects)
|
|
265
|
+
Field: Team_Member (Lookup → Employees)
|
|
266
|
+
Field: Role (Picklist: Lead, Member, Reviewer)
|
|
267
|
+
Field: Start_Date (Date)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Cascading Lookups
|
|
271
|
+
|
|
272
|
+
```
|
|
273
|
+
Form: Support_Tickets
|
|
274
|
+
Field: Client (Lookup → Clients)
|
|
275
|
+
Field: Project (Lookup → Projects, filtered by Client)
|
|
276
|
+
Field: Contact (Lookup → Contacts, filtered by Client)
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Performance Optimization
|
|
282
|
+
|
|
283
|
+
| Technique | Impact | When to Apply |
|
|
284
|
+
|-----------|--------|---------------|
|
|
285
|
+
| Limit subform rows to <50 | Faster form load | Always |
|
|
286
|
+
| Use page rules to hide sections | Less DOM rendering | Forms with 20+ fields |
|
|
287
|
+
| Formula fields over workflows | No script execution | Computed values |
|
|
288
|
+
| Limit lookup display fields | Fewer DB queries | Lookups showing 3+ columns |
|
|
289
|
+
| Aggregate fields on parent | Avoid report calculations | Dashboards, summaries |
|
|
290
|
+
| Archive old records | Smaller active dataset | Records >2 years old |
|
|
291
|
+
| Index frequently-filtered fields | Faster report loading | High-traffic reports |
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Form Naming Conventions
|
|
296
|
+
|
|
297
|
+
| Convention | Example | Rule |
|
|
298
|
+
|-----------|---------|------|
|
|
299
|
+
| Form name | `Customer_Intake` | PascalCase with underscores |
|
|
300
|
+
| Field name | `First_Name` | PascalCase with underscores |
|
|
301
|
+
| Subform | `Line_Items` | Plural, PascalCase |
|
|
302
|
+
| Lookup field | `Client_ID` | Referenced form + `_ID` |
|
|
303
|
+
| Formula field | `Calculated_Total` | Prefix with purpose |
|
|
304
|
+
| Audit field | `Last_Modified_By` | Clear description |
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# Creator Publish API Patterns
|
|
2
|
+
|
|
3
|
+
## Why Publish API?
|
|
4
|
+
|
|
5
|
+
> **CRITICAL:** Widgets do NOT work on published (external-facing) Creator pages. When you need to provide interactive functionality to external users (customers, vendors, partners), use the Publish API instead.
|
|
6
|
+
|
|
7
|
+
## Decision Framework
|
|
8
|
+
|
|
9
|
+
| Scenario | Use Widget | Use Publish API |
|
|
10
|
+
|----------|-----------|-----------------|
|
|
11
|
+
| Internal team data entry | Yes | No |
|
|
12
|
+
| Customer-facing portal | No | Yes |
|
|
13
|
+
| Embedded in Zoho apps | Yes | No |
|
|
14
|
+
| Public data submission | No | Yes |
|
|
15
|
+
| Complex UI with React/Vue | Maybe (internal) | Yes (external) |
|
|
16
|
+
| Needs Zoho SDK context | Yes | No |
|
|
17
|
+
|
|
18
|
+
## Publish API Authentication
|
|
19
|
+
|
|
20
|
+
### API Key Method (Simple)
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
// Generate API key: Setup > Developer > API Key
|
|
24
|
+
const API_KEY = process.env.ZOHO_CREATOR_API_KEY;
|
|
25
|
+
|
|
26
|
+
// Include in all requests
|
|
27
|
+
const headers = {
|
|
28
|
+
"Authorization": `Zoho-oauthtoken ${accessToken}`
|
|
29
|
+
};
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### OAuth Method (Production)
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
// For server-to-server or user-delegated access
|
|
36
|
+
const axios = require("axios");
|
|
37
|
+
|
|
38
|
+
async function getCreatorData(appName, reportName, criteria) {
|
|
39
|
+
const accessToken = await getValidAccessToken(); // See oauth-token-management.md
|
|
40
|
+
|
|
41
|
+
const response = await axios.get(
|
|
42
|
+
`https://creator.zoho.com/api/v2/${process.env.ZOHO_OWNER}/${appName}/report/${reportName}`,
|
|
43
|
+
{
|
|
44
|
+
headers: {
|
|
45
|
+
"Authorization": `Zoho-oauthtoken ${accessToken}`
|
|
46
|
+
},
|
|
47
|
+
params: {
|
|
48
|
+
criteria: criteria,
|
|
49
|
+
limit: 200,
|
|
50
|
+
start_index: 0
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
return response.data;
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Rate Limits
|
|
60
|
+
|
|
61
|
+
| Plan | Requests/Day | Requests/Minute |
|
|
62
|
+
|------|-------------|-----------------|
|
|
63
|
+
| Free | 1,000 | 20 |
|
|
64
|
+
| Standard | 5,000 | 50 |
|
|
65
|
+
| Professional | 10,000 | 100 |
|
|
66
|
+
| Enterprise | 25,000 | 200 |
|
|
67
|
+
|
|
68
|
+
> **WARNING:** Rate limits are per-org, not per-app. Multiple apps share the same quota.
|
|
69
|
+
|
|
70
|
+
### Rate Limit Handling
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
async function apiCallWithRetry(fn, maxRetries = 3) {
|
|
74
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
75
|
+
try {
|
|
76
|
+
const response = await fn();
|
|
77
|
+
return response;
|
|
78
|
+
} catch (error) {
|
|
79
|
+
if (error.response && error.response.status === 429) {
|
|
80
|
+
// Rate limited - wait with exponential backoff
|
|
81
|
+
const waitMs = Math.pow(2, attempt) * 1000;
|
|
82
|
+
console.warn(`Rate limited. Retry ${attempt}/${maxRetries} in ${waitMs}ms`);
|
|
83
|
+
await new Promise(resolve => setTimeout(resolve, waitMs));
|
|
84
|
+
} else {
|
|
85
|
+
throw error; // Non-rate-limit error, don't retry
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
throw new Error("Max retries exceeded for rate-limited API call");
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## CRUD Operations via API
|
|
94
|
+
|
|
95
|
+
### Create Record
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
async function createRecord(appName, formName, data) {
|
|
99
|
+
const accessToken = await getValidAccessToken();
|
|
100
|
+
|
|
101
|
+
const response = await axios.post(
|
|
102
|
+
`https://creator.zoho.com/api/v2/${OWNER}/${appName}/form/${formName}`,
|
|
103
|
+
{ data: data },
|
|
104
|
+
{
|
|
105
|
+
headers: {
|
|
106
|
+
"Authorization": `Zoho-oauthtoken ${accessToken}`,
|
|
107
|
+
"Content-Type": "application/json"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
return response.data; // { code: 3000, data: { ID: "123456" } }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Usage
|
|
116
|
+
const newRecord = await createRecord("billing-app", "Invoices", {
|
|
117
|
+
Customer_Name: "Acme Corp",
|
|
118
|
+
Amount: 5000,
|
|
119
|
+
Due_Date: "2024-03-15",
|
|
120
|
+
Line_Items: [
|
|
121
|
+
{ Item: "Consulting", Quantity: 10, Rate: 500 }
|
|
122
|
+
]
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Read Records (with Pagination)
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
async function getAllRecords(appName, reportName, criteria = "") {
|
|
130
|
+
const accessToken = await getValidAccessToken();
|
|
131
|
+
let allRecords = [];
|
|
132
|
+
let startIndex = 0;
|
|
133
|
+
const pageSize = 200; // Max per page
|
|
134
|
+
let hasMore = true;
|
|
135
|
+
|
|
136
|
+
while (hasMore) {
|
|
137
|
+
const response = await axios.get(
|
|
138
|
+
`https://creator.zoho.com/api/v2/${OWNER}/${appName}/report/${reportName}`,
|
|
139
|
+
{
|
|
140
|
+
headers: { "Authorization": `Zoho-oauthtoken ${accessToken}` },
|
|
141
|
+
params: {
|
|
142
|
+
criteria: criteria,
|
|
143
|
+
limit: pageSize,
|
|
144
|
+
start_index: startIndex
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
const records = response.data.data || [];
|
|
150
|
+
allRecords = allRecords.concat(records);
|
|
151
|
+
|
|
152
|
+
// Check if more pages exist
|
|
153
|
+
if (records.length < pageSize) {
|
|
154
|
+
hasMore = false;
|
|
155
|
+
} else {
|
|
156
|
+
startIndex += pageSize;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return allRecords;
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Update Record
|
|
165
|
+
|
|
166
|
+
```javascript
|
|
167
|
+
async function updateRecord(appName, formName, recordId, data) {
|
|
168
|
+
const accessToken = await getValidAccessToken();
|
|
169
|
+
|
|
170
|
+
const response = await axios.patch(
|
|
171
|
+
`https://creator.zoho.com/api/v2/${OWNER}/${appName}/form/${formName}/${recordId}`,
|
|
172
|
+
{ data: data },
|
|
173
|
+
{
|
|
174
|
+
headers: {
|
|
175
|
+
"Authorization": `Zoho-oauthtoken ${accessToken}`,
|
|
176
|
+
"Content-Type": "application/json"
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
return response.data;
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Delete Record
|
|
186
|
+
|
|
187
|
+
```javascript
|
|
188
|
+
async function deleteRecord(appName, formName, recordId) {
|
|
189
|
+
const accessToken = await getValidAccessToken();
|
|
190
|
+
|
|
191
|
+
const response = await axios.delete(
|
|
192
|
+
`https://creator.zoho.com/api/v2/${OWNER}/${appName}/form/${formName}/${recordId}`,
|
|
193
|
+
{
|
|
194
|
+
headers: { "Authorization": `Zoho-oauthtoken ${accessToken}` }
|
|
195
|
+
}
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
return response.data;
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Response Format
|
|
203
|
+
|
|
204
|
+
### Success Response
|
|
205
|
+
|
|
206
|
+
```json
|
|
207
|
+
{
|
|
208
|
+
"code": 3000,
|
|
209
|
+
"data": {
|
|
210
|
+
"ID": "1234567890",
|
|
211
|
+
"Customer_Name": "Acme Corp",
|
|
212
|
+
"Amount": 5000
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Error Response
|
|
218
|
+
|
|
219
|
+
```json
|
|
220
|
+
{
|
|
221
|
+
"code": 2900,
|
|
222
|
+
"error": {
|
|
223
|
+
"message": "Invalid criteria format",
|
|
224
|
+
"details": {
|
|
225
|
+
"field": "criteria",
|
|
226
|
+
"expected": "valid Zoho criteria expression"
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Error Codes
|
|
233
|
+
|
|
234
|
+
| Code | Meaning | Action |
|
|
235
|
+
|------|---------|--------|
|
|
236
|
+
| 3000 | Success | Process data |
|
|
237
|
+
| 2890 | Invalid auth | Refresh token |
|
|
238
|
+
| 2900 | Bad request | Check request format |
|
|
239
|
+
| 2891 | Permission denied | Check app sharing settings |
|
|
240
|
+
| 4000 | Rate limit exceeded | Retry with backoff |
|
|
241
|
+
| 4100 | Record not found | Verify record ID |
|
|
242
|
+
|
|
243
|
+
## Webhook Alternatives
|
|
244
|
+
|
|
245
|
+
For real-time notifications instead of polling the API:
|
|
246
|
+
|
|
247
|
+
```deluge
|
|
248
|
+
// In Creator workflow (On Create/Edit), push data to external webhook
|
|
249
|
+
webhookUrl = "https://your-app.com/webhook/creator-update";
|
|
250
|
+
|
|
251
|
+
payload = Map();
|
|
252
|
+
payload.put("event", "record_created");
|
|
253
|
+
payload.put("form", "Invoices");
|
|
254
|
+
payload.put("record_id", input.ID.toString());
|
|
255
|
+
payload.put("data", {
|
|
256
|
+
"customer": input.Customer_Name,
|
|
257
|
+
"amount": input.Amount,
|
|
258
|
+
"status": input.Status
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
try
|
|
262
|
+
{
|
|
263
|
+
response = invokeUrl [
|
|
264
|
+
url: webhookUrl
|
|
265
|
+
type: POST
|
|
266
|
+
headers: {
|
|
267
|
+
"Content-Type": "application/json",
|
|
268
|
+
"X-Webhook-Secret": "your-shared-secret"
|
|
269
|
+
}
|
|
270
|
+
body: payload.toString()
|
|
271
|
+
];
|
|
272
|
+
info "Webhook delivered: " + response;
|
|
273
|
+
}
|
|
274
|
+
catch (e)
|
|
275
|
+
{
|
|
276
|
+
// Log failure but don't block record creation
|
|
277
|
+
info "Webhook delivery failed: " + e.toString();
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Webhook Verification (Receiving End)
|
|
282
|
+
|
|
283
|
+
```javascript
|
|
284
|
+
// Express.js webhook receiver
|
|
285
|
+
const crypto = require("crypto");
|
|
286
|
+
|
|
287
|
+
app.post("/webhook/creator-update", (req, res) => {
|
|
288
|
+
// Verify webhook signature
|
|
289
|
+
const secret = process.env.WEBHOOK_SECRET;
|
|
290
|
+
const signature = req.headers["x-webhook-secret"];
|
|
291
|
+
|
|
292
|
+
if (signature !== secret) {
|
|
293
|
+
return res.status(401).json({ error: "Invalid signature" });
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const { event, form, record_id, data } = req.body;
|
|
297
|
+
|
|
298
|
+
// Process async to respond quickly
|
|
299
|
+
processWebhookAsync(event, form, record_id, data);
|
|
300
|
+
|
|
301
|
+
// Respond immediately (Creator invokeUrl has 40-second timeout)
|
|
302
|
+
res.status(200).json({ received: true });
|
|
303
|
+
});
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Security Best Practices
|
|
307
|
+
|
|
308
|
+
1. **Never expose API keys in client-side code** - Use server-side proxy
|
|
309
|
+
2. **Validate all input** before passing to Creator API
|
|
310
|
+
3. **Use field-level permissions** to restrict API access to specific fields
|
|
311
|
+
4. **Enable IP whitelisting** in Creator API settings for production servers
|
|
312
|
+
5. **Rotate credentials** quarterly for SOC2 compliance clients
|
|
313
|
+
6. **Log all API access** for audit trail (HIPAA requirement)
|