@enfocussw/switch-scripting-context 0.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.
Files changed (33) hide show
  1. package/CHANGELOG.md +504 -0
  2. package/README.md +192 -0
  3. package/bin/cli.js +8 -0
  4. package/dist/init.d.ts +78 -0
  5. package/dist/init.js +894 -0
  6. package/docs/switch-api/api-versions.md +127 -0
  7. package/docs/switch-api/connection.md +82 -0
  8. package/docs/switch-api/document-classes.md +189 -0
  9. package/docs/switch-api/entry-points.md +185 -0
  10. package/docs/switch-api/enums.md +181 -0
  11. package/docs/switch-api/execution-environment.md +143 -0
  12. package/docs/switch-api/flow-element.md +143 -0
  13. package/docs/switch-api/http.md +96 -0
  14. package/docs/switch-api/job-patterns.md +238 -0
  15. package/docs/switch-api/job.md +187 -0
  16. package/docs/switch-api/logging.md +117 -0
  17. package/docs/switch-api/switch.md +210 -0
  18. package/docs/switch-appstore/app-guidelines.md +281 -0
  19. package/docs/switch-appstore/app-manual.md +84 -0
  20. package/docs/switch-appstore/app-store-listing.md +69 -0
  21. package/docs/switch-appstore/app-store-submission.md +83 -0
  22. package/docs/switch-project/debugging.md +61 -0
  23. package/docs/switch-project/logs-and-dataroot.md +80 -0
  24. package/docs/switch-project/node-versions.md +87 -0
  25. package/docs/switch-project/project-planning.md +149 -0
  26. package/docs/switch-project/property-documentation.md +75 -0
  27. package/docs/switch-project/property-editors.md +249 -0
  28. package/docs/switch-project/script-declaration.md +407 -0
  29. package/docs/switch-project/script-structure.md +157 -0
  30. package/docs/switch-project/tooling.md +165 -0
  31. package/docs/switch-project/vscode.md +90 -0
  32. package/docs/switch-scripting.md +70 -0
  33. package/package.json +65 -0
@@ -0,0 +1,249 @@
1
+ ---
2
+ id: property-editors
3
+ category: switch-project
4
+ order: 15
5
+ summary: "Property editor types, string return values, literal editors, dropdowns"
6
+ triggers:
7
+ - "Defining property editors in XML or reading property values in code"
8
+ ---
9
+
10
+ # Property Editors
11
+
12
+ Property editors determine how a user enters a value in Switch Designer, and what string is
13
+ returned by `getPropertyStringValue()` at runtime. They're set in the XML declaration via the
14
+ `Editor` and `Type` attributes on a custom property — see
15
+ [script-declaration.md](script-declaration.md) for the surrounding attribute grammar.
16
+
17
+ All property values are returned as `string` or `string[]`. `getPropertyType()` returns one of a
18
+ fixed set of `PropertyType` values (`literal`, `string`, `number`, `date`, `boolean`, `filepath`,
19
+ `folderpath`, `regex`, `oauthtoken`, etc. — see [enums.md](../switch-api/enums.md)) describing what kind of
20
+ value is actually present; `literal` is only one of these, not a binary "literal vs. user-entered"
21
+ flag. Use it before interpreting the returned string, e.g. to check for a literal editor's constant
22
+ before comparing it.
23
+
24
+ `Editor` is a `;`-joined list: the inline editor's token (if any) first, then modal editor tokens in
25
+ the order they're offered. `Type` follows from which editor(s) are chosen — see the tables below and
26
+ [the Type reference](script-declaration.md#type-reference).
27
+
28
+ ---
29
+
30
+ <!-- docs-index:contents begin -->
31
+ ## Contents
32
+
33
+ - Inline editors
34
+ - Modal editors
35
+ - Literal editors
36
+ - Extra XML attributes for certain editors
37
+ - Common practices
38
+ - A property whose shape varies by a type selector
39
+ - Notes
40
+ <!-- docs-index:contents end -->
41
+
42
+ ## Inline editors
43
+
44
+ The inline editor slot is always the single token `inline` in `Editor` — what differs is `Type`.
45
+
46
+ | Editor / Type | Resulting `getPropertyStringValue()` value |
47
+ |---|---|
48
+ | `Editor="inline" Type="string"` | Single-line text as entered |
49
+ | `Editor="inline" Type="password"` | Text as entered (displayed masked) |
50
+ | `Editor="inline" Type="number"` | Integer as a string |
51
+ | `Editor="inline" Type="time"` | `"hh:mm"` (zero-padded, e.g. `"09:05"`) |
52
+ | `Editor="inline" Type="date"` | Date as entered |
53
+ | `Editor="inline" Type="datetime"` | Date and time as entered |
54
+ | `Editor="inline" Type="bool"` | `"No"` or `"Yes"` |
55
+ | `Editor="inline" Type="enum:Item1;Item2;..."` | The selected item string (one of the declared values) |
56
+
57
+ > The `rational` (decimal) inline editor is not allowed in Node.js scripts. Don't declare
58
+ > `Type="rational"`.
59
+
60
+ ---
61
+
62
+ ## Modal editors
63
+
64
+ Additional editor tokens appended after `inline` (or used alone, with no inline component). These
65
+ open a dialog when the user clicks the editor button. All have `Type="string"` unless noted.
66
+
67
+ | `Editor` token | Resulting `getPropertyStringValue()` value |
68
+ |---|---|
69
+ | `choosefile` | Absolute file path as a string |
70
+ | `choosefolder` | Absolute folder path as a string |
71
+ | `regexp` | Regular expression string as entered |
72
+ | `filetype` | Filename pattern(s) for the selected file type |
73
+ | `types` (`Type="filefilter"`) | `string[]` — one pattern string per selected file type |
74
+ | `askplugin` | String value selected from the library dialog (calls `getLibraryForProperty`) — **requires the script to implement `getLibraryForProperty`** (`getLibraryForConnectionProperty` for a connection field), see [entry-points.md](../switch-api/entry-points.md#property-ui-callbacks) |
75
+ | `askplugin2` | `string[]` — one string per selected library item (calls `getLibraryForMultipleProperty`) — **requires a matching library-callback entry point**, same as `askplugin` above. ⚠ `getLibraryForMultipleProperty` isn't documented anywhere in [entry-points.md](../switch-api/entry-points.md#property-ui-callbacks), which only lists `getLibraryForProperty`/`getLibraryForConnectionProperty` — this may be the same entry point handling both single- and multi-select, or a genuinely separate, undocumented one. Unconfirmed, so treat the name as unverified. |
76
+ | `description` | Multi-line text as a single string (may include newlines) |
77
+ | `scriptexp` | Result of script expression evaluated in job context, as a string |
78
+ | `sltextwithvar` | Single-line text with variables substituted, as a string |
79
+ | `mltextwithvar` | Multi-line text with variables substituted, as a string |
80
+ | `conditionwithvar` | `"true"` or `"false"` after evaluating condition with variables |
81
+ | `filepatterns` | `string[]` — one pattern string per entry |
82
+ | `folderpatterns` | `string[]` — one pattern string per entry |
83
+ | `stringlist` (`Type="stringlist"`) | `string[]` — one string per line |
84
+ | `oauth` | OAuth 2.0 access token string, or `""` if not yet authorized — see [ExtraProperties](script-declaration.md#extraproperties) |
85
+ | `external`, `external2`, … | File path to a property set edited by an external companion app |
86
+
87
+ > Duplicate tokens in `Editor` are meaningless — each modal editor can only be offered once, except
88
+ > `external` which can appear multiple times with numeric suffixes (`external`, `external2`, `external3`, …).
89
+
90
+ ---
91
+
92
+ ## Literal editors
93
+
94
+ A literal editor makes a property return a **fixed string** regardless of user input. Combine it
95
+ with another editor in the `Editor` chain (e.g. `Editor="default;choosefolder"`) to offer the
96
+ constant as one of the choices; all literal tokens have `Type="string"`.
97
+
98
+ Always call `getPropertyType()` first to check whether the value is a literal before comparing the
99
+ string.
100
+
101
+ Use the matching literal editor for a keyword-style value like "Default", "None", or "Automatic"
102
+ instead of making it a typed string default — e.g. `default` instead of a `Default`
103
+ attribute set to the literal text `"Default"`. Typing the keyword as an ordinary string default lets
104
+ a user accidentally change it to arbitrary text and loses the `PropertyType.Literal` signal the
105
+ script relies on. `none` is specifically the sanctioned way to let a property hold an empty value
106
+ under `Validation="Standard"` — combine it into the `Editor` chain instead of relaxing to
107
+ `Validation="None"` just to permit emptiness.
108
+
109
+ | `Editor` token | `getPropertyStringValue()` returns |
110
+ |---|---|
111
+ | `default` | `"Default"` |
112
+ | `none` | `""` (empty string) |
113
+ | `automatic` | `"Automatic"` |
114
+ | `nofiles` | `"No Files"` |
115
+ | `allfiles` | `"All Files"` |
116
+ | `allotherfiles` | `"All Other Files"` |
117
+ | `nofolders` | `"No Folders"` |
118
+ | `allfolders` | `"All Folders"` |
119
+ | `allotherfolders` | `"All Other Folders"` |
120
+ | `next` | `"Next"` |
121
+ | `current` | `"Current"` |
122
+
123
+ `nofiles`/`allfiles`/`allotherfiles` and `nofolders`/`allfolders`/`allotherfolders` are not
124
+ general-purpose — every real use of them is a connection **include/exclude filter mask** (an
125
+ `IncludeMask`/`ExcludeMask`, or `IncludeFolderMask`/`ExcludeFolderMask`, on a `ConnectionType="Filter"`
126
+ connection). Switch Designer labels them "No/All/All other jobs" and "No/All folders" in that
127
+ context, not the XML token names above. See [Common practices](#common-practices) below for the
128
+ exact chain.
129
+
130
+ `next` and `current` exist in the editor grammar but have no confirmed script-facing use case — no
131
+ built-in Switch flow element declares a property using them, and Enfocus's own property-editor
132
+ documentation omits both (along with `allotherfolders`, apparently by oversight, since it's used the
133
+ same way as `allotherfiles`). Don't reach for `next`/`current` without confirming a concrete need
134
+ first.
135
+
136
+ ---
137
+
138
+ ## Extra XML attributes for certain editors
139
+
140
+ **Dropdown (`Type="enum:..."`)** — items are embedded in the `Type` value itself:
141
+ `Type="enum:Option A;Option B;Option C"`.
142
+
143
+ **`askplugin` / `askplugin2`** — add a `SelectFromLibMes` (single) or `SelectManyFromLibMes` (multi)
144
+ attribute to the property element to set a custom dialog message.
145
+
146
+ **`stringlist`** — add a `StringListMes` attribute to show a custom message in the editor dialog.
147
+
148
+ **`choosefile`** — add `Opaque="true"` to include the referenced file as an opaque payload when a
149
+ flow is exported.
150
+
151
+ **`external`** (and `external2`, …) — add matching-suffixed `ExternalEditorName`,
152
+ `ExternalValueOverlay`, `ExternalApplication`, `ExternalArgForNew`, `ExternalArgForEdit`, and
153
+ `ExternalFileFormat` (`Custom` or `Switch`) attributes.
154
+
155
+ ---
156
+
157
+ ## Common practices
158
+
159
+ The following are recommended conventions for pairing property kinds with editor chains, not
160
+ restrictions enforced by Switch — a script writer can combine editors differently if asked to.
161
+
162
+ Enable the dynamic editors (`sltextwithvar`/`mltextwithvar` and `conditionwithvar`, `scriptexp`)
163
+ wherever the value could plausibly vary per job — the rows below already reflect this. Conversely,
164
+ don't add them to a property whose value is inherently static (e.g. a dataset name, or anything a
165
+ `Dependency` master needs to read at flow-configuration time) — offering a variable/script option
166
+ there just invites a value the script can't sensibly use.
167
+
168
+ **App guideline (mandatory for apps, recommended for scripts):** make sure at least one editor in
169
+ the chain works without an add-on Switch module: `scriptexp` requires the Scripting Module, so never
170
+ offer it as the property's only editor — pair it with a module-free option (e.g. `inline` or
171
+ `sltextwithvar`) so the property still works for a user without that module.
172
+
173
+ | Property kind | Recommended `Editor` chain | Why |
174
+ |---|---|---|
175
+ | Secret (password, token, API key) | `inline` only, with `Type="password"` and **`Subtype=""`** (not `"inline"`) | Masks the value and avoids leaking it via logs or variable inspection if a var/expression editor were combined. `password` is a `Type`, not an editor token — there is no `password` entry in the [modal editor](#modal-editors) list, so `Editor="password"` is wrong. `Subtype="inline"` (the usual value for a single inline editor, per [script-declaration.md](script-declaration.md#custom-property-elements-elementfields)) is rejected at script load with "editor that is not supported in Node.js scripting"; Switch Designer itself saves `Type="password"` with `Subtype=""`. |
176
+ | Scalar job-specific value (job ID, copy count, company name, date, etc.) | `inline` (`Type` matching the value) + `sltextwithvar` + `scriptexp` | Hard-coded default, plus dynamic substitution and full expression evaluation. |
177
+ | Array/list job-specific value | `stringlist` + `mltextwithvar` + `scriptexp` | One item per line. **Caveat:** the intent is that every path returns a `string[]`, but the [modal editor table](#modal-editors) lists `mltextwithvar` as returning a single string, and which one holds for this chain is unverified. Handle both — split on newlines when a bare string comes back. |
178
+ | Structured blob text (XML/JSON/HTML, email body) | `description` + `mltextwithvar` + `scriptexp` | Free multi-line text suits a single blob of content better than a line-per-item list. |
179
+ | Boolean used as a `Dependency` master | `inline` only | Other properties' visibility depends on a value known at design time. |
180
+ | Boolean consumed directly by script logic (not a `Dependency` master) | `inline` + `conditionwithvar` + `scriptexp` | Safe to toggle dynamically since nothing else depends on it for visibility. Also covers booleans that are themselves a `Dependency` *dependent* (not a master). |
181
+ | Enum (`Type="enum:..."`) | `inline` only, always | No editor guarantees a var/expression result matches one of the declared items. |
182
+ | File/folder path that must exist for the app to work | `choosefile`/`choosefolder` only | Switch validates the picked path exists at flow start. |
183
+ | File/folder path that legitimately varies per job | `choosefile`/`choosefolder` + `sltextwithvar` + `scriptexp` | Dynamic values only resolve when read during `jobArrived` — see the "Workaround for deferred processing" note in [flow-element.md](../switch-api/flow-element.md#properties) if the path is needed later in the flow. |
184
+ | Connection include-mask filter (which jobs pass through) | `allfiles;allotherfiles;types;filepatterns;regexp;scriptexp`, `Default="All Files"`, `Subtype="allfiles"` | Matches Switch's own built-in connection filter properties exactly — `Default`/`Subtype` must hold the chosen literal's exact rendered string. Folder version: `allfolders;allotherfolders;folderpatterns;regexp;scriptexp` with `Default="All Folders"`, `Subtype="allfolders"`. |
185
+ | Connection exclude-mask filter (which jobs are blocked) | `nofiles;types;filepatterns;regexp;scriptexp`, `Default="No Files"`, `Subtype="nofiles"` | Same reasoning as the include mask, starting from `nofiles` instead since there's no "exclude all/all other" case. Folder version: `nofolders;folderpatterns;regexp;scriptexp` with `Default="No Folders"`, `Subtype="nofolders"`. |
186
+
187
+ `regexp`, `filetype`/`types`, `askplugin`/`askplugin2`, `oauth`, and `external` can technically be
188
+ combined with `sltextwithvar`/`scriptexp` too, but this is uncommon in practice and not covered by a
189
+ dedicated row above.
190
+
191
+ ### A property whose shape varies by a type selector
192
+
193
+ When what a property must hold depends on another property's value — a map for one type, an
194
+ ordered list for another, a pair of labelled strings for a third — don't reach for one property
195
+ holding JSON or a hand-rolled line format. Declare an enum master and one dependent per shape, each
196
+ with the editor that natively fits it, and read only the dependent the master currently shows.
197
+
198
+ The shapes then need no parsing at all in the common cases, and the property pane shows one
199
+ type-appropriate editor with a label that explains itself instead of a text box whose format lives
200
+ in the documentation:
201
+
202
+ ```xml
203
+ <!-- master: enum, inline only, so the value is known at flow-configuration time -->
204
+ <QType UserDefined="true" Type="enum:(not used);List;Ordered;Pair" Editor="inline" Subtype="inline"
205
+ LocalizedTagName="Type" Tooltip="" DetailedInfo="" Validation="Standard"
206
+ Default="(not used)">(not used)</QType>
207
+
208
+ <!-- one dependent per shape; each is hidden unless its condition holds -->
209
+ <QList UserDefined="true" Type="stringlist" Editor="stringlist" Subtype="stringlist"
210
+ Dependency="QType" DependencyCondition="Equals" Dependencyvalue="List"
211
+ LocalizedTagName="Items" Tooltip="" DetailedInfo="" Validation="Standard"></QList>
212
+ <QLow UserDefined="true" Type="string" Editor="description" Subtype=""
213
+ Dependency="QType" DependencyCondition="Equals" Dependencyvalue="Pair"
214
+ LocalizedTagName="What a low value means" Tooltip="" DetailedInfo=""
215
+ Validation="Standard" Default=""></QLow>
216
+ ```
217
+
218
+ Adding `(not used)` to the master's items makes it double as the group's on/off switch, so the
219
+ group needs no separate boolean.
220
+
221
+ Two constraints come with the pattern:
222
+
223
+ - The master must be an enum or a boolean with `inline` only, per the rows above. A dynamic master
224
+ makes the visible set differ per job, which the dependents' own editors cannot account for.
225
+ - Reading a hidden dependent throws `"Invalid tag: <tag>"`. Check the master's value, or call
226
+ `hasProperty(tag)`, before every read — see
227
+ [script-declaration.md § Dependency](script-declaration.md#custom-property-elements-elementfields).
228
+ This bites hardest in a loop over jobs or connections, where the throw repeats on every
229
+ invocation.
230
+
231
+ A shape the master cannot enumerate, or one that must vary per job, is the case this pattern does
232
+ not cover; that is where a single `description` property holding a structured blob is the honest
233
+ answer.
234
+
235
+ ---
236
+
237
+ ## Notes
238
+
239
+ - **OAuth 2.0**: endpoint, client ID/secret, scope, and redirect ports are configured per-property
240
+ in a matching `<ExtraProperties>` child element (see
241
+ [script-declaration.md § ExtraProperties](script-declaration.md#extraproperties)), not in
242
+ `Editor`/`Type`. The script receives a ready-to-use access token string via
243
+ `getPropertyStringValue()`.
244
+ - **External editor**: requires a separate companion application. The script receives a file path to
245
+ the property set file. Entry point `findExternalEditorPath` resolves the editor executable path.
246
+ One of these two must be true — either a dependent property named `Application` (see
247
+ [Dependency](script-declaration.md#custom-property-elements-elementfields)) is non-empty, or
248
+ the script implements `findExternalEditorPath` — see
249
+ [entry-points.md](../switch-api/entry-points.md#property-ui-callbacks).