every-plugin 3.0.0-rc.3 → 3.0.0-rc.4
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/dist/client.cjs +69 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +15 -0
- package/dist/client.d.cts.map +1 -0
- package/dist/client.d.mts +15 -0
- package/dist/client.d.mts.map +1 -0
- package/dist/client.mjs +68 -0
- package/dist/client.mjs.map +1 -0
- package/dist/dev/host.cjs +149 -0
- package/dist/dev/host.cjs.map +1 -0
- package/dist/dev/host.d.cts +32 -0
- package/dist/dev/host.d.cts.map +1 -0
- package/dist/dev/host.d.mts +32 -0
- package/dist/dev/host.d.mts.map +1 -0
- package/dist/dev/host.mjs +148 -0
- package/dist/dev/host.mjs.map +1 -0
- package/dist/dev/serve.cjs +14 -109
- package/dist/dev/serve.cjs.map +1 -1
- package/dist/dev/serve.d.cts.map +1 -1
- package/dist/dev/serve.d.mts.map +1 -1
- package/dist/dev/serve.mjs +14 -109
- package/dist/dev/serve.mjs.map +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.d.cts +3 -2
- package/dist/index.d.mts +3 -2
- package/dist/index.mjs +2 -1
- package/dist/plugin.d.cts +1 -1
- package/dist/runtime/mf-config.cjs +1 -1
- package/dist/runtime/mf-config.mjs +1 -1
- package/dist/runtime/services/plugin-loader.service.d.cts +2 -2
- package/dist/types.d.cts +23 -2
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +22 -1
- package/dist/types.d.mts.map +1 -1
- package/package.json +19 -2
- package/src/client.ts +111 -0
- package/src/dev/host.ts +235 -0
- package/src/dev/serve.ts +14 -135
- package/src/index.ts +9 -0
- package/src/types.ts +36 -2
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createRpcClient } from "./client.mjs";
|
|
1
2
|
import { buildScoped, buildScopedContext } from "./effect-helpers.mjs";
|
|
2
3
|
import { ModuleFederationError, PluginRuntimeError, ValidationError, classifyPluginFailure, defaultMissingSecretWarnings, extractFromFiberFailure, formatORPCError, toPluginRuntimeError, wrapORPCError } from "./runtime/errors.mjs";
|
|
3
4
|
import { BAD_REQUEST, CONNECTION_ERROR, FORBIDDEN, NOT_FOUND, PLUGIN_ERROR_STATUS_MAP, PluginErrors, RATE_LIMITED, SERVICE_UNAVAILABLE, TIMEOUT, UNAUTHORIZED } from "./errors.mjs";
|
|
@@ -6,4 +7,4 @@ import { remoteName } from "./identity.mjs";
|
|
|
6
7
|
import { PluginRuntime, createPluginRuntime } from "./runtime/index.mjs";
|
|
7
8
|
import "@orpc/openapi/extensions/route";
|
|
8
9
|
|
|
9
|
-
export { BAD_REQUEST, CONNECTION_ERROR, FORBIDDEN, ModuleFederationError, NOT_FOUND, PLUGIN_ERROR_STATUS_MAP, PluginErrors, PluginIdTag, PluginRuntime, PluginRuntimeError, RATE_LIMITED, SERVICE_UNAVAILABLE, TIMEOUT, UNAUTHORIZED, ValidationError, buildScoped, buildScopedContext, classifyPluginFailure, createPlugin, createPluginRuntime, defaultMissingSecretWarnings, extractFromFiberFailure, formatORPCError, remoteName as getNormalizedRemoteName, toPluginRuntimeError, withPlugins, wrapORPCError };
|
|
10
|
+
export { BAD_REQUEST, CONNECTION_ERROR, FORBIDDEN, ModuleFederationError, NOT_FOUND, PLUGIN_ERROR_STATUS_MAP, PluginErrors, PluginIdTag, PluginRuntime, PluginRuntimeError, RATE_LIMITED, SERVICE_UNAVAILABLE, TIMEOUT, UNAUTHORIZED, ValidationError, buildScoped, buildScopedContext, classifyPluginFailure, createPlugin, createPluginRuntime, createRpcClient, defaultMissingSecretWarnings, extractFromFiberFailure, formatORPCError, remoteName as getNormalizedRemoteName, toPluginRuntimeError, withPlugins, wrapORPCError };
|
package/dist/plugin.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PluginRuntimeError, PluginWarningInfo } from "./runtime/errors.cjs";
|
|
2
|
+
import { AnyContractRouter, AnySchema, InferSchemaOutput } from "@orpc/contract";
|
|
2
3
|
import { ContractedRouter, Implementer } from "@orpc/server";
|
|
3
4
|
import { Context, Effect, Layer, Scope } from "effect";
|
|
4
|
-
import { AnyContractRouter, AnySchema, InferSchemaOutput } from "@orpc/contract";
|
|
5
5
|
import { WithEffectContext } from "@orpc/experimental-effect";
|
|
6
6
|
import "@orpc/experimental-effect/extensions/effect";
|
|
7
7
|
//#region src/plugin.d.ts
|
|
@@ -3,7 +3,7 @@ const require_shared_deps_spec = require('../shared-deps-spec.cjs');
|
|
|
3
3
|
let node_fs = require("node:fs");
|
|
4
4
|
|
|
5
5
|
//#region src/runtime/mf-config.ts
|
|
6
|
-
const PLUGIN_VERSION = "3.0.0-rc.
|
|
6
|
+
const PLUGIN_VERSION = "3.0.0-rc.4";
|
|
7
7
|
const MF_CORE_SHARED_DEPS = require_shared_deps_spec.buildMfCoreSharedDependencies({ ownVersion: PLUGIN_VERSION });
|
|
8
8
|
|
|
9
9
|
//#endregion
|
|
@@ -2,7 +2,7 @@ import { buildMfCoreSharedDependencies } from "../shared-deps-spec.mjs";
|
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
|
|
4
4
|
//#region src/runtime/mf-config.ts
|
|
5
|
-
const PLUGIN_VERSION = "3.0.0-rc.
|
|
5
|
+
const PLUGIN_VERSION = "3.0.0-rc.4";
|
|
6
6
|
const MF_CORE_SHARED_DEPS = buildMfCoreSharedDependencies({ ownVersion: PLUGIN_VERSION });
|
|
7
7
|
|
|
8
8
|
//#endregion
|
|
@@ -2,5 +2,5 @@ import "../errors.cjs";
|
|
|
2
2
|
import "../../types.cjs";
|
|
3
3
|
import "./module-federation.service.cjs";
|
|
4
4
|
import "./secrets.service.cjs";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { InferSchemaInput } from "@orpc/contract";
|
|
6
|
+
import { Context, Effect, Layer } from "effect";
|
package/dist/types.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { PluginWarningInfo } from "./runtime/errors.cjs";
|
|
2
2
|
import { Plugin } from "./plugin.cjs";
|
|
3
|
+
import { AnyContractRouter, AnySchema, InferSchemaInput, InferSchemaOutput } from "@orpc/contract";
|
|
3
4
|
import { ContractedRouter, RouterClient } from "@orpc/server";
|
|
4
5
|
import { Context, Scope } from "effect";
|
|
5
|
-
import { AnyContractRouter, AnySchema, InferSchemaInput, InferSchemaOutput } from "@orpc/contract";
|
|
6
6
|
//#region src/types.d.ts
|
|
7
7
|
/**
|
|
8
8
|
* Registry bindings interface - populated via module augmentation
|
|
@@ -17,6 +17,18 @@ import { AnyContractRouter, AnySchema, InferSchemaInput, InferSchemaOutput } fro
|
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
19
|
interface RegisteredPlugins {}
|
|
20
|
+
type ModuleTransport = "inproc" | "rpc" | "mf";
|
|
21
|
+
type ModuleSurface = "api" | "ui" | "jobs";
|
|
22
|
+
interface ModuleEndpoint {
|
|
23
|
+
readonly transport: ModuleTransport;
|
|
24
|
+
readonly surface?: ModuleSurface;
|
|
25
|
+
readonly url: string;
|
|
26
|
+
readonly path?: `/${string}`;
|
|
27
|
+
readonly manifest?: string;
|
|
28
|
+
}
|
|
29
|
+
type PluginTransport = ModuleTransport;
|
|
30
|
+
type PluginSurface = ModuleSurface;
|
|
31
|
+
type PluginEndpoint = ModuleEndpoint;
|
|
20
32
|
/**
|
|
21
33
|
* Base type for any plugin instance.
|
|
22
34
|
*/
|
|
@@ -39,10 +51,12 @@ type AnyPluginConstructor = {
|
|
|
39
51
|
type PluginRegistryEntry = {
|
|
40
52
|
module: AnyPluginConstructor;
|
|
41
53
|
remote?: string;
|
|
54
|
+
endpoint?: PluginEndpoint;
|
|
42
55
|
version?: string;
|
|
43
56
|
description?: string;
|
|
44
57
|
} | {
|
|
45
58
|
remote: string;
|
|
59
|
+
endpoint?: PluginEndpoint;
|
|
46
60
|
version?: string;
|
|
47
61
|
description?: string;
|
|
48
62
|
};
|
|
@@ -107,7 +121,14 @@ type PluginClientType<T> = RouterClient<PluginRouterType<T>>;
|
|
|
107
121
|
type PluginServicesEntry<T = any> = {
|
|
108
122
|
client: (context?: PluginContextInput<T>) => PluginClientType<T>;
|
|
109
123
|
router: PluginRouterType<T>;
|
|
124
|
+
endpoint?: PluginEndpoint;
|
|
125
|
+
};
|
|
126
|
+
type ModuleClientEntry<C extends AnyContractRouter = AnyContractRouter> = {
|
|
127
|
+
client: (context?: Record<string, unknown>) => RouterClient<ContractedRouter<C, any>>;
|
|
128
|
+
router?: ContractedRouter<C, any>;
|
|
129
|
+
endpoint?: PluginEndpoint;
|
|
110
130
|
};
|
|
131
|
+
type PluginClientEntry<C extends AnyContractRouter = AnyContractRouter> = ModuleClientEntry<C>;
|
|
111
132
|
/**
|
|
112
133
|
* Extract plugin type from registered plugins by key
|
|
113
134
|
* @param K - The plugin key
|
|
@@ -247,5 +268,5 @@ interface PluginRuntimeConfig<R extends Record<string, PluginRegistryEntry> = Re
|
|
|
247
268
|
secrets?: SecretsConfig;
|
|
248
269
|
}
|
|
249
270
|
//#endregion
|
|
250
|
-
export { AnyPlugin, AnyPluginConstructor, EveryPlugin, ExtractPluginType, InferRegistryFromEntries, InitializedPlugin, LoadedPlugin, PluginClientType, PluginConfigInput, PluginContext, PluginContextInput, PluginContract, PluginInstance, PluginMetadata, PluginRegistry, PluginRegistryEntry, PluginRouterType, PluginRuntimeConfig, PluginSecrets, PluginServicesEntry, PluginVariables, RegisteredPlugin, RegisteredPlugins, SecretsConfig, UsePluginResult };
|
|
271
|
+
export { AnyPlugin, AnyPluginConstructor, EveryPlugin, ExtractPluginType, InferRegistryFromEntries, InitializedPlugin, LoadedPlugin, ModuleClientEntry, ModuleEndpoint, ModuleSurface, ModuleTransport, PluginClientEntry, PluginClientType, PluginConfigInput, PluginContext, PluginContextInput, PluginContract, PluginEndpoint, PluginInstance, PluginMetadata, PluginRegistry, PluginRegistryEntry, PluginRouterType, PluginRuntimeConfig, PluginSecrets, PluginServicesEntry, PluginSurface, PluginTransport, PluginVariables, RegisteredPlugin, RegisteredPlugins, SecretsConfig, UsePluginResult };
|
|
251
272
|
//# sourceMappingURL=types.d.cts.map
|
package/dist/types.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.cts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;;;;;;;;;;;;;;UAwBiB;;;;
|
|
1
|
+
{"version":3,"file":"types.d.cts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;;;;;;;;;;;;;;UAwBiB;KAEL;KAEA;UAEK;WACN,WAAW;WACX,UAAU;WACV;WACA;WACA;;KAGC,kBAAkB;KAElB,gBAAgB;KAEhB,iBAAiB;;;;KAKjB,YAAY,OAAO,mBAAmB,WAAW,WAAW;;;;KAK5D;UACF;EACR;IACE,UAAU;IACV,WAAW;IACX,SAAS;IACT,SAAS;;;;;;KAOD;EAEN,QAAQ;EACR;EACA,WAAW;EACX;EACA;;EAEA;EAAgB,WAAW;EAAgB;EAAkB;;;;;KAKvD,kBAAkB,KAAK;EAAY,cAAc;IAAM;;;;KAKvD,yBAAyB,UAAU,eAAe,2BAC3D,WAAW,IAAI,EAAE;EAAa,cAAc;IACzC,IACA,gBAAgB,oBACd,kBAAkB;;;;KAOd,eAAe,KAAK;EAC9B;IAAW,gBAAgB,UAAU;;IAEnC;;;;KAMQ,gBAAgB,KAAK;EAAY;IAAW,iBAAiB,UAAU;;IAC/E;;;;KAMQ,cAAc,KAAK;EAAY;IAAW,eAAe,UAAU;;IAC3E;;;;KAMQ,cAAc,KAAK;EAC7B;IAAW,eAAe,UAAU;;IAElC;;;;;KAOQ,iBAAiB,KAAK,iBAAiB,eAAe;;;;KAKtD,iBAAiB,KAAK,aAAa,iBAAiB;;;;;;KAOpD,oBAAoB;EAC9B,SAAS,UAAU,mBAAmB,OAAO,iBAAiB;EAC9D,QAAQ,iBAAiB;EACzB,WAAW;;KAGD,kBAAkB,UAAU,oBAAoB;EAC1D,SAAS,UAAU,4BAA4B,aAAa,iBAAiB;EAC7E,SAAS,iBAAiB;EAC1B,WAAW;;KAGD,kBAAkB,UAAU,oBAAoB,qBAC1D,kBAAkB;;;;;;KAOR,iBAAiB,gBAAgB,GAAG,IAAI,qBAAqB,EAAE;EACzE,eAAe;IAEb;EACE,gBAAgB,UAAU;EAC1B,iBAAiB,UAAU;EAC3B,eAAe,UAAU;EACzB,eAAe,wBAAwB;IAEvC,OAAO,GAAG,GAAG,GAAG;;;;KAOV,mBAAmB,KAC7B,cAAc,WAAW,YAAY,iBAAiB,cAAc;;;;KAK1D,kBAAkB;EAC5B,WAAW,iBAAiB,gBAAgB;EAC5C,SAAS,iBAAiB,cAAc;;;;;KAM9B;WACD;WACA;WACA;;;;;KAMC,iBAAiB,eAAe;;;;;UAM3B;GACd;;;;;UAMc,aAAa,UAAU,YAAY;WACzC,gBAAgB;WAChB,UAAU;;;;;UAMJ,eAAe,UAAU,YAAY;WAC3C,QAAQ;WACR,UAAU;;;;;UAMJ,kBAAkB,UAAU,YAAY;WAC9C,QAAQ;WACR,UAAU;WACV;IACP,WAAW,kBAAkB;IAC7B,SAAS,kBAAkB;;;;;;;WAOpB,eAAe,QAAQ;WACvB,OAAO,MAAM;;WAEb,UAAU;;;;;KAMhB,oBAAoB,gBAAgB,GAAG,IAAI,qBAAqB,EAAE;EACrE,eAAe;IAEb;EACE,UAAU;EACV,WAAW;EACX,SAAS;EACT,SAAS;wBAGI,4IACF;;;;;;KAOL,gBAAgB,gBAAgB,GAAG,IAAI,qBACjD,oBAAoB,GAAG;WAER,eAAe,UAAU,mBAAmB,EAAE,QAAQ,iBAAiB,EAAE;WACzE,QAAQ,iBAAiB,EAAE;WAC3B,UAAU;WACV,aAAa,kBAAkB,iBAAiB,GAAG;IAE9D,oBAAoB,GAAG;;;;;;;KAQxB,WAAW,KAAK;EAAY,uBAAuB;IAAM,IAAI;;;;kBAKjD;;;;;;;;;;;;;;;;;;OAkBH,MACV,kBACA,SAAS,qBACP,gBAAgB,WAAW,UAAU,gBAAgB,GAAG,WAAW;;;;;UAMxD,oBACf,UAAU,eAAe,uBAAuB,eAAe;EAE/D,UAAU;EACV,UAAU"}
|
package/dist/types.d.mts
CHANGED
|
@@ -17,6 +17,18 @@ import { AnyContractRouter, AnySchema, InferSchemaInput, InferSchemaOutput } fro
|
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
19
|
interface RegisteredPlugins {}
|
|
20
|
+
type ModuleTransport = "inproc" | "rpc" | "mf";
|
|
21
|
+
type ModuleSurface = "api" | "ui" | "jobs";
|
|
22
|
+
interface ModuleEndpoint {
|
|
23
|
+
readonly transport: ModuleTransport;
|
|
24
|
+
readonly surface?: ModuleSurface;
|
|
25
|
+
readonly url: string;
|
|
26
|
+
readonly path?: `/${string}`;
|
|
27
|
+
readonly manifest?: string;
|
|
28
|
+
}
|
|
29
|
+
type PluginTransport = ModuleTransport;
|
|
30
|
+
type PluginSurface = ModuleSurface;
|
|
31
|
+
type PluginEndpoint = ModuleEndpoint;
|
|
20
32
|
/**
|
|
21
33
|
* Base type for any plugin instance.
|
|
22
34
|
*/
|
|
@@ -39,10 +51,12 @@ type AnyPluginConstructor = {
|
|
|
39
51
|
type PluginRegistryEntry = {
|
|
40
52
|
module: AnyPluginConstructor;
|
|
41
53
|
remote?: string;
|
|
54
|
+
endpoint?: PluginEndpoint;
|
|
42
55
|
version?: string;
|
|
43
56
|
description?: string;
|
|
44
57
|
} | {
|
|
45
58
|
remote: string;
|
|
59
|
+
endpoint?: PluginEndpoint;
|
|
46
60
|
version?: string;
|
|
47
61
|
description?: string;
|
|
48
62
|
};
|
|
@@ -107,7 +121,14 @@ type PluginClientType<T> = RouterClient<PluginRouterType<T>>;
|
|
|
107
121
|
type PluginServicesEntry<T = any> = {
|
|
108
122
|
client: (context?: PluginContextInput<T>) => PluginClientType<T>;
|
|
109
123
|
router: PluginRouterType<T>;
|
|
124
|
+
endpoint?: PluginEndpoint;
|
|
125
|
+
};
|
|
126
|
+
type ModuleClientEntry<C extends AnyContractRouter = AnyContractRouter> = {
|
|
127
|
+
client: (context?: Record<string, unknown>) => RouterClient<ContractedRouter<C, any>>;
|
|
128
|
+
router?: ContractedRouter<C, any>;
|
|
129
|
+
endpoint?: PluginEndpoint;
|
|
110
130
|
};
|
|
131
|
+
type PluginClientEntry<C extends AnyContractRouter = AnyContractRouter> = ModuleClientEntry<C>;
|
|
111
132
|
/**
|
|
112
133
|
* Extract plugin type from registered plugins by key
|
|
113
134
|
* @param K - The plugin key
|
|
@@ -247,5 +268,5 @@ interface PluginRuntimeConfig<R extends Record<string, PluginRegistryEntry> = Re
|
|
|
247
268
|
secrets?: SecretsConfig;
|
|
248
269
|
}
|
|
249
270
|
//#endregion
|
|
250
|
-
export { AnyPlugin, AnyPluginConstructor, EveryPlugin, ExtractPluginType, InferRegistryFromEntries, InitializedPlugin, LoadedPlugin, PluginClientType, PluginConfigInput, PluginContext, PluginContextInput, PluginContract, PluginInstance, PluginMetadata, PluginRegistry, PluginRegistryEntry, PluginRouterType, PluginRuntimeConfig, PluginSecrets, PluginServicesEntry, PluginVariables, RegisteredPlugin, RegisteredPlugins, SecretsConfig, UsePluginResult };
|
|
271
|
+
export { AnyPlugin, AnyPluginConstructor, EveryPlugin, ExtractPluginType, InferRegistryFromEntries, InitializedPlugin, LoadedPlugin, ModuleClientEntry, ModuleEndpoint, ModuleSurface, ModuleTransport, PluginClientEntry, PluginClientType, PluginConfigInput, PluginContext, PluginContextInput, PluginContract, PluginEndpoint, PluginInstance, PluginMetadata, PluginRegistry, PluginRegistryEntry, PluginRouterType, PluginRuntimeConfig, PluginSecrets, PluginServicesEntry, PluginSurface, PluginTransport, PluginVariables, RegisteredPlugin, RegisteredPlugins, SecretsConfig, UsePluginResult };
|
|
251
272
|
//# sourceMappingURL=types.d.mts.map
|
package/dist/types.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.mts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;;;;;;;;;;;;;;UAwBiB;;;;
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;;;;;;;;;;;;;;UAwBiB;KAEL;KAEA;UAEK;WACN,WAAW;WACX,UAAU;WACV;WACA;WACA;;KAGC,kBAAkB;KAElB,gBAAgB;KAEhB,iBAAiB;;;;KAKjB,YAAY,OAAO,mBAAmB,WAAW,WAAW;;;;KAK5D;UACF;EACR;IACE,UAAU;IACV,WAAW;IACX,SAAS;IACT,SAAS;;;;;;KAOD;EAEN,QAAQ;EACR;EACA,WAAW;EACX;EACA;;EAEA;EAAgB,WAAW;EAAgB;EAAkB;;;;;KAKvD,kBAAkB,KAAK;EAAY,cAAc;IAAM;;;;KAKvD,yBAAyB,UAAU,eAAe,2BAC3D,WAAW,IAAI,EAAE;EAAa,cAAc;IACzC,IACA,gBAAgB,oBACd,kBAAkB;;;;KAOd,eAAe,KAAK;EAC9B;IAAW,gBAAgB,UAAU;;IAEnC;;;;KAMQ,gBAAgB,KAAK;EAAY;IAAW,iBAAiB,UAAU;;IAC/E;;;;KAMQ,cAAc,KAAK;EAAY;IAAW,eAAe,UAAU;;IAC3E;;;;KAMQ,cAAc,KAAK;EAC7B;IAAW,eAAe,UAAU;;IAElC;;;;;KAOQ,iBAAiB,KAAK,iBAAiB,eAAe;;;;KAKtD,iBAAiB,KAAK,aAAa,iBAAiB;;;;;;KAOpD,oBAAoB;EAC9B,SAAS,UAAU,mBAAmB,OAAO,iBAAiB;EAC9D,QAAQ,iBAAiB;EACzB,WAAW;;KAGD,kBAAkB,UAAU,oBAAoB;EAC1D,SAAS,UAAU,4BAA4B,aAAa,iBAAiB;EAC7E,SAAS,iBAAiB;EAC1B,WAAW;;KAGD,kBAAkB,UAAU,oBAAoB,qBAC1D,kBAAkB;;;;;;KAOR,iBAAiB,gBAAgB,GAAG,IAAI,qBAAqB,EAAE;EACzE,eAAe;IAEb;EACE,gBAAgB,UAAU;EAC1B,iBAAiB,UAAU;EAC3B,eAAe,UAAU;EACzB,eAAe,wBAAwB;IAEvC,OAAO,GAAG,GAAG,GAAG;;;;KAOV,mBAAmB,KAC7B,cAAc,WAAW,YAAY,iBAAiB,cAAc;;;;KAK1D,kBAAkB;EAC5B,WAAW,iBAAiB,gBAAgB;EAC5C,SAAS,iBAAiB,cAAc;;;;;KAM9B;WACD;WACA;WACA;;;;;KAMC,iBAAiB,eAAe;;;;;UAM3B;GACd;;;;;UAMc,aAAa,UAAU,YAAY;WACzC,gBAAgB;WAChB,UAAU;;;;;UAMJ,eAAe,UAAU,YAAY;WAC3C,QAAQ;WACR,UAAU;;;;;UAMJ,kBAAkB,UAAU,YAAY;WAC9C,QAAQ;WACR,UAAU;WACV;IACP,WAAW,kBAAkB;IAC7B,SAAS,kBAAkB;;;;;;;WAOpB,eAAe,QAAQ;WACvB,OAAO,MAAM;;WAEb,UAAU;;;;;KAMhB,oBAAoB,gBAAgB,GAAG,IAAI,qBAAqB,EAAE;EACrE,eAAe;IAEb;EACE,UAAU;EACV,WAAW;EACX,SAAS;EACT,SAAS;wBAGI,4IACF;;;;;;KAOL,gBAAgB,gBAAgB,GAAG,IAAI,qBACjD,oBAAoB,GAAG;WAER,eAAe,UAAU,mBAAmB,EAAE,QAAQ,iBAAiB,EAAE;WACzE,QAAQ,iBAAiB,EAAE;WAC3B,UAAU;WACV,aAAa,kBAAkB,iBAAiB,GAAG;IAE9D,oBAAoB,GAAG;;;;;;;KAQxB,WAAW,KAAK;EAAY,uBAAuB;IAAM,IAAI;;;;kBAKjD;;;;;;;;;;;;;;;;;;OAkBH,MACV,kBACA,SAAS,qBACP,gBAAgB,WAAW,UAAU,gBAAgB,GAAG,WAAW;;;;;UAMxD,oBACf,UAAU,eAAe,uBAAuB,eAAe;EAE/D,UAAU;EACV,UAAU"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "every-plugin",
|
|
3
|
-
"version": "3.0.0-rc.
|
|
3
|
+
"version": "3.0.0-rc.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -18,6 +18,14 @@
|
|
|
18
18
|
"import": "./dist/index.mjs",
|
|
19
19
|
"require": "./dist/index.cjs"
|
|
20
20
|
},
|
|
21
|
+
"./client": {
|
|
22
|
+
"bun": {
|
|
23
|
+
"types": "./src/client.ts",
|
|
24
|
+
"import": "./src/client.ts"
|
|
25
|
+
},
|
|
26
|
+
"types": "./dist/client.d.mts",
|
|
27
|
+
"import": "./dist/client.mjs"
|
|
28
|
+
},
|
|
21
29
|
"./identity": {
|
|
22
30
|
"bun": {
|
|
23
31
|
"types": "./src/identity.ts",
|
|
@@ -144,6 +152,14 @@
|
|
|
144
152
|
"import": "./dist/build/ui/index.mjs",
|
|
145
153
|
"require": "./dist/build/ui/index.cjs"
|
|
146
154
|
},
|
|
155
|
+
"./dev-host": {
|
|
156
|
+
"bun": {
|
|
157
|
+
"types": "./src/dev/host.ts",
|
|
158
|
+
"import": "./src/dev/host.ts"
|
|
159
|
+
},
|
|
160
|
+
"types": "./dist/dev/host.d.mts",
|
|
161
|
+
"import": "./dist/dev/host.mjs"
|
|
162
|
+
},
|
|
147
163
|
"./dev-serve": {
|
|
148
164
|
"bun": {
|
|
149
165
|
"types": "./src/dev/serve.ts",
|
|
@@ -222,7 +238,8 @@
|
|
|
222
238
|
"@rsbuild/plugin-react": "2.1.0",
|
|
223
239
|
"@tanstack/router-generator": "1.167.33",
|
|
224
240
|
"@tanstack/router-plugin": "1.168.35",
|
|
225
|
-
"sirv": "3.0.2"
|
|
241
|
+
"sirv": "3.0.2",
|
|
242
|
+
"sonner": ">=2.0.0"
|
|
226
243
|
},
|
|
227
244
|
"keywords": [
|
|
228
245
|
"plugin",
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { createORPCClient, onError } from "@orpc/client";
|
|
2
|
+
import { RPCLink } from "@orpc/client/fetch";
|
|
3
|
+
import type { ContractRouterClient, RouterContract } from "@orpc/contract";
|
|
4
|
+
|
|
5
|
+
export type RpcConnectionErrorCopy = () => { title: string; description: string };
|
|
6
|
+
|
|
7
|
+
export interface RpcClientConfig {
|
|
8
|
+
hostUrl: string;
|
|
9
|
+
path: `/${string}`;
|
|
10
|
+
connectionError?: RpcConnectionErrorCopy;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const RATE_LIMIT_MAX_RETRIES = 3;
|
|
14
|
+
const RATE_LIMIT_RETRY_CAP_MS = 2_000;
|
|
15
|
+
const browserClients = new Map<string, unknown>();
|
|
16
|
+
type FetchInput = Parameters<typeof fetch>[0];
|
|
17
|
+
|
|
18
|
+
async function fetchWithRateLimitRetry(
|
|
19
|
+
fetchUrl: FetchInput,
|
|
20
|
+
options?: RequestInit,
|
|
21
|
+
): Promise<Response> {
|
|
22
|
+
let response = await fetch(fetchUrl, options);
|
|
23
|
+
for (let attempt = 1; attempt <= RATE_LIMIT_MAX_RETRIES && response.status === 429; attempt++) {
|
|
24
|
+
const retryAfterSeconds = Number(response.headers.get("retry-after"));
|
|
25
|
+
const delay =
|
|
26
|
+
Number.isFinite(retryAfterSeconds) && retryAfterSeconds > 0
|
|
27
|
+
? Math.min(retryAfterSeconds * 1000, RATE_LIMIT_RETRY_CAP_MS)
|
|
28
|
+
: 100 * attempt;
|
|
29
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
30
|
+
response = await fetch(fetchUrl, options);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return response;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function createRpcLink(config: RpcClientConfig, headers?: Headers) {
|
|
37
|
+
return new RPCLink({
|
|
38
|
+
origin: config.hostUrl,
|
|
39
|
+
url: config.path,
|
|
40
|
+
interceptors: [
|
|
41
|
+
onError((error: unknown) => {
|
|
42
|
+
const browserWindow = (globalThis as { window?: unknown }).window;
|
|
43
|
+
if (typeof browserWindow === "undefined") {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (error && typeof error === "object" && "message" in error) {
|
|
48
|
+
const message = String(error.message).toLowerCase();
|
|
49
|
+
if (
|
|
50
|
+
message.includes("fetch") ||
|
|
51
|
+
message.includes("network") ||
|
|
52
|
+
message.includes("failed to fetch")
|
|
53
|
+
) {
|
|
54
|
+
void import("sonner")
|
|
55
|
+
.then(({ toast }) => {
|
|
56
|
+
const message = config.connectionError?.() ?? {
|
|
57
|
+
title: "Unable to connect to API",
|
|
58
|
+
description: "The API is currently unavailable. Please try again later.",
|
|
59
|
+
};
|
|
60
|
+
toast.error(message.title, {
|
|
61
|
+
id: "api-connection-error",
|
|
62
|
+
description: message.description,
|
|
63
|
+
});
|
|
64
|
+
})
|
|
65
|
+
.catch(() => {});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}),
|
|
69
|
+
],
|
|
70
|
+
fetch(fetchUrl: FetchInput, options?: RequestInit) {
|
|
71
|
+
return fetchWithRateLimitRetry(fetchUrl, {
|
|
72
|
+
...options,
|
|
73
|
+
credentials: "include",
|
|
74
|
+
headers: headers
|
|
75
|
+
? { ...Object.fromEntries(headers), ...(options?.headers as Record<string, string>) }
|
|
76
|
+
: options?.headers,
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function buildRpcClient<T extends RouterContract>(
|
|
83
|
+
config: RpcClientConfig,
|
|
84
|
+
headers?: Headers,
|
|
85
|
+
): ContractRouterClient<T> {
|
|
86
|
+
if (!config.hostUrl) {
|
|
87
|
+
throw new Error("Missing runtime host URL");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return createORPCClient(createRpcLink(config, headers)) as ContractRouterClient<T>;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function createRpcClient<T extends RouterContract = RouterContract>(
|
|
94
|
+
config: RpcClientConfig,
|
|
95
|
+
headers?: Headers,
|
|
96
|
+
): ContractRouterClient<T> {
|
|
97
|
+
const browserWindow = (globalThis as { window?: unknown }).window;
|
|
98
|
+
if (typeof browserWindow !== "undefined" && !headers) {
|
|
99
|
+
const key = `${config.hostUrl}${config.path}`;
|
|
100
|
+
const memoized = browserClients.get(key);
|
|
101
|
+
if (memoized) {
|
|
102
|
+
return memoized as ContractRouterClient<T>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const client = buildRpcClient<T>(config, headers);
|
|
106
|
+
browserClients.set(key, client);
|
|
107
|
+
return client;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return buildRpcClient<T>(config, headers);
|
|
111
|
+
}
|
package/src/dev/host.ts
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import type http from "node:http";
|
|
2
|
+
import { createServer } from "node:http";
|
|
3
|
+
|
|
4
|
+
const corsHeaders = {
|
|
5
|
+
"Access-Control-Allow-Origin": "*",
|
|
6
|
+
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
|
|
7
|
+
"Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization",
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const applyCorsHeaders = (res: http.ServerResponse) => {
|
|
11
|
+
Object.entries(corsHeaders).forEach(([key, value]) => {
|
|
12
|
+
res.setHeader(key, value);
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const sendJson = (res: http.ServerResponse, status: number, body: unknown) => {
|
|
17
|
+
res.statusCode = status;
|
|
18
|
+
res.setHeader("content-type", "application/json; charset=utf-8");
|
|
19
|
+
res.end(JSON.stringify(body));
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const sendText = (res: http.ServerResponse, status: number, text: string) => {
|
|
23
|
+
res.statusCode = status;
|
|
24
|
+
res.setHeader("content-type", "text/plain; charset=utf-8");
|
|
25
|
+
res.end(text);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const pathnameOf = (req: http.IncomingMessage): string =>
|
|
29
|
+
((req.url ?? "/").split("?")[0] ?? "/").replace(/\/+$/, "") || "/";
|
|
30
|
+
|
|
31
|
+
const toWebRequest = (req: http.IncomingMessage, port: number): Request => {
|
|
32
|
+
const url = `http://localhost:${port}${req.url}`;
|
|
33
|
+
return new Request(url, {
|
|
34
|
+
method: req.method,
|
|
35
|
+
headers: req.headers,
|
|
36
|
+
body: req.method !== "GET" && req.method !== "HEAD" ? req : undefined,
|
|
37
|
+
duplex: req.method !== "GET" && req.method !== "HEAD" ? "half" : undefined,
|
|
38
|
+
} as RequestInit);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const buildHostContext = (
|
|
42
|
+
effectContext: unknown,
|
|
43
|
+
webRequest: Request,
|
|
44
|
+
cachedRawBodyRef: { value: string | null },
|
|
45
|
+
) => {
|
|
46
|
+
const rawClone =
|
|
47
|
+
webRequest.method === "GET" || webRequest.method === "HEAD" ? null : webRequest.clone();
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
reqHeaders: webRequest.headers,
|
|
51
|
+
"effect/context": effectContext,
|
|
52
|
+
getRawBody: async (): Promise<string> => {
|
|
53
|
+
if (cachedRawBodyRef.value !== null) return cachedRawBodyRef.value;
|
|
54
|
+
if (!rawClone) {
|
|
55
|
+
cachedRawBodyRef.value = "";
|
|
56
|
+
return cachedRawBodyRef.value;
|
|
57
|
+
}
|
|
58
|
+
cachedRawBodyRef.value = await rawClone.text();
|
|
59
|
+
return cachedRawBodyRef.value;
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export interface DirectModuleHostHandler {
|
|
65
|
+
handle(
|
|
66
|
+
request: Request,
|
|
67
|
+
options: { prefix: string; context: unknown },
|
|
68
|
+
): Promise<{ response?: Response }>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const handleOrpc = async (
|
|
72
|
+
req: http.IncomingMessage,
|
|
73
|
+
res: http.ServerResponse,
|
|
74
|
+
handler: DirectModuleHostHandler,
|
|
75
|
+
prefix: string,
|
|
76
|
+
errorLabel: string,
|
|
77
|
+
effectContext: unknown,
|
|
78
|
+
port: number,
|
|
79
|
+
) => {
|
|
80
|
+
try {
|
|
81
|
+
const webRequest = toWebRequest(req, port);
|
|
82
|
+
const cachedRawBodyRef = { value: null as string | null };
|
|
83
|
+
const result = await handler.handle(webRequest, {
|
|
84
|
+
prefix,
|
|
85
|
+
context: buildHostContext(effectContext, webRequest, cachedRawBodyRef),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (result.response) {
|
|
89
|
+
res.statusCode = result.response.status;
|
|
90
|
+
result.response.headers.forEach((value: string, key: string) => {
|
|
91
|
+
res.setHeader(key, value);
|
|
92
|
+
});
|
|
93
|
+
const text = await result.response.text();
|
|
94
|
+
if (!res.getHeader("content-length")) {
|
|
95
|
+
res.setHeader("content-length", Buffer.byteLength(text).toString());
|
|
96
|
+
}
|
|
97
|
+
res.end(text);
|
|
98
|
+
} else {
|
|
99
|
+
sendText(res, 404, "Not Found");
|
|
100
|
+
}
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.error(`${errorLabel} error:`, error);
|
|
103
|
+
sendJson(res, 500, { error: (error as Error).message });
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export interface DirectModuleHostHandlers {
|
|
108
|
+
rpc: DirectModuleHostHandler | null;
|
|
109
|
+
api: DirectModuleHostHandler | null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface DirectModuleHostOptions {
|
|
113
|
+
name: string;
|
|
114
|
+
handlers: DirectModuleHostHandlers;
|
|
115
|
+
effectContext: unknown;
|
|
116
|
+
port?: number;
|
|
117
|
+
version?: string;
|
|
118
|
+
rpcPrefix?: `/${string}`;
|
|
119
|
+
apiPrefix?: `/${string}`;
|
|
120
|
+
staticHandler?:
|
|
121
|
+
| ((req: http.IncomingMessage, res: http.ServerResponse, next: () => void) => void)
|
|
122
|
+
| null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface DirectModuleHostHandle {
|
|
126
|
+
port: number;
|
|
127
|
+
close: () => Promise<void>;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export async function startDirectModuleHost(
|
|
131
|
+
options: DirectModuleHostOptions,
|
|
132
|
+
): Promise<DirectModuleHostHandle> {
|
|
133
|
+
const port = options.port ?? 0;
|
|
134
|
+
let resolvedPort = port;
|
|
135
|
+
const rpcPrefix = options.rpcPrefix ?? "/api/rpc";
|
|
136
|
+
const apiPrefix = options.apiPrefix ?? "/api";
|
|
137
|
+
const staticHandler = options.staticHandler ?? null;
|
|
138
|
+
const resolveEffectContext: () => unknown =
|
|
139
|
+
typeof options.effectContext === "function"
|
|
140
|
+
? (options.effectContext as () => unknown)
|
|
141
|
+
: () => options.effectContext;
|
|
142
|
+
|
|
143
|
+
const server = createServer((req, res) => {
|
|
144
|
+
applyCorsHeaders(res);
|
|
145
|
+
const pathname = pathnameOf(req);
|
|
146
|
+
|
|
147
|
+
if (req.method === "OPTIONS") {
|
|
148
|
+
res.statusCode = 200;
|
|
149
|
+
res.end();
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (pathname === "/" && (req.method === "GET" || req.method === "HEAD")) {
|
|
154
|
+
sendJson(res, 200, {
|
|
155
|
+
ok: true,
|
|
156
|
+
module: options.name,
|
|
157
|
+
version: options.version,
|
|
158
|
+
status: options.handlers.rpc ? "ready" : "loading",
|
|
159
|
+
endpoints: {
|
|
160
|
+
health: "/health",
|
|
161
|
+
docs: apiPrefix,
|
|
162
|
+
rpc: rpcPrefix,
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (pathname === "/health" && (req.method === "GET" || req.method === "HEAD")) {
|
|
169
|
+
sendText(res, 200, "OK");
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (pathname.startsWith(`${rpcPrefix}/`)) {
|
|
174
|
+
if (!options.handlers.rpc) {
|
|
175
|
+
sendJson(res, 503, { error: "Plugin still loading..." });
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
handleOrpc(
|
|
179
|
+
req,
|
|
180
|
+
res,
|
|
181
|
+
options.handlers.rpc,
|
|
182
|
+
rpcPrefix,
|
|
183
|
+
"RPC",
|
|
184
|
+
resolveEffectContext(),
|
|
185
|
+
resolvedPort,
|
|
186
|
+
).catch(() => {});
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (pathname === apiPrefix || pathname.startsWith(`${apiPrefix}/`)) {
|
|
191
|
+
if (!options.handlers.api) {
|
|
192
|
+
sendJson(res, 503, { error: "Plugin still loading..." });
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
handleOrpc(
|
|
196
|
+
req,
|
|
197
|
+
res,
|
|
198
|
+
options.handlers.api,
|
|
199
|
+
apiPrefix,
|
|
200
|
+
"OpenAPI",
|
|
201
|
+
resolveEffectContext(),
|
|
202
|
+
resolvedPort,
|
|
203
|
+
).catch(() => {});
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (staticHandler) {
|
|
208
|
+
staticHandler(req, res, () => {
|
|
209
|
+
sendText(res, 404, "Not Found");
|
|
210
|
+
});
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
sendText(res, 404, "Not Found");
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
await new Promise<void>((resolve, reject) => {
|
|
218
|
+
server.once("error", reject);
|
|
219
|
+
server.listen(port, () => resolve());
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const address = server.address();
|
|
223
|
+
if (!address || typeof address === "string") {
|
|
224
|
+
await new Promise<void>((resolve) => server.close(() => resolve()));
|
|
225
|
+
throw new Error("Failed to resolve host port");
|
|
226
|
+
}
|
|
227
|
+
resolvedPort = address.port;
|
|
228
|
+
|
|
229
|
+
return {
|
|
230
|
+
port: resolvedPort,
|
|
231
|
+
close: async () => {
|
|
232
|
+
await new Promise<void>((resolve) => server.close(() => resolve()));
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
}
|