@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.
- package/CHANGELOG.md +504 -0
- package/README.md +192 -0
- package/bin/cli.js +8 -0
- package/dist/init.d.ts +78 -0
- package/dist/init.js +894 -0
- package/docs/switch-api/api-versions.md +127 -0
- package/docs/switch-api/connection.md +82 -0
- package/docs/switch-api/document-classes.md +189 -0
- package/docs/switch-api/entry-points.md +185 -0
- package/docs/switch-api/enums.md +181 -0
- package/docs/switch-api/execution-environment.md +143 -0
- package/docs/switch-api/flow-element.md +143 -0
- package/docs/switch-api/http.md +96 -0
- package/docs/switch-api/job-patterns.md +238 -0
- package/docs/switch-api/job.md +187 -0
- package/docs/switch-api/logging.md +117 -0
- package/docs/switch-api/switch.md +210 -0
- package/docs/switch-appstore/app-guidelines.md +281 -0
- package/docs/switch-appstore/app-manual.md +84 -0
- package/docs/switch-appstore/app-store-listing.md +69 -0
- package/docs/switch-appstore/app-store-submission.md +83 -0
- package/docs/switch-project/debugging.md +61 -0
- package/docs/switch-project/logs-and-dataroot.md +80 -0
- package/docs/switch-project/node-versions.md +87 -0
- package/docs/switch-project/project-planning.md +149 -0
- package/docs/switch-project/property-documentation.md +75 -0
- package/docs/switch-project/property-editors.md +249 -0
- package/docs/switch-project/script-declaration.md +407 -0
- package/docs/switch-project/script-structure.md +157 -0
- package/docs/switch-project/tooling.md +165 -0
- package/docs/switch-project/vscode.md +90 -0
- package/docs/switch-scripting.md +70 -0
- 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).
|