import { HandlerWrapper } from "../types/rpc.js";
import { ServiceComponent, VirtualObjectComponent, WorkflowComponent } from "./components.js";
import { LogSource } from "../logging/logger_transport.js";
import { defaultLoggerTransport } from "../logging/console_logger_transport.js";
import { createLogger } from "../logging/logger.js";

//#region src/endpoint/endpoint.ts
function isServiceDefinition(m) {
	return m && m.service !== void 0;
}
function isObjectDefinition(m) {
	return m && m.object !== void 0;
}
function isWorkflowDefinition(m) {
	return m && m.workflow !== void 0;
}
var EndpointBuilder = class {
	serviceDefinitions = /* @__PURE__ */ new Map();
	loggerTransport = defaultLoggerTransport;
	keySet = [];
	defaultServiceOptions = {};
	journalValueCodecProvider;
	bind(definition) {
		if (definition.name.indexOf("/") !== -1) throw new Error("service name must not contain any slash '/'");
		this.serviceDefinitions.set(definition.name, definition);
	}
	addIdentityKeys(...keys) {
		this.keySet.push(...keys);
	}
	setDefaultServiceOptions(options) {
		this.defaultServiceOptions = options;
	}
	setLogger(newLogger) {
		this.loggerTransport = newLogger;
	}
	setJournalValueCodecProvider(codecProvider) {
		this.journalValueCodecProvider = codecProvider;
	}
	build() {
		const rlog = createLogger(this.loggerTransport, LogSource.SYSTEM);
		const components = /* @__PURE__ */ new Map();
		for (const [name, definition] of this.serviceDefinitions) if (isServiceDefinition(definition)) {
			const { name: name$1, service } = definition;
			if (!service) throw new TypeError(`no service implementation found.`);
			components.set(name$1, buildServiceComponent(name$1, service, definition, this.defaultServiceOptions));
		} else if (isObjectDefinition(definition)) {
			const { name: name$1, object } = definition;
			if (!object) throw new TypeError(`no object implementation found.`);
			components.set(name$1, buildVirtualObjectComponent(name$1, object, definition, this.defaultServiceOptions));
		} else if (isWorkflowDefinition(definition)) {
			const { name: name$1, workflow } = definition;
			if (!workflow) throw new TypeError(`no workflow implementation found.`);
			components.set(name$1, buildWorkflowComponent(name$1, workflow, definition, this.defaultServiceOptions));
		} else throw new TypeError(`cannot bind ${name}, can only bind a service or a virtual object or a workflow definition`);
		const discoveryMetadata = computeDiscovery(components);
		return {
			keySet: this.keySet,
			loggerTransport: this.loggerTransport,
			rlog,
			components,
			discoveryMetadata,
			journalValueCodec: this.journalValueCodecProvider ? this.journalValueCodecProvider() : void 0
		};
	}
};
function computeDiscovery(components) {
	return {
		minProtocolVersion: 5,
		maxProtocolVersion: 6,
		services: [...components.values()].map((c) => c.discovery())
	};
}
function buildServiceComponent(name, router, definition, defaultServiceOptions) {
	if (name.indexOf("/") !== -1) throw new Error("service name must not contain any slash '/'");
	const component = new ServiceComponent(name, definition.description, definition.metadata, {
		...defaultServiceOptions,
		...definition?.options
	});
	for (const [route, handler] of Object.entries(router)) {
		const wrapper = HandlerWrapper.fromHandler(handler);
		if (!wrapper) throw new TypeError(`${route} is not a restate handler.`);
		wrapper.bindInstance(router);
		component.add(route, wrapper);
	}
	return component;
}
function buildVirtualObjectComponent(name, router, definition, defaultServiceOptions) {
	if (name.indexOf("/") !== -1) throw new Error("service name must not contain any slash '/'");
	const component = new VirtualObjectComponent(name, definition.description, definition.metadata, {
		...defaultServiceOptions,
		...definition?.options
	});
	for (const [route, handler] of Object.entries(router)) {
		const wrapper = HandlerWrapper.fromHandler(handler);
		if (!wrapper) throw new TypeError(`${route} is not a restate handler.`);
		wrapper.bindInstance(router);
		component.add(route, wrapper);
	}
	return component;
}
function buildWorkflowComponent(name, workflow, definition, defaultServiceOptions) {
	if (name.indexOf("/") !== -1) throw new Error("service name must not contain any slash '/'");
	const component = new WorkflowComponent(name, definition.description, definition.metadata, {
		...defaultServiceOptions,
		...definition?.options
	});
	for (const [route, handler] of Object.entries(workflow)) {
		const wrapper = HandlerWrapper.fromHandler(handler);
		if (!wrapper) throw new TypeError(`${route} is not a restate handler.`);
		wrapper.bindInstance(workflow);
		component.add(route, wrapper);
	}
	return component;
}

//#endregion
export { EndpointBuilder };
//# sourceMappingURL=endpoint.js.map