@rglabs/butterfly 2.0.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 (117) hide show
  1. package/CLAUDE.md +201 -0
  2. package/README.md +371 -0
  3. package/dist/commands/add.d.ts +23 -0
  4. package/dist/commands/add.js +303 -0
  5. package/dist/commands/code.d.ts +11 -0
  6. package/dist/commands/code.js +72 -0
  7. package/dist/commands/create-object.d.ts +6 -0
  8. package/dist/commands/create-object.js +293 -0
  9. package/dist/commands/create-report.d.ts +6 -0
  10. package/dist/commands/create-report.js +154 -0
  11. package/dist/commands/diff.d.ts +4 -0
  12. package/dist/commands/diff.js +238 -0
  13. package/dist/commands/download.d.ts +4 -0
  14. package/dist/commands/download.js +374 -0
  15. package/dist/commands/layout.d.ts +12 -0
  16. package/dist/commands/layout.js +83 -0
  17. package/dist/commands/record.d.ts +21 -0
  18. package/dist/commands/record.js +483 -0
  19. package/dist/commands/run-poc.d.ts +3 -0
  20. package/dist/commands/run-poc.js +18 -0
  21. package/dist/commands/setup.d.ts +3 -0
  22. package/dist/commands/setup.js +66 -0
  23. package/dist/commands/start-poc.d.ts +3 -0
  24. package/dist/commands/start-poc.js +55 -0
  25. package/dist/commands/sync-docs.d.ts +3 -0
  26. package/dist/commands/sync-docs.js +27 -0
  27. package/dist/commands/translate.d.ts +13 -0
  28. package/dist/commands/translate.js +401 -0
  29. package/dist/commands/upload.d.ts +3 -0
  30. package/dist/commands/upload.js +150 -0
  31. package/dist/commands/workflow-info.d.ts +13 -0
  32. package/dist/commands/workflow-info.js +161 -0
  33. package/dist/components/ConflictResolver.d.ts +12 -0
  34. package/dist/components/ConflictResolver.js +77 -0
  35. package/dist/components/DiffView.d.ts +11 -0
  36. package/dist/components/DiffView.js +101 -0
  37. package/dist/components/DownloadProgress.d.ts +11 -0
  38. package/dist/components/DownloadProgress.js +29 -0
  39. package/dist/components/RecordPreview.d.ts +11 -0
  40. package/dist/components/RecordPreview.js +91 -0
  41. package/dist/components/SetupForm.d.ts +8 -0
  42. package/dist/components/SetupForm.js +56 -0
  43. package/dist/components/UploadProgress.d.ts +13 -0
  44. package/dist/components/UploadProgress.js +42 -0
  45. package/dist/diff/adapters/index.d.ts +8 -0
  46. package/dist/diff/adapters/index.js +18 -0
  47. package/dist/diff/adapters/objectsAdapter.d.ts +13 -0
  48. package/dist/diff/adapters/objectsAdapter.js +177 -0
  49. package/dist/diff/adapters/reportsAdapter.d.ts +14 -0
  50. package/dist/diff/adapters/reportsAdapter.js +212 -0
  51. package/dist/diff/adapters/types.d.ts +19 -0
  52. package/dist/diff/adapters/types.js +2 -0
  53. package/dist/diff/engine.d.ts +19 -0
  54. package/dist/diff/engine.js +57 -0
  55. package/dist/diff/types.d.ts +34 -0
  56. package/dist/diff/types.js +110 -0
  57. package/dist/index.d.ts +3 -0
  58. package/dist/index.js +117 -0
  59. package/dist/types/index.d.ts +18 -0
  60. package/dist/types/index.js +2 -0
  61. package/dist/utils/api.d.ts +85 -0
  62. package/dist/utils/api.js +1031 -0
  63. package/dist/utils/auth.d.ts +4 -0
  64. package/dist/utils/auth.js +22 -0
  65. package/dist/utils/bfySplitter.d.ts +12 -0
  66. package/dist/utils/bfySplitter.js +151 -0
  67. package/dist/utils/docs.d.ts +16 -0
  68. package/dist/utils/docs.js +186 -0
  69. package/dist/utils/errorLogger.d.ts +6 -0
  70. package/dist/utils/errorLogger.js +29 -0
  71. package/dist/utils/files.d.ts +14 -0
  72. package/dist/utils/files.js +772 -0
  73. package/dist/utils/lockManager.d.ts +15 -0
  74. package/dist/utils/lockManager.js +126 -0
  75. package/dist/utils/resourceHandlers.d.ts +50 -0
  76. package/dist/utils/resourceHandlers.js +684 -0
  77. package/dist/utils/resourceMapping.d.ts +32 -0
  78. package/dist/utils/resourceMapping.js +210 -0
  79. package/dist/utils/singleResourceDownload.d.ts +14 -0
  80. package/dist/utils/singleResourceDownload.js +261 -0
  81. package/dist/utils/summaryGenerator.d.ts +2 -0
  82. package/dist/utils/summaryGenerator.js +183 -0
  83. package/dist/utils/uploadHandler.d.ts +31 -0
  84. package/dist/utils/uploadHandler.js +263 -0
  85. package/docs/AI_API.md +93 -0
  86. package/docs/CLAUDE.md +216 -0
  87. package/docs/PROJECT_SPECIFIC.md +1 -0
  88. package/docs/RECORD_COMMAND.md +262 -0
  89. package/docs/WORKFLOW_API.md +480 -0
  90. package/docs/bfy-splitting.md +126 -0
  91. package/docs/cli-commands.md +333 -0
  92. package/docs/examples/README.md +95 -0
  93. package/docs/examples/order-system.md +147 -0
  94. package/docs/examples/product-catalog.md +195 -0
  95. package/docs/examples/reports.md +187 -0
  96. package/docs/excel-export.md +216 -0
  97. package/docs/field-types/README.md +29 -0
  98. package/docs/field-types/calculated.md +147 -0
  99. package/docs/field-types/code-mappings.md +84 -0
  100. package/docs/field-types/custom.md +340 -0
  101. package/docs/object-specs/README.md +136 -0
  102. package/docs/object-specs/code-parameters.md +151 -0
  103. package/docs/object-specs/creating.md +203 -0
  104. package/docs/object-specs/js-code-examples.md +208 -0
  105. package/docs/object-specs/js-field-updates.md +168 -0
  106. package/docs/objects/README.md +89 -0
  107. package/docs/objects/creating.md +127 -0
  108. package/docs/page-layout.md +361 -0
  109. package/docs/permissions.md +260 -0
  110. package/docs/reports.md +197 -0
  111. package/docs/state-machines.md +544 -0
  112. package/docs/tasks/create-object.md +81 -0
  113. package/docs/translations.md +346 -0
  114. package/docs/twig-helpers.md +283 -0
  115. package/docs/webservices.md +159 -0
  116. package/docs/workspaces.md +176 -0
  117. package/package.json +59 -0
@@ -0,0 +1,147 @@
1
+ # Calculated Field Type
2
+
3
+ Computed field using Twig expressions. Value is calculated server-side.
4
+
5
+ ## Type
6
+
7
+ ```
8
+ type: "calculated"
9
+ ```
10
+
11
+ ## Parameters
12
+
13
+ | Field | Type | Description |
14
+ |-------|------|-------------|
15
+ | `val_1` | string | Twig code for calculation |
16
+
17
+ ## File Export
18
+
19
+ When downloaded, `val_1` is exported to `code.bfy`.
20
+
21
+ ## Basic Example
22
+
23
+ Calculate total from price and quantity:
24
+
25
+ ```bash
26
+ butterfly-cli record add object_specs --data '{
27
+ "object_id": 128,
28
+ "name": "Total",
29
+ "column_name": "total",
30
+ "type": "calculated",
31
+ "val_1": "{{ info.price * info.quantity }}"
32
+ }'
33
+ ```
34
+
35
+ ## Available Variables
36
+
37
+ | Variable | Description |
38
+ |----------|-------------|
39
+ | `info` | Current record data (e.g., `info.price`, `info.quantity`) |
40
+ | `_user` | Current logged-in user |
41
+ | `_GET` | GET parameters |
42
+ | `_POST` | POST parameters |
43
+
44
+ ## Examples
45
+
46
+ ### Simple Math
47
+
48
+ ```bash
49
+ butterfly-cli record add object_specs --data '{
50
+ "object_id": 128,
51
+ "name": "Tax Amount",
52
+ "column_name": "tax_amount",
53
+ "type": "calculated",
54
+ "val_1": "{{ info.subtotal * 0.18 }}"
55
+ }'
56
+ ```
57
+
58
+ ### String Concatenation
59
+
60
+ ```bash
61
+ butterfly-cli record add object_specs --data '{
62
+ "object_id": 128,
63
+ "name": "Full Name",
64
+ "column_name": "full_name",
65
+ "type": "calculated",
66
+ "val_1": "{{ info.first_name ~ \" \" ~ info.last_name }}"
67
+ }'
68
+ ```
69
+
70
+ ### Conditional Value
71
+
72
+ ```bash
73
+ butterfly-cli record add object_specs --data '{
74
+ "object_id": 128,
75
+ "name": "Status Label",
76
+ "column_name": "status_label",
77
+ "type": "calculated",
78
+ "val_1": "{% if info.status == 1 %}Active{% else %}Inactive{% endif %}"
79
+ }'
80
+ ```
81
+
82
+ ### Date Formatting
83
+
84
+ ```bash
85
+ butterfly-cli record add object_specs --data '{
86
+ "object_id": 128,
87
+ "name": "Formatted Date",
88
+ "column_name": "formatted_date",
89
+ "type": "calculated",
90
+ "val_1": "{{ info.created_at|date(\"d/m/Y\") }}"
91
+ }'
92
+ ```
93
+
94
+ ### Database Query
95
+
96
+ ```bash
97
+ butterfly-cli record add object_specs --data '{
98
+ "object_id": 128,
99
+ "name": "Order Count",
100
+ "column_name": "order_count",
101
+ "type": "calculated",
102
+ "val_1": "{% set count = db().table(\"orders\").where(\"customer_id\", info.id).count() %}{{ count }}"
103
+ }'
104
+ ```
105
+
106
+ ### Related Record Lookup
107
+
108
+ ```bash
109
+ butterfly-cli record add object_specs --data '{
110
+ "object_id": 128,
111
+ "name": "Category Name",
112
+ "column_name": "category_name",
113
+ "type": "calculated",
114
+ "val_1": "{% set cat = db().table(\"categories\").where(\"id\", info.category_id).first() %}{{ cat.name|default(\"-\") }}"
115
+ }'
116
+ ```
117
+
118
+ ### Price with Currency
119
+
120
+ ```bash
121
+ butterfly-cli record add object_specs --data '{
122
+ "object_id": 128,
123
+ "name": "Price Display",
124
+ "column_name": "price_display",
125
+ "type": "calculated",
126
+ "val_1": "{{ info.price|number_format(2, \",\", \".\") }} TL"
127
+ }'
128
+ ```
129
+
130
+ ### Complex Calculation
131
+
132
+ ```bash
133
+ butterfly-cli record add object_specs --data '{
134
+ "object_id": 128,
135
+ "name": "Grand Total",
136
+ "column_name": "grand_total",
137
+ "type": "calculated",
138
+ "val_1": "{% set subtotal = info.price * info.quantity %}{% set discount = subtotal * (info.discount_percent / 100) %}{% set tax = (subtotal - discount) * 0.18 %}{{ subtotal - discount + tax }}"
139
+ }'
140
+ ```
141
+
142
+ ## Notes
143
+
144
+ - Calculated fields are read-only in the form
145
+ - Values are recalculated on each view/save
146
+ - Use `|default()` filter for null handling
147
+ - Complex calculations should be tested with the `code` command first
@@ -0,0 +1,84 @@
1
+ # Field Type Code Parameter Mappings
2
+
3
+ The CLI automatically exports code parameters from field specs based on their field types. Only parameters that contain actual code/configuration are exported as separate files.
4
+
5
+ ## Field Types That Export Code Files
6
+
7
+ | Field Type | Parameter | Exported File | Description |
8
+ |------------|-----------|---------------|-------------|
9
+ | `calculated` | `val_1` | `code.bfy` | Twig calculation code |
10
+ | `custom` | `val_1` | `template_code.bfy` | Twig template code |
11
+ | `custom` | `val_2` | `processing_code.bfy` | Twig processing code |
12
+ | `filter` | `val_3` | `filter_code.bfy` | Twig filter code |
13
+ | `nested` | `val_1` | `configuration.yaml` | YAML configuration |
14
+ | `nested_single` | `val_1` | `configuration.yaml` | YAML configuration |
15
+
16
+ ## Object Spec Fields That Export Code Files
17
+
18
+ | Field | Exported File | Description |
19
+ |-------|---------------|-------------|
20
+ | `js_code` | `code.js` | JavaScript code |
21
+ | `css_code` | `style.css` | CSS code |
22
+
23
+ ## Field Types That DO NOT Export Code Files
24
+
25
+ - **code**: Despite the name, this field type only stores dropdown selections for code language and AI tasks, not actual code content
26
+ - All other field types: Only contain string, dropdown, integer, or checkbox parameters
27
+
28
+ ## Object Files Exported
29
+
30
+ | File | Description |
31
+ |------|-------------|
32
+ | `object.json` | Complete object definition |
33
+ | `listing_query.bfy` | Object's listing query (if present) |
34
+
35
+ ## Report Files Exported
36
+
37
+ | File | Description |
38
+ |------|-------------|
39
+ | `report.json` | Report definition from `cms_reports` |
40
+ | `main_query.bfy` | **DEPRECATED** - legacy file, do not use |
41
+ | `categories.json` | All report categories (shared file) |
42
+
43
+ ### Report Query Files
44
+
45
+ | File | Description |
46
+ |------|-------------|
47
+ | `query.json` | Query definition from `cms_report_queries` |
48
+ | `query_code.bfy` | Twig code from `query` field |
49
+ | `script.js` | JavaScript from `js_code` field (if exists) |
50
+
51
+ ### Report Spec Files
52
+
53
+ | File | Description |
54
+ |------|-------------|
55
+ | `spec.json` | Spec definition from `cms_report_specs` |
56
+ | `code.js` | JavaScript from `js_code` field (if exists) |
57
+
58
+ ## Directory Structure
59
+
60
+ ```
61
+ butterfly-resources/
62
+ └── objects/
63
+ └── [butterfly|app]/
64
+ └── [table_name]/
65
+ ├── object.json
66
+ ├── listing_query.bfy
67
+ └── [field_name]/
68
+ ├── spec.json
69
+ ├── code.bfy # For calculated
70
+ ├── template_code.bfy # For custom (val_1)
71
+ ├── processing_code.bfy # For custom (val_2)
72
+ ├── filter_code.bfy # For filter
73
+ ├── configuration.yaml # For nested/nested_single
74
+ ├── code.js # If js_code exists
75
+ └── style.css # If css_code exists
76
+ ```
77
+
78
+ ## Usage Notes
79
+
80
+ 1. **Report specs use the same field types** as object specs. Use the same `type` and `val_*` parameter conventions.
81
+
82
+ 2. **When creating reports**, always use `cms_report_queries` for Twig query code. The `query` field in `cms_reports` is deprecated.
83
+
84
+ 3. **Code files can be uploaded** using `butterfly-cli upload <path>`.
@@ -0,0 +1,340 @@
1
+ # Custom Field Type
2
+
3
+ Custom field with Twig template for display and processing code for form submissions.
4
+
5
+ ## Type
6
+
7
+ ```
8
+ type: "custom"
9
+ ```
10
+
11
+ ## Parameters
12
+
13
+ | Field | Type | Description |
14
+ |-------|------|-------------|
15
+ | `val_1` | string | Template code (Twig) - rendered in form |
16
+ | `val_2` | string | Processing code (Twig) - executed on submit |
17
+
18
+ ## File Export
19
+
20
+ When downloaded:
21
+ - `val_1` → `template_code.bfy`
22
+ - `val_2` → `processing_code.bfy`
23
+
24
+ ## Basic Example
25
+
26
+ Button that sets a field value:
27
+
28
+ ```bash
29
+ butterfly-cli record add object_specs --data '{
30
+ "object_id": 128,
31
+ "name": "Process",
32
+ "column_name": "process_action",
33
+ "type": "custom",
34
+ "val_1": "<button type=\"submit\" name=\"process\" class=\"btn btn-primary\">Process</button>",
35
+ "val_2": "{% if _POST.process %}{{ setValue(\"status\", \"processed\") }}{% endif %}"
36
+ }'
37
+ ```
38
+
39
+ ## Template Code (val_1)
40
+
41
+ The template is rendered in the edit form. Available variables:
42
+
43
+ | Variable | Description |
44
+ |----------|-------------|
45
+ | `info` | Current record data (e.g., `info.title`, `info.status`) |
46
+ | `_user` | Current logged-in user |
47
+ | `id` | Current record ID |
48
+
49
+ ### Display Information
50
+
51
+ ```twig
52
+ <div class="alert alert-info">
53
+ Created by: {{ info.created_by_name }}<br>
54
+ Created at: {{ info.created_at|date("d/m/Y H:i") }}
55
+ </div>
56
+ ```
57
+
58
+ ### Button with Confirmation
59
+
60
+ ```twig
61
+ <button type="submit" name="approve" class="btn btn-success"
62
+ onclick="return confirm('Are you sure?')">
63
+ Approve
64
+ </button>
65
+ ```
66
+
67
+ ### Input Masking
68
+
69
+ ```twig
70
+ <input type="text" name="phone" id="phone" class="form-control" value="{{ info.phone }}">
71
+ <script>
72
+ Inputmask('(599) 999 99 99').mask($('#phone'));
73
+ </script>
74
+ ```
75
+
76
+ ## Processing Code (val_2)
77
+
78
+ Executed when form is submitted. Available functions:
79
+
80
+ | Function | Description |
81
+ |----------|-------------|
82
+ | `setValue(column, value)` | Set field value |
83
+ | `getValue(column)` | Get field value |
84
+ | `errorMessage(msg)` | Show error and stop |
85
+ | `crud()` | CRUD operations on other tables |
86
+ | `db()` | Database queries |
87
+
88
+ ### Set Value
89
+
90
+ ```twig
91
+ {% if _POST.approve %}
92
+ {{ setValue('status', 'approved') }}
93
+ {{ setValue('approved_at', 'now'|date('Y-m-d H:i:s')) }}
94
+ {{ setValue('approved_by', _user.id) }}
95
+ {% endif %}
96
+ ```
97
+
98
+ ### Insert Related Record
99
+
100
+ ```twig
101
+ {% if _POST.create_invoice %}
102
+ {% set response = crud()
103
+ .table('invoices')
104
+ .insert({
105
+ "order_id": getValue('id'),
106
+ "amount": getValue('total'),
107
+ "status": "draft"
108
+ })
109
+ %}
110
+ {% if response.success %}
111
+ {{ setValue('invoice_id', response.id) }}
112
+ {% else %}
113
+ {{ errorMessage(response.message) }}
114
+ {% endif %}
115
+ {% endif %}
116
+ ```
117
+
118
+ ### Update Related Record
119
+
120
+ ```twig
121
+ {% if _POST.update_stock %}
122
+ {% set response = crud()
123
+ .table('products')
124
+ .update({
125
+ "id": getValue('product_id'),
126
+ "stock": getValue('new_stock')
127
+ })
128
+ %}
129
+ {% endif %}
130
+ ```
131
+
132
+ ### Validation
133
+
134
+ ```twig
135
+ {% if _POST.submit %}
136
+ {% if getValue('quantity') < 1 %}
137
+ {{ errorMessage('Quantity must be at least 1') }}
138
+ {% endif %}
139
+ {% if getValue('price') <= 0 %}
140
+ {{ errorMessage('Price must be positive') }}
141
+ {% endif %}
142
+ {% endif %}
143
+ ```
144
+
145
+ ### Query and Update
146
+
147
+ ```twig
148
+ {% if _POST.apply_discount %}
149
+ {% set product = db().table('products').where('id', getValue('product_id')).first() %}
150
+ {% set discounted = product.price * 0.9 %}
151
+ {{ setValue('final_price', discounted) }}
152
+ {% endif %}
153
+ ```
154
+
155
+ ## Complete Examples
156
+
157
+ ### Approval Button
158
+
159
+ ```bash
160
+ butterfly-cli record add object_specs --data '{
161
+ "object_id": 128,
162
+ "name": "Approval",
163
+ "column_name": "approval_action",
164
+ "type": "custom",
165
+ "val_1": "{% if info.status != \"approved\" %}<button type=\"submit\" name=\"approve\" class=\"btn btn-success\">Approve</button>{% else %}<span class=\"badge bg-success\">Approved</span>{% endif %}",
166
+ "val_2": "{% if _POST.approve %}{{ setValue(\"status\", \"approved\") }}{{ setValue(\"approved_at\", \"now\"|date(\"Y-m-d H:i:s\")) }}{% endif %}"
167
+ }'
168
+ ```
169
+
170
+ ### Status Workflow
171
+
172
+ ```bash
173
+ butterfly-cli record add object_specs --data '{
174
+ "object_id": 128,
175
+ "name": "Actions",
176
+ "column_name": "workflow_actions",
177
+ "type": "custom",
178
+ "val_1": "{% if info.status == \"draft\" %}<button type=\"submit\" name=\"submit_review\" class=\"btn btn-primary\">Submit for Review</button>{% elseif info.status == \"review\" %}<button type=\"submit\" name=\"approve\" class=\"btn btn-success\">Approve</button> <button type=\"submit\" name=\"reject\" class=\"btn btn-danger\">Reject</button>{% endif %}",
179
+ "val_2": "{% if _POST.submit_review %}{{ setValue(\"status\", \"review\") }}{% elseif _POST.approve %}{{ setValue(\"status\", \"approved\") }}{% elseif _POST.reject %}{{ setValue(\"status\", \"rejected\") }}{% endif %}"
180
+ }'
181
+ ```
182
+
183
+ ## Notes
184
+
185
+ - Custom fields don't create database columns
186
+ - Use for actions, computed displays, and form submissions
187
+ - Template code runs on every page load
188
+ - Processing code runs only on form submit
189
+
190
+ > **IMPORTANT - Form Input Naming:** Custom fields use `column_name=1` internally to enable the field. When adding form inputs in `template_code`, you MUST use a different `name` attribute than the field's `column_name`. For example, if the custom field's `column_name` is `my_field`, use `<input name="my_field_value" />` instead of `<input name="my_field" />` to avoid conflicts.
191
+
192
+ ---
193
+
194
+ ## Advanced Processing Code Patterns
195
+
196
+ ### Block After (Post-Save Processing)
197
+
198
+ By default, `processing_code` runs **BEFORE** form data is saved. If you use `setValue()` on a field that's in the form, the form POST value will override it.
199
+
200
+ To run code **AFTER** save, use `{% block after %}`:
201
+
202
+ ```twig
203
+ {% block after %}
204
+ {{ setValue('calculated_total', getValue('quantity') * getValue('price')) }}
205
+ {{ setValue('updated_at', 'now'|date('Y-m-d H:i:s')) }}
206
+ {% endblock %}
207
+ ```
208
+
209
+ > **Important:** `{% block after %}` is **isolated** - it cannot access variables from the main processing_code block. Use `getValue()` or `db()` queries to get data.
210
+
211
+ #### Execution Order
212
+
213
+ 1. `processing_code` (main block) - runs BEFORE save
214
+ 2. Form POST data is saved to database
215
+ 3. `{% block after %}` - runs AFTER save (isolated scope)
216
+
217
+ #### Wrong vs Correct
218
+
219
+ ```twig
220
+ {# WRONG - variable from main block NOT accessible #}
221
+ {% set myValue = 5 %}
222
+ {% block after %}
223
+ {{ setValue('test_id', myValue) }} {# ERROR: myValue is undefined #}
224
+ {% endblock %}
225
+
226
+ {# CORRECT - use getValue() or hardcoded values #}
227
+ {% block after %}
228
+ {{ setValue('test_id', 5) }}
229
+ {{ setValue('total', getValue('quantity') * getValue('price')) }}
230
+
231
+ {# Fetch data using db() #}
232
+ {% set related = db().table('other_table').where('id', getValue('related_id')).first() %}
233
+ {{ setValue('related_name', related.name) }}
234
+ {% endblock %}
235
+ ```
236
+
237
+ ### Page Refresh After Save
238
+
239
+ To refresh the page after save (edit operations only):
240
+
241
+ ```twig
242
+ {{ registry('page_refresh', 1) }}
243
+ ```
244
+
245
+ Use when:
246
+ - Twig conditions in template_code depend on saved values
247
+ - UI elements need to update based on new state
248
+ - Calculated/displayed fields need immediate refresh
249
+
250
+ > **Note:** Add operations already refresh/redirect by default.
251
+
252
+ ### Accessing Current Record Data
253
+
254
+ | Context | Method | Example |
255
+ |---------|--------|---------|
256
+ | `template_code` | `info.column` | `{{ info.title }}` |
257
+ | `processing_code` | `getValue('column')` | `{{ getValue('title') }}` |
258
+
259
+ ```twig
260
+ {# In template_code.bfy #}
261
+ {{ info.title }}
262
+ {{ info.status }}
263
+ {% if info.is_active == 1 %}Active{% endif %}
264
+
265
+ {# In processing_code.bfy #}
266
+ {% set title = getValue('title') %}
267
+ {% if getValue('status') == 'pending' %}
268
+ {{ setValue('status', 'processed') }}
269
+ {% endif %}
270
+ ```
271
+
272
+ ### Getting Request Parameters
273
+
274
+ ```twig
275
+ {# Get POST or GET parameter #}
276
+ {% set userId = getParameter('user_id') %}
277
+
278
+ {# Conditional logic #}
279
+ {% if getParameter('action') == 'approve' %}
280
+ {{ setValue('status', 'approved') }}
281
+ {% endif %}
282
+
283
+ {# Multiple parameters #}
284
+ {% set data = {
285
+ "name": getParameter('name'),
286
+ "email": getParameter('email'),
287
+ "phone": getParameter('phone')
288
+ } %}
289
+ ```
290
+
291
+ ### CRUD Operations in Processing Code
292
+
293
+ #### Insert
294
+
295
+ ```twig
296
+ {% set response = crud()
297
+ .table('TARGET_TABLE')
298
+ .insert({
299
+ "field_name": "value"
300
+ })
301
+ %}
302
+
303
+ {% if response.success %}
304
+ {{ response.id }}
305
+ {% else %}
306
+ {{ errorMessage(response.message) }}
307
+ {% endif %}
308
+ ```
309
+
310
+ #### Update
311
+
312
+ ```twig
313
+ {% set response = crud()
314
+ .table('TARGET_TABLE')
315
+ .update({
316
+ "id": "RECORD_ID",
317
+ "field_name": "value"
318
+ })
319
+ %}
320
+ ```
321
+
322
+ #### Delete
323
+
324
+ ```twig
325
+ {% set response = crud()
326
+ .table('TARGET_TABLE')
327
+ .delete({
328
+ "id": "RECORD_ID"
329
+ })
330
+ %}
331
+ ```
332
+
333
+ #### For Webservices (No Auth)
334
+
335
+ ```twig
336
+ {% set response = crud('default', false)
337
+ .table('TARGET_TABLE')
338
+ .insert({...})
339
+ %}
340
+ ```
@@ -0,0 +1,136 @@
1
+ # Object Specs
2
+
3
+ Object specs define the fields (columns) of an object. Each spec represents a form field and database column.
4
+
5
+ ## Table: `object_specs`
6
+
7
+ ## Required Fields
8
+
9
+ | Field | Type | Description |
10
+ |-------|------|-------------|
11
+ | `object_id` | int | Parent object ID |
12
+ | `name` | string | Display label |
13
+ | `column_name` | string | Database column name |
14
+ | `type` | string | Field type (see [Field Types](../field-types/README.md)) |
15
+
16
+ ## Common Fields
17
+
18
+ | Field | Type | Default | Description |
19
+ |-------|------|---------|-------------|
20
+ | `required` | int | `0` | `1` = required field |
21
+ | `list_column` | int | `0` | `1` = show in list view |
22
+ | `search_column` | int | `0` | `1` = searchable |
23
+ | `edit_order_no` | int | null | Order in edit form |
24
+ | `list_order_no` | int | null | Order in list view |
25
+ | `default_value` | string | null | Default value |
26
+ | `description` | string | null | Help text |
27
+
28
+ ## Display Fields
29
+
30
+ | Field | Type | Description |
31
+ |-------|------|-------------|
32
+ | `width` | int | Field width |
33
+ | `height` | int | Field height (for textarea) |
34
+ | `column_size` | string | Bootstrap column size (e.g., "col-md-6") |
35
+ | `section_title` | string | Section header above field |
36
+ | `edit_position` | int | Position: `0`=main, `1`=sidebar |
37
+ | `edit_place_no` | int | Place number within position |
38
+
39
+ ## Validation Fields
40
+
41
+ | Field | Type | Description |
42
+ |-------|------|-------------|
43
+ | `validation_type` | string | Validation rule |
44
+ | `manipulation_type` | string | Data manipulation |
45
+ | `is_readonly` | int | `1` = read-only field |
46
+ | `is_sensitive` | int | `1` = sensitive data (masked) |
47
+
48
+ ## Code Fields
49
+
50
+ | Field | Type | Description | Export File |
51
+ |-------|------|-------------|-------------|
52
+ | `js_code` | string | JavaScript for field behavior | `code.js` |
53
+ | `css_code` | string | Custom CSS styles | `style.css` |
54
+
55
+ ## Type-Specific Value Fields
56
+
57
+ | Field | Description |
58
+ |-------|-------------|
59
+ | `val_1` | Type-specific parameter 1 |
60
+ | `val_2` | Type-specific parameter 2 |
61
+ | `val_3` | Type-specific parameter 3 |
62
+ | `val_4` | Type-specific parameter 4 |
63
+ | `val_5` | Type-specific parameter 5 |
64
+
65
+ See [Field Types](../field-types/README.md) for what each `val_*` means per type.
66
+
67
+ ## Creating a Spec
68
+
69
+ ### Basic String Field
70
+
71
+ ```bash
72
+ butterfly-cli record add object_specs --data '{
73
+ "object_id": 128,
74
+ "name": "Title",
75
+ "column_name": "title",
76
+ "type": "string",
77
+ "required": 1,
78
+ "list_column": 1,
79
+ "edit_order_no": 1
80
+ }'
81
+ ```
82
+
83
+ ### Dropdown Field
84
+
85
+ ```bash
86
+ butterfly-cli record add object_specs --data '{
87
+ "object_id": 128,
88
+ "name": "Status",
89
+ "column_name": "status",
90
+ "type": "from_list",
91
+ "val_1": "active:Active,inactive:Inactive,pending:Pending",
92
+ "edit_order_no": 2
93
+ }'
94
+ ```
95
+
96
+ ### Foreign Key (dropdown)
97
+
98
+ ```bash
99
+ butterfly-cli record add object_specs --data '{
100
+ "object_id": 128,
101
+ "name": "Category",
102
+ "column_name": "category_id",
103
+ "type": "dropdown",
104
+ "val_1": "categories",
105
+ "val_2": "id",
106
+ "val_3": "name",
107
+ "edit_order_no": 3
108
+ }'
109
+ ```
110
+
111
+ ## Get Specs for an Object
112
+
113
+ ```bash
114
+ butterfly-cli record get object_specs --column object_id --value 128
115
+ ```
116
+
117
+ ## Update a Spec
118
+
119
+ ```bash
120
+ butterfly-cli record edit object_specs --id 1071 --data '{
121
+ "required": 1,
122
+ "list_column": 1
123
+ }'
124
+ ```
125
+
126
+ ## Delete a Spec
127
+
128
+ ```bash
129
+ butterfly-cli record delete object_specs --id 1071
130
+ ```
131
+
132
+ ## Related
133
+
134
+ - [Creating Specs Guide](./creating.md)
135
+ - [Code Parameters](./code-parameters.md)
136
+ - [Field Types Reference](../field-types/README.md)