@jigx/core-sdk 1.0.0 → 1.2.0-rc

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 (41) hide show
  1. package/README.md +2 -0
  2. package/dist/action/ja.generate-pdf.d.ts +17 -1
  3. package/dist/action/ja.generate-pdf.d.ts.map +1 -1
  4. package/dist/action/ja.generate-pdf.js +4 -1
  5. package/dist/action/ja.in-background.d.ts +3 -2
  6. package/dist/action/ja.in-background.d.ts.map +1 -1
  7. package/dist/action/ja.in-background.js +1 -1
  8. package/dist/assets/example-extraction-cache.json +3 -3
  9. package/dist/assets/extracted-core-sdk-examples.yaml +18 -0
  10. package/dist/assets/extracted-core-sdk-types.yaml +58 -0
  11. package/dist/assets/type-extraction-cache.json +3 -3
  12. package/docs/array-fields.md +371 -0
  13. package/docs/conditional-logic.md +178 -0
  14. package/docs/convention-naming.md +102 -0
  15. package/docs/date-field.md +92 -0
  16. package/docs/dropdown-fields.md +879 -0
  17. package/docs/field-state.md +131 -0
  18. package/docs/field-types-overview.md +132 -0
  19. package/docs/formatting.md +421 -0
  20. package/docs/icons.md +142 -0
  21. package/docs/index.md +23 -0
  22. package/docs/jsonata-expressions.md +200 -0
  23. package/docs/media-fields.md +107 -0
  24. package/docs/overview.md +467 -0
  25. package/docs/pattern-build-deploy.md +91 -0
  26. package/docs/pattern-datasources.md +459 -0
  27. package/docs/pattern-forms.md +528 -0
  28. package/docs/pattern-global-actions.md +92 -0
  29. package/docs/pattern-javascript-functions.md +452 -0
  30. package/docs/pattern-navigation.md +304 -0
  31. package/docs/pattern-pdf-generation.md +391 -0
  32. package/docs/pattern-rest-acumatica.md +660 -0
  33. package/docs/pattern-sync-progress.md +96 -0
  34. package/docs/pattern-sync.md +653 -0
  35. package/docs/pattern-tabs-form.md +293 -0
  36. package/docs/recipe-index.md +64 -0
  37. package/docs/runtime-variables.md +127 -0
  38. package/docs/sections.md +81 -0
  39. package/docs/validation-patterns.md +150 -0
  40. package/package.json +5 -4
  41. package/CHANGELOG.md +0 -95
@@ -0,0 +1,467 @@
1
+ # Expert SDK Overview
2
+
3
+ Available documentation resources for Core SDK forms and wizards.
4
+
5
+ ## Field Types
6
+
7
+ Expert SDK provides these field types:
8
+
9
+ | Type | Purpose | Default Required |
10
+ | --- | --- | --- |
11
+ | `text` | Single/multi-line text input | Yes |
12
+ | `email` | Email with format validation | Yes |
13
+ | `phone` | Phone with phone-pad keyboard | Yes |
14
+ | `number` | Numeric input | Yes |
15
+ | `checkbox` | Boolean toggle | **No** |
16
+ | `date` | Date/time picker (mode: date/time/datetime) | Yes |
17
+ | `dropdown` | Single/multi selection from list | Yes |
18
+ | `choice-field` | Radio buttons or chips | Yes |
19
+ | `media` | File/image upload | Yes |
20
+ | `signature` | Signature capture pad | Yes |
21
+ | `duration-picker` | Time duration selector | Yes |
22
+ | `avatar-field` | Profile picture selector | Yes |
23
+ | `location` | GPS coordinate capture | Yes |
24
+ | `rating` | Star rating scale | Yes |
25
+ | `slider` | Range selection with min/max | Yes |
26
+
27
+ **Common properties** (all fields): `icon`, `helperText`, `errorText`, `value`, `isDisabled`, `isRequired`, `isVisible`
28
+
29
+ **Ref:** `./dropdown-fields.md` for dropdown patterns
30
+ **Ref:** `./choice-fields.md` for choice vs dropdown decision
31
+
32
+ **Details:** [Field Types Overview](./field-types-overview.md)
33
+
34
+ ---
35
+
36
+ ## Field State
37
+
38
+ Every field has `.state.value` that provides live access to the current field value. Updates immediately as user types.
39
+
40
+ **Scope:** Current step only - not accessible from other steps.
41
+
42
+ **Use for:**
43
+
44
+ - Same-step conditional visibility
45
+ - Same-step validation
46
+ - Real-time field dependencies within one step
47
+
48
+ **For cross-step data:** Use `step.data.getFieldData()` instead.
49
+
50
+ **Dropdown special case:** Dropdowns also expose `dropdownField.state.selected` for full object access in the same step.
51
+
52
+ **Details:** [Field State](./field-state.md)
53
+
54
+ ---
55
+
56
+ ## About JSONata
57
+
58
+ The Expert SDK uses [JSONata](https://jsonata.org/) (v1.8) as its expression language. JSONata is a lightweight query and transformation language for JSON data, similar to XPath for XML.
59
+
60
+ **Key characteristics and rules:**
61
+
62
+ - Functional expression language (no side effects)
63
+ - Path navigation with dot notation
64
+ - Built-in functions for string, array, date manipulation
65
+ - Single `=` for equality (not `==`)
66
+ - `&` for string concatenation (not `+`)
67
+ - `$now()` returns ISO string — use `$millis()` for date comparisons/diffs
68
+ - `null` can't be used in math, string concat, comparisons, or array operations — always check first: `$x ? $x > 0 : false`
69
+
70
+ Official docs: [jsonata.org](https://jsonata.org/)
71
+
72
+ ## Value Types
73
+
74
+ Field properties support two modes:
75
+
76
+ | Mode | API | Use When |
77
+ | --- | --- | --- |
78
+ | **Static** | Constructor arg or `.with()` | Constant values that never change |
79
+ | **Dynamic** | `new JsonataBuilder(body, variables)` | Values dependent on other data |
80
+
81
+ ## JSONata Reference
82
+
83
+ | Operator | Example | ⚠️ Never Use |
84
+ | --- | --- | --- |
85
+ | `=` | `$x = "value"` | `==` |
86
+ | `!=` | `$x != "value"` | `!==`, `<>` |
87
+ | `and` | `$a and $b` | `&&` |
88
+ | `or` | `$a or $b` | `\|\|` |
89
+ | `$not()` | `$not($a)` | `!`, `not` |
90
+ | `&` | `$a & " " & $b` | `+` (except math) |
91
+ | `? :` | `$x ? "yes" : "no"` | (ternary conditional) |
92
+ | `:=` | `$temp := $x * 2` | (assignment) |
93
+ | `..` | `1..10` | (range → array) |
94
+ | `~>` | `$x ~> $uppercase` | (pipe/transform) |
95
+
96
+ **Fallback pattern** (use ternary instead of elvis/null coalesce):
97
+
98
+ ```text
99
+ $x ? $x : "default"
100
+ ```
101
+
102
+ **Functions:**
103
+
104
+ | Category | Functions |
105
+ | --- | --- |
106
+ | String | `$uppercase` `$lowercase` `$substring` `$length` `$trim` `$contains` `$split` `$join` |
107
+ | Array | `$count` `$sum` `$max` `$min` `$distinct` `$sort` `$reverse` `$filter` `$map` `$in` |
108
+ | Date | `$now` `$millis` `$toMillis` `$fromMillis` |
109
+ | Type | `$string` `$number` `$boolean` `$type` |
110
+
111
+ **Details:** [JSONata Expressions](./jsonata-expressions.md)
112
+
113
+ ---
114
+
115
+ ## Conditional Logic
116
+
117
+ Make fields conditionally visible or required based on other field values using `JsonataBuilder`.
118
+
119
+ **Common patterns:**
120
+
121
+ - Show field when another has specific value
122
+ - Require field only when relevant
123
+ - Combine multiple conditions
124
+
125
+ **Details:** [Conditional Logic](./conditional-logic.md)
126
+
127
+ ---
128
+
129
+ ## Field Validation
130
+
131
+ Use `errorText` with `JsonataBuilder` to show validation messages based on field values. Messages appear when expression returns non-null string.
132
+
133
+ **Pattern:** Expression returns error message string when invalid, `null` when valid.
134
+
135
+ **Details:** [Validation Patterns](./validation-patterns.md)
136
+
137
+ ---
138
+
139
+ ## Sections
140
+
141
+ Use `addSection()` to group related fields visually within a step. Improves form organization and user experience.
142
+
143
+ **When to use:**
144
+
145
+ - Group 3+ related fields together
146
+ - Separate different types of information (personal vs professional)
147
+ - Create visual hierarchy in longer forms
148
+ - Improve scannability
149
+
150
+ **Details:** [Sections](./sections.md)
151
+
152
+ ---
153
+
154
+ ## Dropdown Fields
155
+
156
+ Four data source patterns for dropdown options:
157
+
158
+ | Source | Use When | Data Type |
159
+ | --- | --- | --- |
160
+ | **Static** | Fixed list <20 items (priorities, statuses) | `{label, value, icon?}[]` |
161
+ | **Dynamic** | Database-backed data (products, customers) | `DatasourceBuilder` |
162
+ | **ArrayField** | Cross-step data from arrayField | `step.data.getArrayFieldData()` |
163
+ | **Package** | ERP/CRM data via data packages (Acumatica, etc.) | `PackageDataBuilder` |
164
+
165
+ **Dropdown vs Choice:**
166
+
167
+ - Dropdown: >6 options OR long option labels
168
+ - Choice: ≤6 options AND short labels
169
+
170
+ **Multi-selection:** Set `isMultiple: true` for multiple selections.
171
+
172
+ ---
173
+
174
+ ## Static vs Dynamic Decision
175
+
176
+ **Use static options when:**
177
+
178
+ - Small fixed sets unlikely to change (Yes/No, gender, true/false)
179
+ - Values tied to app logic (status enums where code branches on specific values)
180
+ - Fewer than ~8 items that are universal across deployments
181
+
182
+ **Use dynamic (lookup table) when:**
183
+
184
+ - User says "managed", "from database", "editable", "configurable"
185
+ - Domain/reference data that may grow (countries, products, customers, categories)
186
+ - User provides a large list (>10 items)
187
+ - Values that different orgs/deployments would customize
188
+ - Data that non-developers should be able to edit in management portal
189
+
190
+ **If uncertain**, ask the user whether the options are fixed or may change over time.
191
+
192
+ ---
193
+
194
+ ### Value Collection
195
+
196
+ If values are clear from context, suggest initial values and ask for confirmation. If unclear, ask the user what values to populate.
197
+
198
+ When ambiguous (e.g., "add a status field" without specifying values), ask the user whether the values should be static or managed dynamically.
199
+
200
+ ---
201
+
202
+ ### Displaying Lookup Data
203
+
204
+ When showing lookup table contents to the user, format as a markdown table:
205
+
206
+ | Value | Label | Sort |
207
+ | --- | --- | ---: |
208
+ | high | High | 1 |
209
+ | medium | Medium | 2 |
210
+ | low | Low | 3 |
211
+
212
+ ---
213
+
214
+ ## Choice Fields
215
+
216
+ Use choice fields for small, fixed option sets displayed as radio buttons or chips.
217
+
218
+ **When to use:**
219
+
220
+ - ≤6 options with short labels
221
+ - Visual selection (user sees all options at once)
222
+ - Grid layout desired
223
+
224
+ **Choice vs Dropdown:**
225
+
226
+ | Criteria | Choice | Dropdown |
227
+ | --- | --- | --- |
228
+ | Options count | ≤6 | >6 |
229
+ | Label length | Short | Any |
230
+ | Display | All visible | Collapsed list |
231
+
232
+ **Choice vs Checkbox for yes/no:**
233
+
234
+ - Required yes/no: Use choice (checkbox fails validation when unchecked)
235
+ - 3-state logic: Use choice (Yes/No/NA, True/False/Unknown)
236
+ - Optional toggle: Use checkbox
237
+
238
+ **Details:** [Choice Fields](./choice-fields.md)
239
+
240
+ ---
241
+
242
+ ## Array Fields
243
+
244
+ **Use ArrayField when you need a "form within a form"** - a repeatable group of fields where users can add/remove multiple entries of the same structure.
245
+
246
+ **When to use:**
247
+
248
+ - Invoice/order with multiple line items (product, quantity, price per item)
249
+ - Team registration with multiple members (name, email, role per person)
250
+ - Inspection checklist with multiple items (item name, status, notes per check)
251
+ - Any scenario requiring "Add another [X]" functionality
252
+
253
+ **How it works:** ArrayField creates a nested, repeatable form section. Each item contains the same field structure. Users tap "Add" to create new items and can remove existing ones.
254
+
255
+ | Property | Type | Description |
256
+ | --- | --- | --- |
257
+ | `name` | string | Field identifier (required) |
258
+ | `label` | string | Display label (required) |
259
+ | `title` | TextValueBuilder | Item title in the array list (required) |
260
+ | `subtitle` | TextValueBuilder | Item subtitle in the array list |
261
+ | `description` | TextValueBuilder | Item description in the array list |
262
+ | `addButtonLabel` | string | Custom "Add" button text |
263
+ | `value` | ArrayFieldValue[] \| JsonataBuilder | Initial data for fixed-size arrays (hides add/delete) |
264
+ | `keyField` | string | Field to match init items with saved data (required with `value`) |
265
+
266
+ **Three ways to use ArrayField:**
267
+
268
+ | Mode | `value` | Behavior |
269
+ | --- | --- | --- |
270
+ | **User-managed** | (not set) | Users add/remove items freely |
271
+ | **Static** | Array literal | Fixed items (subform, checklist) |
272
+ | **Dynamic** | Expression/field ref | Items regenerate from source |
273
+
274
+ **Ref:** `./predefined-array-items.md` for static and dynamic initialization
275
+
276
+ **Title is required** - identifies items in the list and delete confirmation.
277
+
278
+ **Ref:** `./cross-step-data.md` for accessing array data in other steps
279
+
280
+ **Recognize repeated data patterns:**
281
+
282
+ | User describes... | Use |
283
+ | --- | --- |
284
+ | "3 passengers on booking" | ArrayField + 3 predefined items |
285
+ | "5 emergency contacts" | ArrayField + 5 predefined items |
286
+ | "Add ingredients to recipe" | ArrayField (user-managed) |
287
+ | "Track project milestones" | ArrayField (user-managed) |
288
+
289
+ **Anti-pattern:** Creating multiple sections with duplicated fields (e.g., "Contact 1 Name", "Contact 1 Phone", "Contact 2 Name"...). This creates longer forms and inconsistent data structure.
290
+
291
+ **Default rule:** Same data type captured multiple times → ArrayField, not duplicated sections.
292
+
293
+ **Details:** [Array Fields](./array-fields.md)
294
+
295
+ ---
296
+
297
+ ## Array Initialization
298
+
299
+ Use ArrayField with `value` to initialize items. Add/delete buttons hidden automatically.
300
+
301
+ | Mode | `value` | Regenerates | Use Case |
302
+ | --- | --- | --- | --- |
303
+ | **Subform** | 1 static item | No | Nested details (vehicle, address) |
304
+ | **Fixed list** | N static items | No | Scorecards, checklists |
305
+ | **Dynamic** | Expression/field ref | Yes | Date ranges, count from field |
306
+
307
+ **Key properties:**
308
+
309
+ | Property | Description |
310
+ | --- | --- |
311
+ | `value` | Initial items (static array or JsonataBuilder expression) |
312
+ | `keyField` | Field to match items with saved data (required for dynamic, optional for static) |
313
+
314
+ **Ref:** `./array-fields.md` for full ArrayField API
315
+
316
+ **Details:** [Array Initialization](./predefined-array-items.md)
317
+
318
+ ---
319
+
320
+ ## Date Field
321
+
322
+ Use `addDate()` to capture dates, times, or both with a native picker.
323
+
324
+ | Property | Type | Description |
325
+ | --- | --- | --- |
326
+ | `mode` | `'date'` \| `'time'` \| `'datetime'` | Picker type (default: 'date') |
327
+ | `minimum` | `string` \| `number` \| `JsonataBuilder` | Earliest selectable date |
328
+ | `maximum` | `string` \| `number` \| `JsonataBuilder` | Latest selectable date |
329
+
330
+ | Mode | Picker | Use Case |
331
+ | --- | --- | --- |
332
+ | `'date'` | Date only | Birthdays, deadlines |
333
+ | `'time'` | Time only | Meeting times, schedules |
334
+ | `'datetime'` | Both | Appointments, events |
335
+
336
+ **Details:** [Date Field](./date-field.md)
337
+
338
+ ---
339
+
340
+ ## Formatting
341
+
342
+ Two ways to format values:
343
+
344
+ | Approach | Use Case |
345
+ | --- | --- |
346
+ | **Field `format` property** | Format numbers in disabled (read-only) fields |
347
+ | **`FormatBuilder` class** | Format any value for text display: `submissionItemTitle`, `submissionItemSubtitle`, arrayField `title`/`subtitle`/`description`, step `title` |
348
+
349
+ **Details:** [Formatting](./formatting.md)
350
+
351
+ ---
352
+
353
+ **Read the YAML schemas before writing any SQL query.** They document available tables, fields, nullable columns, relationships, and common query patterns.
354
+
355
+ ### When to Use Custom Sync Parameters
356
+
357
+ | Use Case | Parameters |
358
+ | --- | --- |
359
+ | Fetch all records | None (uses package defaults) |
360
+ | Only sync active records | Custom filter to limit fetched records |
361
+ | Reduce sync volume | Filter expression |
362
+ | Different expand per screen | Expand override |
363
+
364
+ ### Handling Null Values (COALESCE)
365
+
366
+ External data fields can be null. **Use COALESCE** for display fields to prevent empty UI labels. Check the package's schema files for which fields are nullable and their recommended fallbacks.
367
+
368
+ ### JOIN Queries (Multiple Tables)
369
+
370
+ **Always wrap `json_extract()` in `TRIM()` for JOIN conditions.** External data often contains leading/trailing whitespace that breaks equality comparisons.
371
+
372
+ ---
373
+
374
+ ## Media & Specialized Fields
375
+
376
+ Core SDK provides these media capture fields:
377
+
378
+ | Type | Purpose |
379
+ | --- | --- |
380
+ | `media` | File/image upload (single or multiple) |
381
+ | `signature` | Signature capture pad |
382
+ | `avatar-field` | Profile picture selector |
383
+ | `duration-picker` | Time duration selector |
384
+
385
+ **Details:** [Media Fields](./media-fields.md)
386
+
387
+ ---
388
+
389
+ ## Location Field
390
+
391
+ The `addLocation()` method creates a field that auto-captures GPS coordinates as "lat,lng" format.
392
+
393
+ **Two patterns:**
394
+
395
+ | Pattern | Use Case | isDisabled |
396
+ | --- | --- | --- |
397
+ | Current location (readonly) | Check-ins, service visits, asset tagging | `true` |
398
+ | Generic location (editable) | Delivery addresses, event venues | `false` (default) |
399
+
400
+ **Details:** [Location Field](./location-field.md)
401
+
402
+ ---
403
+
404
+ ## Icons
405
+
406
+ Expert SDK includes 18,000+ icons. Icon names are validated at build time - invalid names cause build failures.
407
+
408
+ **Never guess icon names** - always search via MCP.
409
+
410
+ **Details:** [Icons](./icons.md)
411
+
412
+ ---
413
+
414
+ ## Runtime Variables
415
+
416
+ Access runtime context using `System` and `Auth.user` from Expert SDK:
417
+
418
+ ```typescript
419
+ import { Auth, System, JsonataBuilder } from '@jigx/expert-sdk'
420
+ ```
421
+
422
+ | Namespace | Purpose |
423
+ | --- | --- |
424
+ | `System.*` | Device info, network status, location |
425
+ | `Auth.user.*` | Authenticated user data |
426
+
427
+ **Details:** [Runtime Variables](./runtime-variables.md)
428
+
429
+ ---
430
+
431
+ ## Internationalization (i18n)
432
+
433
+ Build multi-language forms using the `I18nBuilder` class. Supports:
434
+
435
+ - Translation keys with fallback messages
436
+ - Placeholder interpolation with `JsonataBuilder`
437
+ - Formatted values with `FormatBuilder` class
438
+ - Formatted strings combining multiple values
439
+
440
+ **Priority:** `I18nBuilder` > `format property` > `direct value`
441
+
442
+
443
+ **When to use I18nBuilder:**
444
+ - Combining multiple field values with text
445
+ - Formatting dates, currencies, numbers, or percentages
446
+ - Multi-language support needed
447
+ - Complex string interpolation
448
+
449
+ **Details:** [Internationalization](./i18n.md)
450
+
451
+ ---
452
+
453
+ ## Submission Display
454
+
455
+ Use `step.data.getFieldData()` to configure what information appears in the submission list. Shows meaningful data instead of generic IDs.
456
+
457
+ **Properties (both required):**
458
+ - `submissionItemTitle` — primary text shown for each submission
459
+ - `submissionItemSubtitle` — secondary text shown below the title
460
+
461
+ **Important:** Both `submissionItemTitle` and `submissionItemSubtitle` must be defined. Form validation will fail if either is missing.
462
+
463
+ **Date/number formatting:** Use `FormatBuilder` when displaying date, currency, or number values in `submissionItemTitle` or `submissionItemSubtitle`. See `./formatting.md` for details.
464
+
465
+ **Details:** [Submission Display](./submission-display.md)
466
+
467
+ ---
@@ -0,0 +1,91 @@
1
+ # Pattern: Build and Deploy
2
+
3
+ ## Build order matters
4
+
5
+ Register in this order in `app.ts`:
6
+
7
+ 1. Database tables
8
+ 2. App-scoped datasources
9
+ 3. Functions (before actions that reference them)
10
+ 4. Global actions (before screens that reference them)
11
+ 5. Tab content screens (before the tabs screen that embeds them)
12
+ 6. Tabs screen
13
+ 7. Other screens
14
+
15
+ ## Prerequisites
16
+
17
+ Core SDK must be compiled before workspace projects can build (tsx imports compiled output):
18
+
19
+ ```bash
20
+ yarn workspace @jigx/core-sdk build
21
+ ```
22
+
23
+ ## Commands
24
+
25
+ ```bash
26
+ # Typecheck
27
+ npx tsc --noEmit --strict --target es2022 --module esnext \
28
+ --moduleResolution bundler --customConditions source \
29
+ --esModuleInterop --skipLibCheck workspace/acumatica-apps/create-customer/src/app.ts
30
+
31
+ # Build JSON + YAML
32
+ npx tsx workspace/build.ts workspace/acumatica-apps/create-customer
33
+ npx tsx workspace/build-yaml.ts workspace/acumatica-apps/create-customer
34
+
35
+ # Deploy (env vars or .env)
36
+ STAMP=PROD ORGANIZATION_ID="..." JIGX_API_KEY="..." \
37
+ ./workspace/acumatica-apps/create-customer/build-publish.sh
38
+ ```
39
+
40
+ ## Build scripts
41
+
42
+ | Script | Output | Location |
43
+ | ---: | --- | --- |
44
+ | `workspace/build.ts` | `build/output.json` + `build/output.yaml` | Single merged file |
45
+ | `workspace/build-yaml.ts` | `build/jigx-project/` | Individual `.jigx` files matching standard Jigx YAML project structure |
46
+ | `build-publish.sh` | Builds + publishes to Jigx API | Per-project script |
47
+
48
+ ## YAML project output
49
+
50
+ The `build-yaml.ts` script decomposes the single JSON output into individual files:
51
+
52
+ | JSON key | Output |
53
+ | ---: | --- |
54
+ | `name`, `title`, `category`, `tabs` | `index.jigx` |
55
+ | `databases["default"]` | `databases/default.jigx` |
56
+ | `datasources["<id>"]` | `datasources/<id>.jigx` |
57
+ | `jigs["<id>"]` | `jigs/<id>.jigx` (screen-scoped datasources stay inline) |
58
+ | `actions["<id>"]` | `actions/<id>.jigx` |
59
+ | `functions["<id>"]` | `functions/<id>.jigx` |
60
+
61
+ Internal IDs (`jigId`, `datasourceId`, `instanceId`, `databaseId`) are stripped — they're implied by the filename.
62
+
63
+ ## Deploy script (`build-publish.sh`)
64
+
65
+ Each project has a `build-publish.sh` that builds and publishes to the Jigx API. Required env vars (from `.env` or inline):
66
+
67
+ | Variable | Description |
68
+ | ---: | --- |
69
+ | `ORGANIZATION_ID` | Jigx organization UUID |
70
+ | `JIGX_API_KEY` | PAT for Jigx API (store in `.env`, never commit) |
71
+ | `STAMP` | `DEV` (default) or `PROD` |
72
+
73
+ API base URLs:
74
+
75
+ - DEV: `https://us-west-2.dev-api.jigx.com/v2.0`
76
+ - PROD: `https://us-east-1.api.jigx.com/v2.0`
77
+
78
+ Deploy flow:
79
+
80
+ 1. Build `output.json` via `workspace/build.ts`
81
+ 2. `GET /strata/organizations/{orgId}/solutions/{appName}` — look up existing solution
82
+ 3. If 404: `POST /strata/organizations/{orgId}/solutions/` — create new solution
83
+ 4. `PUT /strata/organizations/{orgId}/solutions/{solutionId}/content` — publish full `output.json` as body
84
+
85
+ All calls use `Authorization: Bearer {JIGX_API_KEY}`.
86
+
87
+ Inline env vars override `.env` defaults — pass credentials on the command line to avoid storing prod keys:
88
+
89
+ ```bash
90
+ STAMP=PROD ORGANIZATION_ID="..." JIGX_API_KEY="..." ./workspace/acumatica-apps/create-customer/build-publish.sh
91
+ ```