@aglyn/aglyn 1.0.0-beta.220 → 1.0.0-beta.221

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/package.json +11 -11
  2. package/src/lib/app-utils/docs-help.generated.d.ts +2 -2
  3. package/src/lib/app-utils/docs-help.generated.js +3 -0
  4. package/src/lib/app-utils/docs-help.generated.js.map +1 -1
  5. package/src/lib/app-utils/docs-index.generated.js +9 -2
  6. package/src/lib/app-utils/docs-index.generated.js.map +1 -1
  7. package/src/lib/app-utils/health-report.js +22 -0
  8. package/src/lib/app-utils/health-report.js.map +1 -1
  9. package/src/lib/app-utils/leaving-notice.d.ts +96 -0
  10. package/src/lib/app-utils/leaving-notice.js +157 -0
  11. package/src/lib/app-utils/leaving-notice.js.map +1 -0
  12. package/src/lib/app-utils/operator-alerts.js +17 -0
  13. package/src/lib/app-utils/operator-alerts.js.map +1 -1
  14. package/src/lib/app-utils/screen-link-context-value.d.ts +7 -0
  15. package/src/lib/app-utils/screen-link-context-value.js.map +1 -1
  16. package/src/lib/app-utils/screen-link-context.js +14 -2
  17. package/src/lib/app-utils/screen-link-context.js.map +1 -1
  18. package/src/lib/app-utils/screen-route.d.ts +3 -0
  19. package/src/lib/app-utils/screen-route.js +6 -1
  20. package/src/lib/app-utils/screen-route.js.map +1 -1
  21. package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +6 -0
  22. package/src/lib/plugin-manager/first-party-plugins.generated.js +4 -0
  23. package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
  24. package/src/lib/plugin-manager/plugin-server-steps.d.ts +170 -0
  25. package/src/lib/plugin-manager/plugin-server-steps.js +116 -0
  26. package/src/lib/plugin-manager/plugin-server-steps.js.map +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/plugin-server-steps.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getRegisteringPluginId } from '../app-utils/registering-plugin'\nimport { PLUGIN_SERVER_STEPS_DECLARED } from './first-party-plugins.generated'\nimport { runPluginDeclarationsRepair } from './plugin-declarations-repair'\n\n/**\n * A SERVER STEP ANOTHER PLUGIN RUNS (AGL-3080).\n *\n * An interaction's steps are the platform's client steps plus whatever steps\n * the plugins add (`site-interactions.ts`), and every step that is not a\n * client step is the server's to run. The plugin that runs a server run — the\n * automation engine — knows its own steps. A step that acts on ANOTHER\n * plugin's records is that plugin's: writing a dataset row is the data\n * plugin's, moving a contact's stage is the CRM's. The engine used to carry\n * each of those writes itself, which made it the keeper of every plugin's\n * storage.\n *\n * So the plugin that owns a step REGISTERS ITS EXECUTOR here, by step type,\n * and the engine hands it the step when a run reaches one. The engine keeps\n * what every step shares — the step's guard, the run's order, its history,\n * the nesting cap — and the executor does the step's one write. Neither\n * imports the other: both meet at this module, which names no plugin, so a\n * marketplace plugin adds a step the same way a first-party one does.\n *\n * ## Declared, then registered — and an absent executor is refused\n *\n * The executor is registered from the owning plugin's `serverDeclarations`\n * entry, which every app runs at boot. An empty registry must not read as an\n * answer: a step whose executor never registered would otherwise fall through\n * the engine as a step nobody runs, and a run history would say the record\n * was written when it was not.\n *\n * So a first-party plugin also DECLARES the steps it runs, under\n * `serverSteps` in `plugins.config.json`, compiled into core. The three cases\n * are kept apart:\n *\n * - registered — the executor runs the step, declared or not (a marketplace\n * plugin's steps are registered and never compiled);\n * - declared and NOT registered — the boot failed. The app's declarations\n * step is run again ({@link runPluginDeclarationsRepair}); if the executor\n * is still missing, {@link pluginServerStepExecutor} THROWS\n * {@link ServerStepUnavailableError}, which the engine records as the\n * step's failure;\n * - neither — no plugin runs the type, and the caller answers `null` as it\n * would for any step it does not know.\n *\n * A type the engine runs itself never reaches this registry, so a\n * registration cannot replace one of the engine's own steps.\n *\n * Reached by path, never through a barrel: only server code asks.\n */\n\n/** The automation a step belongs to, as its history and its records name it. */\nexport interface ServerStepRunRef {\n /** Which kind of automation is running — the engine's own vocabulary. */\n kind: string\n /** The automation's document id. */\n id: string\n /** Its name at the time of the run. */\n name: string\n}\n\n/** One step, handed to the plugin that runs it. */\nexport interface ServerStepRequest {\n /** The site the run is on. Every write is scoped to what this site may see. */\n hostId: string\n /**\n * The owning organization's billing document, already read by the gate\n * that admitted the run, and its id beside it — so an executor gating on\n * the plan or counting against a cap pays no second read. Null when the\n * site has no resolvable organization, which every gate reads as Free.\n */\n org: unknown\n orgId: string | null\n /** The automation whose step this is. */\n run: ServerStepRunRef\n /** The event the run is answering. */\n event: string\n /** The event's payload: the values a step reads. */\n payload: Record<string, unknown>\n /** The step exactly as it is stored. */\n step: { type: string; [field: string]: unknown }\n}\n\n/**\n * What one step did.\n *\n * Nothing set is a step that did its work. `error` is a step that did not —\n * the run records it and goes on to the next step, so an executor answers a\n * refusal rather than throwing one; a throw is read the same way.\n */\nexport interface ServerStepAnswer {\n /** Why nothing was written, when nothing was — a line of the run history. */\n error?: string\n /** The one fact worth carrying into the run summary: a record's name, a status. */\n detail?: string\n /**\n * An event this step's write earned, for the ENGINE to raise. Not raised\n * by the executor: an automation whose step causes the event it listens\n * for would otherwise run until a meter stopped it, and only the engine\n * holds the nesting cap that stops it first.\n */\n emit?: { event: string; payload: Record<string, unknown> }\n}\n\n/** Runs one step of the types it was registered for. */\nexport type ServerStepExecutor = (request: ServerStepRequest) => Promise<ServerStepAnswer>\n\n/** The compiled declaration: which plugin runs which step type. */\nexport interface ServerStepDeclaration {\n pluginId: string\n /** The stored step `type`. */\n type: string\n}\n\n/** Every server step a first-party plugin declares, in `plugins.config.json` order. */\nexport function declaredServerSteps(): readonly ServerStepDeclaration[] {\n return PLUGIN_SERVER_STEPS_DECLARED\n}\n\n/** The declaration of this step type, or `null` for one no plugin declares. */\nexport function declaredServerStep(type: string): ServerStepDeclaration | null {\n return PLUGIN_SERVER_STEPS_DECLARED.find((declaration) => declaration.type === type) ?? null\n}\n\n/** A registered executor, with the plugin it belongs to. */\nexport interface RegisteredServerStepExecutor {\n pluginId: string\n run: ServerStepExecutor\n}\n\n/**\n * One table per process, on `globalThis` (AGL-3412): the app registers from\n * `instrumentation.ts`, which Next compiles apart from the routes that run\n * steps, and a module-scoped map would be filled in one copy and read empty\n * in the other.\n */\nconst EXECUTORS_KEY = Symbol.for('@aglyn/aglyn:server-step-executors')\n\nconst globalScope = globalThis as typeof globalThis & {\n [EXECUTORS_KEY]?: Map<string, RegisteredServerStepExecutor>\n}\n\nconst executors: Map<string, RegisteredServerStepExecutor> =\n globalScope[EXECUTORS_KEY] ?? (globalScope[EXECUTORS_KEY] = new Map())\n\nconst PLAIN_TYPE = /^[a-z][A-Za-z0-9]*$/\n\n/**\n * Registers the executor of one or more step types. Returns the unregister,\n * which removes each type only while this executor still holds it.\n *\n * The owner is the plugin whose register fn is running, or the `pluginId`\n * passed for a boot declaration, where the loader's marker is not set. A\n * registration with neither is refused; so is a type another plugin declares\n * or already holds, because two executors for one step would each write the\n * other's records. The same plugin registering again replaces its own (a\n * second surface, a repeated boot). Nothing is registered unless every type\n * is accepted.\n */\nexport function registerServerStepExecutor(\n types: readonly string[],\n run: ServerStepExecutor,\n options?: { pluginId?: string },\n): () => void {\n const pluginId = (getRegisteringPluginId() ?? options?.pluginId ?? '').trim()\n if (!pluginId) {\n throw new Error(\n 'a server step executor was registered with no owner: pass { pluginId } ' +\n 'when registering outside a plugin register fn',\n )\n }\n const list = [...new Set(types.map((type) => type.trim()))]\n if (!list.length) throw new Error(`\"${pluginId}\" registered a server step executor for no step type`)\n for (const type of list) {\n if (!PLAIN_TYPE.test(type)) {\n throw new Error(`\"${pluginId}\" registered a server step executor for \"${type}\", which is not a plain step type`)\n }\n const declared = declaredServerStep(type)\n if (declared && declared.pluginId !== pluginId) {\n throw new Error(\n `server step \"${type}\" is declared by \"${declared.pluginId}\"; refused an executor from \"${pluginId}\"`,\n )\n }\n const held = executors.get(type)\n if (held && held.pluginId !== pluginId) {\n throw new Error(\n `server step \"${type}\" already has an executor from \"${held.pluginId}\"; refused \"${pluginId}\"`,\n )\n }\n }\n const entry: RegisteredServerStepExecutor = { pluginId, run }\n for (const type of list) executors.set(type, entry)\n return () => {\n for (const type of list) if (executors.get(type) === entry) executors.delete(type)\n }\n}\n\n/** The executor registered for a step type, with its owner, or `null`. Never repairs. */\nexport function registeredServerStepExecutor(type: string): RegisteredServerStepExecutor | null {\n return executors.get(type) ?? null\n}\n\n/** Only for specs: forgets every registered executor. */\nexport function resetServerStepExecutorsForTests(): void {\n executors.clear()\n}\n\n/**\n * The declared step's executor was not registered, even after the app's\n * declarations step ran again. Its message is the step's line in the run\n * history, so it says what happened in the words a site owner reads.\n */\nexport class ServerStepUnavailableError extends Error {\n constructor(readonly declaration: ServerStepDeclaration) {\n super(\n `the \"${declaration.type}\" step did not run: the plugin that runs it ` +\n `(\"${declaration.pluginId}\") is not loaded on this server`,\n )\n this.name = 'ServerStepUnavailableError'\n }\n}\n\n/**\n * The executor for a step type, for a run that has reached one. See the\n * module note for the three cases: registered answers it, declared but\n * missing throws after the repair has had its turn, and neither answers\n * `null`.\n */\nexport async function pluginServerStepExecutor(\n type: string,\n): Promise<RegisteredServerStepExecutor | null> {\n const registered = executors.get(type)\n if (registered) return registered\n const declared = declaredServerStep(type)\n if (!declared) return null\n try {\n await runPluginDeclarationsRepair()\n } catch (error) {\n console.error('[server-steps] the declarations repair failed', error)\n }\n const repaired = executors.get(type)\n if (!repaired) throw new ServerStepUnavailableError(declared)\n return repaired\n}\n"],"names":["globalScope","getRegisteringPluginId","PLUGIN_SERVER_STEPS_DECLARED","runPluginDeclarationsRepair","declaredServerSteps","declaredServerStep","type","find","declaration","EXECUTORS_KEY","Symbol","for","globalThis","executors","Map","PLAIN_TYPE","registerServerStepExecutor","types","run","options","pluginId","trim","Error","list","Set","map","length","test","declared","held","get","entry","set","delete","registeredServerStepExecutor","resetServerStepExecutorsForTests","clear","ServerStepUnavailableError","name","pluginServerStepExecutor","registered","error","console","repaired"],"mappings":"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"}