@enfocussw/switch-scripting-context 25.11.0-beta.12 → 25.11.0-beta.14
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 +81 -0
- package/README.md +36 -35
- package/dist/init.d.ts +15 -0
- package/dist/init.js +65 -67
- package/docs/switch-api/api-app-guidelines.md +132 -13
- package/docs/switch-api/api-entry-points.md +10 -0
- package/docs/switch-api/api-execution-environment.md +21 -5
- package/docs/switch-api/api-job-patterns.md +29 -0
- package/docs/switch-api/api-project-planning.md +100 -0
- package/docs/switch-api/api-script-structure.md +38 -31
- package/docs/switch-api/api-switch.md +49 -0
- package/docs/switch-scripting.md +18 -7
- package/package.json +7 -4
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,87 @@ All notable changes to this package are documented here. Format follows
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [25.11.0-beta.14] - 2026-09-09
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `switch-scripting.md` now tells agents to grep `docs/switch-api/` for `known issue`, `gotcha`,
|
|
12
|
+
`quirk`, `caveat` to find documented pitfalls before writing code in an area.
|
|
13
|
+
- `api-entry-points.md` documents that a flow restart replays every queued job through `jobArrived`
|
|
14
|
+
again, even one whose processing was deferred to `timerFired`. A script relying on that pattern
|
|
15
|
+
must recognize an already-registered job and return quickly, or a large backlog is slow to clear.
|
|
16
|
+
- `api-project-planning.md`, a pre-scaffolding checklist for new scripts and apps: Script vs App,
|
|
17
|
+
job-processing approach, target OS, Switch version baseline, concurrency, native/binary npm
|
|
18
|
+
dependency feasibility, and Appstore competition risk. Loaded before any files are scaffolded.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
- `README.md` no longer uses dashes as punctuation. Wording is unchanged otherwise.
|
|
22
|
+
- The published README now links to the changelog on jsdelivr, pinned to the version being
|
|
23
|
+
installed. Relative links were rewritten by npm to the private repo, so they were dead for
|
|
24
|
+
consumers. `prepack` swaps them in and `postpack` swaps them back.
|
|
25
|
+
|
|
26
|
+
## [25.11.0-beta.13] - 2026-09-09
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
- README's two CHANGELOG links pointed at an unversioned jsdelivr URL, which always serves the
|
|
30
|
+
*latest published* file. On GitHub that showed the published file rather than the repo's live one,
|
|
31
|
+
hiding unreleased entries. Both are now relative links, so GitHub resolves them to the live file.
|
|
32
|
+
- Generated tool config (Cursor, Codex/OpenCode, Windsurf, Zed, Cline) — the "Core rules" block told
|
|
33
|
+
agents never to edit `<ScriptID>.xml` and to send the user to SwitchScripter instead. That has
|
|
34
|
+
contradicted `api-script-declaration.md` and the `switch-scripting.md` key rules since the agent
|
|
35
|
+
editing policy was added, and it sat in an always-on rules file that outranks any doc the agent
|
|
36
|
+
loads later. Now matches the docs: direct editing is fine under the declaration's rules.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
- `api-switch.md` — a "Translation extraction rules" section under `Switch.tr()`. Extraction is
|
|
40
|
+
static source analysis, so aliasing `Switch.tr`, concatenating with a variable, or interpolating
|
|
41
|
+
a template literal silently produces no translation entry at all. Documents what does work
|
|
42
|
+
(all quote styles, multi-line, literal-only concatenation, marking a string away from its use
|
|
43
|
+
site) and the `%1` + `messageParams` pattern for dynamic values.
|
|
44
|
+
- `api-job-patterns.md` — "Driving a third-party CLI application", the Node.js replacement for the
|
|
45
|
+
legacy `findApplicationPath`/`ApplicationPath` mechanism: a custom path property on the
|
|
46
|
+
`automatic;choosefile;sltextwithvar;scriptexp` chain, resolved once in `flowStartTriggered` into
|
|
47
|
+
`Scope.FlowElement` global data, with `failProcess()` when discovery fails and cleanup in
|
|
48
|
+
`flowStopTriggered`.
|
|
49
|
+
- `api-script-structure.md` — "Packing an app" and SwitchScripter/Switch version compatibility:
|
|
50
|
+
script folders can only be typed `Script` (pack, then retype to `App` in SwitchScripter), extra
|
|
51
|
+
files are unavailable in script-folder mode, the pack ID is always `com.enfocus.*` and is carried
|
|
52
|
+
over by opening the previous `.enfpack`, an app loads only in its build version or newer (no
|
|
53
|
+
Scripter for 25.07/25.11 — use 2024 Fall), and an unsigned app loads only on the machine that
|
|
54
|
+
built it.
|
|
55
|
+
- `api-app-guidelines.md` — the App-only section is now split into Identity and versioning,
|
|
56
|
+
Top-level declaration properties, Password protection, Localization, Icon, Extra files, Source
|
|
57
|
+
and review hygiene, and what review does and doesn't cover. New rules from the App SDK: script ID
|
|
58
|
+
charset and uniqueness, resubmit-without-bumping after a rejection, minor-version format, the
|
|
59
|
+
three-category limit and Product Management approval, unsigned apps always loading under
|
|
60
|
+
"Custom", `DetailedInfo` feeding the generated HTML docs, `ExecutionGroup` coordination for a
|
|
61
|
+
shared third-party application, `Compatibility`/`SupportInfo`/`AppDiscovery` being required to
|
|
62
|
+
build the pack at all, Node.js password protection being unrecoverable, the six-language limit on
|
|
63
|
+
app translations, the 200×200 Appstore icon, and macOS notarization checks via `codesign -dv`.
|
|
64
|
+
- Generated tool config and `switch-scripting.md` key rules — added the entry-point scanner
|
|
65
|
+
constraints (literal `function` keyword; no trailing-backslash string literals, regex literals, or
|
|
66
|
+
non-`word / word` division) to the always-on rules. Previously these lived only in
|
|
67
|
+
`api-entry-points.md`, so an agent making a small edit without opening that file had no signal
|
|
68
|
+
that the failure mode exists, and it fails silently.
|
|
69
|
+
|
|
70
|
+
### Changed
|
|
71
|
+
- Generated tool config for Cursor, Codex/OpenCode, Windsurf, Zed and Cline now lists each API doc
|
|
72
|
+
with its "Load when" routing text instead of a bare filename, so those agents can open the one
|
|
73
|
+
file they need without reading `switch-scripting.md` first. Costs ~600 tokens in the always-on
|
|
74
|
+
block, saves a ~1,300-token hub read per session.
|
|
75
|
+
- The routing table in `docs/switch-scripting.md` is now the single source for that list. `init.ts`
|
|
76
|
+
parses it (`parseRoutingTable()`); the two hardcoded 19-entry arrays are gone, as is the drift
|
|
77
|
+
they invited.
|
|
78
|
+
- `api-script-structure.md` — moved "App Store submission guidelines" into
|
|
79
|
+
`api-app-guidelines.md` § App-only and "Execution modes" into `api-execution-environment.md`,
|
|
80
|
+
leaving pointers at both old headings. Reviewing an app or reasoning about concurrency previously
|
|
81
|
+
needed two files for one topic. Existing anchor links still resolve.
|
|
82
|
+
- `docs/switch-scripting.md` and `README.md` — sharpened the routing descriptions for
|
|
83
|
+
`api-job.md` (signatures) vs `api-job-patterns.md` (rules and gotchas), and for
|
|
84
|
+
`api-script-structure.md` vs `api-tooling.md`. Their triggers overlapped enough that an agent had
|
|
85
|
+
to load both files for any job-handling task.
|
|
86
|
+
- `init` no longer copies `docs/superpowers`, `docs/temp`, or `.DS_Store` into a consuming project.
|
|
87
|
+
The published tarball already excludes them, but `init` run from a git clone did not.
|
|
88
|
+
|
|
8
89
|
## [25.11.0-beta.12] - 2026-09-08
|
|
9
90
|
|
|
10
91
|
### Fixed
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ AI coding assistant context for [Enfocus Switch](https://www.enfocus.com/en/swit
|
|
|
4
4
|
|
|
5
5
|
Installs curated API reference docs and generates config files for 8 AI coding agents (Claude Code, GitHub Copilot, Cursor, Codex CLI/OpenCode, Gemini CLI, Windsurf, Zed, and Cline) so AI assistants understand the Switch scripting API out of the box.
|
|
6
6
|
|
|
7
|
-
See [CHANGELOG.md](https://cdn.jsdelivr.net/npm/@enfocussw/switch-scripting-context/CHANGELOG.md) (also included in this package) for what's changed between versions.
|
|
7
|
+
See [CHANGELOG.md](https://cdn.jsdelivr.net/npm/@enfocussw/switch-scripting-context@25.11.0-beta.14/CHANGELOG.md) (also included in this package) for what's changed between versions.
|
|
8
8
|
|
|
9
9
|
## Usage
|
|
10
10
|
|
|
@@ -34,13 +34,13 @@ The package version tracks the Switch release its docs describe:
|
|
|
34
34
|
└────── Switch version (25.11)
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
- `25.11.x
|
|
37
|
+
- `25.11.x`: every release of this package documenting **Switch 25.11**. Patch increments are doc updates, fixes, and new features of the CLI itself.
|
|
38
38
|
- The next Switch release moves the first two numbers (e.g. Switch 27.07 → `27.7.0`). Note that semver forbids leading zeros, so `27.07` is published as `27.7`.
|
|
39
39
|
- **Pin with `~`, not `^`.** `~25.11.0` stays on Switch 25.11; `^25.11.0` would happily install `25.12.0`, which targets a different Switch release.
|
|
40
40
|
|
|
41
41
|
### Prereleases
|
|
42
42
|
|
|
43
|
-
Beta builds append a prerelease suffix
|
|
43
|
+
Beta builds append a prerelease suffix, for example `25.11.0-beta.1`. These sort *below* `25.11.0`,
|
|
44
44
|
so the beta line precedes GA and leaves `25.11.0` free for the first published release.
|
|
45
45
|
|
|
46
46
|
## What it does
|
|
@@ -53,9 +53,9 @@ so the beta line precedes GA and leaves `25.11.0` free for the first published r
|
|
|
53
53
|
|
|
54
54
|
| Tool | File | How context is loaded |
|
|
55
55
|
|---|---|---|
|
|
56
|
-
| Claude Code / ClawCode | `CLAUDE.md` | `@switch-docs/switch-scripting.md` import
|
|
56
|
+
| Claude Code / ClawCode | `CLAUDE.md` | `@switch-docs/switch-scripting.md` import; hub file routes to specific API docs on demand |
|
|
57
57
|
| GitHub Copilot | `.github/copilot-instructions.md` | `#file:` reference to hub |
|
|
58
|
-
| GitHub Copilot (scoped) | `.github/instructions/switch-scripting.instructions.md` | `applyTo: "**/*.ts"
|
|
58
|
+
| GitHub Copilot (scoped) | `.github/instructions/switch-scripting.instructions.md` | `applyTo: "**/*.ts"`; auto-attaches to every TypeScript file edit |
|
|
59
59
|
| Cursor | `.cursor/rules/switch-scripting.mdc` | Inline key rules + full API file path list |
|
|
60
60
|
| Codex CLI / OpenCode | `AGENTS.md` | Inline key rules + full API file path list |
|
|
61
61
|
| Gemini CLI | `GEMINI.md` | `@switch-docs/switch-scripting.md` import |
|
|
@@ -63,28 +63,28 @@ so the beta line precedes GA and leaves `25.11.0` free for the first published r
|
|
|
63
63
|
| Zed | `.rules` | Inline key rules + full API file path list |
|
|
64
64
|
| Cline | `.clinerules` | Inline key rules + full API file path list |
|
|
65
65
|
|
|
66
|
-
All files use `<!-- switch-scripting-context begin -->` / `<!-- switch-scripting-context end -->` markers. Re-running `init` replaces only the Switch section in existing files
|
|
66
|
+
All files use `<!-- switch-scripting-context begin -->` / `<!-- switch-scripting-context end -->` markers. Re-running `init` replaces only the Switch section in existing files. Project-specific rules outside the markers are untouched.
|
|
67
67
|
|
|
68
68
|
## Using this with your coding agent
|
|
69
69
|
|
|
70
|
-
Once `init` has run, just work normally
|
|
70
|
+
Once `init` has run, just work normally. Describe what you want in plain terms and prompt as you
|
|
71
71
|
usually would. Your agent picks up the Switch context automatically (via `@import` for Claude
|
|
72
72
|
Code/Gemini, or the inlined rules + file list for the others) whenever it's working in the project,
|
|
73
73
|
and pulls in the specific API doc it needs for the task at hand on its own. You don't need to know
|
|
74
74
|
the doc file names or tell it which one to read.
|
|
75
75
|
|
|
76
76
|
A few things this gets you without asking for them by name:
|
|
77
|
-
- Scaffolding a new entry point, handling a webhook, or reading/creating datasets and jobs
|
|
77
|
+
- Scaffolding a new entry point, handling a webhook, or reading/creating datasets and jobs. The
|
|
78
78
|
agent consults the matching API reference before writing the code.
|
|
79
|
-
- Diagnosing why a script isn't behaving as expected
|
|
79
|
+
- Diagnosing why a script isn't behaving as expected. The agent knows it can locate and query
|
|
80
80
|
Switch's own log database (`ServerLogs.db3`) rather than only re-reasoning about the code.
|
|
81
|
-
- Creating, packing, or deploying a script
|
|
82
|
-
flags and
|
|
83
|
-
- Editing the script's XML declaration
|
|
84
|
-
properties (app path/
|
|
81
|
+
- Creating, packing, or deploying a script. The agent uses `SwitchScriptTool` with the documented
|
|
82
|
+
flags and behaviour, rather than hand-rolling the steps.
|
|
83
|
+
- Editing the script's XML declaration. The agent follows the documented rules and knows which
|
|
84
|
+
properties (app path/licence) are off-limits and left to SwitchScripter's GUI instead.
|
|
85
85
|
|
|
86
|
-
Re-run `init` after upgrading this package so the copied docs and generated config files catch up
|
|
87
|
-
|
|
86
|
+
Re-run `init` after upgrading this package so the copied docs and generated config files catch up.
|
|
87
|
+
See [CHANGELOG.md](https://cdn.jsdelivr.net/npm/@enfocussw/switch-scripting-context@25.11.0-beta.14/CHANGELOG.md) for what changed.
|
|
88
88
|
|
|
89
89
|
## Options
|
|
90
90
|
|
|
@@ -130,23 +130,24 @@ npm install --save-dev "https://github.com/enfocus-switch/types-switch-scripting
|
|
|
130
130
|
|
|
131
131
|
The `switch-docs/` folder contains:
|
|
132
132
|
|
|
133
|
-
- `switch-scripting.md
|
|
134
|
-
- `switch-api/api-
|
|
135
|
-
- `switch-api/api-
|
|
136
|
-
- `switch-api/api-
|
|
137
|
-
- `switch-api/api-
|
|
138
|
-
- `switch-api/api-
|
|
139
|
-
- `switch-api/api-
|
|
140
|
-
- `switch-api/api-
|
|
141
|
-
- `switch-api/api-
|
|
142
|
-
- `switch-api/api-
|
|
143
|
-
- `switch-api/api-script-
|
|
144
|
-
- `switch-api/api-
|
|
145
|
-
- `switch-api/api-
|
|
146
|
-
- `switch-api/api-
|
|
147
|
-
- `switch-api/api-
|
|
148
|
-
- `switch-api/api-
|
|
149
|
-
- `switch-api/api-
|
|
150
|
-
- `switch-api/api-
|
|
151
|
-
- `switch-api/api-
|
|
152
|
-
- `switch-api/api-
|
|
133
|
+
- `switch-scripting.md`: master index with execution environment rules and "load when" routing table
|
|
134
|
+
- `switch-api/api-project-planning.md`: pre-scaffolding checklist covering Script vs App, job-processing approach, target OS, Switch version baseline, concurrency, native/binary npm dependencies, Appstore competition risk
|
|
135
|
+
- `switch-api/api-entry-points.md`: all entry point signatures and when each is called
|
|
136
|
+
- `switch-api/api-job.md`: `Job` class signatures for routing, file access, child jobs, private data, datasets
|
|
137
|
+
- `switch-api/api-flow-element.md`: `FlowElement`: properties, connections, job creation, logging
|
|
138
|
+
- `switch-api/api-switch.md`: `Switch` global: global data, webhooks, abort, server utilities
|
|
139
|
+
- `switch-api/api-connection.md`: `Connection`: type, properties, file count
|
|
140
|
+
- `switch-api/api-http.md`: `HttpRequest` / `HttpResponse` and webhook pattern
|
|
141
|
+
- `switch-api/api-enums.md`: all enums with string values (`LogLevel`, `AccessLevel`, `Scope`, etc.)
|
|
142
|
+
- `switch-api/api-document-classes.md`: `PdfDocument`, `ImageDocument`, `XmlDocument`, `XmpDocument`
|
|
143
|
+
- `switch-api/api-script-declaration.md`: XML declaration reference
|
|
144
|
+
- `switch-api/api-script-structure.md`: script folder contents, manifest format, Node.js version per Switch release, Script vs App
|
|
145
|
+
- `switch-api/api-tooling.md`: SwitchScriptTool commands, script folder vs package, build and deployment
|
|
146
|
+
- `switch-api/api-debugging.md`: enabling debug mode, debuggable entry points, VS Code attach
|
|
147
|
+
- `switch-api/api-logging.md`: log levels, when/what to log, `console.log` limitation, common gotchas
|
|
148
|
+
- `switch-api/api-logs-and-dataroot.md`: locating the application data root, querying `ServerLogs.db3` directly to diagnose a script
|
|
149
|
+
- `switch-api/api-vscode.md`: type declarations, tsconfig for TypeScript 6, ESLint rules
|
|
150
|
+
- `switch-api/api-property-editors.md`: property editor types and string return values
|
|
151
|
+
- `switch-api/api-job-patterns.md`: `Job` rules and gotchas covering file access semantics, temp cleanup, routing rules, child jobs, executor limits
|
|
152
|
+
- `switch-api/api-execution-environment.md`: execution modes, process model, state persistence across jobs, error handling, npm/native module constraints
|
|
153
|
+
- `switch-api/api-app-guidelines.md`: pre-publish checklist for Appstore apps covering property naming/tooltips/editors, entry point and sendTo consistency, logging quality, packaging, app-only submission rules
|
package/dist/init.d.ts
CHANGED
|
@@ -9,6 +9,21 @@ export interface ToolDefinition {
|
|
|
9
9
|
altIds?: string[];
|
|
10
10
|
files: ToolFile[];
|
|
11
11
|
}
|
|
12
|
+
export interface ApiDoc {
|
|
13
|
+
/** Filename within docs/switch-api/, e.g. "api-job.md". */
|
|
14
|
+
file: string;
|
|
15
|
+
/** The routing table's "Load when" text, verbatim. */
|
|
16
|
+
loadWhen: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The routing table in docs/switch-scripting.md is the single source of truth for
|
|
20
|
+
* which API docs exist and when to load each one. Everything the CLI generates is
|
|
21
|
+
* derived from it, so a new doc file needs registering in exactly one place here
|
|
22
|
+
* (plus README.md, which init.test.ts checks).
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseRoutingTable(root?: string): ApiDoc[];
|
|
25
|
+
/** Filenames only, in routing-table order. */
|
|
26
|
+
export declare function apiFiles(root?: string): string[];
|
|
12
27
|
export declare function generateAgentsMd(docsDir: string): string;
|
|
13
28
|
export declare function generateGeminiMd(docsDir: string): string;
|
|
14
29
|
export declare function generateWindsurfRules(docsDir: string): string;
|
package/dist/init.js
CHANGED
|
@@ -33,6 +33,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.parseRoutingTable = parseRoutingTable;
|
|
37
|
+
exports.apiFiles = apiFiles;
|
|
36
38
|
exports.generateAgentsMd = generateAgentsMd;
|
|
37
39
|
exports.generateGeminiMd = generateGeminiMd;
|
|
38
40
|
exports.generateWindsurfRules = generateWindsurfRules;
|
|
@@ -47,6 +49,46 @@ const readline = __importStar(require("readline"));
|
|
|
47
49
|
// ─── Markers ─────────────────────────────────────────────────────────────────
|
|
48
50
|
const MARKER_BEGIN = '<!-- switch-scripting-context begin -->';
|
|
49
51
|
const MARKER_END = '<!-- switch-scripting-context end -->';
|
|
52
|
+
// ─── Shared content (single source of truth for all generated tool files) ────
|
|
53
|
+
/** Package root, whether running from src/ (ts-node) or dist/. */
|
|
54
|
+
function packageRoot() {
|
|
55
|
+
return path.resolve(__dirname, '..');
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The routing table in docs/switch-scripting.md is the single source of truth for
|
|
59
|
+
* which API docs exist and when to load each one. Everything the CLI generates is
|
|
60
|
+
* derived from it, so a new doc file needs registering in exactly one place here
|
|
61
|
+
* (plus README.md, which init.test.ts checks).
|
|
62
|
+
*/
|
|
63
|
+
function parseRoutingTable(root = packageRoot()) {
|
|
64
|
+
const hub = fs.readFileSync(path.join(root, 'docs', 'switch-scripting.md'), 'utf8');
|
|
65
|
+
const docs = [];
|
|
66
|
+
for (const line of hub.split('\n')) {
|
|
67
|
+
// | `switch-api/<file>.md` | <contents> | <load when> |
|
|
68
|
+
const m = /^\|\s*`switch-api\/(api-[a-z0-9-]+\.md)`\s*\|(.*)\|(.*)\|\s*$/.exec(line);
|
|
69
|
+
if (m)
|
|
70
|
+
docs.push({ file: m[1], loadWhen: m[3].trim() });
|
|
71
|
+
}
|
|
72
|
+
if (docs.length === 0) {
|
|
73
|
+
throw new Error('No API docs found in docs/switch-scripting.md — the routing table format changed. ' +
|
|
74
|
+
'Generated tool config would be empty; fix parseRoutingTable() before publishing.');
|
|
75
|
+
}
|
|
76
|
+
return docs;
|
|
77
|
+
}
|
|
78
|
+
/** Filenames only, in routing-table order. */
|
|
79
|
+
function apiFiles(root) {
|
|
80
|
+
return parseRoutingTable(root).map(d => d.file);
|
|
81
|
+
}
|
|
82
|
+
const INLINE_CORE_RULES = `## Core rules
|
|
83
|
+
|
|
84
|
+
- Entry point functions are top-level async functions — do NOT use \`export\`, arrow functions, or class methods; declare them with the literal \`function\` keyword.
|
|
85
|
+
- Switch finds entry points with a regex, not a parser. Never write a string literal whose content ends with a backslash, a regex literal, or division outside the plain \`word / word\` shape — each silently deletes a span of real code and the entry points inside it, with no error. Read \`api-entry-points.md\` § Entry-point scanner constraints before editing \`main.ts\`/\`main.js\`.
|
|
86
|
+
- Every \`jobArrived\` must end with exactly one \`job.sendTo*()\` or \`job.fail()\`.
|
|
87
|
+
- Use \`AccessLevel.ReadOnly\` for \`job.get()\` unless the file content will be modified.
|
|
88
|
+
- After \`createJob()\`, \`createChild()\`, or \`createDataset()\` with a file path, delete the source file after routing — Switch does not auto-remove it.
|
|
89
|
+
- The XML declaration (\`<ScriptID>.xml\`) can be edited directly — read \`api-script-declaration.md\` first and follow its rules exactly (nothing validates this format, so mistakes fail silently). Never change an existing script's \`Name\`; bump \`Version\` on every declaration edit. Leave \`manifest.xml\` to the user unless explicitly asked.
|
|
90
|
+
- After editing \`main.ts\`, transpile with \`SwitchScriptTool --transpile <folder>\` — do not use \`tsc\` directly.
|
|
91
|
+
- Never use a script folder in production — pack with \`SwitchScriptTool --pack\` first; folders are excluded from flow exports.`;
|
|
50
92
|
// ─── Content generators ──────────────────────────────────────────────────────
|
|
51
93
|
function generateClaudeMd(docsDir) {
|
|
52
94
|
return `${MARKER_BEGIN}
|
|
@@ -76,28 +118,6 @@ You are working on an Enfocus Switch scripting project (Node.js/TypeScript).
|
|
|
76
118
|
${MARKER_END}`;
|
|
77
119
|
}
|
|
78
120
|
function generateCursorMdc(docsDir) {
|
|
79
|
-
const apiFiles = [
|
|
80
|
-
'api-entry-points.md',
|
|
81
|
-
'api-job.md',
|
|
82
|
-
'api-flow-element.md',
|
|
83
|
-
'api-connection.md',
|
|
84
|
-
'api-http.md',
|
|
85
|
-
'api-enums.md',
|
|
86
|
-
'api-document-classes.md',
|
|
87
|
-
'api-script-declaration.md',
|
|
88
|
-
'api-script-structure.md',
|
|
89
|
-
'api-tooling.md',
|
|
90
|
-
'api-debugging.md',
|
|
91
|
-
'api-vscode.md',
|
|
92
|
-
'api-property-editors.md',
|
|
93
|
-
'api-job-patterns.md',
|
|
94
|
-
'api-switch.md',
|
|
95
|
-
'api-execution-environment.md',
|
|
96
|
-
'api-logging.md',
|
|
97
|
-
'api-logs-and-dataroot.md',
|
|
98
|
-
'api-app-guidelines.md',
|
|
99
|
-
];
|
|
100
|
-
const fileList = apiFiles.map(f => `- \`${docsDir}/switch-api/${f}\``).join('\n');
|
|
101
121
|
return `---
|
|
102
122
|
description: Enfocus Switch scripting rules and API reference for Node.js/TypeScript scripts
|
|
103
123
|
globs: ["**/*.ts", "**/*.js"]
|
|
@@ -107,56 +127,21 @@ alwaysApply: false
|
|
|
107
127
|
${MARKER_BEGIN}
|
|
108
128
|
You are working on an Enfocus Switch scripting project (Node.js/TypeScript).
|
|
109
129
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
- Entry point functions are top-level async functions — do NOT use \`export\`.
|
|
113
|
-
- Every \`jobArrived\` must end with exactly one \`job.sendTo*()\` or \`job.fail()\`.
|
|
114
|
-
- Use \`AccessLevel.ReadOnly\` for \`job.get()\` unless the file content will be modified.
|
|
115
|
-
- After \`createJob()\`, \`createChild()\`, or \`createDataset()\` with a file path, delete the source file after routing — Switch does not auto-remove it.
|
|
116
|
-
- Never edit \`<ScriptID>.xml\` or \`manifest.xml\` directly. For property/connection changes, instruct the user to use SwitchScripter.
|
|
117
|
-
- After editing \`main.ts\`, transpile with \`SwitchScriptTool --transpile <folder>\` — do not use \`tsc\` directly.
|
|
118
|
-
- Never use a script folder in production — pack with \`SwitchScriptTool --pack\` first; folders are excluded from flow exports.
|
|
130
|
+
${INLINE_CORE_RULES}
|
|
119
131
|
|
|
120
132
|
## API reference
|
|
121
133
|
|
|
122
|
-
|
|
134
|
+
Load the file matching the task below. \`${docsDir}/switch-scripting.md\` has the same index plus
|
|
135
|
+
the project-wide key rules:
|
|
123
136
|
|
|
124
|
-
${
|
|
137
|
+
${inlineApiFileList(docsDir)}
|
|
125
138
|
${MARKER_END}`;
|
|
126
139
|
}
|
|
127
|
-
// ───
|
|
128
|
-
const INLINE_CORE_RULES = `## Core rules
|
|
129
|
-
|
|
130
|
-
- Entry point functions are top-level async functions — do NOT use \`export\`.
|
|
131
|
-
- Every \`jobArrived\` must end with exactly one \`job.sendTo*()\` or \`job.fail()\`.
|
|
132
|
-
- Use \`AccessLevel.ReadOnly\` for \`job.get()\` unless the file content will be modified.
|
|
133
|
-
- After \`createJob()\`, \`createChild()\`, or \`createDataset()\` with a file path, delete the source file after routing — Switch does not auto-remove it.
|
|
134
|
-
- Never edit \`<ScriptID>.xml\` or \`manifest.xml\` directly. For property/connection changes, instruct the user to use SwitchScripter.
|
|
135
|
-
- After editing \`main.ts\`, transpile with \`SwitchScriptTool --transpile <folder>\` — do not use \`tsc\` directly.
|
|
136
|
-
- Never use a script folder in production — pack with \`SwitchScriptTool --pack\` first; folders are excluded from flow exports.`;
|
|
137
|
-
const API_FILES = [
|
|
138
|
-
'api-entry-points.md',
|
|
139
|
-
'api-job.md',
|
|
140
|
-
'api-flow-element.md',
|
|
141
|
-
'api-connection.md',
|
|
142
|
-
'api-http.md',
|
|
143
|
-
'api-enums.md',
|
|
144
|
-
'api-document-classes.md',
|
|
145
|
-
'api-script-declaration.md',
|
|
146
|
-
'api-script-structure.md',
|
|
147
|
-
'api-tooling.md',
|
|
148
|
-
'api-debugging.md',
|
|
149
|
-
'api-vscode.md',
|
|
150
|
-
'api-property-editors.md',
|
|
151
|
-
'api-job-patterns.md',
|
|
152
|
-
'api-switch.md',
|
|
153
|
-
'api-execution-environment.md',
|
|
154
|
-
'api-logging.md',
|
|
155
|
-
'api-logs-and-dataroot.md',
|
|
156
|
-
'api-app-guidelines.md',
|
|
157
|
-
];
|
|
140
|
+
// ─── Inline block (for tools without @file import support) ──────────────────
|
|
158
141
|
function inlineApiFileList(docsDir) {
|
|
159
|
-
return
|
|
142
|
+
return parseRoutingTable()
|
|
143
|
+
.map(d => `- \`${docsDir}/switch-api/${d.file}\` — ${d.loadWhen}`)
|
|
144
|
+
.join('\n');
|
|
160
145
|
}
|
|
161
146
|
function generateInlineBlock(docsDir) {
|
|
162
147
|
return `You are working on an Enfocus Switch scripting project (Node.js/TypeScript).
|
|
@@ -165,7 +150,8 @@ ${INLINE_CORE_RULES}
|
|
|
165
150
|
|
|
166
151
|
## API reference
|
|
167
152
|
|
|
168
|
-
|
|
153
|
+
Load the file matching the task below. \`${docsDir}/switch-scripting.md\` has the same index plus
|
|
154
|
+
the project-wide key rules:
|
|
169
155
|
|
|
170
156
|
${inlineApiFileList(docsDir)}`;
|
|
171
157
|
}
|
|
@@ -347,13 +333,25 @@ function applyFileAction(action, dryRun) {
|
|
|
347
333
|
console.log(` ${rel} → ${label}`);
|
|
348
334
|
}
|
|
349
335
|
// ─── Docs copy ────────────────────────────────────────────────────────────────
|
|
336
|
+
/** Paths under docs/ that are never shipped to a consuming project. */
|
|
337
|
+
const DOCS_EXCLUDE = ['superpowers', 'temp'];
|
|
350
338
|
function copyDocs(packageRoot, destDir, dryRun) {
|
|
351
339
|
const src = path.join(packageRoot, 'docs');
|
|
352
340
|
if (dryRun) {
|
|
353
341
|
console.log(` [dry-run] Copying docs/ → ${path.relative(process.cwd(), destDir)}/`);
|
|
354
342
|
return;
|
|
355
343
|
}
|
|
356
|
-
|
|
344
|
+
// The published tarball already omits these, but init may run from a git clone.
|
|
345
|
+
fs.cpSync(src, destDir, {
|
|
346
|
+
recursive: true,
|
|
347
|
+
filter: (from) => {
|
|
348
|
+
const rel = path.relative(src, from);
|
|
349
|
+
if (!rel)
|
|
350
|
+
return true;
|
|
351
|
+
const [top] = rel.split(path.sep);
|
|
352
|
+
return !DOCS_EXCLUDE.includes(top) && path.basename(from) !== '.DS_Store';
|
|
353
|
+
},
|
|
354
|
+
});
|
|
357
355
|
console.log(` docs → ${path.relative(process.cwd(), destDir)}/`);
|
|
358
356
|
}
|
|
359
357
|
// ─── .gitignore update ───────────────────────────────────────────────────────
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
A pre-publish checklist for a script intended for the Enfocus Appstore (`ScriptPackageType="App"`
|
|
4
4
|
— see [api-script-structure.md § Script vs App](api-script-structure.md#script-vs-app)). Each item
|
|
5
5
|
here is enforced in more detail at the linked section — this page exists to be read top-to-bottom
|
|
6
|
-
right before submission, not as the primary source for any individual rule.
|
|
6
|
+
right before submission, not as the primary source for any individual rule. The one exception is
|
|
7
|
+
[App-only](#app-only) at the bottom, which is documented in full here.
|
|
7
8
|
|
|
8
9
|
Items fall into three tiers, marked on each one:
|
|
9
10
|
|
|
@@ -108,15 +109,133 @@ detail.
|
|
|
108
109
|
|
|
109
110
|
## App-only
|
|
110
111
|
|
|
111
|
-
The following apply only to `ScriptPackageType="App"`, not to a plain `Script` package at all.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
- [ ]
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
112
|
+
The following apply only to `ScriptPackageType="App"`, not to a plain `Script` package at all.
|
|
113
|
+
Unlike the sections above, these are documented in full here rather than deferring elsewhere.
|
|
114
|
+
|
|
115
|
+
### Identity and versioning
|
|
116
|
+
|
|
117
|
+
- [ ] **`Name` (Script ID) matches `[A-Za-z0-9_-]+`** — letters, digits, hyphens and underscores
|
|
118
|
+
only, no spaces. It must also be globally unique across the Appstore; Enfocus checks for clashes
|
|
119
|
+
at review and may require a change. Pick something unlikely to collide.
|
|
120
|
+
- [ ] **`Name` never changes across versions.** It is what identifies the app in an existing
|
|
121
|
+
customer flow, so changing it breaks the upgrade path. `DisplayName` *can* change freely between
|
|
122
|
+
versions without breaking upgrades — so keep any third-party application version number out of
|
|
123
|
+
`Name`, and preferably out of `DisplayName` too, or every application release forces a rename.
|
|
124
|
+
- [ ] **`Version` is only incremented once the previous version was actually published.** If a
|
|
125
|
+
submission is rejected, resubmit under the *same* version number rather than bumping. Minor
|
|
126
|
+
versions are allowed to one level (`1.1`, `1.10`, `1.34`); leading zeros are not (`1.01` is
|
|
127
|
+
invalid).
|
|
128
|
+
- [ ] **Every app in an app bundle carries the same version**, including the master app entry.
|
|
129
|
+
- [ ] **The pack ID always starts with `com.enfocus.`**, generated from the script ID, regardless
|
|
130
|
+
of the company name and domain set in SwitchScripter preferences. To keep it stable when
|
|
131
|
+
updating, open the existing `.enfpack` (not the `.sscript`) before re-packing — SwitchScripter
|
|
132
|
+
remembers the pack ID from the pack it opened.
|
|
133
|
+
|
|
134
|
+
### Top-level declaration properties
|
|
135
|
+
|
|
136
|
+
- [ ] **App-level `Tooltip` is filled in** — this is the tooltip on the icon in the Elements pane,
|
|
137
|
+
separate from the per-property tooltips above.
|
|
138
|
+
- [ ] **`Keywords` is populated and matches the keywords on the app's Appstore detail page.** Words
|
|
139
|
+
already in `DisplayName` are implicitly searchable and don't need repeating. Matching is
|
|
140
|
+
case-insensitive.
|
|
141
|
+
- [ ] **`ExecutionMode="Concurrent"` wherever the script allows it.** `Serialized` is the default
|
|
142
|
+
and the slower choice; concurrent is preferred for throughput. If you go concurrent, the script
|
|
143
|
+
must synchronise its own access to any shared resource — see
|
|
144
|
+
[api-execution-environment.md § Execution modes](api-execution-environment.md#execution-modes).
|
|
145
|
+
- [ ] **`ExecutionGroup` is shared across every app that drives the same non-concurrent third-party
|
|
146
|
+
application**, so Switch can stop them using it simultaneously. If your app is in that situation,
|
|
147
|
+
ask Enfocus which group name to use rather than inventing one.
|
|
148
|
+
- [ ] **`PerformanceTuning="Yes"` only with a concrete reason.** It exposes `IdleAfterJob` (and
|
|
149
|
+
`NumberOfSlots`) to the user; don't surface those knobs by default.
|
|
150
|
+
- [ ] **At most three categories, and `SubcategoryInElementPane` is filled in.** New categories need
|
|
151
|
+
Enfocus Product Management approval, and an app listed in more than three needs additional
|
|
152
|
+
approval. Note that an unsigned app always loads under the **Custom** subcategory regardless of
|
|
153
|
+
what it declares — the declared subcategory only takes effect once Enfocus has signed the app, and
|
|
154
|
+
review may change it.
|
|
155
|
+
- [ ] **`DetailedInfo` is present on every property and every connection**, not just `Tooltip`.
|
|
156
|
+
Switch Designer generates the app's HTML documentation from these, so an empty `DetailedInfo`
|
|
157
|
+
produces a blank entry in the shipped docs.
|
|
158
|
+
- [ ] **`Description`, `Compatibility`, `SupportInfo` and `AppDiscovery` are filled in.** These are
|
|
159
|
+
required to create the `.enfpack` at all, and `SupportInfo` must point at *your* support channel,
|
|
160
|
+
never Enfocus Support.
|
|
161
|
+
- [ ] **The declared incoming/outgoing connection topology matches what the code actually does** —
|
|
162
|
+
see [Entry points](#entry-points) and [Sending jobs](#sending-jobs) above.
|
|
163
|
+
- [ ] **Dependent properties have real dependency conditions and values, never left empty**, and the
|
|
164
|
+
script does not read a dependent property's value when its master isn't set to the value that
|
|
165
|
+
makes it relevant.
|
|
166
|
+
|
|
167
|
+
### Password protection
|
|
168
|
+
|
|
169
|
+
- [ ] **The app is password protected with a non-trivial password** (8+ characters, mixed case,
|
|
170
|
+
digits, symbols). Enfocus checks the password strength at review.
|
|
171
|
+
- [ ] **Don't lose the password.** For a Node.js app, Switch runs an obfuscated copy of the code
|
|
172
|
+
produced at save time and never needs the original source, so the protection is genuinely
|
|
173
|
+
one-way: Enfocus cannot recover a Node.js script's source if the author forgets the password.
|
|
174
|
+
(For legacy JavaScript/VBScript a bypass mechanism exists internally at Enfocus, so that
|
|
175
|
+
protection is weaker — another reason to be on Node.js.)
|
|
176
|
+
- [ ] Note that a published Node.js app ships only the obfuscated code, re-protected with a random
|
|
177
|
+
password Enfocus generates during review — not the password you set.
|
|
178
|
+
|
|
179
|
+
### Localization
|
|
180
|
+
|
|
181
|
+
- [ ] **Prefer more than one language.** An app is preferably localized beyond English — see
|
|
182
|
+
[Translation files](api-script-structure.md#script-folder-files) (`<LanguageCode>.ts`) and
|
|
183
|
+
`SwitchScriptTool --generate-translations` in [api-tooling.md](api-tooling.md).
|
|
184
|
+
- [ ] **The app's own translations are limited to the six Switch UI languages** (English, French,
|
|
185
|
+
German, Italian, Chinese, Japanese); other languages are not accepted for the app itself. The
|
|
186
|
+
separate Appstore *documentation* may be supplied in additional languages, since it isn't
|
|
187
|
+
generated through the SDK.
|
|
188
|
+
- [ ] **Translations must be complete, and logging must go through the translation mechanism.** A
|
|
189
|
+
partially-translated app (some strings translated, others not) is not acceptable — every
|
|
190
|
+
user-facing message needs an entry in each shipped language file, and log calls must go through
|
|
191
|
+
that mechanism rather than hardcoding English text that bypasses it. Note that
|
|
192
|
+
`Switch.tr()` extraction is static and silently skips anything that isn't a plain string literal
|
|
193
|
+
— see [api-switch.md § Translation extraction rules](api-switch.md#translation-extraction-rules).
|
|
194
|
+
Check the generated `.ts` files rather than assuming.
|
|
195
|
+
|
|
196
|
+
### Icon
|
|
197
|
+
|
|
198
|
+
- [ ] **32×32 PNG, RGB, transparent background**, attached as the app icon. This is what appears in
|
|
199
|
+
the Elements pane and in flows.
|
|
200
|
+
- [ ] **A separate 200×200 version is supplied to Enfocus** for the Appstore listing — it is not
|
|
201
|
+
part of the pack.
|
|
202
|
+
|
|
203
|
+
### Extra files
|
|
204
|
+
|
|
205
|
+
- [ ] **macOS Mach-O binaries in extra files (`Resources/`) must be universal.** Any bundled macOS
|
|
206
|
+
application, framework bundle, executable, or dynamic library must include both `x86_64` and
|
|
207
|
+
`arm64` architectures. Relying on Rosetta 2 costs performance and isn't a long-term option.
|
|
208
|
+
- [ ] **macOS Mach-O binaries in extra files must be signed and notarized.** An unsigned or
|
|
209
|
+
incorrectly signed executable or dynamic library will fail Appstore review. At minimum, sign with
|
|
210
|
+
hardened runtime enabled and a secure timestamp; verify with `codesign -dv <file>` and check the
|
|
211
|
+
output contains a `Timestamp` line and the `runtime` flag on the `CodeDirectory` line.
|
|
212
|
+
- [ ] **Extra files must not change at runtime.** Don't place files the script might modify or
|
|
213
|
+
regenerate at runtime — license files included — inside the app's own package folder. Switch
|
|
214
|
+
validates the app package's signature, and content that changes after signing fails that
|
|
215
|
+
validation, causing Switch to remove the app. Write runtime-mutable data (temp files, caches,
|
|
216
|
+
generated output) outside the app folder — see
|
|
217
|
+
[api-job-patterns.md § Temp file cleanup](api-job-patterns.md#temp-file-cleanup).
|
|
218
|
+
- [ ] Find bundled files at runtime with `flowElement.getPluginResourcesPath()` — see
|
|
219
|
+
[api-flow-element.md](api-flow-element.md).
|
|
220
|
+
|
|
221
|
+
### Source and review hygiene
|
|
222
|
+
|
|
223
|
+
- [ ] **Comments in the source are in English**, so Enfocus reviewers can read them.
|
|
224
|
+
- [ ] **No malicious or unrelated payload** — nothing that harms the user's machine or installs
|
|
225
|
+
additional software.
|
|
226
|
+
- [ ] **No Oracle JRE embedded**, in a script or an app, for licensing reasons — see
|
|
227
|
+
[api-script-structure.md § Script folder files](api-script-structure.md#script-folder-files).
|
|
228
|
+
- [ ] **Automating a third-party application doesn't breach that application's licence.** Some
|
|
229
|
+
vendors' terms explicitly exclude automation; check before building.
|
|
230
|
+
|
|
231
|
+
### What review does and doesn't cover
|
|
232
|
+
|
|
233
|
+
Enfocus verifies that the app loads correctly and becomes available as a flow element, and checks
|
|
234
|
+
the items above. It does **not** test that the app works — functional correctness, error handling,
|
|
235
|
+
code structure and naming are the app creator's responsibility, though good practice in all of them
|
|
236
|
+
is assumed. Items marked as rejection-triggers in the SDK's own checklist are the identity,
|
|
237
|
+
password, icon, signing and architecture ones above.
|
|
238
|
+
|
|
239
|
+
Budget roughly **10 business days** for a review. An unsigned app only loads in Switch on the
|
|
240
|
+
machine that created it, which is what makes local testing possible before submission; once signed
|
|
241
|
+
it loads anywhere. Apps require Switch 13.1 or later.
|
|
@@ -86,6 +86,16 @@ Called when a job arrives. Must eventually call a `job.sendTo*()` or `job.fail()
|
|
|
86
86
|
[api-script-declaration.md](api-script-declaration.md#built-in-elementfields). Never leave an empty
|
|
87
87
|
`jobArrived` or `timerFired` in the script — remove the function entirely if it does nothing.
|
|
88
88
|
|
|
89
|
+
**Gotcha: a flow restart replays every queued job through `jobArrived` again.** This includes a job
|
|
90
|
+
whose real processing was deferred elsewhere, such as a job registered in global data and actually
|
|
91
|
+
handled later in `timerFired`. `jobArrived` does not skip a job just because it was already
|
|
92
|
+
registered on a previous run; if the element still has a large backlog queued when the flow
|
|
93
|
+
restarts, every one of those jobs fires `jobArrived` again, and working through a long backlog this
|
|
94
|
+
way can take a long time even when each invocation only needs to recognize the job as already
|
|
95
|
+
registered and return. A script that defers processing this way must check global data at the top
|
|
96
|
+
of `jobArrived` and return immediately for a job already registered there, rather than assuming
|
|
97
|
+
`jobArrived` fires exactly once per job.
|
|
98
|
+
|
|
89
99
|
```ts
|
|
90
100
|
async function abort(s: Switch, flowElement: FlowElement, job: Job, abortData: any): Promise<void>
|
|
91
101
|
```
|
|
@@ -1,13 +1,29 @@
|
|
|
1
1
|
# Execution Environment
|
|
2
2
|
|
|
3
|
-
How the Node.js process a script runs in behaves, beyond the entry point API itself.
|
|
4
|
-
consequences of the host process model
|
|
5
|
-
subtle bugs around state persistence and error handling.
|
|
3
|
+
How the Node.js process a script runs in behaves, beyond the entry point API itself. Apart from the
|
|
4
|
+
execution mode below, these are consequences of the host process model rather than things a script
|
|
5
|
+
configures — understanding them avoids subtle bugs around state persistence and error handling.
|
|
6
|
+
|
|
7
|
+
## Execution modes
|
|
8
|
+
|
|
9
|
+
Set in the XML declaration via SwitchScripter, or by editing it directly (see
|
|
10
|
+
[api-script-declaration.md](api-script-declaration.md#built-in-elementfields)). Applies to all
|
|
11
|
+
instances of the script.
|
|
12
|
+
|
|
13
|
+
**Concurrent** — entry points for the same or different instances may run in parallel. Scripts must
|
|
14
|
+
synchronize access to any shared resources. `NumberOfSlots` is only meaningful in this mode.
|
|
15
|
+
|
|
16
|
+
**Serialized** — entry points within the same **execution group** are never concurrent. Instances
|
|
17
|
+
in different execution groups may still run in parallel.
|
|
18
|
+
|
|
19
|
+
**Execution group** — only relevant for Serialized mode. Should be a reverse-domain string (e.g.
|
|
20
|
+
`com.mycompany.myScript`) to avoid collisions. Defaults to the Script ID if left empty.
|
|
21
|
+
|
|
22
|
+
Neither setting maps to a count of Node.js OS processes — see below.
|
|
6
23
|
|
|
7
24
|
## Two independent concurrency tiers
|
|
8
25
|
|
|
9
|
-
`NumberOfSlots`/`ExecutionGroup` (
|
|
10
|
-
[Execution modes](api-script-structure.md#execution-modes)) and the pool of Node.js processes that
|
|
26
|
+
`NumberOfSlots`/`ExecutionGroup` (above) and the pool of Node.js processes that
|
|
11
27
|
actually run script code are governed completely separately — there is no one-to-one mapping between
|
|
12
28
|
them:
|
|
13
29
|
|
|
@@ -132,3 +132,32 @@ The Node.js executor process is recycled when any of the following thresholds is
|
|
|
132
132
|
On cleanup, any files/folders created in the temp area are removed. Always close file handles and database connections before the entry point returns.
|
|
133
133
|
|
|
134
134
|
See [api-execution-environment.md](api-execution-environment.md) for how this process model affects state persistence and error handling across job invocations.
|
|
135
|
+
|
|
136
|
+
## Driving a third-party CLI application
|
|
137
|
+
|
|
138
|
+
`findApplicationPath` and the `ApplicationPath` property are the legacy-scripting mechanism for
|
|
139
|
+
locating a third-party application; neither is available to Node.js scripts, and `ApplicationPath`
|
|
140
|
+
is a reserved name Switch silently drops from the declaration (see
|
|
141
|
+
[api-script-declaration.md](api-script-declaration.md#built-in-elementfields)). A Node.js script or
|
|
142
|
+
app that shells out to an external binary resolves the path itself, using the following pattern.
|
|
143
|
+
|
|
144
|
+
1. Declare an ordinary custom property for the path under a name of your own — `cliPath`, not
|
|
145
|
+
`ApplicationPath`.
|
|
146
|
+
2. Give it the editor chain `automatic;choosefile;sltextwithvar;scriptexp`, with
|
|
147
|
+
`Default="Automatic"` and `Subtype="automatic"`. The `automatic` literal editor is what lets the
|
|
148
|
+
user express "find it yourself" without typing a magic string, and `getPropertyStringValue()`
|
|
149
|
+
returns the literal `"Automatic"` for it — see
|
|
150
|
+
[api-property-editors.md § Literal editors](api-property-editors.md#literal-editors).
|
|
151
|
+
3. Resolve the path once per flow start, in `flowStartTriggered`: if the property reads
|
|
152
|
+
`Automatic`, run whatever discovery the application needs; otherwise take
|
|
153
|
+
`flowElement.getPropertyStringValue('cliPath')`. Verify the resulting path actually exists, then
|
|
154
|
+
store it in global data at `Scope.FlowElement`. If it doesn't exist, store an empty string
|
|
155
|
+
rather than leaving the tag unset.
|
|
156
|
+
4. In `jobArrived`/`timerFired`, read the path back from global data. An empty string means
|
|
157
|
+
discovery failed: call `flowElement.failProcess()` so the element goes into an error state,
|
|
158
|
+
instead of failing every individual job.
|
|
159
|
+
5. Remove the global data entry in `flowStopTriggered` — global data is never cleaned up
|
|
160
|
+
automatically (see [api-switch.md § Global data](api-switch.md#global-data)).
|
|
161
|
+
|
|
162
|
+
Doing discovery once at flow start rather than per job keeps a filesystem search off the job path,
|
|
163
|
+
and gives the operator a single clear element-level error when the application is missing.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Project Planning
|
|
2
|
+
|
|
3
|
+
A pre-scaffolding checklist for a new script or app. Work through this with the user before
|
|
4
|
+
creating any files. The goal is to make a few decisions deliberately up front, because retrofitting
|
|
5
|
+
them after code exists is expensive: password protection and localization for an app, path handling
|
|
6
|
+
for a second target OS, synchronizing shared-resource access for concurrency, or restructuring entry
|
|
7
|
+
points around a job-processing approach chosen too casually.
|
|
8
|
+
|
|
9
|
+
Two items below are direct questions for the user. The rest are not questions to ask upfront; they
|
|
10
|
+
are checks the agent runs against what's actually being built, raised only when they become
|
|
11
|
+
relevant.
|
|
12
|
+
|
|
13
|
+
## Ask the user directly
|
|
14
|
+
|
|
15
|
+
### 1. Script or App?
|
|
16
|
+
|
|
17
|
+
Ask whether this is for private or internal use (a plain `Script`, distributed freely) or intended
|
|
18
|
+
for the Enfocus Appstore (an `App`). See
|
|
19
|
+
[api-script-structure.md § Script vs App](api-script-structure.md#script-vs-app) for what differs.
|
|
20
|
+
|
|
21
|
+
This answer gates several items below:
|
|
22
|
+
|
|
23
|
+
- **App**: localization, password protection, `Name`-never-changes discipline, `Concurrent`-by-default
|
|
24
|
+
expectation, icon/keywords, and the version-baseline and Appstore-competition checks further down
|
|
25
|
+
all apply. See [api-app-guidelines.md](api-app-guidelines.md) for the full pre-publish checklist,
|
|
26
|
+
most of which is worth designing toward from the start rather than retrofitting later.
|
|
27
|
+
- **Script**: none of the app-only items apply. Keep it simple and don't raise app concerns for a
|
|
28
|
+
plain script.
|
|
29
|
+
|
|
30
|
+
If App, also ask which languages it must support. English is required; more than one language is
|
|
31
|
+
preferable, see [api-app-guidelines.md § Localization](api-app-guidelines.md#localization).
|
|
32
|
+
|
|
33
|
+
### 2. What should job processing look like in their flow?
|
|
34
|
+
|
|
35
|
+
Ask about job handling at a functional level: what should happen when a job arrives, does anything
|
|
36
|
+
need to wait on an external process or resource, could more than one job at a time contend for a
|
|
37
|
+
shared resource. Don't ask the user to pick entry points or connection types directly. Translate the
|
|
38
|
+
answer into a concrete proposal (which entry points, which `sendTo*()` methods, whether `jobArrived`
|
|
39
|
+
alone is enough or work must be deferred to `timerFired`) using
|
|
40
|
+
[api-entry-points.md](api-entry-points.md) and
|
|
41
|
+
[api-job-patterns.md § Sending jobs](api-job-patterns.md#sending-jobs), and be upfront about
|
|
42
|
+
limitations and tradeoffs so the user can make an informed choice, rather than silently picking an
|
|
43
|
+
approach.
|
|
44
|
+
|
|
45
|
+
If the design defers job processing to `timerFired` via global data, say explicitly that a flow
|
|
46
|
+
restart replays every queued job through `jobArrived` again, and the script must recognize and skip
|
|
47
|
+
an already-registered job quickly, or a large backlog is slow to clear, see
|
|
48
|
+
[api-entry-points.md § Job processing](api-entry-points.md#job-processing).
|
|
49
|
+
|
|
50
|
+
## Evaluate and flag, don't ask upfront
|
|
51
|
+
|
|
52
|
+
### Target OS
|
|
53
|
+
|
|
54
|
+
Switch Server runs on Windows and macOS. Default to writing platform-independent code (the `path`
|
|
55
|
+
module, no hardcoded separators, see
|
|
56
|
+
[api-job-patterns.md § Platform-independent paths](api-job-patterns.md#platform-independent-paths))
|
|
57
|
+
without asking. Only raise target OS as an explicit question once the script needs OS-specific code,
|
|
58
|
+
bundles a native binary, or ships a platform-specific package build, since only then does the answer
|
|
59
|
+
change anything.
|
|
60
|
+
|
|
61
|
+
### Switch version baseline (apps only)
|
|
62
|
+
|
|
63
|
+
Once Script vs App is answered as App, ask or infer the oldest Switch version the app must support.
|
|
64
|
+
This sets the Node.js baseline (see
|
|
65
|
+
[api-script-structure.md § Node.js version per Switch version](api-script-structure.md#nodejs-version-per-switch-version))
|
|
66
|
+
and which SwitchScripter build is needed to produce a compatible `.enfpack`. Don't ask this for a
|
|
67
|
+
plain script.
|
|
68
|
+
|
|
69
|
+
### Concurrency
|
|
70
|
+
|
|
71
|
+
Default to `Concurrent` execution; it's the preferred choice for apps per
|
|
72
|
+
[api-app-guidelines.md § Top-level declaration properties](api-app-guidelines.md#top-level-declaration-properties).
|
|
73
|
+
Don't ask the user to choose upfront. Only raise `Serialized`, and explain why, when the design has
|
|
74
|
+
an actual reason to need it: a third-party application or shared resource that can't tolerate
|
|
75
|
+
concurrent access, or an API the script drives that isn't safe to call in parallel. See
|
|
76
|
+
[api-execution-environment.md § Execution modes](api-execution-environment.md#execution-modes).
|
|
77
|
+
|
|
78
|
+
### Native or binary npm dependencies
|
|
79
|
+
|
|
80
|
+
A file-based script or app that ends up on the ESM bundling path cannot use native (binary) Node
|
|
81
|
+
addons at all, see
|
|
82
|
+
[api-execution-environment.md § Native (binary) addons are not supported](api-execution-environment.md#native-binary-addons-are-not-supported).
|
|
83
|
+
If a planned dependency needs one, for example `sharp` or native `sqlite3` bindings, say so before
|
|
84
|
+
the user commits to that library, and suggest a pure JavaScript alternative or a workaround, such as
|
|
85
|
+
shelling out to an external binary, see
|
|
86
|
+
[api-job-patterns.md § Driving a third-party CLI application](api-job-patterns.md#driving-a-third-party-cli-application),
|
|
87
|
+
where one exists.
|
|
88
|
+
|
|
89
|
+
### Appstore competition risk (apps only)
|
|
90
|
+
|
|
91
|
+
An app whose core functionality duplicates an existing Switch module without requiring that module
|
|
92
|
+
risks Appstore rejection. For example, an app that performs database CRUD operations without
|
|
93
|
+
requiring the Database Module competes directly with it. If the planned app looks like it falls into
|
|
94
|
+
this category, say so before significant effort is spent, and suggest either gating the app behind
|
|
95
|
+
the relevant module license or contacting Enfocus to check before proceeding.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
This checklist stops at planning. Once these are answered, move to
|
|
100
|
+
[api-script-structure.md](api-script-structure.md) to scaffold the project.
|
|
@@ -72,39 +72,46 @@ A Switch script project lives in a **script folder** during development and is d
|
|
|
72
72
|
| Distribution | Freely | Enfocus Appstore only |
|
|
73
73
|
| Position in pane | — | Configured via `PositionInElementPane` in XML |
|
|
74
74
|
|
|
75
|
+
## Packing an app
|
|
76
|
+
|
|
77
|
+
An app is produced by SwitchScripter, not by SwitchScriptTool, and the two workflows have to be
|
|
78
|
+
joined up explicitly:
|
|
79
|
+
|
|
80
|
+
- **A script folder can only be typed `Script`.** To ship one as an app, pack it with
|
|
81
|
+
`SwitchScriptTool --pack` first, then open the resulting package in SwitchScripter and change the
|
|
82
|
+
type to `App` before creating the `.enfpack`. If "Create pack" is greyed out, the type is still
|
|
83
|
+
`Script`.
|
|
84
|
+
- **Extra files can't be managed while SwitchScripter is working with a script folder.** Convert to
|
|
85
|
+
a script package first. The conversion is reversible, so the `.pdesc` holding the extra-files
|
|
86
|
+
configuration can be round-tripped back into the script folder and kept in version control.
|
|
87
|
+
- **Creating a pack does not save the script.** Save first, or the pack is built from the last
|
|
88
|
+
saved state.
|
|
89
|
+
- **The pack ID is derived from the script ID and always starts with `com.enfocus.`**, whatever the
|
|
90
|
+
company name and domain in SwitchScripter preferences. To keep it stable across an update, open
|
|
91
|
+
the previous `.enfpack` rather than the `.sscript` — SwitchScripter carries the pack ID over from
|
|
92
|
+
the pack it opened, even if the script ID or domain has since changed.
|
|
93
|
+
|
|
94
|
+
### SwitchScripter and Switch version compatibility
|
|
95
|
+
|
|
96
|
+
An app loads in the Switch version it was built with **or newer**, never older. So the SwitchScripter
|
|
97
|
+
used must be at or below the oldest Switch version you intend to support, and portable
|
|
98
|
+
SwitchScripters exist for older releases specifically to build backwards-compatible apps. There is
|
|
99
|
+
no SwitchScripter for Switch 25.07 or 25.11 — use the Switch 2024 Fall SwitchScripter for those.
|
|
100
|
+
Apps as a concept require Switch 13.1 or later.
|
|
101
|
+
|
|
102
|
+
An unsigned app loads only in Switch on the machine that created it. That's what allows local
|
|
103
|
+
testing before submission; it loads elsewhere only once Enfocus has signed it.
|
|
104
|
+
|
|
75
105
|
## App Store submission guidelines
|
|
76
106
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
- **Prefer more than one language.** An app is preferably localized beyond English — see
|
|
82
|
-
[Translation files](#script-folder-files) (`<LanguageCode>.ts`) and
|
|
83
|
-
`SwitchScriptTool --generate-translations` in [api-tooling.md](api-tooling.md).
|
|
84
|
-
- **Translations must be complete, and logging must go through the translation mechanism.** A
|
|
85
|
-
partially-translated app (some strings translated, others not) is not acceptable — every
|
|
86
|
-
user-facing message needs an entry in each shipped language file, and log calls must go through
|
|
87
|
-
that mechanism (see [api-switch.md](api-switch.md) for `Switch.translate`) rather than
|
|
88
|
-
hardcoding English text that bypasses it.
|
|
89
|
-
- **macOS Mach-O binaries in extra files (`Resources/`) must be universal.** Any bundled macOS
|
|
90
|
-
application, framework bundle, executable, or dynamic library must include both `x86_64` and
|
|
91
|
-
`arm64` architectures.
|
|
92
|
-
- **macOS Mach-O binaries in extra files must be signed.** An unsigned executable or dynamic
|
|
93
|
-
library bundled as an extra file will fail Appstore review.
|
|
94
|
-
- **Extra files must not change at runtime.** Don't place files the script might modify or
|
|
95
|
-
regenerate at runtime inside the app's own package folder — Switch validates the app package's
|
|
96
|
-
signature, and content that changes after signing fails that validation, causing Switch to remove
|
|
97
|
-
the app. Write runtime-mutable data (temp files, caches, generated output) outside the app
|
|
98
|
-
folder — see [api-job-patterns.md § Temp file cleanup](api-job-patterns.md#temp-file-cleanup).
|
|
107
|
+
App-specific submission rules (localization, universal/signed macOS binaries, immutable extra
|
|
108
|
+
files) live in [api-app-guidelines.md § App-only](api-app-guidelines.md#app-only), alongside the
|
|
109
|
+
rest of the pre-publish checklist.
|
|
99
110
|
|
|
100
111
|
## Execution modes
|
|
101
112
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
**Execution group** — only relevant for Serialized mode. Should be a reverse-domain string (e.g. `com.mycompany.myScript`) to avoid collisions. Defaults to the Script ID if left empty.
|
|
109
|
-
|
|
110
|
-
See [api-execution-environment.md](api-execution-environment.md#two-independent-concurrency-tiers) — neither `NumberOfSlots` nor execution group maps to a count of Node.js OS processes; they gate job dispatch on the Switch Server, separate from the pooled executor processes that actually run script code.
|
|
113
|
+
`Concurrent`/`Serialized`, `ExecutionGroup` and `NumberOfSlots` are set in the XML declaration (see
|
|
114
|
+
[api-script-declaration.md](api-script-declaration.md#built-in-elementfields) for the attributes)
|
|
115
|
+
and documented in
|
|
116
|
+
[api-execution-environment.md § Execution modes](api-execution-environment.md#execution-modes),
|
|
117
|
+
which also explains why none of them maps to a count of Node.js processes.
|
|
@@ -73,3 +73,52 @@ Returns the Switch server version as `majorVersion + updateNumber/100` (e.g. Swi
|
|
|
73
73
|
Switch.tr(str: string): string
|
|
74
74
|
```
|
|
75
75
|
Static method. Marks a string literal for translation (used by SwitchScriptTool). Returns the string unchanged at runtime.
|
|
76
|
+
|
|
77
|
+
### Translation extraction rules
|
|
78
|
+
|
|
79
|
+
`SwitchScriptTool --generate-translations` extracts strings by **static analysis of the source
|
|
80
|
+
text**, not by running it. It only ever sees a `Switch.tr(...)` call whose argument is a string
|
|
81
|
+
literal, spelled exactly like that. Anything it can't resolve statically is silently skipped — no
|
|
82
|
+
error, no warning, just a missing entry in the `.ts` file. Always check the generated `.ts` for the
|
|
83
|
+
strings you expected.
|
|
84
|
+
|
|
85
|
+
What extraction handles:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
Switch.tr('single'); // single, double and backtick quotes all work
|
|
89
|
+
Switch.tr(`multi
|
|
90
|
+
line`); // multi-line literals work
|
|
91
|
+
Switch.tr('one ' + 'two '); // concatenation of literals works
|
|
92
|
+
// The tr() call doesn't have to sit at the point of use:
|
|
93
|
+
const s = Switch.tr('Predefined string');
|
|
94
|
+
await job.log(LogLevel.Info, s); // extracted, and translated at runtime
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
What it does **not** handle:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
const t = Switch.tr; // aliasing the function: never extracted
|
|
101
|
+
await job.log(LogLevel.Info, t('nope'));
|
|
102
|
+
|
|
103
|
+
const token = getToken();
|
|
104
|
+
Switch.tr('prefix ' + token); // concatenation with a non-literal
|
|
105
|
+
Switch.tr(`prefix ${token}`); // template interpolation
|
|
106
|
+
Switch.tr('Job ID = ' + job.getId());
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
For dynamic values, mark the template and pass the values as `messageParams` — the template gets
|
|
110
|
+
translated, the substituted values don't:
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
await job.log(LogLevel.Info, Switch.tr('Job ID = %1'), [job.getId()]);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Arguments can themselves be translated by wrapping them separately:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
const mode = readOnly ? Switch.tr('Read-only') : Switch.tr('Regular');
|
|
120
|
+
await job.log(LogLevel.Info, Switch.tr('Job ID = %1, Mode = %2'), [job.getId(), mode]);
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
See [api-logging.md § Placeholders instead of concatenation](api-logging.md#placeholders-instead-of-concatenation)
|
|
124
|
+
for the same rule stated from the logging side.
|
package/docs/switch-scripting.md
CHANGED
|
@@ -11,29 +11,40 @@ Detailed API docs are in `docs/switch-api/`:
|
|
|
11
11
|
|
|
12
12
|
| File | Contents | Load when |
|
|
13
13
|
|---|---|---|
|
|
14
|
+
| `switch-api/api-project-planning.md` | Pre-scaffolding checklist: Script vs App, job-processing approach, target OS, Switch version baseline, concurrency, native/binary npm dependencies, Appstore competition risk | Starting a new script or app, before scaffolding any files |
|
|
14
15
|
| `switch-api/api-entry-points.md` | All entry point signatures, constraints, and when each is called | Scaffolding a script, adding/editing an entry point, or making any edit to main.ts/main.js |
|
|
15
16
|
| `switch-api/api-switch.md` | `Switch` (`s`) — global data, webhooks, abort, server utilities | Using global data, webhooks, abort, or server settings |
|
|
16
17
|
| `switch-api/api-flow-element.md` | `FlowElement` — properties, connections, job creation, logging | Reading properties, creating jobs, logging, connections |
|
|
17
|
-
| `switch-api/api-job.md` | `Job`
|
|
18
|
+
| `switch-api/api-job.md` | `Job` **signatures**: routing, file access, child jobs, private data, datasets | Looking up what a `job.*` method takes, returns, or throws |
|
|
18
19
|
| `switch-api/api-connection.md` | `Connection` — type, properties, file count | Routing to specific connections or reading connection properties |
|
|
19
20
|
| `switch-api/api-http.md` | `HttpRequest` / `HttpResponse` + webhook pattern | Handling incoming HTTP webhooks |
|
|
20
21
|
| `switch-api/api-enums.md` | All enums with string values (`LogLevel`, `AccessLevel`, `DatasetModel`, `Scope`, `Priority`, `Connection.Level`, etc.) | Looking up enum values |
|
|
21
22
|
| `switch-api/api-document-classes.md` | `PdfDocument`, `PdfPage`, `ImageDocument`, `XmlDocument`, `XmpDocument` — read-only file introspection | Inspecting PDF, image, XML, or XMP file contents |
|
|
22
|
-
| `switch-api/api-script-structure.md` |
|
|
23
|
-
| `switch-api/api-tooling.md` | SwitchScriptTool commands,
|
|
23
|
+
| `switch-api/api-script-structure.md` | What files a script folder contains, `manifest.xml` format, Node.js version per Switch release, Script vs App | Setting up a new script project, or converting a Script to an App |
|
|
24
|
+
| `switch-api/api-tooling.md` | SwitchScriptTool commands and install paths, folder vs `.sscript` trade-offs, deployment | Running SwitchScriptTool: transpiling, packing, unpacking, or deploying |
|
|
24
25
|
| `switch-api/api-debugging.md` | Enabling debug mode in Switch Designer, debuggable entry points, VS Code attach | Debugging a script |
|
|
25
26
|
| `switch-api/api-vscode.md` | Type declarations, tsconfig for TypeScript 6, ESLint rules | Setting up VS Code or fixing type errors |
|
|
26
27
|
| `switch-api/api-script-declaration.md` | XML declaration reference: properties, connections, execution config — agents may edit this file directly | Understanding, adding, or editing script properties/connections/execution config |
|
|
27
28
|
| `switch-api/api-property-editors.md` | Property editor types, string return values, literal editors, dropdowns | Defining property editors in XML or reading property values in code |
|
|
28
|
-
| `switch-api/api-job-patterns.md` |
|
|
29
|
-
| `switch-api/api-execution-environment.md` |
|
|
29
|
+
| `switch-api/api-job-patterns.md` | `Job` **rules and gotchas**: file access semantics, temp cleanup, which `sendTo*()` suits which connection type, dataset/child ordering, executor limits | Writing or reviewing job-handling code. Pair with `api-job.md` when you also need signatures |
|
|
30
|
+
| `switch-api/api-execution-environment.md` | Execution modes (`Concurrent`/`Serialized`, `ExecutionGroup`, `NumberOfSlots`), process/concurrency model, state persistence across job invocations, unhandled-rejection behavior, npm/native module constraints | Choosing or changing an execution mode, relying on module-level state across jobs, handling errors/rejections, or using third-party npm packages |
|
|
30
31
|
| `switch-api/api-logging.md` | Log level semantics, logging practice, `console.log` limitation, common gotchas | Adding or reviewing `job.log()`/`flowElement.log()`/`job.fail()`/`failProcess()` calls |
|
|
31
32
|
| `switch-api/api-logs-and-dataroot.md` | Locating the Application Data Root, querying `ServerLogs.db3` directly | Diagnosing or validating a script from its actual log output rather than by reading the code |
|
|
32
|
-
| `switch-api/api-app-guidelines.md` | Pre-publish checklist for Appstore apps: property naming/tooltips/editors, entry point and sendTo consistency, logging quality, packaging | Preparing a script for publication as an app, or reviewing one against Appstore submission criteria |
|
|
33
|
+
| `switch-api/api-app-guidelines.md` | Pre-publish checklist for Appstore apps: property naming/tooltips/editors, entry point and sendTo consistency, logging quality, packaging, and the app-only submission rules (localization, signed universal macOS binaries) | Preparing a script for publication as an app, or reviewing one against Appstore submission criteria |
|
|
33
34
|
|
|
34
35
|
## Key rules
|
|
36
|
+
- Before scaffolding a new script or app, work through `switch-api/api-project-planning.md` with the user.
|
|
35
37
|
- Always consult the API reference files above before writing or modifying script code.
|
|
36
|
-
-
|
|
38
|
+
- To find documented behavioural pitfalls before writing code in an area, grep `docs/switch-api/`
|
|
39
|
+
for `known issue`, `gotcha`, `quirk`, `caveat` (case-insensitive) — every documented pitfall uses
|
|
40
|
+
one of these four terms.
|
|
41
|
+
- Do not `export` entry point functions. Declare them with the literal `function` keyword at top
|
|
42
|
+
level — arrow functions, `exports.name = ...`, and class methods are invisible to Switch.
|
|
43
|
+
- Switch discovers entry points with a regex, not a parser. Never write a string literal whose
|
|
44
|
+
content ends with a backslash, a regex literal, or division outside the plain `word / word`
|
|
45
|
+
shape — each silently deletes a span of real code, and every entry point inside that span
|
|
46
|
+
disappears with no error anywhere. Read `switch-api/api-entry-points.md` §
|
|
47
|
+
Entry-point scanner constraints before editing `main.ts`/`main.js`.
|
|
37
48
|
- Every `jobArrived` invocation must end with exactly one `job.sendTo*()` or `job.fail()` call — either in the same invocation or deferred to `timerFired` via job information stored in global data.
|
|
38
49
|
- Use `AccessLevel.ReadOnly` for `job.get()` unless the file content will be modified.
|
|
39
50
|
- Use VS Code snippets (`.vscode/switch.code-snippets`, prefix `switch…`) to scaffold entry points.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enfocussw/switch-scripting-context",
|
|
3
|
-
"version": "25.11.0-beta.
|
|
3
|
+
"version": "25.11.0-beta.14",
|
|
4
4
|
"description": "AI coding assistant context for Enfocus Switch scripting (Node.js/TypeScript)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"switch",
|
|
@@ -27,14 +27,17 @@
|
|
|
27
27
|
"docs/",
|
|
28
28
|
"!docs/superpowers",
|
|
29
29
|
"!docs/temp",
|
|
30
|
+
"!docs/adr",
|
|
30
31
|
"CHANGELOG.md"
|
|
31
32
|
],
|
|
32
33
|
"scripts": {
|
|
33
34
|
"build": "tsc -p tsconfig.json",
|
|
34
35
|
"build:test": "tsc src/init.test.ts --outDir dist --target ES2020 --module commonjs --lib ES2020 --types node --strict --esModuleInterop --skipLibCheck",
|
|
35
|
-
"test": "npm run build && npm run build:test && node dist/init.test.js",
|
|
36
|
-
"prepack": "npm run build",
|
|
37
|
-
"postpack": "node -e \"const fs=require('fs');const version=process.env.npm_package_version;const scoped=process.env.npm_package_name.replace(/^@/,'').replace('/','-')+'-'+version+'.tgz';const unscoped=process.env.npm_package_name.replace(/^@[^/]+\\//,'')+'-'+version+'.tgz';if(scoped!==unscoped&&fs.existsSync(scoped))fs.renameSync(scoped,unscoped);\""
|
|
36
|
+
"test": "npm run build && npm run build:test && node dist/init.test.js && node scripts/check-prose.js && node scripts/check-gotcha-tags.js",
|
|
37
|
+
"prepack": "npm run build && node scripts/readme-links.js --publish",
|
|
38
|
+
"postpack": "node scripts/readme-links.js --restore && node -e \"const fs=require('fs');const version=process.env.npm_package_version;const scoped=process.env.npm_package_name.replace(/^@/,'').replace('/','-')+'-'+version+'.tgz';const unscoped=process.env.npm_package_name.replace(/^@[^/]+\\//,'')+'-'+version+'.tgz';if(scoped!==unscoped&&fs.existsSync(scoped))fs.renameSync(scoped,unscoped);\"",
|
|
39
|
+
"lint:prose": "node scripts/check-prose.js",
|
|
40
|
+
"lint:gotchas": "node scripts/check-gotcha-tags.js"
|
|
38
41
|
},
|
|
39
42
|
"author": "Sam Wallace",
|
|
40
43
|
"license": "ISC",
|