{"id":34753245,"url":"https://github.com/anikitenko/fdo-sdk","last_synced_at":"2026-04-02T18:02:11.591Z","repository":{"id":276341297,"uuid":"928997560","full_name":"anikitenko/fdo-sdk","owner":"anikitenko","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-24T21:47:00.000Z","size":1248,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-26T01:52:02.939Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anikitenko.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-02-07T16:11:56.000Z","updated_at":"2026-03-24T21:46:58.000Z","dependencies_parsed_at":"2025-02-07T17:24:18.747Z","dependency_job_id":"0d9f808f-e886-45ed-aa9c-4d28a90cf514","html_url":"https://github.com/anikitenko/fdo-sdk","commit_stats":null,"previous_names":["anikitenko/fdo-sdk"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/anikitenko/fdo-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anikitenko%2Ffdo-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anikitenko%2Ffdo-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anikitenko%2Ffdo-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anikitenko%2Ffdo-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anikitenko","download_url":"https://codeload.github.com/anikitenko/fdo-sdk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anikitenko%2Ffdo-sdk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31312744,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-25T05:27:22.052Z","updated_at":"2026-04-02T18:02:11.566Z","avatar_url":"https://github.com/anikitenko.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SDK for FlexDevOPs Application modules\n\n## Overview\n\nThe FDO SDK provides a toolkit for building application modules (plugins) for the FlexDevOps (FDO) desktop application ecosystem.\n\nThe important runtime detail is that FDO plugins do not render by dropping raw HTML directly into the host DOM. A plugin's `render()` output is consumed by the FDO iframe host pipeline, transformed, and mounted inside a React-hosted sandboxed iframe. In practice, the SDK's DOM helpers generate JSX-like UI strings for that host pipeline.\n\nPlugin development therefore spans two different runtimes:\n\n- Plugin backend/runtime: your plugin class, handlers, storage, logging, and initialization run in the plugin process.\n- Plugin UI/runtime: rendered UI code runs inside the sandboxed iframe host, where FDO injects browser-side helpers and selected UI libraries.\n\nThe supported lifecycle contract is synchronous:\n\n- `init()` performs setup\n- `render()` returns a UI string\n- `renderOnLoad()` optionally returns an on-load string\n- the SDK serializes those values for host transport separately\n\nPlugin metadata is also part of the host contract. In particular, `metadata.icon` must be a valid BlueprintJS v6 icon name because FDO uses BlueprintJS v6 in the host application.\n\nFor the detailed render/runtime contract, see [docs/RENDER_RUNTIME_CONTRACT.md](./docs/RENDER_RUNTIME_CONTRACT.md).\n\n## Features\n\n### DOM Element Generation\n\nThe SDK provides extensive DOM element creation capabilities through specialized classes:\n\n- **DOMTable**: Create HTML tables with thead, tbody, tfoot, tr, th, td, and caption elements\n- **DOMMedia**: Create media elements including images with accessibility support\n- **DOMSemantic**: Create semantic HTML5 elements (article, section, nav, header, footer, aside, main)\n- **DOMNested**: Create container elements including ordered lists (ol), definition lists (dl, dt, dd), and more\n- **DOMInput**: Create form inputs including select dropdowns with options and optgroups\n- **DOMText**: Create text elements (headings, paragraphs, spans, etc.)\n- **DOMButton**: Create button elements with event handlers\n- **DOMLink**: Create anchor elements\n- **DOMMisc**: Create miscellaneous elements like horizontal rules\n\nAll DOM classes support:\n- Custom CSS styling via goober CSS-in-JS in the iframe UI runtime\n- Custom classes and inline styles\n- Custom HTML attributes\n- Event handlers\n- Accessibility attributes\n\n### Plugin Framework\n\n- **FDO_SDK Base Class**: Abstract base class with lifecycle hooks (init, render)\n- **IPC Communication**: Message-based communication between plugin workers and main application\n- **Data Persistence**: Plugin-scoped storage backends (in-memory, JSON file-based)\n- **Capability-Gated Integration**: Host-granted capabilities for privileged SDK paths\n- **Contract Validation**: Runtime validators for metadata, host/UI envelopes, and privileged action payloads\n\n### Injected Libraries\n\nThe FDO application injects several helper functions and UI libraries into the iframe UI runtime:\n\n- **CSS Frameworks**: Pure CSS, Notyf notifications, Highlight.js themes\n- **JavaScript Libraries**: FontAwesome icons, Split Grid, Highlight.js, Notyf, ACE Editor, Goober (CSS-in-JS)\n- **Helper Functions**: Backend communication, DOM utilities, event management\n\nThese injected globals are not guaranteed in backend/bootstrap/error-fallback paths. For complete documentation on available libraries and usage examples, see [Injected Libraries Documentation](./docs/INJECTED_LIBRARIES.md).\n\n## Getting Started\n\n### Installation\n\n```bash\nnpm install @anikitenko/fdo-sdk\n```\n\nThis package is intended for FDO plugin development. Import the root package entry from TypeScript plugin code:\n\n```typescript\nimport { FDO_SDK, FDOInterface, PluginMetadata } from \"@anikitenko/fdo-sdk\";\n```\n\nDistribution mode:\n\n- The published runtime artifact is Node/CommonJS-oriented (`dist/fdo-sdk.bundle.js`).\n- The package does not expose a browser-global SDK contract; FDO host/runtime wiring is the supported path.\n- `electron` is declared as a peer dependency (not bundled as an SDK runtime dependency).\n- `docs/` and `examples/` are included in the published package for offline reference.\n\n### Creating a Plugin\n\n```typescript\nimport { FDO_SDK, FDOInterface, PluginMetadata } from \"@anikitenko/fdo-sdk\";\n\nexport default class MyPlugin extends FDO_SDK implements FDOInterface {\n    private readonly _metadata: PluginMetadata = {\n        name: \"My Plugin\",\n        version: \"1.0.0\",\n        author: \"Your Name\",\n        description: \"Plugin description\",\n        icon: \"cog\"\n    };\n\n    get metadata(): PluginMetadata {\n        return this._metadata;\n    }\n\n    init(): void {\n        this.log(\"MyPlugin initialized!\");\n    }\n\n    render(): string {\n        return `\u003cdiv\u003eHello World\u003c/div\u003e`;\n    }\n}\n\nnew MyPlugin();\n```\n\n### Example Usage\n\nSee `examples/example_plugin.ts` for a basic plugin example.\n\nSee `examples/dom_elements_plugin.ts` for comprehensive examples of using the new DOM element creation capabilities including tables, media, semantic HTML, lists, and form controls.\n\nSee `examples/08-privileged-actions-plugin.ts` for host privileged action request flow (`createBackendReq`) with correlation IDs and stable response envelope handling.\n\n## Capability And Privileged Actions Model\n\nThe SDK uses explicit host-granted capabilities from `PLUGIN_INIT.content.capabilities` (validated at runtime).\n\nCore capabilities:\n\n- `storage.json` - required for `PluginRegistry.useStore(\"json\")`\n- `sudo.prompt` - required for `runWithSudo(...)`\n- `system.hosts.write` - required for host-mediated hosts updates and scoped privileged fs API\n- `system.fs.scope.\u003cscope-id\u003e` - host-defined scoped permission for `system.fs.mutate`\n\nPrivileged action contracts:\n\n- `system.hosts.write`\n- `system.fs.mutate`\n\nPublic helpers exported from root package:\n\n- `validateHostPrivilegedActionRequest(...)`\n- `createHostsWriteActionRequest(...)`\n- `createFilesystemMutateActionRequest(...)`\n- `createFilesystemScopeCapability(...)`\n\nDesign rule:\n\n- plugin runtime filesystem writes remain constrained by host policy (`PLUGIN_HOME`)\n- external privileged writes must be host-mediated, scoped, and auditable\n\n## Storage Notes\n\n- `PluginRegistry.useStore(\"default\")` returns an in-memory store scoped to the active plugin.\n- `PluginRegistry.useStore(\"json\")` returns a JSON-backed store scoped to the active plugin.\n- JSON persistence now requires an explicit storage root from the host via `PluginRegistry.configureStorage({ rootDir })` or the `FDO_SDK_STORAGE_ROOT` environment variable.\n- If no storage root is configured, requesting the JSON store throws instead of silently writing to `process.cwd()`.\n\n## Logging Notes\n\n- Log files are written under a configurable root directory via `FDO_SDK_LOG_ROOT` (or fallback `./logs`).\n- Logs are namespaced by plugin scope in per-plugin subdirectories.\n- Lifecycle/IPC logs now include structured event fields and correlation IDs for host-side aggregation.\n\nPlugin author logging API:\n\n- `this.log(message)` basic log entry\n- `this.info(message, ...meta)` info log\n- `this.warn(message, ...meta)` warning log\n- `this.debug(message, ...meta)` debug log\n- `this.verbose(message, ...meta)` verbose log\n- `this.silly(message, ...meta)` low-priority trace log\n- `this.error(error)` error log\n- `this.event(name, payload)` structured event log, returns a correlation ID\n\nExample:\n\n```typescript\ninit(): void {\n  this.info(\"Plugin init started\", { plugin: this.metadata.name });\n  const correlationId = this.event(\"plugin.init.custom\", { phase: \"start\" });\n  this.debug(\"Custom init event emitted\", { correlationId });\n}\n```\n\n## Host Diagnostics Notes\n\n- The SDK exposes a reserved diagnostics handler: `PluginRegistry.DIAGNOSTICS_HANDLER` (`\"__sdk.getDiagnostics\"`).\n- Hosts can query runtime health/capabilities/notifications via a `UI_MESSAGE` request without adding custom plugin handlers.\n- Diagnostics include capability grant and usage/denial counters for permission auditing.\n\nExample host request payload:\n\n```typescript\n{\n  message: \"UI_MESSAGE\",\n  content: {\n    handler: \"__sdk.getDiagnostics\",\n    content: { notificationsLimit: 20 }\n  }\n}\n```\n\n## Development\n\n### Building\n\n```bash\nnpm run build        # Build webpack bundle and emit TypeScript declarations\nnpm run build:bundle # Build runtime bundle only\nnpm run build:types  # Generate TypeScript declarations only\nnpm run verify:pack  # Verify declaration artifacts and npm pack contents\n```\n\nBuild artifacts required for publish:\n\n- `dist/fdo-sdk.bundle.js`\n- `dist/dom-metadata.json`\n- `dist/@types/**` (including `dist/@types/index.d.ts`)\n\n### Testing\n\n```bash\nnpm test             # Run Vitest tests\nnpm run test:coverage # Run tests with coverage report\nnpm run coverage:open # Open coverage report in browser\n```\n\n### Publishing\n\nThe package includes strict verification gates before publishing:\n\n- `prepack` runs `build` and `verify:types:local`\n- `prepublishOnly` runs tests, example type checks, build, and `verify:pack`\n\n`verify:pack` fails if:\n\n- `dist/@types/index.d.ts` is missing\n- no declaration files are present under `dist/@types/`\n- `package.json.types` or `exports[\".\"].types` do not resolve to existing files\n- `npm pack --dry-run --json` does not include declaration files\n\n#### Release Automation\n\n- CI (`.github/workflows/ci.yml`) runs on PRs and on pushes to `main`.\n- Release automation (`.github/workflows/release-please.yml`) runs on `main` and:\n  - opens/updates a release PR with version and changelog changes\n  - creates a `v*` git tag when that release PR is merged\n- `CHANGELOG.md` is updated automatically by release-please during release PR updates.\n- Publish (`.github/workflows/publish.yml`) runs on `v*` tag push and publishes to npm with provenance.\n\nTypical fully automated flow:\n\n1. Merge feature/fix PRs to `main`.\n2. Merge the generated release PR.\n3. Tag-triggered publish runs automatically.\n\nManual fallback flow:\n\n```bash\nnpm version patch\ngit push origin main --follow-tags\n```\n\n## Documentation\n\n- Full API documentation is available in the TypeScript declaration files\n- All public methods include JSDoc comments with usage examples\n- See the `examples/` directory for working plugin implementations\n- See [docs/RENDER_RUNTIME_CONTRACT.md](./docs/RENDER_RUNTIME_CONTRACT.md) for backend-vs-iframe runtime rules and render pipeline expectations\n- See [docs/ARCHITECTURE.md](./docs/ARCHITECTURE.md) for SDK runtime/lifecycle/message/storage architecture\n- See [docs/BUNDLE_BOUNDARY_REVIEW.md](./docs/BUNDLE_BOUNDARY_REVIEW.md) for current FDO-aligned dependency/bundle boundary decisions\n- See [docs/API_STABILITY.md](./docs/API_STABILITY.md) for stable vs internal API rules and semver expectations\n- See [docs/SAFE_PLUGIN_AUTHORING.md](./docs/SAFE_PLUGIN_AUTHORING.md) for backend/UI/runtime-safe authoring practices, logging, and storage usage\n- See [docs/EXTENSION_POINTS.md](./docs/EXTENSION_POINTS.md) for supported plugin extension points and anti-patterns\n- See [docs/HOST_PRIVILEGED_ACTIONS_CONTRACT.md](./docs/HOST_PRIVILEGED_ACTIONS_CONTRACT.md) for privileged action request/response contracts, scope model, and host enforcement guidance\n\n## License\n\nISC\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanikitenko%2Ffdo-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanikitenko%2Ffdo-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanikitenko%2Ffdo-sdk/lists"}