@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,407 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: script-declaration
|
|
3
|
+
category: switch-project
|
|
4
|
+
order: 14
|
|
5
|
+
summary: "XML declaration reference: properties, connections, execution config; agents may edit this file directly"
|
|
6
|
+
triggers:
|
|
7
|
+
- "Understanding, adding, or editing script properties/connections/execution config"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Script Declaration (XML)
|
|
11
|
+
|
|
12
|
+
The file `<ScriptID>.xml` defines the script's metadata, custom properties, connection properties,
|
|
13
|
+
and execution configuration. It is normally written by **SwitchScripter**, but the format is fully
|
|
14
|
+
documented below — you can edit it directly.
|
|
15
|
+
|
|
16
|
+
<!-- docs-index:contents begin -->
|
|
17
|
+
## Contents
|
|
18
|
+
|
|
19
|
+
- Agent editing policy
|
|
20
|
+
- XML structure overview
|
|
21
|
+
- Built-in ElementFields
|
|
22
|
+
- Custom property elements (ElementFields)
|
|
23
|
+
- ConnectionFields
|
|
24
|
+
- ExtraProperties
|
|
25
|
+
- Type reference
|
|
26
|
+
- Escaped `ValueDescription` payloads
|
|
27
|
+
- Reserved tag names
|
|
28
|
+
- Annotated example
|
|
29
|
+
<!-- docs-index:contents end -->
|
|
30
|
+
|
|
31
|
+
## Agent editing policy
|
|
32
|
+
|
|
33
|
+
- Editing this file directly is safe as long as you follow the rules on this page exactly — the
|
|
34
|
+
format has no schema, so Switch will silently misbehave (not error) on a malformed attribute.
|
|
35
|
+
- Preserve every attribute you don't intend to change. Don't reformat, reorder attributes, or drop
|
|
36
|
+
fields you don't understand.
|
|
37
|
+
- `Name` is the script's stable ID — never change it on an existing script (it's used as the flow
|
|
38
|
+
element type and referenced by installed flows). `DisplayName`, tooltips, defaults, adding/removing
|
|
39
|
+
custom properties, and connection topology are all safe to change directly.
|
|
40
|
+
- `Version` identifies a released build, not an edit. Bump it only when the current value has
|
|
41
|
+
already been released (installed on a customer's or production Switch, or published on the
|
|
42
|
+
Appstore). If the current value was never released, keep editing under it; don't bump per
|
|
43
|
+
change. See the `Version` row below for format and what Switch does with it.
|
|
44
|
+
- Custom property tag names must match `^[A-Za-z][A-Za-z0-9]*$`, must not start with `xml`
|
|
45
|
+
(case-insensitive), and must not collide with a [reserved tag](#reserved-tag-names) below. Switch
|
|
46
|
+
does **not** sanitize or rewrite bad tag names on load — it just fails to work correctly.
|
|
47
|
+
- `manifest.xml` (declares the package's program file(s) and type) rarely needs edits; treat it as
|
|
48
|
+
low-risk to read but confirm with the user before changing `ScriptPackageType`,
|
|
49
|
+
`ScriptDeclarationFile`, or `ScriptProgramFiles`.
|
|
50
|
+
- Never add or edit `ApplicationPath` or `ApplicationLicense` — these are app-only properties that
|
|
51
|
+
point Switch at a third-party application's install location and license. They must be set by the
|
|
52
|
+
user from the Switch Scripter GUI after the script package has been packed; Switch silently drops
|
|
53
|
+
them if written into the declaration file directly.
|
|
54
|
+
- **Gotcha: reload the script element after changing properties.** When the declaration of a script
|
|
55
|
+
that is already used in a flow gains a property or a property changes, right-click the element in
|
|
56
|
+
Switch Designer and choose "Reload script" before activating the flow. Until then the element
|
|
57
|
+
keeps the old declaration: a new property doesn't appear in the element, and
|
|
58
|
+
`getPropertyStringValue()` on it throws `"Invalid tag: <tag>"`. Seen with a script folder on
|
|
59
|
+
Switch 26.07.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## XML structure overview
|
|
64
|
+
|
|
65
|
+
```xml
|
|
66
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
67
|
+
<Object>
|
|
68
|
+
<ElementFields> <!-- required: built-in fields + custom property elements -->
|
|
69
|
+
<ConnectionFields> <!-- optional: custom outgoing-connection property elements -->
|
|
70
|
+
<ExtraProperties> <!-- optional: OAuth 2.0 editor config only -->
|
|
71
|
+
</Object>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`ElementFields` is required — Switch rejects the whole declaration without it. `ConnectionFields`
|
|
75
|
+
and `ExtraProperties` may be omitted or left empty.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Built-in ElementFields
|
|
80
|
+
|
|
81
|
+
These configure the flow element (name, topology, execution, pane placement, docs). All carry
|
|
82
|
+
`Editor="hide"` and are never shown to the user directly. Add `Type="..."` to a field only when the
|
|
83
|
+
value is non-string (see the table); an empty string field can omit `Type`.
|
|
84
|
+
|
|
85
|
+
| Element | Values | Notes |
|
|
86
|
+
|---|---|---|
|
|
87
|
+
| `Name` | string | Stable script ID — **never change on an existing script**. Becomes the flow element `Type`. |
|
|
88
|
+
| `DisplayName` | string | Shown in Switch. Empty falls back to `Name`. A `~` splits "Vendor~Element" — Switch shows the part after `~` as the short name and the whole string (space-joined) as the full name. |
|
|
89
|
+
| `Version` | number | Format `[1-9][0-9]*(\.(0\|[1-9][0-9]*))*`, e.g. `1`, `2.1`. SwitchScripter accepts a whole number only for a script and at most one minor level for an app (`2.1`); it resets anything else. Bump once per release, not per edit (see [Agent editing policy](#agent-editing-policy)). Each flow records the version of the element it uses; Switch compares that recorded value with `UpgradeMaximumVersion` to decide whether to show `FlowUpgradeWarning`. |
|
|
90
|
+
| `Keywords` | string | Space/comma/semicolon-separated. Elements pane search. |
|
|
91
|
+
| `Tooltip` | string | Elements pane tooltip. |
|
|
92
|
+
| `IncomingConnections` | `Yes` \| `No` | Add `RequireAtLeastOne="Yes"` when `Yes`. When `Yes`, the script must implement `jobArrived` (optionally `timerFired` too); when `No`, it must implement `timerFired` instead — see [entry-points.md](../switch-api/entry-points.md#job-processing). Setting `IncomingConnections="Yes" RequireAtLeastOne="No"` makes the incoming connection optional per instance: some instances can have zero incoming connections (e.g. a flow-starting webhook trigger) and others one wired in (e.g. a mid-flow processing step), with the script branching on both cases at runtime, typically gated by a property such as a mode enum. Confirmed working in Switch Designer. |
|
|
93
|
+
| `OutgoingConnections` | `No` \| `One` \| `Unlimited` | Add `RequireAtLeastOne="Yes"` when `One`/`Unlimited`. `One` with `RequireAtLeastOne="No"` makes the outgoing connection optional: a flow with an instance that had no outgoing connection validated and activated (Switch 26.07). Always carries `DetailedInfo=""` (or a prose description of the connections, for generated docs). When not `No`, the script must call a `sendTo*()` method at least once for any job it actually routes (a purely timer/event-driven script that never touches a job — polling an API, rotating logs, etc. — is a legitimate exception); when `Unlimited`, never use `job.sendToSingle()` — see [job-patterns.md § Sending jobs](../switch-api/job-patterns.md#sending-jobs). |
|
|
94
|
+
| `ConnectionType` | `Move` \| `Filter` \| `TrafficLight` | Governs which `ConnectionFields` children are legal — see [ConnectionFields](#connectionfields). |
|
|
95
|
+
| `FunctionsNodeJSScript` | `;`-separated names | Entry point function names found in the script. Omit the element entirely if there is no Node.js program. |
|
|
96
|
+
| `ExecutionMode` | `Concurrent` \| `Serialized` | |
|
|
97
|
+
| `NumberOfSlots` | `Default` \| integer | Only meaningful when `Concurrent`. |
|
|
98
|
+
| `ExecutionGroup` | string | Only meaningful when `Serialized`. Empty falls back to `Name`. |
|
|
99
|
+
| `PerformanceTuning` | `Yes` \| `No` | When `Yes`, `IdleAfterJob` (and `NumberOfSlots` if concurrent) become visible/editable in Switch. |
|
|
100
|
+
| `IdleAfterJob` | number (seconds) | |
|
|
101
|
+
| `PositionInElementPane` | `Basics` \| `Tools` \| `Communication` \| `Apps` \| `Configurators` \| `Metadata` \| `Database` | Which section of the Elements pane the script appears under. |
|
|
102
|
+
| `SubcategoryInElementPane` | escaped XML, see [§ escaped payloads](#escaped-valuedescription-payloads) | Apps/Configurators only. |
|
|
103
|
+
| `DispositionInElementPane` | numeric string or empty | Sort position within the category. Empty = alphabetical. |
|
|
104
|
+
| `Description` | string | Long description. |
|
|
105
|
+
| `Compatibility` | string | Configurator only: third-party app compatibility notes. |
|
|
106
|
+
| `SupportInfo` | string | Configurator only: support email/URL. |
|
|
107
|
+
| `AppDiscovery` | string | Configurator only: how the app is located on disk. |
|
|
108
|
+
| `FlowUpgradeWarning` | string | Warning shown during flow upgrade. |
|
|
109
|
+
| `UpgradeMaximumVersion` | number | Previous version up to which the upgrade warning is shown. Optional. |
|
|
110
|
+
| `Connections` | string | Prose description of outgoing connections, for generated docs. |
|
|
111
|
+
| `SwitchModule` | `Configurator` \| `Metadata` \| `Scripting` \| `Database` \| `SwitchClient` \| `SwitchClientSDK` | Licensing module. |
|
|
112
|
+
| `ObsoleteProperties` | `;`/`,`/whitespace-separated tag names | Suppresses "unknown property" warnings when a flow already has properties you removed. Add old tag names here when removing a custom property. |
|
|
113
|
+
| `ObsoleteConnectionProperties` | same | Same, for removed connection properties. |
|
|
114
|
+
|
|
115
|
+
Do **not** add `ApplicationPath` or `ApplicationLicense` as element names — Switch silently drops
|
|
116
|
+
them. These app-only properties must be configured by the user from the Switch Scripter GUI after
|
|
117
|
+
the package is packed, not written into the declaration file.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Custom property elements (ElementFields)
|
|
122
|
+
|
|
123
|
+
Each user-defined property is a child element of `<ElementFields>` with `UserDefined="true"`. The
|
|
124
|
+
element name is the property's **tag** (used as the `tag` argument in `getPropertyStringValue()`)
|
|
125
|
+
and must follow the [tag name rules](#reserved-tag-names).
|
|
126
|
+
|
|
127
|
+
The element must **never be self-closing**. Its text content holds the property's *current value*
|
|
128
|
+
— e.g. `<Count ...>8</Count>`, not `<Count ... Default="8" />`. A self-closing custom property is
|
|
129
|
+
non-editable in Switch Designer.
|
|
130
|
+
|
|
131
|
+
```xml
|
|
132
|
+
<MyProperty UserDefined="true" Type="string" Editor="choosefolder" LocalizedTagName="My Property"
|
|
133
|
+
Tooltip="Select the output folder" DetailedInfo="" Validation="Standard" Default=""
|
|
134
|
+
Subtype="">Default value goes here</MyProperty>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Key attributes:
|
|
138
|
+
|
|
139
|
+
| Attribute | Description |
|
|
140
|
+
|---|---|
|
|
141
|
+
| `UserDefined` | Always `"true"` for custom properties. |
|
|
142
|
+
| `Type` | Value type discriminator — see [Type reference](#type-reference). |
|
|
143
|
+
| `Editor` | `;`-joined chain of editor tokens (inline editor first, then modal editors) — see [property-editors.md](property-editors.md). |
|
|
144
|
+
| `Subtype` | Which editor in the `Editor` chain is currently active for the stored value. For a single-editor property this equals that editor's token (e.g. `"inline"`); for a bare modal editor with no inline component, leave it `""`. Exception: `Type="password"` takes `Subtype=""` even though `Editor="inline"` alone — see [property-editors.md](property-editors.md#common-practices). This attribute is read by Switch's validator at runtime, not just bookkeeping — keep it consistent with `Editor`. |
|
|
145
|
+
| `LocalizedTagName` | Display name shown in the Properties pane. **App guideline (mandatory for apps, recommended for scripts):** 30 characters max, sentence-style capitalization (`"Customer name"`, not `"Customer Name"`). |
|
|
146
|
+
| `Tooltip` | Tooltip shown in the Properties pane. **App guideline (mandatory for apps, recommended for scripts):** give every property a tooltip. The only exception is a property that's fully self-explanatory from its name alone with no extra constraints (e.g. "Number of copies" with no min/max) — if there's anything a user would need to know (units, valid range, format, an example value), put it in the tooltip. |
|
|
147
|
+
| `DetailedInfo` | Long-form description for generated docs. Always include the attribute (empty string `""` is fine) — omitting it makes the property non-editable in Switch Designer. |
|
|
148
|
+
| `Validation` | `None` (skip validation) \| `Standard` (built-in validator) \| `Custom` (needs a `validateProperties` entry point) \| `Standard and custom` (both, custom only runs if standard passes). If any property uses `Custom` or `Standard and custom`, the script must implement `validateProperties` (or `validateConnectionProperties` for a connection field) — see [entry-points.md](../switch-api/entry-points.md#property-ui-callbacks). To let a property hold an empty value under `Standard` validation, add the `none` literal editor to the `Editor` chain (see [property-editors.md § Literal editors](property-editors.md#literal-editors)) instead of relaxing to `Validation="None"` just to permit emptiness. |
|
|
149
|
+
| `Default` | Default value string. Omit only if the value is emitted as CDATA instead. **App guideline (mandatory for apps, recommended for scripts):** always provide a default unless there's genuinely no sensible one; if a default truly isn't possible, give an example value in the `Tooltip` instead. |
|
|
150
|
+
| `Dependency` | Tag of the master property this one depends on. Written flat (not nested) — the dependent element is a sibling of its master, not a child. |
|
|
151
|
+
| `DependencyCondition` | One of: `Not-empty`, `Equals`, `Not-equals`, `Contains`, `Does not contain`, `Matches`, `Does not match`, `Starts with`, `Does not start with`. |
|
|
152
|
+
| `Dependencyvalue` | Value(s) to compare against — `;`-separated for multiple. Note the lowercase `v`. |
|
|
153
|
+
|
|
154
|
+
**Dependency example** — show `OutputFolder` only when `Mode` equals `"Custom"`:
|
|
155
|
+
|
|
156
|
+
```xml
|
|
157
|
+
<Mode UserDefined="true" Type="enum:Default;Custom" Editor="inline" Subtype="inline"
|
|
158
|
+
LocalizedTagName="Mode" Tooltip="" DetailedInfo="" Validation="Standard"
|
|
159
|
+
Default="Default">Default</Mode>
|
|
160
|
+
<OutputFolder UserDefined="true" Type="string" Editor="choosefolder" Subtype=""
|
|
161
|
+
Dependency="Mode" DependencyCondition="Equals" Dependencyvalue="Custom"
|
|
162
|
+
LocalizedTagName="Output folder" Tooltip="" DetailedInfo=""
|
|
163
|
+
Validation="Standard" Default=""></OutputFolder>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Runtime pitfall:** when a dependent property is hidden (its master's current value doesn't satisfy
|
|
167
|
+
`DependencyCondition`/`Dependencyvalue`), Switch treats the tag as if it doesn't exist. Calling
|
|
168
|
+
`flowElement.getPropertyStringValue(tag)` on it throws `"Invalid tag: <tag>"` — see
|
|
169
|
+
[flow-element.md](../switch-api/flow-element.md#properties). Only fetch a dependent property once you know
|
|
170
|
+
its condition holds, either by checking the already-read master value yourself, or by calling
|
|
171
|
+
`flowElement.hasProperty(tag)` first (it returns `false` for a hidden dependent). This matters most
|
|
172
|
+
for an enum/drop-down master with several dependents keyed off different values — fetch only the
|
|
173
|
+
ones actually shown for the current selection, not all of them.
|
|
174
|
+
|
|
175
|
+
A script must never assume the set of fetchable dependents is fixed once at flow configuration
|
|
176
|
+
time: if the master's own value is dynamic (a Switch variable or script expression, resolved per
|
|
177
|
+
job in `jobArrived`), which dependents are shown can differ from job to job in the same flow
|
|
178
|
+
execution. Re-check the condition (or call `hasProperty()`) on every invocation rather than caching
|
|
179
|
+
an earlier "shown" determination. There is no way to read a currently-hidden dependent's value for
|
|
180
|
+
a given job — if a script genuinely needs data from more than one dependency group at once (e.g.
|
|
181
|
+
values entered while the master previously pointed elsewhere), this pattern cannot provide it, and
|
|
182
|
+
a different property structure (not `Dependency`-based hiding) is needed instead.
|
|
183
|
+
|
|
184
|
+
Attribute order in the file doesn't matter functionally — SwitchScripter's own output happens to be
|
|
185
|
+
alphabetical (QDom sorts attributes on write), but any order parses correctly.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## ConnectionFields
|
|
190
|
+
|
|
191
|
+
Custom outgoing-connection properties follow the same attribute pattern as element properties, with
|
|
192
|
+
one addition: `AvailableFor="Data"` or `AvailableFor="Log"` restricts which connection kind shows the
|
|
193
|
+
property; omit the attribute for both.
|
|
194
|
+
|
|
195
|
+
```xml
|
|
196
|
+
<ConnectionFields>
|
|
197
|
+
<TargetFolder AvailableFor="Data" UserDefined="true" Type="string" Editor="choosefolder"
|
|
198
|
+
Subtype="" LocalizedTagName="Target folder" Tooltip="" DetailedInfo=""
|
|
199
|
+
Validation="Standard" Default=""></TargetFolder>
|
|
200
|
+
</ConnectionFields>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Connection property values are read at runtime via `connection.getPropertyStringValue(tag)`.
|
|
204
|
+
|
|
205
|
+
**`ConnectionType` gates which built-in connection fields may appear here** — this is the single
|
|
206
|
+
most important thing to get right when hand-editing this section:
|
|
207
|
+
|
|
208
|
+
| `ConnectionType` | Legal built-in children |
|
|
209
|
+
|---|---|
|
|
210
|
+
| `Move` | none — `<ConnectionFields/>` must be empty of built-ins |
|
|
211
|
+
| `Filter` | `IncludeFolderMask`, `ExcludeFolderMask` (both or neither) |
|
|
212
|
+
| `TrafficLight` | `Success`, `Warning`, `Error`, each optionally with `AvailableFor="Data"` or `AvailableFor="Log"` (omit the attribute if available for both; omit the whole element if available for neither) |
|
|
213
|
+
|
|
214
|
+
```xml
|
|
215
|
+
<!-- ConnectionType = TrafficLight -->
|
|
216
|
+
<ConnectionFields>
|
|
217
|
+
<Success AvailableFor="Data" LocalizedTagName="Success out" Type="bool" Editor="inline" Default="Yes">Yes</Success>
|
|
218
|
+
<Error AvailableFor="Data" LocalizedTagName="Error out" Type="bool" Editor="inline" Default="Yes">Yes</Error>
|
|
219
|
+
<!-- no Warning element: not available for Data or Log -->
|
|
220
|
+
</ConnectionFields>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Custom (author-defined) connection properties may be added regardless of `ConnectionType`.
|
|
224
|
+
|
|
225
|
+
The declared connections and the script's `sendTo*()` calls must agree with each other — see
|
|
226
|
+
[job-patterns.md § Sending jobs](../switch-api/job-patterns.md#sending-jobs) for the exact rules per
|
|
227
|
+
`ConnectionType`. In particular, omit a `Success`/`Warning`/`Error` element entirely (as shown
|
|
228
|
+
above) if the script never routes to it, rather than leaving an unused connection declared.
|
|
229
|
+
|
|
230
|
+
**Caution — package-swap connection preservation:** Switch Designer decides whether existing flow
|
|
231
|
+
connections survive a script package replace by comparing the serialised `ConnectionFields` and
|
|
232
|
+
`IncomingConnections` text **byte-for-byte** between old and new declarations, and additionally
|
|
233
|
+
checks whether `ConnectionType`/`OutgoingConnections` changed. Don't make cosmetic whitespace or
|
|
234
|
+
attribute-order changes to those sections without expecting existing flows' outgoing connection
|
|
235
|
+
properties to reset on next package update.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## ExtraProperties
|
|
240
|
+
|
|
241
|
+
Only used for OAuth 2.0 (`Editor` containing `oauth`, see
|
|
242
|
+
[property-editors.md](property-editors.md)). One child element per OAuth property, named
|
|
243
|
+
identically to the property's tag, in `ElementFields` or `ConnectionFields`:
|
|
244
|
+
|
|
245
|
+
```xml
|
|
246
|
+
<ElementFields>
|
|
247
|
+
<OAuth1 UserDefined="true" Type="string" Editor="oauth" Subtype="" LocalizedTagName="OAuth1"
|
|
248
|
+
Tooltip="" DetailedInfo="" Validation="Standard" Default=""></OAuth1>
|
|
249
|
+
</ElementFields>
|
|
250
|
+
<ExtraProperties>
|
|
251
|
+
<OAuth1 OAuthAuthorizationEndpoint="http://auth-url"
|
|
252
|
+
OAuthClientID="AppID1"
|
|
253
|
+
OAuthClientSecret="Application Password 123"
|
|
254
|
+
OAuthClientSecretEditor="inline"
|
|
255
|
+
OAuthRedirPorts="666"
|
|
256
|
+
OAuthRedirPortsEditor="inline"
|
|
257
|
+
OAuthScope="some-random-scope"
|
|
258
|
+
OAuthScopeEditor="inline"
|
|
259
|
+
OAuthTokenEndpoint="http://token-url"/>
|
|
260
|
+
</ExtraProperties>
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Attributes: `OAuthAuthorizationEndpoint`, `OAuthClientID`, `OAuthClientSecret`, `OAuthRedirPorts`,
|
|
264
|
+
`OAuthTokenEndpoint`, `OAuthScope`. A companion `<Attr>Editor` attribute is only needed when that
|
|
265
|
+
attribute has more than one valid input mode; otherwise omit it. If the package is
|
|
266
|
+
password-protected, `OAuthClientSecret` must be stored encrypted — leave OAuth secret edits to the
|
|
267
|
+
user rather than writing a plaintext secret into a password-protected package.
|
|
268
|
+
|
|
269
|
+
If no OAuth property exists on the script, omit `ExtraProperties` entirely or leave it empty
|
|
270
|
+
(`<ExtraProperties/>`).
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Type reference
|
|
275
|
+
|
|
276
|
+
`Type` is a single token, except for enums:
|
|
277
|
+
|
|
278
|
+
| Token | Meaning |
|
|
279
|
+
|---|---|
|
|
280
|
+
| `string` | Text |
|
|
281
|
+
| `number` | Integer |
|
|
282
|
+
| `password` | Masked text |
|
|
283
|
+
| `bool` | `Yes`/`No` |
|
|
284
|
+
| `date`, `datetime`, `time` | `time` is hours-and-minutes |
|
|
285
|
+
| `path` | Filesystem path |
|
|
286
|
+
| `enum:A;B;C` | Closed choice list, `;`-separated (a trailing `;` is tolerated) |
|
|
287
|
+
| `filefilter`, `folderfilter` | File / folder filter values |
|
|
288
|
+
| `stringlist` | List of strings |
|
|
289
|
+
| `accountlist` | Account list |
|
|
290
|
+
|
|
291
|
+
This is the *authoring* vocabulary written into the XML `Type` attribute. It does not map one-to-one
|
|
292
|
+
onto the runtime `PropertyType` returned by `getPropertyType()` (see
|
|
293
|
+
[property-editors.md](property-editors.md) and [enums.md](../switch-api/enums.md)) — e.g. XML
|
|
294
|
+
`bool` becomes runtime `boolean`, XML `path` splits into runtime `filepath`/`folderpath`, and several
|
|
295
|
+
XML types (`stringlist`, `accountlist`, `enum:...`, `datetime`, `time`) have no direct
|
|
296
|
+
`PropertyType` counterpart while several runtime values (`filetype`, `folderpattern`, `regex`,
|
|
297
|
+
`oauthtoken`, `literal`) have no direct XML `Type` counterpart. Don't assume the two vocabularies are
|
|
298
|
+
interchangeable.
|
|
299
|
+
|
|
300
|
+
`rational` (decimal) is not a valid `Type` for Node.js scripts.
|
|
301
|
+
|
|
302
|
+
`Type` is not independently authored on properties with a modal editor chain — it follows from
|
|
303
|
+
which editor(s) you choose, per [property-editors.md](property-editors.md). When combining
|
|
304
|
+
an inline editor with modal editors (e.g. `Editor="inline;sltextwithvar;scriptexp"`), the inline
|
|
305
|
+
editor's type wins: an inline Number editor plus those modal editors still yields `Type="number"`.
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## Escaped `ValueDescription` payloads
|
|
310
|
+
|
|
311
|
+
`SubcategoryInElementPane` (and a couple of internal-only fields) store a nested XML fragment,
|
|
312
|
+
escaped into the text node:
|
|
313
|
+
|
|
314
|
+
```xml
|
|
315
|
+
<SubcategoryInElementPane Editor="hide"><ValueDescription Type="stringlist">
|
|
316
|
+
<Value>Communication</Value>
|
|
317
|
+
</ValueDescription>
|
|
318
|
+
</SubcategoryInElementPane>
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Decodes to:
|
|
322
|
+
|
|
323
|
+
```xml
|
|
324
|
+
<ValueDescription Type="stringlist">
|
|
325
|
+
<Value>Communication</Value>
|
|
326
|
+
</ValueDescription>
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
One `Value` child per subcategory string. Escaping only `<` (not also `"`) is fine — both forms
|
|
330
|
+
parse.
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## Reserved tag names
|
|
335
|
+
|
|
336
|
+
A custom property or connection property tag must not collide with any built-in field name. Do not
|
|
337
|
+
use any of:
|
|
338
|
+
|
|
339
|
+
- Any [built-in `ElementFields` name](#built-in-elementfields) above.
|
|
340
|
+
- Any built-in `ConnectionFields` name: `IncludeFolderMask`, `ExcludeFolderMask`, `Success`,
|
|
341
|
+
`Warning`, `Error`.
|
|
342
|
+
- `Type`, `Category`, `ElementDescription`, `LogDebugMessages`, `SPSDebugMode`, `SPSDebugPort`,
|
|
343
|
+
`SPSDebugEntryPoints`, `AbortTimeoutMinutes`, `ScriptPackagePath`, `Xpos`, `Ypos`, `ElementIcon`,
|
|
344
|
+
`LastModified`, `Path`, `customExecutionMode`, `AdvancedTuningEnabled`, `Hold`, `TrafficType`,
|
|
345
|
+
`CorneringFactor`, `ElementType`.
|
|
346
|
+
- `ApplicationPath`, `ApplicationLicense` (legal as a tag, but Switch silently drops these two from
|
|
347
|
+
the flow element's property set, so don't use them). These are app-only properties, set by the
|
|
348
|
+
user from the Switch Scripter GUI after packing — never modify them directly.
|
|
349
|
+
|
|
350
|
+
Also required: tag matches `^[A-Za-z][A-Za-z0-9]*$` and does not start with `xml` (case-insensitive).
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## Annotated example
|
|
355
|
+
|
|
356
|
+
Representative declaration with Move connections, custom properties, and a dependency chain:
|
|
357
|
+
|
|
358
|
+
```xml
|
|
359
|
+
<Object>
|
|
360
|
+
<ElementFields>
|
|
361
|
+
<Name Editor="hide" Type="string">depositJob</Name>
|
|
362
|
+
<DisplayName Editor="hide" Type="string"></DisplayName>
|
|
363
|
+
<Version Editor="hide" Type="number">1</Version>
|
|
364
|
+
<Keywords Editor="hide" Type="string"></Keywords>
|
|
365
|
+
<Tooltip Editor="hide" Type="string"></Tooltip>
|
|
366
|
+
<IncomingConnections RequireAtLeastOne="Yes" Editor="hide">Yes</IncomingConnections>
|
|
367
|
+
<OutgoingConnections RequireAtLeastOne="Yes" DetailedInfo="" Editor="hide">Unlimited</OutgoingConnections>
|
|
368
|
+
<ConnectionType Editor="hide">Move</ConnectionType>
|
|
369
|
+
<FunctionsNodeJSScript Editor="hide">jobArrived</FunctionsNodeJSScript>
|
|
370
|
+
<ExecutionMode Editor="hide">Concurrent</ExecutionMode>
|
|
371
|
+
<NumberOfSlots Editor="hide">Default</NumberOfSlots>
|
|
372
|
+
<ExecutionGroup Editor="hide"></ExecutionGroup>
|
|
373
|
+
<PerformanceTuning Editor="hide">No</PerformanceTuning>
|
|
374
|
+
<IdleAfterJob Editor="hide" Type="number">0</IdleAfterJob>
|
|
375
|
+
<PositionInElementPane Editor="hide">Tools</PositionInElementPane>
|
|
376
|
+
<DispositionInElementPane Editor="hide" Type="number"></DispositionInElementPane>
|
|
377
|
+
<Description Editor="hide" Type="string"></Description>
|
|
378
|
+
<Connections Editor="hide" Type="string"></Connections>
|
|
379
|
+
<SwitchModule Editor="hide" Type="string">Scripting</SwitchModule>
|
|
380
|
+
<ObsoleteProperties Editor="hide" Type="string"></ObsoleteProperties>
|
|
381
|
+
<ObsoleteConnectionProperties Editor="hide" Type="string"></ObsoleteConnectionProperties>
|
|
382
|
+
|
|
383
|
+
<!-- Custom property: folder chooser -->
|
|
384
|
+
<DepositFolder UserDefined="true" Type="string" Editor="choosefolder" Subtype=""
|
|
385
|
+
LocalizedTagName="Deposit folder" Tooltip="" DetailedInfo=""
|
|
386
|
+
Validation="Standard" Default=""></DepositFolder>
|
|
387
|
+
|
|
388
|
+
<!-- Custom property: dropdown enum -->
|
|
389
|
+
<AttachAs UserDefined="true" Type="enum:Job;Dataset" Editor="inline" Subtype="inline"
|
|
390
|
+
LocalizedTagName="Attach as" Tooltip="" DetailedInfo="" Validation="Standard"
|
|
391
|
+
Default="Job">Job</AttachAs>
|
|
392
|
+
|
|
393
|
+
<!-- Custom property: bool, depends on AttachAs = "Dataset" -->
|
|
394
|
+
<IncludeMetadata UserDefined="true" Type="bool" Editor="inline" Subtype="inline"
|
|
395
|
+
Dependency="AttachAs" DependencyCondition="Equals" Dependencyvalue="Dataset"
|
|
396
|
+
LocalizedTagName="Include metadata" Tooltip="" DetailedInfo=""
|
|
397
|
+
Validation="Standard" Default="No">No</IncludeMetadata>
|
|
398
|
+
|
|
399
|
+
<!-- Custom property: literal "Default" editor combined with a modal editor -->
|
|
400
|
+
<FallbackFolder UserDefined="true" Type="string" Editor="default;choosefolder" Subtype=""
|
|
401
|
+
LocalizedTagName="Fallback folder" Tooltip="" DetailedInfo=""
|
|
402
|
+
Validation="Standard" Default="Default">Default</FallbackFolder>
|
|
403
|
+
</ElementFields>
|
|
404
|
+
<ConnectionFields/>
|
|
405
|
+
<ExtraProperties/>
|
|
406
|
+
</Object>
|
|
407
|
+
```
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: script-structure
|
|
3
|
+
category: switch-project
|
|
4
|
+
order: 10
|
|
5
|
+
summary: "What files a script folder contains, laying out several script folders side by side, `manifest.xml` format, Script vs App, packing an app with SwitchScripter"
|
|
6
|
+
triggers:
|
|
7
|
+
- "Setting up a new script project or converting a Script to an App"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Script Project Structure
|
|
11
|
+
|
|
12
|
+
A Switch script project lives in a **script folder** during development and is distributed as a `.sscript` package (ZIP).
|
|
13
|
+
|
|
14
|
+
> **Agent editing policy**: Edit TypeScript/JavaScript source files (`main.ts`, `main.js`) and the XML declaration (`<ScriptID>.xml`) freely — see [script-declaration.md](script-declaration.md) for the declaration's rules, and [entry-points.md § Entry-point scanner constraints](../switch-api/entry-points.md#entry-point-scanner-constraints) before writing any string/regex literal or division, since certain shapes make Switch's entry-point scanner silently drop functions. Leave `manifest.xml` to the user unless explicitly asked.
|
|
15
|
+
|
|
16
|
+
<!-- docs-index:contents begin -->
|
|
17
|
+
## Contents
|
|
18
|
+
|
|
19
|
+
- Script folder files
|
|
20
|
+
- Several script folders side by side
|
|
21
|
+
- manifest.xml format
|
|
22
|
+
- Node.js version per Switch version
|
|
23
|
+
- Script vs App
|
|
24
|
+
- Packing an app
|
|
25
|
+
- SwitchScripter and Switch version compatibility
|
|
26
|
+
- App Store submission guidelines
|
|
27
|
+
- Execution modes
|
|
28
|
+
<!-- docs-index:contents end -->
|
|
29
|
+
|
|
30
|
+
## Script folder files
|
|
31
|
+
|
|
32
|
+
| File | Required | Notes |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `manifest.xml` | Yes | Switch internal use only. Do not edit manually. |
|
|
35
|
+
| `<ScriptID>.xml` | Yes | Script declaration (properties, connections, execution config). See [script-declaration.md](script-declaration.md). |
|
|
36
|
+
| `main.ts` | Yes (TypeScript) | Source file. Edit this. |
|
|
37
|
+
| `main.js` | Yes | Compiled output executed by Switch. Generated by transpiling `main.ts`. |
|
|
38
|
+
| `main.js.map` | No | Source map, generated alongside `main.js`. |
|
|
39
|
+
| `package.json` | Yes (TypeScript) | NPM config for type declarations. |
|
|
40
|
+
| `tsconfig.json` | Yes (TypeScript) | TypeScript transpilation options. |
|
|
41
|
+
| `<IconFileName>.png` | No | 32×32 px, RGB, not interlaced. Extension must be `.png`. |
|
|
42
|
+
| `node_modules/` | No | Local npm packages. |
|
|
43
|
+
| `Resources/` | No | Extra resource files bundled when packing with SwitchScriptTool. Never bundle an Oracle Java Runtime Environment here — licensing terms don't permit redistributing it, in a script or an app. |
|
|
44
|
+
| `<LanguageCode>.ts` | No | Translation files (Switch App SDK). |
|
|
45
|
+
| `.vscode/launch.json` | No | Debug config (created by SwitchScriptTool). |
|
|
46
|
+
| `.vscode/switch.code-snippets` | No | Entry point snippets (TypeScript only). |
|
|
47
|
+
|
|
48
|
+
> After editing `main.ts`, transpile with SwitchScriptTool to regenerate `main.js` before testing in Switch.
|
|
49
|
+
|
|
50
|
+
## Several script folders side by side
|
|
51
|
+
|
|
52
|
+
One script folder produces one flow element. A design that needs several flow elements, such as
|
|
53
|
+
the apps in an app bundle, needs one script folder per element. Keep them in one parent folder, a
|
|
54
|
+
**script collection**:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
my-collection/ the folder the user works in; AI agent config and docs live here
|
|
58
|
+
├── FirstElement/ script folder (manifest.xml, FirstElement.xml, main.ts, ...)
|
|
59
|
+
└── SecondElement/ script folder
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
- Put each script folder directly under the collection, one level down. Don't nest a script folder
|
|
63
|
+
inside another script folder, and don't add grouping folders in between.
|
|
64
|
+
- Create each one with `SwitchScriptTool --create <ScriptID> <CollectionFolder>`. First check that
|
|
65
|
+
`<CollectionFolder>/<ScriptID>/` doesn't exist: `--create` deletes an existing target folder and
|
|
66
|
+
everything in it without asking.
|
|
67
|
+
- Never use `--create` to turn the collection folder itself into a script folder
|
|
68
|
+
(`--create <CollectionFolderName> <ParentFolder>`). That deletes the whole collection, including
|
|
69
|
+
`.git/` and AI agent config. If the user wants a script folder at the top level of the folder
|
|
70
|
+
they work in, or wants an existing top-level script folder moved down into a subfolder, stop and
|
|
71
|
+
leave that step to the user.
|
|
72
|
+
- Each script folder keeps its own `package.json`, `node_modules/` and `tsconfig.json`. Run npm,
|
|
73
|
+
transpile and pack per script folder.
|
|
74
|
+
|
|
75
|
+
## manifest.xml format
|
|
76
|
+
|
|
77
|
+
```xml
|
|
78
|
+
<Manifest>
|
|
79
|
+
<ScripterInstanceName>myScript</ScripterInstanceName>
|
|
80
|
+
<SwitchVersion>24.0</SwitchVersion>
|
|
81
|
+
<ScriptPackageFormatVersion>1.0</ScriptPackageFormatVersion>
|
|
82
|
+
<ScriptPasswordProtected>No</ScriptPasswordProtected>
|
|
83
|
+
<ScriptPackageType>Script</ScriptPackageType>
|
|
84
|
+
<ScriptDeclarationFile>myScript.xml</ScriptDeclarationFile>
|
|
85
|
+
<ScriptProgramFiles>
|
|
86
|
+
<ScriptProgramFile ScriptLanguage="NodeJSScript">main.ts</ScriptProgramFile>
|
|
87
|
+
</ScriptProgramFiles>
|
|
88
|
+
<ScriptIconFile>myScript_32.png</ScriptIconFile>
|
|
89
|
+
<LocalizationItems/>
|
|
90
|
+
</Manifest>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`ScriptPackageType` is either `Script` (regular) or `App` (scripted plug-in).
|
|
94
|
+
|
|
95
|
+
## Node.js version per Switch version
|
|
96
|
+
|
|
97
|
+
`SwitchVersion` in `manifest.xml` selects the Node.js version the script runs on, and SwitchScriptTool
|
|
98
|
+
and SwitchScripter overwrite it. See [node-versions.md](node-versions.md).
|
|
99
|
+
|
|
100
|
+
## Script vs App
|
|
101
|
+
|
|
102
|
+
| | Script | App |
|
|
103
|
+
|---|---|---|
|
|
104
|
+
| `ScriptPackageType` | `Script` | `App` |
|
|
105
|
+
| Appears in Elements pane | No (used via Script element) | Yes, as its own element |
|
|
106
|
+
| Distribution | Freely | Enfocus Appstore only |
|
|
107
|
+
| Position in pane | — | Configured via `PositionInElementPane` in XML |
|
|
108
|
+
|
|
109
|
+
## Packing an app
|
|
110
|
+
|
|
111
|
+
An app is produced by SwitchScripter, not by SwitchScriptTool, and the two workflows have to be
|
|
112
|
+
joined up explicitly:
|
|
113
|
+
|
|
114
|
+
- **A script folder can only be typed `Script`.** To ship one as an app, pack it with
|
|
115
|
+
`SwitchScriptTool --pack` first, then open the resulting package in SwitchScripter and change the
|
|
116
|
+
type to `App` before creating the `.enfpack`. If "Create pack" is greyed out, the type is still
|
|
117
|
+
`Script`.
|
|
118
|
+
- **Extra files can't be managed while SwitchScripter is working with a script folder.** Convert to
|
|
119
|
+
a script package first. The conversion is reversible, so the `.pdesc` holding the extra-files
|
|
120
|
+
configuration can be round-tripped back into the script folder and kept in version control.
|
|
121
|
+
- **Creating a pack does not save the script.** Save first, or the pack is built from the last
|
|
122
|
+
saved state.
|
|
123
|
+
- **The pack ID is derived from the script ID and always starts with `com.enfocus.`**, whatever the
|
|
124
|
+
company name and domain in SwitchScripter preferences. To keep it stable across an update, open
|
|
125
|
+
the previous `.enfpack` rather than the `.sscript` — SwitchScripter carries the pack ID over from
|
|
126
|
+
the pack it opened, even if the script ID or domain has since changed.
|
|
127
|
+
|
|
128
|
+
### SwitchScripter and Switch version compatibility
|
|
129
|
+
|
|
130
|
+
An app loads in the Switch version it was built with **or newer**, never older. So the SwitchScripter
|
|
131
|
+
used must be at or below the oldest Switch version you intend to support, and portable
|
|
132
|
+
SwitchScripters exist for older releases specifically to build backwards-compatible apps. There is
|
|
133
|
+
no SwitchScripter for Switch 25.11 — use the Switch 2024 Fall SwitchScripter for it.
|
|
134
|
+
Apps as a concept require Switch 13.1 or later.
|
|
135
|
+
|
|
136
|
+
The SwitchScripter version also fixes the app's Node.js version, see
|
|
137
|
+
[node-versions.md](node-versions.md). An app built with the
|
|
138
|
+
Switch 2024 Fall SwitchScripter has `SwitchVersion` `24.1`, so it runs on Node.js 20 in every Switch
|
|
139
|
+
version that loads it, including 26.x. Switch 26.11 ships SwitchScripter 26.11. An app built with
|
|
140
|
+
it runs on Node.js 24, and it loads only in Switch 26.11 or newer.
|
|
141
|
+
|
|
142
|
+
An unsigned app loads only in Switch on the machine that created it. That's what allows local
|
|
143
|
+
testing before submission; it loads elsewhere only once Enfocus has signed it.
|
|
144
|
+
|
|
145
|
+
## App Store submission guidelines
|
|
146
|
+
|
|
147
|
+
App-specific submission rules (localization, universal/signed macOS binaries, immutable extra
|
|
148
|
+
files) live in [app-guidelines.md § App-only](../switch-appstore/app-guidelines.md#app-only), alongside the
|
|
149
|
+
rest of the pre-publish checklist.
|
|
150
|
+
|
|
151
|
+
## Execution modes
|
|
152
|
+
|
|
153
|
+
`Concurrent`/`Serialized`, `ExecutionGroup` and `NumberOfSlots` are set in the XML declaration (see
|
|
154
|
+
[script-declaration.md](script-declaration.md#built-in-elementfields) for the attributes)
|
|
155
|
+
and documented in
|
|
156
|
+
[execution-environment.md § Execution modes](../switch-api/execution-environment.md#execution-modes),
|
|
157
|
+
which also explains why none of them maps to a count of Node.js processes.
|