@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,151 @@
1
+ # Code Parameters
2
+
3
+ Object specs support custom JavaScript and CSS for field behavior and styling.
4
+
5
+ ## JavaScript (js_code)
6
+
7
+ The `js_code` field adds client-side behavior to fields.
8
+
9
+ ### Placeholder: `%element%`
10
+
11
+ Use `%element%` as a placeholder for the current field's jQuery selector. It gets replaced with the actual selector at runtime.
12
+
13
+ ### Conditional Field Display
14
+
15
+ Show/hide fields based on dropdown selection:
16
+
17
+ ```bash
18
+ butterfly-cli record add object_specs --data '{
19
+ "object_id": 128,
20
+ "name": "Type",
21
+ "column_name": "type",
22
+ "type": "from_list",
23
+ "val_1": "1:Physical,2:Digital",
24
+ "js_code": "%element%.condition({\"1\": [\"weight\", \"dimensions\"], \"2\": [\"download_url\"]})"
25
+ }'
26
+ ```
27
+
28
+ This shows `weight` and `dimensions` fields when "Physical" is selected, and `download_url` when "Digital" is selected.
29
+
30
+ ### On Change Handler
31
+
32
+ Fetch data from another table when field changes:
33
+
34
+ ```bash
35
+ butterfly-cli record add object_specs --data '{
36
+ "object_id": 128,
37
+ "name": "Customer",
38
+ "column_name": "customer_id",
39
+ "type": "dropdown",
40
+ "val_1": "customers",
41
+ "val_2": "id",
42
+ "val_3": "name",
43
+ "js_code": "%element%.on(\"change\", function() { var id = $(this).val(); $.post(\"/admin/ajax/cms_object/get\", {\"table_name\": \"customers\", \"column\": \"id\", \"value\": id}, function(data) { $(\"[name=email]\").val(data.data[0].email); }); })"
44
+ }'
45
+ ```
46
+
47
+ ### Auto-populate Fields
48
+
49
+ ```javascript
50
+ // js_code value (formatted for readability)
51
+ %element%.on('change', function() {
52
+ var id = $(this).val();
53
+
54
+ $.post('/admin/ajax/cms_object/get', {
55
+ "table_name": "products",
56
+ "column": "id",
57
+ "value": id
58
+ }, function(data) {
59
+ // For dynamic fields (date, dropdown, etc.)
60
+ bfyRefresh_price(data.data[0].price);
61
+
62
+ // For static fields (string, integer, textarea)
63
+ $('[name="sku"]').val(data.data[0].sku).trigger('change');
64
+ });
65
+ });
66
+ ```
67
+
68
+ ### Input Masking
69
+
70
+ ```bash
71
+ butterfly-cli record add object_specs --data '{
72
+ "object_id": 128,
73
+ "name": "Phone",
74
+ "column_name": "phone",
75
+ "type": "string",
76
+ "js_code": "Inputmask(\"(999) 999-9999\").mask(%element%)"
77
+ }'
78
+ ```
79
+
80
+ ## CSS (css_code)
81
+
82
+ The `css_code` field adds custom styles.
83
+
84
+ ### Basic Styling
85
+
86
+ ```bash
87
+ butterfly-cli record add object_specs --data '{
88
+ "object_id": 128,
89
+ "name": "Important Note",
90
+ "column_name": "note",
91
+ "type": "textarea",
92
+ "css_code": ".field-note textarea { background-color: #fff3cd; border-color: #ffc107; }"
93
+ }'
94
+ ```
95
+
96
+ ### Hide Label
97
+
98
+ ```bash
99
+ --data '{
100
+ "css_code": ".field-hidden_field label { display: none; }"
101
+ }'
102
+ ```
103
+
104
+ ## File Export
105
+
106
+ When downloading objects, code fields are exported to separate files:
107
+
108
+ ```
109
+ butterfly-resources/objects/app/table_name/
110
+ ├── object.json
111
+ └── field_name/
112
+ ├── spec.json
113
+ ├── code.js # js_code content
114
+ └── style.css # css_code content
115
+ ```
116
+
117
+ ## Examples
118
+
119
+ ### Complete Dropdown with Conditions
120
+
121
+ ```bash
122
+ butterfly-cli record add object_specs --data '{
123
+ "object_id": 128,
124
+ "name": "Payment Method",
125
+ "column_name": "payment_method",
126
+ "type": "from_list",
127
+ "val_1": "credit_card:Credit Card,bank_transfer:Bank Transfer,cash:Cash",
128
+ "js_code": "%element%.condition({\"credit_card\": [\"card_number\", \"expiry_date\"], \"bank_transfer\": [\"bank_name\", \"account_number\"]})",
129
+ "edit_order_no": 5
130
+ }'
131
+ ```
132
+
133
+ ### Auto-fill from Related Record
134
+
135
+ ```bash
136
+ butterfly-cli record add object_specs --data '{
137
+ "object_id": 128,
138
+ "name": "Product",
139
+ "column_name": "product_id",
140
+ "type": "dropdown",
141
+ "val_1": "products",
142
+ "val_2": "id",
143
+ "val_3": "name",
144
+ "js_code": "%element%.on(\"change\", function() { var id = $(this).val(); if(id) { $.post(\"/admin/ajax/cms_object/get\", {\"table_name\": \"products\", \"column\": \"id\", \"value\": id}, function(data) { if(data.data[0]) { $(\"[name=unit_price]\").val(data.data[0].price).trigger(\"change\"); $(\"[name=sku]\").val(data.data[0].sku).trigger(\"change\"); } }); } })"
145
+ }'
146
+ ```
147
+
148
+ ## Related
149
+
150
+ - [Field Types Reference](../field-types/README.md)
151
+ - [Custom Field Type](../field-types/custom.md) - For complex template/processing code
@@ -0,0 +1,203 @@
1
+ # Creating Object Specs
2
+
3
+ Step-by-step guide to adding fields to objects.
4
+
5
+ ## Prerequisites
6
+
7
+ You need an object ID. Get it by:
8
+
9
+ ```bash
10
+ # By table name
11
+ butterfly-cli record get objects --column table_name --value "products"
12
+
13
+ # Or list all app objects
14
+ butterfly-cli record get objects --column is_cms_object --value 0
15
+ ```
16
+
17
+ ## Basic Field Creation
18
+
19
+ ### Syntax
20
+
21
+ ```bash
22
+ butterfly-cli record add object_specs --data '{
23
+ "object_id": <OBJECT_ID>,
24
+ "name": "<Display Name>",
25
+ "column_name": "<column_name>",
26
+ "type": "<field_type>",
27
+ ...additional options
28
+ }'
29
+ ```
30
+
31
+ ### Simple Text Field
32
+
33
+ ```bash
34
+ butterfly-cli record add object_specs --data '{
35
+ "object_id": 128,
36
+ "name": "Title",
37
+ "column_name": "title",
38
+ "type": "string",
39
+ "required": 1,
40
+ "list_column": 1,
41
+ "search_column": 1,
42
+ "edit_order_no": 1
43
+ }'
44
+ ```
45
+
46
+ ## Field Ordering
47
+
48
+ Use `edit_order_no` to control form layout:
49
+
50
+ ```bash
51
+ # First field
52
+ --data '{"object_id":128,"name":"Name","column_name":"name","type":"string","edit_order_no":1}'
53
+
54
+ # Second field
55
+ --data '{"object_id":128,"name":"Email","column_name":"email","type":"string","edit_order_no":2}'
56
+
57
+ # Third field
58
+ --data '{"object_id":128,"name":"Status","column_name":"status","type":"from_list","edit_order_no":3}'
59
+ ```
60
+
61
+ ## Field Positioning
62
+
63
+ ### Main Content vs Sidebar
64
+
65
+ ```bash
66
+ # Main content area (default)
67
+ --data '{"object_id":128,"name":"Description","column_name":"description","type":"textarea","edit_position":0}'
68
+
69
+ # Sidebar
70
+ --data '{"object_id":128,"name":"Status","column_name":"status","type":"from_list","edit_position":1}'
71
+ ```
72
+
73
+ ### Column Sizing
74
+
75
+ ```bash
76
+ # Half width
77
+ --data '{"object_id":128,"name":"First Name","column_name":"first_name","type":"string","column_size":"col-md-6"}'
78
+
79
+ # Full width (default)
80
+ --data '{"object_id":128,"name":"Bio","column_name":"bio","type":"textarea","column_size":"col-md-12"}'
81
+ ```
82
+
83
+ ## Section Headers
84
+
85
+ Group fields with section titles:
86
+
87
+ ```bash
88
+ # Basic Info section
89
+ --data '{"object_id":128,"name":"Name","column_name":"name","type":"string","section_title":"Basic Information","edit_order_no":1}'
90
+ --data '{"object_id":128,"name":"Email","column_name":"email","type":"string","edit_order_no":2}'
91
+
92
+ # Contact section
93
+ --data '{"object_id":128,"name":"Phone","column_name":"phone","type":"string","section_title":"Contact Details","edit_order_no":3}'
94
+ ```
95
+
96
+ ## Common Field Types
97
+
98
+ ### String (Text Input)
99
+
100
+ ```bash
101
+ butterfly-cli record add object_specs --data '{
102
+ "object_id": 128,
103
+ "name": "Title",
104
+ "column_name": "title",
105
+ "type": "string"
106
+ }'
107
+ ```
108
+
109
+ ### Integer
110
+
111
+ ```bash
112
+ butterfly-cli record add object_specs --data '{
113
+ "object_id": 128,
114
+ "name": "Quantity",
115
+ "column_name": "quantity",
116
+ "type": "integer",
117
+ "default_value": "0"
118
+ }'
119
+ ```
120
+
121
+ ### Textarea
122
+
123
+ ```bash
124
+ butterfly-cli record add object_specs --data '{
125
+ "object_id": 128,
126
+ "name": "Description",
127
+ "column_name": "description",
128
+ "type": "textarea",
129
+ "height": 200
130
+ }'
131
+ ```
132
+
133
+ ### Dropdown (from_list)
134
+
135
+ ```bash
136
+ butterfly-cli record add object_specs --data '{
137
+ "object_id": 128,
138
+ "name": "Status",
139
+ "column_name": "status",
140
+ "type": "from_list",
141
+ "val_1": "draft:Draft,published:Published,archived:Archived"
142
+ }'
143
+ ```
144
+
145
+ ### Foreign Key (dropdown)
146
+
147
+ ```bash
148
+ butterfly-cli record add object_specs --data '{
149
+ "object_id": 128,
150
+ "name": "Category",
151
+ "column_name": "category_id",
152
+ "type": "dropdown",
153
+ "val_1": "categories",
154
+ "val_2": "id",
155
+ "val_3": "name"
156
+ }'
157
+ ```
158
+
159
+ ### Date
160
+
161
+ ```bash
162
+ butterfly-cli record add object_specs --data '{
163
+ "object_id": 128,
164
+ "name": "Due Date",
165
+ "column_name": "due_date",
166
+ "type": "date"
167
+ }'
168
+ ```
169
+
170
+ ### Checkbox
171
+
172
+ ```bash
173
+ butterfly-cli record add object_specs --data '{
174
+ "object_id": 128,
175
+ "name": "Is Active",
176
+ "column_name": "is_active",
177
+ "type": "checkbox",
178
+ "default_value": "1"
179
+ }'
180
+ ```
181
+
182
+ ## Batch Creation
183
+
184
+ Create multiple fields efficiently:
185
+
186
+ ```bash
187
+ # Using a JSON file
188
+ echo '[
189
+ {"object_id":128,"name":"Name","column_name":"name","type":"string","required":1,"edit_order_no":1},
190
+ {"object_id":128,"name":"Email","column_name":"email","type":"string","edit_order_no":2},
191
+ {"object_id":128,"name":"Status","column_name":"status","type":"from_list","val_1":"active:Active,inactive:Inactive","edit_order_no":3}
192
+ ]' > /tmp/specs.json
193
+
194
+ # Create each (loop in shell)
195
+ for spec in $(cat /tmp/specs.json | jq -c '.[]'); do
196
+ butterfly-cli record add object_specs --data "$spec" -y
197
+ done
198
+ ```
199
+
200
+ ## Next Steps
201
+
202
+ - [Code Parameters](./code-parameters.md) - Adding js_code and css_code
203
+ - [Field Types Reference](../field-types/README.md) - All field types and parameters
@@ -0,0 +1,208 @@
1
+ # JavaScript Code Examples for Object Specs
2
+
3
+ The `js_code` field in object specs allows custom JavaScript functionality. Code is exported as `code.js` in the field directory.
4
+
5
+ ## File Location
6
+
7
+ ```
8
+ butterfly-resources/
9
+ └── objects/
10
+ └── [butterfly|app]/
11
+ └── [table_name]/
12
+ └── [field_name]/
13
+ ├── spec.json
14
+ └── code.js # JavaScript code
15
+ ```
16
+
17
+ ## The %element% Placeholder
18
+
19
+ `%element%` is automatically replaced with the jQuery selector for the current field element. Use it to access the field's methods and events.
20
+
21
+ ```javascript
22
+ // %element% becomes something like $('[name="field_name"]')
23
+ %element%.on('change', function() {
24
+ // Handle change
25
+ });
26
+ ```
27
+
28
+ ## Common Patterns
29
+
30
+ ### Conditional Field Visibility
31
+
32
+ Show/hide fields based on dropdown selection:
33
+
34
+ ```javascript
35
+ %element%.condition({
36
+ "1": ["field_a", "field_b"], // Show when value is "1"
37
+ "2": ["field_c"], // Show when value is "2"
38
+ "3": [] // Hide all when value is "3"
39
+ });
40
+ ```
41
+
42
+ ### Fetch Data from Another Table
43
+
44
+ Load related data when field changes:
45
+
46
+ ```javascript
47
+ %element%.on('change', function() {
48
+ var id = $(this).val();
49
+
50
+ if (!id) return;
51
+
52
+ $.post('/admin/ajax/cms_object/get', {
53
+ "table_name": 'source_table',
54
+ "column": "id",
55
+ "value": id
56
+ }, function(response) {
57
+ if (response.data && response.data[0]) {
58
+ var record = response.data[0];
59
+
60
+ // Update calculated/custom/date fields
61
+ bfyRefresh_total(record.total);
62
+ bfyRefresh_due_date(record.due_date);
63
+
64
+ // Update other fields
65
+ $('[name="title"]').val(record.title).trigger('change');
66
+ $('[name="status"]').val(record.status).trigger('change');
67
+ }
68
+ });
69
+ });
70
+ ```
71
+
72
+ > **Note:** The `column` parameter should match `val_3` of the source field (the value column for dropdowns).
73
+
74
+ ### Alert Dialog
75
+
76
+ Show alert with callback:
77
+
78
+ ```javascript
79
+ %element%.on('click', function(e) {
80
+ e.preventDefault();
81
+
82
+ rg_alert('Are you sure you want to proceed?', function() {
83
+ // User clicked OK
84
+ console.log('Confirmed');
85
+ });
86
+ });
87
+ ```
88
+
89
+ ### Input Masking
90
+
91
+ Format user input automatically:
92
+
93
+ ```javascript
94
+ // Phone number
95
+ %element%.maskInput('(999) 999-9999');
96
+
97
+ // Date
98
+ %element%.maskInput('99/99/9999');
99
+
100
+ // Custom format
101
+ %element%.maskInput('AAA-999');
102
+ ```
103
+
104
+ #### Mask Pattern Reference
105
+
106
+ | Character | Description |
107
+ |-----------|-------------|
108
+ | `9` | Digit (0-9) |
109
+ | `a` | Letter (A-Za-z) |
110
+ | `*` | Alphanumeric |
111
+ | `#` | Hex digit (0-9, A-F) |
112
+ | `[x]` | Optional character |
113
+ | `{n}` | Repeat n times |
114
+ | `{n,m}` | Repeat n to m times |
115
+
116
+ ### Validation on Change
117
+
118
+ ```javascript
119
+ %element%.on('change', function() {
120
+ var value = $(this).val();
121
+
122
+ if (value && value.length < 3) {
123
+ rg_alert('Value must be at least 3 characters');
124
+ $(this).val('').trigger('change');
125
+ }
126
+ });
127
+ ```
128
+
129
+ ### Disable Field Based on Condition
130
+
131
+ ```javascript
132
+ $('[name="status"]').on('change', function() {
133
+ var status = $(this).val();
134
+
135
+ if (status === 'locked') {
136
+ %element%.prop('disabled', true);
137
+ } else {
138
+ %element%.prop('disabled', false);
139
+ }
140
+ });
141
+ ```
142
+
143
+ ### Auto-Calculate Value
144
+
145
+ ```javascript
146
+ $('[name="quantity"], [name="unit_price"]').on('change', function() {
147
+ var qty = parseFloat($('[name="quantity"]').val()) || 0;
148
+ var price = parseFloat($('[name="unit_price"]').val()) || 0;
149
+ var total = qty * price;
150
+
151
+ bfyRefresh_total(total.toFixed(2));
152
+ });
153
+ ```
154
+
155
+ ### Load Options Dynamically
156
+
157
+ ```javascript
158
+ %element%.on('focus', function() {
159
+ var $select = $(this);
160
+
161
+ if ($select.data('loaded')) return;
162
+
163
+ $.get('/admin/ajax/cms_object/list', {
164
+ table_name: 'categories'
165
+ }, function(response) {
166
+ $select.empty().append('<option value="">Select...</option>');
167
+
168
+ response.data.forEach(function(item) {
169
+ $select.append('<option value="' + item.id + '">' + item.name + '</option>');
170
+ });
171
+
172
+ $select.data('loaded', true);
173
+ });
174
+ });
175
+ ```
176
+
177
+ ## Field Type Update Methods
178
+
179
+ Remember to use the correct update method:
180
+
181
+ | Field Types | Method |
182
+ |-------------|--------|
183
+ | `calculated`, `custom`, `date` | `bfyRefresh_COLUMN_NAME(value)` |
184
+ | All others | `$('[name="COLUMN_NAME"]').val(value).trigger('change')` |
185
+
186
+ ## Creating JavaScript Code via CLI
187
+
188
+ ```bash
189
+ # The js_code goes in the spec record
190
+ butterfly-cli record add object_specs --data '{
191
+ "object_id": 128,
192
+ "name": "Category",
193
+ "column_name": "category_id",
194
+ "type": "from_list",
195
+ "val_1": "categories",
196
+ "val_3": "id",
197
+ "val_4": "name",
198
+ "js_code": "%element%.on(\"change\", function() { console.log(\"Changed to:\", $(this).val()); });"
199
+ }'
200
+ ```
201
+
202
+ Or edit the `code.js` file directly after downloading:
203
+
204
+ ```bash
205
+ butterfly-cli download -t objects -n my_table
206
+ # Edit butterfly-resources/objects/app/my_table/category_id/code.js
207
+ butterfly-cli upload butterfly-resources/objects/app/my_table/category_id/
208
+ ```