every-plugin 2.10.1 → 3.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/every-plugin-serve.mjs +12 -0
- package/bin/every-plugin.mjs +59 -0
- package/dist/_virtual/_rolldown/runtime.cjs +1 -2
- package/dist/build/artifact-names.cjs +119 -0
- package/dist/build/artifact-names.cjs.map +1 -0
- package/dist/build/artifact-names.d.cts +68 -0
- package/dist/build/artifact-names.d.cts.map +1 -0
- package/dist/build/artifact-names.d.mts +68 -0
- package/dist/build/artifact-names.d.mts.map +1 -0
- package/dist/build/artifact-names.mjs +102 -0
- package/dist/build/artifact-names.mjs.map +1 -0
- package/dist/build/contract-types.cjs +89 -0
- package/dist/build/contract-types.cjs.map +1 -0
- package/dist/build/contract-types.mjs +81 -0
- package/dist/build/contract-types.mjs.map +1 -0
- package/dist/build/rspack/build-report-plugin.cjs +37 -0
- package/dist/build/rspack/build-report-plugin.cjs.map +1 -0
- package/dist/build/rspack/build-report-plugin.d.cts +18 -0
- package/dist/build/rspack/build-report-plugin.d.cts.map +1 -0
- package/dist/build/rspack/build-report-plugin.d.mts +18 -0
- package/dist/build/rspack/build-report-plugin.d.mts.map +1 -0
- package/dist/build/rspack/build-report-plugin.mjs +37 -0
- package/dist/build/rspack/build-report-plugin.mjs.map +1 -0
- package/dist/build/rspack/chunk-completeness-plugin.cjs +47 -0
- package/dist/build/rspack/chunk-completeness-plugin.cjs.map +1 -0
- package/dist/build/rspack/chunk-completeness-plugin.mjs +47 -0
- package/dist/build/rspack/chunk-completeness-plugin.mjs.map +1 -0
- package/dist/build/rspack/compose.cjs +69 -0
- package/dist/build/rspack/compose.cjs.map +1 -0
- package/dist/build/rspack/compose.d.cts +20 -0
- package/dist/build/rspack/compose.d.cts.map +1 -0
- package/dist/build/rspack/compose.d.mts +20 -0
- package/dist/build/rspack/compose.d.mts.map +1 -0
- package/dist/build/rspack/compose.mjs +65 -0
- package/dist/build/rspack/compose.mjs.map +1 -0
- package/dist/build/rspack/fix-mf-data-uri-plugin.cjs +11 -11
- package/dist/build/rspack/fix-mf-data-uri-plugin.cjs.map +1 -1
- package/dist/build/rspack/fix-mf-data-uri-plugin.d.cts +2 -0
- package/dist/build/rspack/fix-mf-data-uri-plugin.d.cts.map +1 -1
- package/dist/build/rspack/fix-mf-data-uri-plugin.d.mts +2 -0
- package/dist/build/rspack/fix-mf-data-uri-plugin.d.mts.map +1 -1
- package/dist/build/rspack/fix-mf-data-uri-plugin.mjs +11 -10
- package/dist/build/rspack/fix-mf-data-uri-plugin.mjs.map +1 -1
- package/dist/build/rspack/generated-config.cjs +35 -0
- package/dist/build/rspack/generated-config.cjs.map +1 -0
- package/dist/build/rspack/generated-config.mjs +32 -0
- package/dist/build/rspack/generated-config.mjs.map +1 -0
- package/dist/build/rspack/index.cjs +8 -5
- package/dist/build/rspack/index.d.cts +5 -3
- package/dist/build/rspack/index.d.mts +5 -3
- package/dist/build/rspack/index.mjs +5 -3
- package/dist/build/rspack/module-federation.cjs +2 -2
- package/dist/build/rspack/module-federation.cjs.map +1 -1
- package/dist/build/rspack/module-federation.mjs +1 -1
- package/dist/build/rspack/module-federation.mjs.map +1 -1
- package/dist/build/rspack/plugin.cjs +44 -69
- package/dist/build/rspack/plugin.cjs.map +1 -1
- package/dist/build/rspack/plugin.d.cts +4 -13
- package/dist/build/rspack/plugin.d.cts.map +1 -1
- package/dist/build/rspack/plugin.d.mts +4 -13
- package/dist/build/rspack/plugin.d.mts.map +1 -1
- package/dist/build/rspack/plugin.mjs +44 -69
- package/dist/build/rspack/plugin.mjs.map +1 -1
- package/dist/build/rspack/utils.cjs +7 -5
- package/dist/build/rspack/utils.cjs.map +1 -1
- package/dist/build/rspack/utils.mjs +7 -6
- package/dist/build/rspack/utils.mjs.map +1 -1
- package/dist/build/ui/factory.cjs +88 -0
- package/dist/build/ui/factory.cjs.map +1 -0
- package/dist/build/ui/factory.d.cts +11 -0
- package/dist/build/ui/factory.d.cts.map +1 -0
- package/dist/build/ui/factory.d.mts +11 -0
- package/dist/build/ui/factory.d.mts.map +1 -0
- package/dist/build/ui/factory.mjs +80 -0
- package/dist/build/ui/factory.mjs.map +1 -0
- package/dist/build/ui/generated-config.cjs +118 -0
- package/dist/build/ui/generated-config.cjs.map +1 -0
- package/dist/build/ui/generated-config.d.cts +33 -0
- package/dist/build/ui/generated-config.d.cts.map +1 -0
- package/dist/build/ui/generated-config.d.mts +33 -0
- package/dist/build/ui/generated-config.d.mts.map +1 -0
- package/dist/build/ui/generated-config.mjs +111 -0
- package/dist/build/ui/generated-config.mjs.map +1 -0
- package/dist/build/ui/hash-artifacts-plugin.cjs +61 -0
- package/dist/build/ui/hash-artifacts-plugin.cjs.map +1 -0
- package/dist/build/ui/hash-artifacts-plugin.d.cts +20 -0
- package/dist/build/ui/hash-artifacts-plugin.d.cts.map +1 -0
- package/dist/build/ui/hash-artifacts-plugin.d.mts +20 -0
- package/dist/build/ui/hash-artifacts-plugin.d.mts.map +1 -0
- package/dist/build/ui/hash-artifacts-plugin.mjs +58 -0
- package/dist/build/ui/hash-artifacts-plugin.mjs.map +1 -0
- package/dist/build/ui/index.cjs +90 -0
- package/dist/build/ui/index.cjs.map +1 -0
- package/dist/build/ui/index.d.cts +29 -0
- package/dist/build/ui/index.d.cts.map +1 -0
- package/dist/build/ui/index.d.mts +29 -0
- package/dist/build/ui/index.d.mts.map +1 -0
- package/dist/build/ui/index.mjs +68 -0
- package/dist/build/ui/index.mjs.map +1 -0
- package/dist/build/ui/manifest-plugin.cjs +37 -0
- package/dist/build/ui/manifest-plugin.cjs.map +1 -0
- package/dist/build/ui/manifest-plugin.d.cts +19 -0
- package/dist/build/ui/manifest-plugin.d.cts.map +1 -0
- package/dist/build/ui/manifest-plugin.d.mts +19 -0
- package/dist/build/ui/manifest-plugin.d.mts.map +1 -0
- package/dist/build/ui/manifest-plugin.mjs +37 -0
- package/dist/build/ui/manifest-plugin.mjs.map +1 -0
- package/dist/build/ui/rsbuild-config.cjs +203 -0
- package/dist/build/ui/rsbuild-config.cjs.map +1 -0
- package/dist/build/ui/rsbuild-config.d.cts +45 -0
- package/dist/build/ui/rsbuild-config.d.cts.map +1 -0
- package/dist/build/ui/rsbuild-config.d.mts +45 -0
- package/dist/build/ui/rsbuild-config.d.mts.map +1 -0
- package/dist/build/ui/rsbuild-config.mjs +200 -0
- package/dist/build/ui/rsbuild-config.mjs.map +1 -0
- package/dist/build/ui/stubs.cjs +107 -0
- package/dist/build/ui/stubs.cjs.map +1 -0
- package/dist/build/ui/stubs.d.cts +25 -0
- package/dist/build/ui/stubs.d.cts.map +1 -0
- package/dist/build/ui/stubs.d.mts +25 -0
- package/dist/build/ui/stubs.d.mts.map +1 -0
- package/dist/build/ui/stubs.mjs +106 -0
- package/dist/build/ui/stubs.mjs.map +1 -0
- package/dist/cli.cjs +83 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +6 -0
- package/dist/cli.d.cts.map +1 -0
- package/dist/cli.d.mts +6 -0
- package/dist/cli.d.mts.map +1 -0
- package/dist/cli.mjs +82 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/dev/serve.cjs +390 -0
- package/dist/dev/serve.cjs.map +1 -0
- package/dist/dev/serve.d.cts +23 -0
- package/dist/dev/serve.d.cts.map +1 -0
- package/dist/dev/serve.d.mts +23 -0
- package/dist/dev/serve.d.mts.map +1 -0
- package/dist/dev/serve.mjs +384 -0
- package/dist/dev/serve.mjs.map +1 -0
- package/dist/dev/watch-kill.cjs +39 -0
- package/dist/dev/watch-kill.cjs.map +1 -0
- package/dist/dev/watch-kill.mjs +38 -0
- package/dist/dev/watch-kill.mjs.map +1 -0
- package/dist/effect-helpers.cjs +23 -0
- package/dist/effect-helpers.cjs.map +1 -0
- package/dist/effect-helpers.d.cts +20 -0
- package/dist/effect-helpers.d.cts.map +1 -0
- package/dist/effect-helpers.d.mts +20 -0
- package/dist/effect-helpers.d.mts.map +1 -0
- package/dist/effect-helpers.mjs +22 -0
- package/dist/effect-helpers.mjs.map +1 -0
- package/dist/errors.cjs +49 -69
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +13 -96
- package/dist/errors.d.cts.map +1 -1
- package/dist/errors.d.mts +13 -96
- package/dist/errors.d.mts.map +1 -1
- package/dist/errors.mjs +16 -34
- package/dist/errors.mjs.map +1 -1
- package/dist/identity.cjs +19 -0
- package/dist/identity.cjs.map +1 -0
- package/dist/identity.d.cts +33 -0
- package/dist/identity.d.cts.map +1 -0
- package/dist/identity.d.mts +33 -0
- package/dist/identity.d.mts.map +1 -0
- package/dist/identity.mjs +16 -0
- package/dist/identity.mjs.map +1 -0
- package/dist/index.cjs +8 -5
- package/dist/index.d.cts +8 -6
- package/dist/index.d.mts +8 -6
- package/dist/index.mjs +6 -4
- package/dist/plugin.cjs +12 -26
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +44 -25
- package/dist/plugin.d.cts.map +1 -1
- package/dist/plugin.d.mts +45 -26
- package/dist/plugin.d.mts.map +1 -1
- package/dist/plugin.mjs +15 -29
- package/dist/plugin.mjs.map +1 -1
- package/dist/remote-entry.cjs +103 -0
- package/dist/remote-entry.cjs.map +1 -0
- package/dist/remote-entry.d.cts +53 -0
- package/dist/remote-entry.d.cts.map +1 -0
- package/dist/remote-entry.d.mts +53 -0
- package/dist/remote-entry.d.mts.map +1 -0
- package/dist/remote-entry.mjs +98 -0
- package/dist/remote-entry.mjs.map +1 -0
- package/dist/runtime/errors.cjs +140 -34
- package/dist/runtime/errors.cjs.map +1 -1
- package/dist/runtime/errors.d.cts +42 -7
- package/dist/runtime/errors.d.cts.map +1 -1
- package/dist/runtime/errors.d.mts +42 -7
- package/dist/runtime/errors.d.mts.map +1 -1
- package/dist/runtime/errors.mjs +136 -31
- package/dist/runtime/errors.mjs.map +1 -1
- package/dist/runtime/index.cjs +95 -23
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.d.cts +16 -0
- package/dist/runtime/index.d.cts.map +1 -1
- package/dist/runtime/index.d.mts +16 -0
- package/dist/runtime/index.d.mts.map +1 -1
- package/dist/runtime/index.mjs +98 -26
- package/dist/runtime/index.mjs.map +1 -1
- package/dist/runtime/mf-config.cjs +3 -78
- package/dist/runtime/mf-config.cjs.map +1 -1
- package/dist/runtime/mf-config.d.cts +3 -49
- package/dist/runtime/mf-config.d.cts.map +1 -1
- package/dist/runtime/mf-config.d.mts +3 -49
- package/dist/runtime/mf-config.d.mts.map +1 -1
- package/dist/runtime/mf-config.mjs +5 -78
- package/dist/runtime/mf-config.mjs.map +1 -1
- package/dist/runtime/services/module-federation.service.cjs +63 -12
- package/dist/runtime/services/module-federation.service.cjs.map +1 -1
- package/dist/runtime/services/module-federation.service.d.cts +4 -13
- package/dist/runtime/services/module-federation.service.d.mts +4 -13
- package/dist/runtime/services/module-federation.service.mjs +63 -14
- package/dist/runtime/services/module-federation.service.mjs.map +1 -1
- package/dist/runtime/services/normalize.cjs +2 -22
- package/dist/runtime/services/normalize.d.cts +2 -21
- package/dist/runtime/services/normalize.d.mts +2 -21
- package/dist/runtime/services/normalize.mjs +2 -21
- package/dist/runtime/services/plugin-lifecycle.service.cjs +9 -11
- package/dist/runtime/services/plugin-lifecycle.service.cjs.map +1 -1
- package/dist/runtime/services/plugin-lifecycle.service.d.cts +3 -16
- package/dist/runtime/services/plugin-lifecycle.service.d.mts +3 -16
- package/dist/runtime/services/plugin-lifecycle.service.mjs +10 -13
- package/dist/runtime/services/plugin-lifecycle.service.mjs.map +1 -1
- package/dist/runtime/services/plugin-loader.service.cjs +30 -29
- package/dist/runtime/services/plugin-loader.service.cjs.map +1 -1
- package/dist/runtime/services/plugin-loader.service.d.cts +6 -53
- package/dist/runtime/services/plugin-loader.service.d.mts +6 -53
- package/dist/runtime/services/plugin-loader.service.mjs +29 -30
- package/dist/runtime/services/plugin-loader.service.mjs.map +1 -1
- package/dist/runtime/services/plugin.service.cjs +10 -12
- package/dist/runtime/services/plugin.service.cjs.map +1 -1
- package/dist/runtime/services/plugin.service.d.cts +14 -36
- package/dist/runtime/services/plugin.service.d.cts.map +1 -1
- package/dist/runtime/services/plugin.service.d.mts +14 -36
- package/dist/runtime/services/plugin.service.d.mts.map +1 -1
- package/dist/runtime/services/plugin.service.mjs +14 -18
- package/dist/runtime/services/plugin.service.mjs.map +1 -1
- package/dist/runtime/services/secrets.service.cjs +12 -12
- package/dist/runtime/services/secrets.service.cjs.map +1 -1
- package/dist/runtime/services/secrets.service.d.cts +3 -15
- package/dist/runtime/services/secrets.service.d.mts +3 -15
- package/dist/runtime/services/secrets.service.mjs +12 -13
- package/dist/runtime/services/secrets.service.mjs.map +1 -1
- package/dist/runtime/services/shared-identity.cjs +40 -0
- package/dist/runtime/services/shared-identity.cjs.map +1 -0
- package/dist/runtime/services/shared-identity.mjs +38 -0
- package/dist/runtime/services/shared-identity.mjs.map +1 -0
- package/dist/runtime/validation.cjs +2 -2
- package/dist/runtime/validation.cjs.map +1 -1
- package/dist/runtime/validation.mjs +2 -2
- package/dist/runtime/validation.mjs.map +1 -1
- package/dist/shared-deps-spec.cjs +384 -0
- package/dist/shared-deps-spec.cjs.map +1 -0
- package/dist/shared-deps-spec.d.cts +182 -0
- package/dist/shared-deps-spec.d.cts.map +1 -0
- package/dist/shared-deps-spec.d.mts +182 -0
- package/dist/shared-deps-spec.d.mts.map +1 -0
- package/dist/shared-deps-spec.mjs +368 -0
- package/dist/shared-deps-spec.mjs.map +1 -0
- package/dist/types.d.cts +22 -41
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +22 -41
- package/dist/types.d.mts.map +1 -1
- package/dist/ui/manifest/construct.cjs +268 -0
- package/dist/ui/manifest/construct.cjs.map +1 -0
- package/dist/ui/manifest/construct.d.cts +48 -0
- package/dist/ui/manifest/construct.d.cts.map +1 -0
- package/dist/ui/manifest/construct.d.mts +48 -0
- package/dist/ui/manifest/construct.d.mts.map +1 -0
- package/dist/ui/manifest/construct.mjs +268 -0
- package/dist/ui/manifest/construct.mjs.map +1 -0
- package/dist/ui/manifest/contract.cjs +34 -0
- package/dist/ui/manifest/contract.cjs.map +1 -0
- package/dist/ui/manifest/contract.d.cts +26 -0
- package/dist/ui/manifest/contract.d.cts.map +1 -0
- package/dist/ui/manifest/contract.d.mts +26 -0
- package/dist/ui/manifest/contract.d.mts.map +1 -0
- package/dist/ui/manifest/contract.mjs +26 -0
- package/dist/ui/manifest/contract.mjs.map +1 -0
- package/dist/ui/manifest/descriptor.cjs +64 -0
- package/dist/ui/manifest/descriptor.cjs.map +1 -0
- package/dist/ui/manifest/descriptor.d.cts +60 -0
- package/dist/ui/manifest/descriptor.d.cts.map +1 -0
- package/dist/ui/manifest/descriptor.d.mts +60 -0
- package/dist/ui/manifest/descriptor.d.mts.map +1 -0
- package/dist/ui/manifest/descriptor.mjs +61 -0
- package/dist/ui/manifest/descriptor.mjs.map +1 -0
- package/dist/ui/manifest/generator.cjs +128 -0
- package/dist/ui/manifest/generator.cjs.map +1 -0
- package/dist/ui/manifest/generator.d.cts +41 -0
- package/dist/ui/manifest/generator.d.cts.map +1 -0
- package/dist/ui/manifest/generator.d.mts +41 -0
- package/dist/ui/manifest/generator.d.mts.map +1 -0
- package/dist/ui/manifest/generator.mjs +125 -0
- package/dist/ui/manifest/generator.mjs.map +1 -0
- package/dist/ui/manifest/index.cjs +35 -0
- package/dist/ui/manifest/index.d.cts +9 -0
- package/dist/ui/manifest/index.d.mts +9 -0
- package/dist/ui/manifest/index.mjs +9 -0
- package/dist/ui/manifest/manifest-schema.cjs +97 -0
- package/dist/ui/manifest/manifest-schema.cjs.map +1 -0
- package/dist/ui/manifest/manifest-schema.d.cts +132 -0
- package/dist/ui/manifest/manifest-schema.d.cts.map +1 -0
- package/dist/ui/manifest/manifest-schema.d.mts +132 -0
- package/dist/ui/manifest/manifest-schema.d.mts.map +1 -0
- package/dist/ui/manifest/manifest-schema.mjs +90 -0
- package/dist/ui/manifest/manifest-schema.mjs.map +1 -0
- package/dist/ui/manifest/mount-registry.cjs +52 -0
- package/dist/ui/manifest/mount-registry.cjs.map +1 -0
- package/dist/ui/manifest/mount-registry.d.cts +61 -0
- package/dist/ui/manifest/mount-registry.d.cts.map +1 -0
- package/dist/ui/manifest/mount-registry.d.mts +61 -0
- package/dist/ui/manifest/mount-registry.d.mts.map +1 -0
- package/dist/ui/manifest/mount-registry.mjs +48 -0
- package/dist/ui/manifest/mount-registry.mjs.map +1 -0
- package/dist/ui/manifest/nav.cjs +13 -0
- package/dist/ui/manifest/nav.cjs.map +1 -0
- package/dist/ui/manifest/nav.d.cts +34 -0
- package/dist/ui/manifest/nav.d.cts.map +1 -0
- package/dist/ui/manifest/nav.d.mts +34 -0
- package/dist/ui/manifest/nav.d.mts.map +1 -0
- package/dist/ui/manifest/nav.mjs +13 -0
- package/dist/ui/manifest/nav.mjs.map +1 -0
- package/dist/ui/manifest/route-config.cjs +33 -0
- package/dist/ui/manifest/route-config.cjs.map +1 -0
- package/dist/ui/manifest/route-config.d.cts +40 -0
- package/dist/ui/manifest/route-config.d.cts.map +1 -0
- package/dist/ui/manifest/route-config.d.mts +40 -0
- package/dist/ui/manifest/route-config.d.mts.map +1 -0
- package/dist/ui/manifest/route-config.mjs +33 -0
- package/dist/ui/manifest/route-config.mjs.map +1 -0
- package/dist/version-manifest.cjs +65 -0
- package/dist/version-manifest.cjs.map +1 -0
- package/dist/version-manifest.d.cts +52 -0
- package/dist/version-manifest.d.cts.map +1 -0
- package/dist/version-manifest.d.mts +52 -0
- package/dist/version-manifest.d.mts.map +1 -0
- package/dist/version-manifest.mjs +63 -0
- package/dist/version-manifest.mjs.map +1 -0
- package/package.json +165 -68
- package/skills/plugin-client/SKILL.md +24 -5
- package/skills/plugin-development/SKILL.md +79 -47
- package/skills/plugin-testing/SKILL.md +41 -12
- package/src/build/artifact-names.ts +117 -0
- package/src/build/contract-types.ts +101 -0
- package/src/build/rspack/build-report-plugin.ts +34 -0
- package/src/build/rspack/chunk-completeness-plugin.ts +57 -0
- package/src/build/rspack/compose.ts +87 -0
- package/src/build/rspack/fix-mf-data-uri-plugin.ts +23 -12
- package/src/build/rspack/generated-config.ts +35 -0
- package/src/build/rspack/index.ts +10 -5
- package/src/build/rspack/module-federation.ts +1 -1
- package/src/build/rspack/plugin.ts +103 -105
- package/src/build/rspack/utils.ts +8 -2
- package/src/build/ui/factory.ts +96 -0
- package/src/build/ui/generated-config.ts +133 -0
- package/src/build/ui/hash-artifacts-plugin.ts +79 -0
- package/src/build/ui/index.ts +98 -0
- package/src/build/ui/manifest-plugin.ts +54 -0
- package/src/build/ui/rsbuild-config.ts +256 -0
- package/src/build/ui/stubs.ts +103 -0
- package/src/cli.ts +100 -0
- package/src/dev/serve.ts +477 -0
- package/src/dev/watch-kill.ts +58 -0
- package/src/effect-helpers.ts +25 -0
- package/src/errors.ts +16 -18
- package/src/identity.ts +36 -0
- package/src/index.ts +4 -0
- package/src/plugin.ts +70 -92
- package/src/remote-entry.ts +171 -0
- package/src/runtime/errors.ts +186 -27
- package/src/runtime/index.ts +132 -43
- package/src/runtime/mf-config.ts +12 -107
- package/src/runtime/services/module-federation.service.ts +221 -117
- package/src/runtime/services/normalize.ts +1 -18
- package/src/runtime/services/plugin-lifecycle.service.ts +66 -75
- package/src/runtime/services/plugin-loader.service.ts +239 -212
- package/src/runtime/services/plugin.service.ts +61 -43
- package/src/runtime/services/secrets.service.ts +20 -15
- package/src/runtime/services/shared-identity.ts +68 -0
- package/src/runtime/validation.ts +5 -7
- package/src/shared-deps-spec.ts +478 -0
- package/src/types.ts +22 -48
- package/src/ui/manifest/construct.ts +403 -0
- package/src/ui/manifest/contract.ts +33 -0
- package/src/ui/manifest/descriptor.ts +96 -0
- package/src/ui/manifest/generator.ts +238 -0
- package/src/ui/manifest/index.ts +55 -0
- package/src/ui/manifest/manifest-schema.ts +107 -0
- package/src/ui/manifest/mount-registry.ts +50 -0
- package/src/ui/manifest/nav.ts +43 -0
- package/src/ui/manifest/route-config.ts +82 -0
- package/src/version-manifest.ts +88 -0
- package/dist/build/rspack/dev-server-middleware.cjs +0 -248
- package/dist/build/rspack/dev-server-middleware.cjs.map +0 -1
- package/dist/build/rspack/dev-server-middleware.mjs +0 -247
- package/dist/build/rspack/dev-server-middleware.mjs.map +0 -1
- package/dist/build/shared-deps.cjs +0 -83
- package/dist/build/shared-deps.cjs.map +0 -1
- package/dist/build/shared-deps.d.cts +0 -67
- package/dist/build/shared-deps.d.cts.map +0 -1
- package/dist/build/shared-deps.d.mts +0 -67
- package/dist/build/shared-deps.d.mts.map +0 -1
- package/dist/build/shared-deps.mjs +0 -79
- package/dist/build/shared-deps.mjs.map +0 -1
- package/dist/effect.cjs +0 -9
- package/dist/effect.d.cts +0 -1
- package/dist/effect.d.mts +0 -1
- package/dist/effect.mjs +0 -3
- package/dist/orpc-openapi.cjs +0 -17
- package/dist/orpc-openapi.d.cts +0 -2
- package/dist/orpc-openapi.d.mts +0 -2
- package/dist/orpc-openapi.mjs +0 -5
- package/dist/orpc.cjs +0 -46
- package/dist/orpc.d.cts +0 -7
- package/dist/orpc.d.mts +0 -7
- package/dist/orpc.mjs +0 -11
- package/dist/package.cjs +0 -23
- package/dist/package.cjs.map +0 -1
- package/dist/package.mjs +0 -17
- package/dist/package.mjs.map +0 -1
- package/dist/runtime/services/module-federation.service.d.cts.map +0 -1
- package/dist/runtime/services/module-federation.service.d.mts.map +0 -1
- package/dist/runtime/services/normalize.cjs.map +0 -1
- package/dist/runtime/services/normalize.d.cts.map +0 -1
- package/dist/runtime/services/normalize.d.mts.map +0 -1
- package/dist/runtime/services/normalize.mjs.map +0 -1
- package/dist/runtime/services/plugin-lifecycle.service.d.cts.map +0 -1
- package/dist/runtime/services/plugin-lifecycle.service.d.mts.map +0 -1
- package/dist/runtime/services/plugin-loader.service.d.cts.map +0 -1
- package/dist/runtime/services/plugin-loader.service.d.mts.map +0 -1
- package/dist/runtime/services/secrets.service.d.cts.map +0 -1
- package/dist/runtime/services/secrets.service.d.mts.map +0 -1
- package/dist/testing/index.cjs +0 -57
- package/dist/testing/index.cjs.map +0 -1
- package/dist/testing/index.d.cts +0 -54
- package/dist/testing/index.d.cts.map +0 -1
- package/dist/testing/index.d.mts +0 -54
- package/dist/testing/index.d.mts.map +0 -1
- package/dist/testing/index.mjs +0 -55
- package/dist/testing/index.mjs.map +0 -1
- package/dist/zod-core.cjs +0 -9
- package/dist/zod-core.d.cts +0 -1
- package/dist/zod-core.d.mts +0 -1
- package/dist/zod-core.mjs +0 -3
- package/dist/zod.cjs +0 -11
- package/dist/zod.d.cts +0 -2
- package/dist/zod.d.mts +0 -2
- package/dist/zod.mjs +0 -3
- package/src/build/rspack/dev-server-middleware.ts +0 -324
- package/src/build/shared-deps.ts +0 -102
- package/src/effect.ts +0 -1
- package/src/orpc-openapi.ts +0 -2
- package/src/orpc.ts +0 -9
- package/src/testing/index.ts +0 -87
- package/src/testing/mocks/module-federation.service.ts +0 -41
- package/src/zod-core.ts +0 -1
- package/src/zod.ts +0 -3
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
interface KillableChild {
|
|
2
|
+
pid?: number | undefined;
|
|
3
|
+
kill: (signal?: NodeJS.Signals) => void;
|
|
4
|
+
exitCode: number | null;
|
|
5
|
+
killed: boolean;
|
|
6
|
+
addListener: (event: "exit", listener: () => void) => unknown;
|
|
7
|
+
removeListener: (event: "exit", listener: () => void) => unknown;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const waitForExit = (child: KillableChild, timeoutMs: number): Promise<boolean> =>
|
|
11
|
+
new Promise((resolve) => {
|
|
12
|
+
if (child.exitCode !== null) {
|
|
13
|
+
resolve(true);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const onExit = () => {
|
|
17
|
+
clearTimeout(timer);
|
|
18
|
+
resolve(true);
|
|
19
|
+
};
|
|
20
|
+
const timer = setTimeout(() => {
|
|
21
|
+
child.removeListener("exit", onExit);
|
|
22
|
+
resolve(false);
|
|
23
|
+
}, timeoutMs);
|
|
24
|
+
child.addListener("exit", onExit);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export const killChildEscalating = async (
|
|
28
|
+
child: KillableChild,
|
|
29
|
+
terminateMs = 2000,
|
|
30
|
+
): Promise<void> => {
|
|
31
|
+
if (child.exitCode !== null || child.killed) return;
|
|
32
|
+
child.kill("SIGTERM");
|
|
33
|
+
const exited = await waitForExit(child, terminateMs);
|
|
34
|
+
if (!exited) child.kill("SIGKILL");
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export interface WatchParentDeathOptions {
|
|
38
|
+
intervalMs?: number;
|
|
39
|
+
getPpid?: () => number;
|
|
40
|
+
onParentDeath?: () => void | Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const watchParentDeath = (
|
|
44
|
+
onParentDeath: () => void | Promise<void>,
|
|
45
|
+
opts?: Omit<WatchParentDeathOptions, "onParentDeath">,
|
|
46
|
+
): { stop: () => void } => {
|
|
47
|
+
const getPpid = opts?.getPpid ?? (() => process.ppid);
|
|
48
|
+
const intervalMs = opts?.intervalMs ?? 200;
|
|
49
|
+
const initialPpid = getPpid();
|
|
50
|
+
const timer = setInterval(() => {
|
|
51
|
+
if (getPpid() !== initialPpid) {
|
|
52
|
+
clearInterval(timer);
|
|
53
|
+
void onParentDeath();
|
|
54
|
+
}
|
|
55
|
+
}, intervalMs);
|
|
56
|
+
timer.unref?.();
|
|
57
|
+
return { stop: () => clearInterval(timer) };
|
|
58
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Context, Effect, Layer, type Scope } from "effect";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Builds a layer with the current scope and returns the built context.
|
|
5
|
+
*
|
|
6
|
+
* Resources are released when the plugin's scope closes. Use inside
|
|
7
|
+
* `initialize` for multi-service layers; resolve individual services from
|
|
8
|
+
* the returned context with `Context.get`.
|
|
9
|
+
*/
|
|
10
|
+
export const buildScopedContext = <A, E, R>(
|
|
11
|
+
layer: Layer.Layer<A, E, R>,
|
|
12
|
+
): Effect.Effect<Context.Context<A>, E, Scope.Scope | R> =>
|
|
13
|
+
Effect.flatMap(Effect.scope, (scope) => Layer.buildWithScope(layer, scope));
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Builds a layer with the current scope and resolves one service from it.
|
|
17
|
+
*
|
|
18
|
+
* Equivalent to `buildScopedContext` + `Context.get` for single-service
|
|
19
|
+
* layers: `const db = yield* buildScoped(DatabaseTag, DatabaseLive(url))`.
|
|
20
|
+
*/
|
|
21
|
+
export const buildScoped = <Identifier, Shape, E, R>(
|
|
22
|
+
tag: Context.Service<Identifier, Shape>,
|
|
23
|
+
layer: Layer.Layer<Identifier, E, R>,
|
|
24
|
+
): Effect.Effect<Shape, E, Scope.Scope | R> =>
|
|
25
|
+
buildScopedContext(layer).pipe(Effect.map((context) => Context.get(context, tag)));
|
package/src/errors.ts
CHANGED
|
@@ -1,18 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Error pattern constants for categorizing infrastructure errors
|
|
5
|
-
*/
|
|
6
|
-
export const ERROR_PATTERNS = {
|
|
7
|
-
CONNECTION_REFUSED: ["ECONNREFUSED"],
|
|
8
|
-
HOST_NOT_FOUND: ["ENOTFOUND", "EHOSTUNREACH"],
|
|
9
|
-
TIMEOUT: ["ETIMEDOUT", "ESOCKETTIMEDOUT", "timeout"],
|
|
10
|
-
CONNECTION_RESET: ["ECONNRESET", "EPIPE"],
|
|
11
|
-
PERMISSION: ["EACCES", "EPERM", "permission denied"],
|
|
12
|
-
AUTH: ["401", "unauthorized", "authentication failed"],
|
|
13
|
-
RATE_LIMITED: ["429", "too many requests", "rate limit"],
|
|
14
|
-
SERVICE_UNAVAILABLE: ["503", "service unavailable"],
|
|
15
|
-
} as const;
|
|
1
|
+
import { COMMON_ERROR_STATUS_MAP } from "@orpc/server";
|
|
2
|
+
import { z } from "zod";
|
|
16
3
|
|
|
17
4
|
/**
|
|
18
5
|
* Common error schemas for plugin contracts.
|
|
@@ -124,14 +111,25 @@ export const PluginErrors = {
|
|
|
124
111
|
} as const;
|
|
125
112
|
|
|
126
113
|
/**
|
|
127
|
-
*
|
|
114
|
+
* Error-code -> HTTP-status map for handlers.
|
|
115
|
+
*
|
|
116
|
+
* oRPC v2 resolves statuses at the handler boundary via `errorStatusMap`
|
|
117
|
+
* (default `COMMON_ERROR_STATUS_MAP`, where TIMEOUT is 408). Providing a
|
|
118
|
+
* map REPLACES the default entirely, so the standard codes must be spread
|
|
119
|
+
* back in. These custom entries preserve the v1 wire behavior:
|
|
120
|
+
* TIMEOUT -> 504, CONNECTION_ERROR -> 502.
|
|
128
121
|
*/
|
|
129
|
-
export const
|
|
122
|
+
export const PLUGIN_ERROR_STATUS_MAP: Record<string, number> = {
|
|
123
|
+
...COMMON_ERROR_STATUS_MAP,
|
|
124
|
+
TIMEOUT: 504,
|
|
125
|
+
CONNECTION_ERROR: 502,
|
|
126
|
+
} as const;
|
|
130
127
|
|
|
128
|
+
export type { PluginLoadFailureInfo } from "./runtime/errors";
|
|
131
129
|
export {
|
|
130
|
+
classifyPluginFailure,
|
|
132
131
|
extractFromFiberFailure,
|
|
133
132
|
formatORPCError,
|
|
134
|
-
isRetryableORPCCode,
|
|
135
133
|
ModuleFederationError,
|
|
136
134
|
PluginRuntimeError,
|
|
137
135
|
toPluginRuntimeError,
|
package/src/identity.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin identity: every name a plugin workspace carries, derived from one
|
|
3
|
+
* input. Two seams live here:
|
|
4
|
+
*
|
|
5
|
+
* - `remoteName`/`containerName` absorb the framework's two normalizers (the
|
|
6
|
+
* Module Federation remote name and the UI container name) — runtime,
|
|
7
|
+
* build, and host consumers delegate to these instead of keeping private
|
|
8
|
+
* copies, so a name can never disagree across contexts.
|
|
9
|
+
* - `identity` derives the full name set from the config layout key (the
|
|
10
|
+
* `plugins/<key>` attachment in `bos.config.json`): the key itself (the
|
|
11
|
+
* composition key), the npm package name under the scaffold convention,
|
|
12
|
+
* and the two normalized build names.
|
|
13
|
+
*
|
|
14
|
+
* Normalization rules:
|
|
15
|
+
* - remote: lowercase, strip a single leading '@', replace '/' with '_',
|
|
16
|
+
* preserve hyphens and other characters
|
|
17
|
+
* ("@scope/my-plugin" → "scope_my-plugin")
|
|
18
|
+
* - container: replace every character outside [A-Za-z0-9_] with '_'
|
|
19
|
+
* ("@everything-dev/auth-plugin" → "_everything_dev_auth_plugin")
|
|
20
|
+
*/
|
|
21
|
+
export interface PluginIdentity {
|
|
22
|
+
key: string;
|
|
23
|
+
npm: string;
|
|
24
|
+
remote: string;
|
|
25
|
+
container: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const remoteName = (name: string): string =>
|
|
29
|
+
name.toLowerCase().replace(/^@/, "").replace(/\//g, "_");
|
|
30
|
+
|
|
31
|
+
export const containerName = (pkgName: string): string => pkgName.replace(/[^A-Za-z0-9_]/g, "_");
|
|
32
|
+
|
|
33
|
+
export const identity = (key: string): PluginIdentity => {
|
|
34
|
+
const npm = `@everything-dev/${key}-plugin`;
|
|
35
|
+
return { key, npm, remote: remoteName(npm), container: containerName(npm) };
|
|
36
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import "@orpc/openapi/extensions/route";
|
|
2
|
+
|
|
3
|
+
export * from "./effect-helpers";
|
|
1
4
|
export * from "./errors";
|
|
2
5
|
export * from "./plugin";
|
|
3
6
|
export * from "./runtime";
|
|
@@ -20,6 +23,7 @@ export type {
|
|
|
20
23
|
PluginRouterType,
|
|
21
24
|
PluginRuntimeConfig,
|
|
22
25
|
PluginSecrets,
|
|
26
|
+
PluginServicesEntry,
|
|
23
27
|
PluginVariables,
|
|
24
28
|
RegisteredPlugins,
|
|
25
29
|
SecretsConfig,
|
package/src/plugin.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { AnyContractRouter, AnySchema, InferSchemaOutput } from "@orpc/contract";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
2
|
+
import type { WithEffectContext } from "@orpc/experimental-effect";
|
|
3
|
+
import "@orpc/experimental-effect/extensions/effect";
|
|
4
|
+
import type { ContractedRouter, Implementer } from "@orpc/server";
|
|
5
|
+
import { implement } from "@orpc/server";
|
|
6
|
+
import type { Scope } from "effect";
|
|
7
|
+
import { Context, Effect, Layer } from "effect";
|
|
8
|
+
import { type PluginRuntimeError, toPluginRuntimeError } from "./runtime/errors";
|
|
7
9
|
|
|
8
10
|
type ContextOutput<T> = T extends AnySchema ? InferSchemaOutput<T> : Record<string, never>;
|
|
9
11
|
|
|
@@ -22,23 +24,19 @@ type PluginInitializeInput<V extends AnySchema, S extends AnySchema> = {
|
|
|
22
24
|
secrets: InferSchemaOutput<S>;
|
|
23
25
|
};
|
|
24
26
|
|
|
27
|
+
export class PluginIdTag extends Context.Service<PluginIdTag, string>()("PluginId") {}
|
|
28
|
+
|
|
25
29
|
/**
|
|
26
|
-
*
|
|
30
|
+
* The `initialize` effect's environment: the plugin lifecycle scope plus the
|
|
31
|
+
* framework-assigned plugin id.
|
|
27
32
|
*/
|
|
28
|
-
type
|
|
29
|
-
|
|
30
|
-
export type PluginServicesTools = {
|
|
31
|
-
buildService: <T>(tag: T, layer: Layer.Layer<any, any, any>) => Effect.Effect<ServiceOf<T>>;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export class PluginIdTag extends Context.Tag("PluginId")<PluginIdTag, string>() {}
|
|
33
|
+
export type PluginEnv = Scope.Scope | PluginIdTag;
|
|
35
34
|
|
|
36
35
|
type PluginDefinition<
|
|
37
36
|
V extends AnySchema,
|
|
38
37
|
S extends AnySchema,
|
|
39
38
|
TContract extends AnyContractRouter,
|
|
40
39
|
TRequestContext extends AnySchema | undefined,
|
|
41
|
-
TDeps extends Record<string, any>,
|
|
42
40
|
P extends Record<string, unknown>,
|
|
43
41
|
> = {
|
|
44
42
|
variables: V;
|
|
@@ -46,20 +44,35 @@ type PluginDefinition<
|
|
|
46
44
|
contract: TContract;
|
|
47
45
|
context?: TRequestContext;
|
|
48
46
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
47
|
+
* Optional tag under which `initialize` exposes the plugin's services.
|
|
48
|
+
* The host uses it to read services (e.g. the auth plugin's Better Auth
|
|
49
|
+
* handler) from the built Effect context without importing the plugin
|
|
50
|
+
* module statically.
|
|
51
|
+
*/
|
|
52
|
+
servicesTag?: Context.Key<any, any>;
|
|
53
|
+
/**
|
|
54
|
+
* Initialize the plugin by returning an Effect `Layer`.
|
|
55
|
+
*
|
|
56
|
+
* The runtime builds the Layer against the plugin's lifecycle scope —
|
|
57
|
+
* scoped resources (db pools, repositories, caches, publishers) release
|
|
58
|
+
* when the plugin shuts down. Services are provided to `.effect()`
|
|
59
|
+
* handlers via the oRPC context (`yield* Tag`).
|
|
52
60
|
*/
|
|
53
61
|
initialize?: (
|
|
54
62
|
config: PluginInitializeInput<V, S>,
|
|
55
63
|
plugins: P,
|
|
56
|
-
|
|
57
|
-
|
|
64
|
+
) => Effect.Effect<Layer.Layer<any, Error, PluginEnv>, Error, PluginEnv>;
|
|
65
|
+
/**
|
|
66
|
+
* Creates the strongly-typed oRPC router for this plugin.
|
|
67
|
+
* Services come from the Effect context — access them with
|
|
68
|
+
* `yield* Tag` in `.effect()` handlers, or
|
|
69
|
+
* `Context.get(context["effect/context"], Tag)` in plain handlers.
|
|
70
|
+
* Sibling plugin entries in `plugins` carry `{ client, router }`.
|
|
71
|
+
*/
|
|
58
72
|
createRouter: (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
) =>
|
|
62
|
-
shutdown?: (deps: TDeps) => Effect.Effect<void, Error, never>;
|
|
73
|
+
builder: Implementer<TContract, ContextOutput<TRequestContext> & WithEffectContext<any>>,
|
|
74
|
+
plugins: P,
|
|
75
|
+
) => ContractedRouter<TContract, any>;
|
|
63
76
|
};
|
|
64
77
|
|
|
65
78
|
/**
|
|
@@ -70,14 +83,14 @@ export interface LoadedPluginWithBinding<
|
|
|
70
83
|
TVariables extends AnySchema,
|
|
71
84
|
TSecrets extends AnySchema,
|
|
72
85
|
TRequestContext extends AnySchema | undefined,
|
|
73
|
-
TDeps extends Record<string, any> = Record<never, never>,
|
|
74
86
|
> {
|
|
75
|
-
new (): Plugin<TContract, TVariables, TSecrets, TRequestContext
|
|
87
|
+
new (): Plugin<TContract, TVariables, TSecrets, TRequestContext>;
|
|
76
88
|
binding: {
|
|
77
89
|
contract: TContract;
|
|
78
90
|
variables: TVariables;
|
|
79
91
|
secrets: TSecrets;
|
|
80
92
|
context: TRequestContext;
|
|
93
|
+
servicesTag?: Context.Key<any, any>;
|
|
81
94
|
};
|
|
82
95
|
}
|
|
83
96
|
|
|
@@ -89,27 +102,25 @@ export interface Plugin<
|
|
|
89
102
|
TVariables extends AnySchema,
|
|
90
103
|
TSecrets extends AnySchema,
|
|
91
104
|
TRequestContext extends AnySchema | undefined,
|
|
92
|
-
TDeps extends Record<string, any> = Record<never, never>,
|
|
93
105
|
> {
|
|
94
106
|
readonly id: string;
|
|
95
107
|
readonly contract: TContract;
|
|
96
108
|
readonly configSchema: PluginConfigFor<TVariables, TSecrets, TRequestContext>;
|
|
109
|
+
readonly servicesTag?: Context.Key<any, any>;
|
|
97
110
|
|
|
98
111
|
initialize(
|
|
99
112
|
config: PluginInitializeInput<TVariables, TSecrets>,
|
|
100
113
|
plugins: Record<string, unknown>,
|
|
101
|
-
|
|
102
|
-
): Effect.Effect<TDeps, unknown, Scope.Scope>;
|
|
103
|
-
|
|
104
|
-
shutdown(): Effect.Effect<void, never>;
|
|
114
|
+
): Effect.Effect<Layer.Layer<any, Error, PluginEnv>, PluginRuntimeError, PluginEnv>;
|
|
105
115
|
|
|
106
116
|
/**
|
|
107
117
|
* Creates the strongly-typed oRPC router for this plugin.
|
|
108
118
|
* The router's procedure types are inferred directly from the contract.
|
|
109
|
-
* @param
|
|
119
|
+
* @param plugins Sibling plugin entries (`{ client, router }`) for
|
|
120
|
+
* cross-plugin composition
|
|
110
121
|
* @returns A router with procedures matching the plugin's contract
|
|
111
122
|
*/
|
|
112
|
-
createRouter(
|
|
123
|
+
createRouter(plugins: Record<string, unknown>): ContractedRouter<TContract, any>;
|
|
113
124
|
}
|
|
114
125
|
|
|
115
126
|
export interface CreatePluginFn {
|
|
@@ -118,11 +129,10 @@ export interface CreatePluginFn {
|
|
|
118
129
|
S extends AnySchema,
|
|
119
130
|
TContract extends AnyContractRouter,
|
|
120
131
|
TRequestContext extends AnySchema | undefined = undefined,
|
|
121
|
-
TDeps extends Record<string, any> = Record<never, never>,
|
|
122
132
|
P extends Record<string, unknown> = Record<string, never>,
|
|
123
133
|
>(
|
|
124
|
-
config: PluginDefinition<V, S, TContract, TRequestContext,
|
|
125
|
-
): LoadedPluginWithBinding<TContract, V, S, TRequestContext
|
|
134
|
+
config: PluginDefinition<V, S, TContract, TRequestContext, P>,
|
|
135
|
+
): LoadedPluginWithBinding<TContract, V, S, TRequestContext>;
|
|
126
136
|
|
|
127
137
|
withPlugins: <P extends Record<string, unknown>>() => CreatePluginWithPlugins<P>;
|
|
128
138
|
}
|
|
@@ -132,84 +142,53 @@ export const createPlugin: CreatePluginFn = function createPlugin<
|
|
|
132
142
|
S extends AnySchema,
|
|
133
143
|
TContract extends AnyContractRouter,
|
|
134
144
|
TRequestContext extends AnySchema | undefined = undefined,
|
|
135
|
-
TDeps extends Record<string, any> = Record<never, never>,
|
|
136
145
|
P extends Record<string, unknown> = Record<string, never>,
|
|
137
|
-
>(config: PluginDefinition<V, S, TContract, TRequestContext,
|
|
146
|
+
>(config: PluginDefinition<V, S, TContract, TRequestContext, P>) {
|
|
138
147
|
const configSchema: PluginConfigFor<V, S, TRequestContext> = {
|
|
139
148
|
variables: config.variables,
|
|
140
149
|
secrets: config.secrets,
|
|
141
150
|
context: config.context as TRequestContext,
|
|
142
151
|
};
|
|
143
152
|
|
|
144
|
-
class CreatedPlugin implements Plugin<TContract, V, S, TRequestContext
|
|
153
|
+
class CreatedPlugin implements Plugin<TContract, V, S, TRequestContext> {
|
|
145
154
|
/** set during instantiation - registry key */
|
|
146
155
|
id!: string;
|
|
147
156
|
readonly contract = config.contract;
|
|
148
157
|
readonly configSchema = configSchema;
|
|
149
|
-
|
|
150
|
-
private _deps: TDeps | null = null;
|
|
158
|
+
readonly servicesTag = config.servicesTag;
|
|
151
159
|
|
|
152
160
|
initialize(
|
|
153
161
|
pluginConfig: PluginInitializeInput<V, S>,
|
|
154
162
|
plugins: Record<string, unknown> = {},
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
163
|
+
): Effect.Effect<Layer.Layer<any, Error, PluginEnv>, PluginRuntimeError, PluginEnv> {
|
|
164
|
+
const init = config.initialize;
|
|
165
|
+
if (!init) {
|
|
166
|
+
return Effect.succeed(Layer.empty as unknown as Layer.Layer<any, Error, PluginEnv>);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return init(pluginConfig, plugins as P).pipe(
|
|
170
|
+
Effect.mapError((error) =>
|
|
171
|
+
toPluginRuntimeError(error, this.id, undefined, "initialize-plugin"),
|
|
164
172
|
),
|
|
165
|
-
Effect.map(() => this._deps as TDeps),
|
|
166
|
-
Effect.mapError((error) => error as unknown),
|
|
167
173
|
);
|
|
168
174
|
}
|
|
169
175
|
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
.shutdown(self._deps)
|
|
176
|
-
.pipe(
|
|
177
|
-
Effect.catchAll((error) =>
|
|
178
|
-
Effect.logWarning(`Plugin shutdown hook failed for ${self.id}`, error),
|
|
179
|
-
),
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
self._deps = null;
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
createRouter(deps: TDeps): Router<TContract, any> {
|
|
187
|
-
const base = implement(config.contract).$context<ContextOutput<TRequestContext>>();
|
|
188
|
-
const errorMiddleware = onError((error: unknown) => {
|
|
189
|
-
const unwrapped = extractFromFiberFailure(error);
|
|
190
|
-
|
|
191
|
-
if (unwrapped !== error && unwrapped instanceof ORPCError) {
|
|
192
|
-
throw unwrapped;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const formatted = formatORPCError(error);
|
|
196
|
-
if (formatted) console.error(formatted);
|
|
197
|
-
throw error;
|
|
198
|
-
}) as any;
|
|
199
|
-
|
|
200
|
-
const builder = (base as any).use(errorMiddleware);
|
|
201
|
-
const router = config.createRouter(deps, builder as any);
|
|
202
|
-
return router as Router<TContract, any>;
|
|
176
|
+
createRouter(plugins: Record<string, unknown>): ContractedRouter<TContract, any> {
|
|
177
|
+
const builder = implement(config.contract).$context<
|
|
178
|
+
ContextOutput<TRequestContext> & WithEffectContext<any>
|
|
179
|
+
>();
|
|
180
|
+
return config.createRouter(builder as any, plugins as P) as ContractedRouter<TContract, any>;
|
|
203
181
|
}
|
|
204
182
|
}
|
|
205
183
|
|
|
206
184
|
const PluginConstructor = CreatedPlugin as unknown as {
|
|
207
|
-
new (): Plugin<TContract, V, S, TRequestContext
|
|
185
|
+
new (): Plugin<TContract, V, S, TRequestContext>;
|
|
208
186
|
binding: {
|
|
209
187
|
contract: TContract;
|
|
210
188
|
variables: V;
|
|
211
189
|
secrets: S;
|
|
212
190
|
context: TRequestContext;
|
|
191
|
+
servicesTag?: Context.Key<any, any>;
|
|
213
192
|
};
|
|
214
193
|
};
|
|
215
194
|
|
|
@@ -218,9 +197,10 @@ export const createPlugin: CreatePluginFn = function createPlugin<
|
|
|
218
197
|
variables: config.variables,
|
|
219
198
|
secrets: config.secrets,
|
|
220
199
|
context: config.context as TRequestContext,
|
|
200
|
+
servicesTag: config.servicesTag,
|
|
221
201
|
};
|
|
222
202
|
|
|
223
|
-
return PluginConstructor as LoadedPluginWithBinding<TContract, V, S, TRequestContext
|
|
203
|
+
return PluginConstructor as LoadedPluginWithBinding<TContract, V, S, TRequestContext>;
|
|
224
204
|
};
|
|
225
205
|
|
|
226
206
|
export type CreatePluginWithPlugins<P extends Record<string, unknown>> = <
|
|
@@ -228,10 +208,9 @@ export type CreatePluginWithPlugins<P extends Record<string, unknown>> = <
|
|
|
228
208
|
S extends AnySchema,
|
|
229
209
|
TContract extends AnyContractRouter,
|
|
230
210
|
TRequestContext extends AnySchema | undefined = undefined,
|
|
231
|
-
TDeps extends Record<string, any> = Record<never, never>,
|
|
232
211
|
>(
|
|
233
|
-
config: PluginDefinition<V, S, TContract, TRequestContext,
|
|
234
|
-
) => LoadedPluginWithBinding<TContract, V, S, TRequestContext
|
|
212
|
+
config: PluginDefinition<V, S, TContract, TRequestContext, P>,
|
|
213
|
+
) => LoadedPluginWithBinding<TContract, V, S, TRequestContext>;
|
|
235
214
|
|
|
236
215
|
export function withPlugins<P extends Record<string, unknown>>(): CreatePluginWithPlugins<P> {
|
|
237
216
|
return <
|
|
@@ -239,10 +218,9 @@ export function withPlugins<P extends Record<string, unknown>>(): CreatePluginWi
|
|
|
239
218
|
S extends AnySchema,
|
|
240
219
|
TContract extends AnyContractRouter,
|
|
241
220
|
TRequestContext extends AnySchema | undefined = undefined,
|
|
242
|
-
TDeps extends Record<string, any> = Record<never, never>,
|
|
243
221
|
>(
|
|
244
|
-
config: PluginDefinition<V, S, TContract, TRequestContext,
|
|
245
|
-
) => createPlugin<V, S, TContract, TRequestContext,
|
|
222
|
+
config: PluginDefinition<V, S, TContract, TRequestContext, P>,
|
|
223
|
+
) => createPlugin<V, S, TContract, TRequestContext, P>(config as any);
|
|
246
224
|
}
|
|
247
225
|
|
|
248
226
|
createPlugin.withPlugins = withPlugins;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote-entry loading resilience — the ONE contract every MF consumer in
|
|
3
|
+
* the dev stack shares (plugin dev serves, the host's plugin loader).
|
|
4
|
+
*
|
|
5
|
+
* Two failure classes it exists for:
|
|
6
|
+
* 1. Cold compile: remoteEntry.js 404s until the remote's first build —
|
|
7
|
+
* the 404 body gets eval'd as JS ("Unexpected identifier 'Found'").
|
|
8
|
+
* 2. Watch-rebuild poisoning: a failed entry load is memoized forever in
|
|
9
|
+
* `globalThis.__GLOBAL_LOADING_REMOTE_ENTRY__` (runtime-core never evicts
|
|
10
|
+
* rejections), so retries without a purge await the same failure.
|
|
11
|
+
*/
|
|
12
|
+
import { Duration, Effect, Schedule } from "effect";
|
|
13
|
+
import type { PluginRuntimeError } from "./runtime/errors";
|
|
14
|
+
import {
|
|
15
|
+
classifyPluginFailure,
|
|
16
|
+
deepestErrorStack,
|
|
17
|
+
type PluginFailureClassification,
|
|
18
|
+
toPluginRuntimeError,
|
|
19
|
+
} from "./runtime/errors";
|
|
20
|
+
|
|
21
|
+
const POLL_INTERVAL_MS = 300;
|
|
22
|
+
const DEFAULT_TIMEOUT_MS = 120_000;
|
|
23
|
+
const RETRY_BASE_DELAY_MS = 500;
|
|
24
|
+
const RETRY_MAX_DELAY_MS = 5_000;
|
|
25
|
+
|
|
26
|
+
export const sleep = (ms: number): Promise<void> =>
|
|
27
|
+
new Promise((resolve) => setTimeout(resolve, ms));
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Deletes the failed remote's keys from the process-global entry-load cache.
|
|
31
|
+
* Deleting a RESOLVED entry would force a wasteful re-eval, so only call
|
|
32
|
+
* this from failure paths.
|
|
33
|
+
*/
|
|
34
|
+
export const purgeRemoteEntryCache = (remoteUrl: string): void => {
|
|
35
|
+
const globalLoading = (globalThis as Record<string, unknown>).__GLOBAL_LOADING_REMOTE_ENTRY__ as
|
|
36
|
+
| Record<string, unknown>
|
|
37
|
+
| undefined;
|
|
38
|
+
if (!globalLoading) return;
|
|
39
|
+
for (const key of Object.keys(globalLoading)) {
|
|
40
|
+
if (key.endsWith(`:${remoteUrl}`)) delete globalLoading[key];
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const isRemoteEntryBody = (body: string): boolean =>
|
|
45
|
+
!/not found|<(!doctype|html)/i.test(body.slice(0, 64));
|
|
46
|
+
|
|
47
|
+
export const waitForRemoteEntryReady = async (
|
|
48
|
+
label: string,
|
|
49
|
+
url: string,
|
|
50
|
+
timeoutMs = DEFAULT_TIMEOUT_MS,
|
|
51
|
+
): Promise<void> => {
|
|
52
|
+
const deadline = Date.now() + timeoutMs;
|
|
53
|
+
let announced = false;
|
|
54
|
+
while (Date.now() < deadline) {
|
|
55
|
+
const res = await fetch(url).catch(() => null);
|
|
56
|
+
if (res?.ok && isRemoteEntryBody(await res.text().catch(() => ""))) return;
|
|
57
|
+
if (!announced) {
|
|
58
|
+
announced = true;
|
|
59
|
+
console.log(`⏳ waiting for ${label} to compile (remote entry not ready)…`);
|
|
60
|
+
}
|
|
61
|
+
await sleep(POLL_INTERVAL_MS);
|
|
62
|
+
}
|
|
63
|
+
throw new Error(`${label} remote entry never became ready at ${url}`);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export interface PluginLoadAttemptInfo {
|
|
67
|
+
attempt: number;
|
|
68
|
+
classification: PluginFailureClassification;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface PluginLoadRetryOptions<T> {
|
|
72
|
+
/** short plugin key for log prefixes (host entry key or plugin id) */
|
|
73
|
+
label: string;
|
|
74
|
+
remoteUrl: string;
|
|
75
|
+
load: () => Promise<T>;
|
|
76
|
+
/** wall-clock budget for the retry loop */
|
|
77
|
+
timeoutMs?: number;
|
|
78
|
+
/**
|
|
79
|
+
* Budget for the readiness poll (cold-compile wait) — defaults to the
|
|
80
|
+
* retry budget, preserving the historical behavior. Pass `0` to skip the
|
|
81
|
+
* poll (useful when the caller stubs `load` and does not need network).
|
|
82
|
+
*/
|
|
83
|
+
readinessTimeoutMs?: number;
|
|
84
|
+
/**
|
|
85
|
+
* Observes every failed attempt (including non-retryable ones that end the
|
|
86
|
+
* loop). Defaults to classification-deduped console.error under the
|
|
87
|
+
* `[Plugins]` prefix.
|
|
88
|
+
*/
|
|
89
|
+
onAttempt?: ((error: unknown, info: PluginLoadAttemptInfo) => void) | undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The one plugin-load retry policy: poll the remote entry until it is actually
|
|
94
|
+
* served, then load with capped exponential backoff — purging the poisoned
|
|
95
|
+
* global entry cache between attempts so each retry genuinely re-fetches.
|
|
96
|
+
*
|
|
97
|
+
* Recovery policy is `classifyPluginFailure().retryable`: transient network
|
|
98
|
+
* conditions retry until the wall-clock budget runs out; permanent failures
|
|
99
|
+
* (MF identity skew, schema validation, dead remotes, TLS verification) fail
|
|
100
|
+
* fast on the first attempt instead of burning the budget silently.
|
|
101
|
+
*
|
|
102
|
+
* Fails with the ORIGINAL error from `load` — the host builds
|
|
103
|
+
* `PluginBootstrapError.cause` from it and classification walks it.
|
|
104
|
+
*/
|
|
105
|
+
export const loadRemoteWithRetry = <T>(
|
|
106
|
+
options: PluginLoadRetryOptions<T>,
|
|
107
|
+
): Effect.Effect<T, PluginRuntimeError> => {
|
|
108
|
+
const {
|
|
109
|
+
label,
|
|
110
|
+
remoteUrl,
|
|
111
|
+
load,
|
|
112
|
+
timeoutMs = DEFAULT_TIMEOUT_MS,
|
|
113
|
+
readinessTimeoutMs,
|
|
114
|
+
onAttempt,
|
|
115
|
+
} = options;
|
|
116
|
+
const readinessTimeout = readinessTimeoutMs ?? timeoutMs;
|
|
117
|
+
|
|
118
|
+
const schedule = Schedule.exponential(Duration.millis(RETRY_BASE_DELAY_MS)).pipe(
|
|
119
|
+
Schedule.modifyDelay(({ output }) =>
|
|
120
|
+
Effect.succeed(
|
|
121
|
+
Duration.toMillis(output) > RETRY_MAX_DELAY_MS
|
|
122
|
+
? Duration.millis(RETRY_MAX_DELAY_MS)
|
|
123
|
+
: output,
|
|
124
|
+
),
|
|
125
|
+
),
|
|
126
|
+
Schedule.upTo({ duration: Duration.millis(timeoutMs) }),
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
let attempt = 0;
|
|
130
|
+
let lastSignature: string | undefined;
|
|
131
|
+
const reportFailure = (error: unknown): void => {
|
|
132
|
+
attempt += 1;
|
|
133
|
+
purgeRemoteEntryCache(remoteUrl);
|
|
134
|
+
const classification = classifyPluginFailure(error);
|
|
135
|
+
if (onAttempt) {
|
|
136
|
+
onAttempt(error, { attempt, classification });
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const signature = `${classification.kind}::${classification.message}`;
|
|
140
|
+
if (signature === lastSignature) return;
|
|
141
|
+
lastSignature = signature;
|
|
142
|
+
// The message alone is rarely enough, and the wrapper's own stack points
|
|
143
|
+
// at the wrapping frames — log the DEEPEST cause's stack (the original
|
|
144
|
+
// throw site inside the evaluated remote entry).
|
|
145
|
+
const stack = deepestErrorStack(error);
|
|
146
|
+
console.error(
|
|
147
|
+
`[Plugins][${label}] ❌ ${classification.kind} failure (attempt ${attempt}): ${classification.message}` +
|
|
148
|
+
(classification.suggestion ? `\n[Plugins][${label}] → ${classification.suggestion}` : "") +
|
|
149
|
+
(stack ? `\n[Plugins][${label}] ${stack}` : ""),
|
|
150
|
+
);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const loadWithRetry = Effect.tryPromise({
|
|
154
|
+
try: load,
|
|
155
|
+
catch: (error) => toPluginRuntimeError(error, label, undefined, "remote-entry-load"),
|
|
156
|
+
}).pipe(
|
|
157
|
+
Effect.tapError((error) => Effect.sync(() => reportFailure(error))),
|
|
158
|
+
Effect.retry({ schedule, while: (error) => classifyPluginFailure(error).retryable }),
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
// readinessTimeoutMs: 0 skips the cold-compile poll (tests stub `load` and
|
|
162
|
+
// must not race a 1ms wall-clock window against the event loop).
|
|
163
|
+
if (readinessTimeout === 0) {
|
|
164
|
+
return loadWithRetry;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return Effect.tryPromise({
|
|
168
|
+
try: () => waitForRemoteEntryReady(label, remoteUrl, readinessTimeout),
|
|
169
|
+
catch: (error) => toPluginRuntimeError(error, label, undefined, "remote-entry-readiness"),
|
|
170
|
+
}).pipe(Effect.flatMap(() => loadWithRetry));
|
|
171
|
+
};
|