@k-msg/provider 0.27.0 → 0.27.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@k-msg/provider",
3
- "version": "0.27.0",
3
+ "version": "0.27.1",
4
4
  "packageManager": "bun@1.3.8",
5
5
  "type": "module",
6
6
  "description": "Complete provider system with adapters and implementations for K-Message platform",
@@ -51,8 +51,8 @@
51
51
  "publish": "bun publish --access public"
52
52
  },
53
53
  "dependencies": {
54
- "@k-msg/core": "0.27.0",
55
- "@k-msg/template": "0.27.0"
54
+ "@k-msg/core": "0.27.1",
55
+ "@k-msg/template": "0.27.1"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/bun": "^1.3.9",
@@ -78,7 +78,9 @@
78
78
  "adapter"
79
79
  ],
80
80
  "files": [
81
- "dist",
81
+ "dist/**/*.js",
82
+ "dist/**/*.mjs",
83
+ "dist/**/*.d.ts",
82
84
  "README.md"
83
85
  ],
84
86
  "repository": {
@@ -1,18 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/aligo/provider.ts", "../src/onboarding/specs.ts", "../src/aligo/aligo.kakao.ts", "../src/shared/type-guards.ts", "../src/aligo/aligo.error.ts", "../src/aligo/aligo.helpers.ts", "../src/aligo/aligo.http.ts", "../src/aligo/aligo.send.ts", "../src/aligo/aligo.template.ts"],
4
- "sourcesContent": [
5
- "import {\n type KakaoChannel,\n type KakaoChannelCategories,\n type KakaoChannelProvider,\n type KMsgError,\n type MessageType,\n type Provider,\n type ProviderHealthStatus,\n type Result,\n readRuntimeEnv,\n type SendOptions,\n type SendResult,\n type Template,\n type TemplateContext,\n type TemplateCreateInput,\n type TemplateInspectionProvider,\n type TemplateProvider,\n type TemplateUpdateInput,\n} from \"@k-msg/core\";\nimport { getProviderOnboardingSpec } from \"../onboarding/specs\";\nimport type { AligoRuntimeContext } from \"./aligo.internal.types\";\nimport {\n addKakaoChannel,\n listKakaoChannelCategories,\n listKakaoChannels,\n requestKakaoChannelAuth,\n} from \"./aligo.kakao\";\nimport { sendWithAligo } from \"./aligo.send\";\nimport {\n createTemplate,\n deleteTemplate,\n getTemplate,\n listTemplates,\n requestTemplateInspection,\n updateTemplate,\n} from \"./aligo.template\";\nimport type { AligoConfig } from \"./types/aligo\";\n\nexport class AligoProvider\n implements\n Provider,\n TemplateProvider,\n TemplateInspectionProvider,\n KakaoChannelProvider\n{\n readonly id = \"aligo\";\n readonly name = \"Aligo Smart SMS\";\n readonly supportedTypes: readonly MessageType[] = [\n \"ALIMTALK\",\n \"FRIENDTALK\",\n \"SMS\",\n \"LMS\",\n \"MMS\",\n ];\n\n private readonly smsHost: string;\n private readonly alimtalkHost: string;\n\n getOnboardingSpec() {\n const spec = getProviderOnboardingSpec(this.id);\n if (!spec) {\n throw new Error(`Onboarding spec missing for provider: ${this.id}`);\n }\n return spec;\n }\n\n constructor(private readonly config: AligoConfig) {\n if (!config || typeof config !== \"object\") {\n throw new Error(\"AligoProvider requires a config object\");\n }\n if (!config.apiKey || config.apiKey.length === 0) {\n throw new Error(\"AligoProvider requires `apiKey`\");\n }\n if (!config.userId || config.userId.length === 0) {\n throw new Error(\"AligoProvider requires `userId`\");\n }\n\n this.smsHost = config.smsBaseUrl || \"https://apis.aligo.in\";\n this.alimtalkHost = config.alimtalkBaseUrl || \"https://kakaoapi.aligo.in\";\n }\n\n private getRuntimeContext(): AligoRuntimeContext {\n return {\n providerId: this.id,\n config: this.config,\n smsHost: this.smsHost,\n alimtalkHost: this.alimtalkHost,\n };\n }\n\n async healthCheck(): Promise<ProviderHealthStatus> {\n const start = Date.now();\n const issues: string[] = [];\n\n try {\n if (!this.config.apiKey) issues.push(\"Missing apiKey\");\n if (!this.config.userId) issues.push(\"Missing userId\");\n if (!this.config.sender) {\n issues.push(\"Missing sender (default from)\");\n }\n\n try {\n new URL(this.smsHost);\n } catch {\n issues.push(\"Invalid smsBaseUrl\");\n }\n\n try {\n new URL(this.alimtalkHost);\n } catch {\n issues.push(\"Invalid alimtalkBaseUrl\");\n }\n\n return {\n healthy: issues.length === 0,\n issues,\n latencyMs: Date.now() - start,\n data: {\n provider: this.id,\n smsBaseUrl: this.smsHost,\n alimtalkBaseUrl: this.alimtalkHost,\n },\n };\n } catch (error) {\n issues.push(error instanceof Error ? error.message : String(error));\n return { healthy: false, issues, latencyMs: Date.now() - start };\n }\n }\n\n async send(options: SendOptions): Promise<Result<SendResult, KMsgError>> {\n const messageId = options.messageId || crypto.randomUUID();\n const normalized = { ...options, messageId } as SendOptions;\n return sendWithAligo(this.getRuntimeContext(), normalized);\n }\n\n async listKakaoChannels(params?: {\n plusId?: string;\n senderKey?: string;\n }): Promise<Result<KakaoChannel[], KMsgError>> {\n return listKakaoChannels(this.getRuntimeContext(), params);\n }\n\n async listKakaoChannelCategories(): Promise<\n Result<KakaoChannelCategories, KMsgError>\n > {\n return listKakaoChannelCategories(this.getRuntimeContext());\n }\n\n async requestKakaoChannelAuth(params: {\n plusId: string;\n phoneNumber: string;\n }): Promise<Result<void, KMsgError>> {\n return requestKakaoChannelAuth(this.getRuntimeContext(), params);\n }\n\n async addKakaoChannel(params: {\n plusId: string;\n authNum: string;\n phoneNumber: string;\n categoryCode: string;\n }): Promise<Result<KakaoChannel, KMsgError>> {\n return addKakaoChannel(this.getRuntimeContext(), params);\n }\n\n async createTemplate(\n input: TemplateCreateInput,\n ctx?: TemplateContext,\n ): Promise<Result<Template, KMsgError>> {\n return createTemplate(this.getRuntimeContext(), input, ctx);\n }\n\n async updateTemplate(\n code: string,\n patch: TemplateUpdateInput,\n ctx?: TemplateContext,\n ): Promise<Result<Template, KMsgError>> {\n return updateTemplate(this.getRuntimeContext(), code, patch, ctx);\n }\n\n async deleteTemplate(\n code: string,\n ctx?: TemplateContext,\n ): Promise<Result<void, KMsgError>> {\n return deleteTemplate(this.getRuntimeContext(), code, ctx);\n }\n\n async getTemplate(\n code: string,\n ctx?: TemplateContext,\n ): Promise<Result<Template, KMsgError>> {\n return getTemplate(this.getRuntimeContext(), code, ctx);\n }\n\n async listTemplates(\n params?: { status?: string; page?: number; limit?: number },\n ctx?: TemplateContext,\n ): Promise<Result<Template[], KMsgError>> {\n return listTemplates(this.getRuntimeContext(), params, ctx);\n }\n\n async requestTemplateInspection(\n code: string,\n ctx?: TemplateContext,\n ): Promise<Result<void, KMsgError>> {\n return requestTemplateInspection(this.getRuntimeContext(), code, ctx);\n }\n}\n\nexport const createAligoProvider = (config: AligoConfig) =>\n new AligoProvider(config);\n\nexport const createDefaultAligoProvider = () => {\n const config: AligoConfig = {\n apiKey: readRuntimeEnv(\"ALIGO_API_KEY\") || \"\",\n userId: readRuntimeEnv(\"ALIGO_USER_ID\") || \"\",\n senderKey: readRuntimeEnv(\"ALIGO_SENDER_KEY\") || \"\",\n sender: readRuntimeEnv(\"ALIGO_SENDER\") || \"\",\n friendtalkEndpoint: readRuntimeEnv(\"ALIGO_FRIENDTALK_ENDPOINT\"),\n testMode: readRuntimeEnv(\"NODE_ENV\") !== \"production\",\n debug: readRuntimeEnv(\"NODE_ENV\") === \"development\",\n };\n\n if (!config.apiKey || !config.userId) {\n throw new Error(\"ALIGO_API_KEY and ALIGO_USER_ID are required\");\n }\n\n return new AligoProvider(config);\n};\n\n// biome-ignore lint/complexity/noStaticOnlyClass: kept as a factory for convenience\nexport class AligoProviderFactory {\n static create(config: AligoConfig): AligoProvider {\n return new AligoProvider(config);\n }\n\n static createDefault(): AligoProvider {\n return createDefaultAligoProvider();\n }\n}\n\nexport function initializeAligo(): void {}\n",
6
- "import type { ProviderOnboardingSpec } from \"@k-msg/core\";\n\nexport const providerOnboardingSpecs: Readonly<\n Record<string, ProviderOnboardingSpec>\n> = {\n iwinv: {\n providerId: \"iwinv\",\n providerName: \"IWINV Messaging Provider\",\n channelOnboarding: \"manual\",\n templateLifecycleApi: \"available\",\n plusIdPolicy: \"optional\",\n plusIdInference: \"unsupported\",\n liveTestSupport: \"supported\",\n checks: [\n {\n id: \"channel_registered_in_console\",\n title: \"Kakao channel is registered in IWINV console\",\n description:\n \"IWINV channel onboarding is manual. Confirm channel registration and approval in console.\",\n kind: \"manual\",\n severity: \"blocker\",\n scopes: [\"doctor\", \"preflight\"],\n },\n {\n id: \"iwinv_config_required\",\n title: \"IWINV config has required keys\",\n kind: \"config\",\n severity: \"blocker\",\n scopes: [\"doctor\", \"preflight\"],\n configKeys: [\"apiKey\"],\n },\n {\n id: \"template_capability_available\",\n title: \"Template lifecycle APIs are available\",\n kind: \"capability\",\n severity: \"warning\",\n scopes: [\"doctor\", \"preflight\"],\n capabilityMethods: [\n \"listTemplates\",\n \"getTemplate\",\n \"createTemplate\",\n \"updateTemplate\",\n \"deleteTemplate\",\n ],\n },\n {\n id: \"template_list_probe\",\n title: \"Template list API probe\",\n kind: \"api_probe\",\n severity: \"warning\",\n scopes: [\"doctor\", \"preflight\"],\n probeOperation: \"list_templates\",\n },\n ],\n notes: [\n \"Channel add/auth is not available via IWINV public API in current integration.\",\n \"Template APIs are available and can be probed.\",\n ],\n },\n aligo: {\n providerId: \"aligo\",\n providerName: \"Aligo Smart SMS\",\n channelOnboarding: \"api\",\n templateLifecycleApi: \"available\",\n plusIdPolicy: \"required_if_no_inference\",\n plusIdInference: \"supported\",\n liveTestSupport: \"supported\",\n checks: [\n {\n id: \"aligo_config_required\",\n title: \"Aligo config has required keys\",\n kind: \"config\",\n severity: \"blocker\",\n scopes: [\"doctor\", \"preflight\"],\n configKeys: [\"apiKey\", \"userId\"],\n },\n {\n id: \"channel_api_capability_available\",\n title: \"Kakao channel APIs are available\",\n kind: \"capability\",\n severity: \"warning\",\n scopes: [\"doctor\", \"preflight\"],\n capabilityMethods: [\n \"listKakaoChannels\",\n \"requestKakaoChannelAuth\",\n \"addKakaoChannel\",\n ],\n },\n {\n id: \"channel_list_probe\",\n title: \"Kakao channel list API probe\",\n kind: \"api_probe\",\n severity: \"warning\",\n scopes: [\"doctor\", \"preflight\"],\n probeOperation: \"list_kakao_channels\",\n },\n {\n id: \"template_list_probe\",\n title: \"Template list API probe\",\n kind: \"api_probe\",\n severity: \"warning\",\n scopes: [\"doctor\", \"preflight\"],\n probeOperation: \"list_templates\",\n },\n ],\n },\n solapi: {\n providerId: \"solapi\",\n providerName: \"SOLAPI Messaging Provider\",\n channelOnboarding: \"none\",\n templateLifecycleApi: \"unavailable\",\n plusIdPolicy: \"required_if_no_inference\",\n plusIdInference: \"unsupported\",\n liveTestSupport: \"partial\",\n checks: [\n {\n id: \"solapi_config_required\",\n title: \"SOLAPI config has required keys\",\n kind: \"config\",\n severity: \"blocker\",\n scopes: [\"doctor\", \"preflight\"],\n configKeys: [\"apiKey\", \"apiSecret\"],\n },\n ],\n notes: [\n \"SOLAPI ALIMTALK requires kakao profileId/pfId, but plusId inference is not available in current integration.\",\n ],\n },\n mock: {\n providerId: \"mock\",\n providerName: \"Mock Provider\",\n channelOnboarding: \"api\",\n templateLifecycleApi: \"available\",\n plusIdPolicy: \"optional\",\n plusIdInference: \"supported\",\n liveTestSupport: \"none\",\n checks: [\n {\n id: \"mock_template_capability_available\",\n title: \"Mock template APIs are available\",\n kind: \"capability\",\n severity: \"info\",\n scopes: [\"doctor\", \"preflight\"],\n capabilityMethods: [\"listTemplates\", \"getTemplate\", \"createTemplate\"],\n },\n ],\n },\n} as const;\n\nexport function getProviderOnboardingSpec(\n providerId: string,\n): ProviderOnboardingSpec | undefined {\n return providerOnboardingSpecs[providerId];\n}\n\nexport function listProviderOnboardingSpecs(): ProviderOnboardingSpec[] {\n return Object.values(providerOnboardingSpecs);\n}\n",
7
- "import {\n fail,\n type KakaoCategoryEntry,\n type KakaoChannel,\n type KakaoChannelCategories,\n KMsgError,\n KMsgErrorCode,\n ok,\n type Result,\n} from \"@k-msg/core\";\nimport { isObjectRecord } from \"../shared/type-guards\";\nimport { mapAligoKakaoError } from \"./aligo.error\";\nimport { parseAligoDateTime } from \"./aligo.helpers\";\nimport { ensureAligoKakaoOk, requestAligo } from \"./aligo.http\";\nimport type { AligoRuntimeContext } from \"./aligo.internal.types\";\n\nexport async function listKakaoChannels(\n ctx: AligoRuntimeContext,\n params?: {\n plusId?: string;\n senderKey?: string;\n },\n): Promise<Result<KakaoChannel[], KMsgError>> {\n try {\n const body: Record<string, unknown> = {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n ...(typeof params?.plusId === \"string\" && params.plusId.trim().length > 0\n ? { plusid: params.plusId.trim() }\n : {}),\n ...(typeof params?.senderKey === \"string\" &&\n params.senderKey.trim().length > 0\n ? { senderkey: params.senderKey.trim() }\n : {}),\n };\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/profile/list/\",\n data: body,\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"channel list failed\",\n });\n if (okResult.isFailure) return okResult;\n\n const listRaw = response.list;\n const list = Array.isArray(listRaw) ? listRaw : [];\n const channels: KakaoChannel[] = list\n .filter(isObjectRecord)\n .map((item) => ({\n providerId: ctx.providerId,\n senderKey: String(item.senderKey ?? \"\"),\n plusId: typeof item.uuid === \"string\" ? item.uuid : undefined,\n name: typeof item.name === \"string\" ? item.name : undefined,\n status: typeof item.status === \"string\" ? item.status : undefined,\n createdAt: parseAligoDateTime(item.cdate),\n updatedAt: parseAligoDateTime(item.udate),\n raw: item,\n }))\n .filter((channel) => channel.senderKey.length > 0);\n\n return ok(channels);\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function listKakaoChannelCategories(\n ctx: AligoRuntimeContext,\n): Promise<Result<KakaoChannelCategories, KMsgError>> {\n try {\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/category/\",\n data: {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n },\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"category list failed\",\n });\n if (okResult.isFailure) return okResult;\n\n const data = isObjectRecord(response.data) ? response.data : {};\n\n const mapEntries = (raw: unknown): KakaoCategoryEntry[] => {\n const arr = Array.isArray(raw) ? raw : [];\n return arr\n .filter(isObjectRecord)\n .map((entry) => ({\n code: String(entry.code ?? \"\"),\n name: String(entry.name ?? \"\"),\n parentCode:\n typeof entry.parentCode === \"string\" && entry.parentCode.length > 0\n ? entry.parentCode\n : undefined,\n }))\n .filter((entry) => entry.code.length > 0);\n };\n\n return ok({\n first: mapEntries(data.firstBusinessType),\n second: mapEntries(data.secondBusinessType),\n third: mapEntries(data.thirdBusinessType),\n });\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function requestKakaoChannelAuth(\n ctx: AligoRuntimeContext,\n params: {\n plusId: string;\n phoneNumber: string;\n },\n): Promise<Result<void, KMsgError>> {\n try {\n const plusId = params.plusId.trim();\n const phoneNumber = params.phoneNumber.trim();\n if (!plusId || !phoneNumber) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"plusId and phoneNumber are required\",\n { providerId: ctx.providerId },\n ),\n );\n }\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/profile/auth/\",\n data: {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n plusid: plusId,\n phonenumber: phoneNumber,\n },\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"channel auth failed\",\n });\n if (okResult.isFailure) return okResult;\n\n return ok(undefined);\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function addKakaoChannel(\n ctx: AligoRuntimeContext,\n params: {\n plusId: string;\n authNum: string;\n phoneNumber: string;\n categoryCode: string;\n },\n): Promise<Result<KakaoChannel, KMsgError>> {\n try {\n const plusId = params.plusId.trim();\n const authNum = params.authNum.trim();\n const phoneNumber = params.phoneNumber.trim();\n const categoryCode = params.categoryCode.trim();\n\n if (!plusId || !authNum || !phoneNumber || !categoryCode) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"plusId, authNum, phoneNumber, categoryCode are required\",\n { providerId: ctx.providerId },\n ),\n );\n }\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/profile/add/\",\n data: {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n plusid: plusId,\n authnum: authNum,\n phonenumber: phoneNumber,\n categorycode: categoryCode,\n },\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"channel add failed\",\n });\n if (okResult.isFailure) return okResult;\n\n const dataRaw = response.data;\n const data = Array.isArray(dataRaw)\n ? dataRaw.find(isObjectRecord)\n : isObjectRecord(dataRaw)\n ? dataRaw\n : undefined;\n\n if (!data) {\n return fail(\n new KMsgError(\n KMsgErrorCode.PROVIDER_ERROR,\n \"channel add returned empty data\",\n {\n providerId: ctx.providerId,\n raw: response,\n },\n ),\n );\n }\n\n const senderKey = String(data.senderKey ?? \"\");\n if (!senderKey) {\n return fail(\n new KMsgError(\n KMsgErrorCode.PROVIDER_ERROR,\n \"channel add did not return senderKey\",\n { providerId: ctx.providerId, raw: data },\n ),\n );\n }\n\n return ok({\n providerId: ctx.providerId,\n senderKey,\n plusId: typeof data.uuid === \"string\" ? data.uuid : plusId,\n name: typeof data.name === \"string\" ? data.name : undefined,\n status: typeof data.status === \"string\" ? data.status : undefined,\n createdAt: parseAligoDateTime(data.cdate),\n updatedAt: parseAligoDateTime(data.udate),\n raw: data,\n });\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n",
8
- "export function isObjectRecord(\n value: unknown,\n): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n",
9
- "import { KMsgError, KMsgErrorCode } from \"@k-msg/core\";\nimport { isObjectRecord } from \"../shared/type-guards\";\n\nexport function mapAligoKakaoError(\n error: unknown,\n providerId: string,\n): KMsgError {\n if (error instanceof KMsgError) return error;\n return new KMsgError(\n KMsgErrorCode.PROVIDER_ERROR,\n error instanceof Error ? error.message : String(error),\n { providerId },\n );\n}\n\nexport function mapAligoError(error: unknown, providerId: string): KMsgError {\n if (error instanceof KMsgError) return error;\n\n const record = isObjectRecord(error) ? error : {};\n const resultCodeRaw = record.result_code;\n const resultCode =\n resultCodeRaw !== undefined && resultCodeRaw !== null\n ? String(resultCodeRaw)\n : \"UNKNOWN\";\n\n const message =\n typeof record.message === \"string\" && record.message.length > 0\n ? record.message\n : typeof record.msg === \"string\" && record.msg.length > 0\n ? record.msg\n : error instanceof Error\n ? error.message\n : \"Unknown Aligo error\";\n\n let code: KMsgErrorCode = KMsgErrorCode.PROVIDER_ERROR;\n\n switch (resultCode) {\n case \"-100\":\n case \"-101\":\n code = KMsgErrorCode.AUTHENTICATION_FAILED;\n break;\n case \"-102\":\n case \"-201\":\n code = KMsgErrorCode.INSUFFICIENT_BALANCE;\n break;\n case \"-103\":\n case \"-105\":\n code = KMsgErrorCode.INVALID_REQUEST;\n break;\n case \"-501\":\n code = KMsgErrorCode.TEMPLATE_NOT_FOUND;\n break;\n default:\n code = KMsgErrorCode.PROVIDER_ERROR;\n }\n\n return new KMsgError(code, `${message} (code: ${resultCode})`, {\n providerId,\n resultCode,\n });\n}\n",
10
- "import {\n KMsgError,\n KMsgErrorCode,\n type MessageBinaryInput,\n type Template,\n type TemplateContext,\n} from \"@k-msg/core\";\nimport {\n ButtonParser,\n interpolate,\n type TemplateButton,\n} from \"@k-msg/template\";\nimport type { AligoConfig } from \"./types/aligo\";\n\nexport function resolveImageRef(options: {\n imageUrl?: string;\n media?: { image?: MessageBinaryInput };\n providerId: string;\n}): string | undefined {\n const imageUrl =\n typeof options.imageUrl === \"string\" && options.imageUrl.trim().length > 0\n ? options.imageUrl.trim()\n : undefined;\n if (imageUrl) return imageUrl;\n\n const image = options.media?.image;\n if (!image) return undefined;\n\n if (\"ref\" in image) {\n const ref = image.ref.trim();\n return ref.length > 0 ? ref : undefined;\n }\n\n throw new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"Aligo MMS/FriendTalk image requires `options.imageUrl` or `options.media.image.ref` (url/path).\",\n { providerId: options.providerId },\n );\n}\n\nexport function getAligoEndpoint(\n operation: \"sendSMS\" | \"sendAlimTalk\" | \"sendFriendTalk\",\n config: AligoConfig,\n): string {\n switch (operation) {\n case \"sendSMS\":\n return \"/send/\";\n case \"sendAlimTalk\":\n return \"/akv10/alimtalk/send/\";\n case \"sendFriendTalk\":\n return config.friendtalkEndpoint || \"/akv10/friendtalk/send/\";\n default:\n return \"/\";\n }\n}\n\nexport function formatAligoDate(date: Date): { date: string; time: string } {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, \"0\");\n const day = String(date.getDate()).padStart(2, \"0\");\n const hours = String(date.getHours()).padStart(2, \"0\");\n const minutes = String(date.getMinutes()).padStart(2, \"0\");\n\n return {\n date: `${year}${month}${day}`,\n time: `${hours}${minutes}`,\n };\n}\n\nexport function normalizeAligoKakaoCode(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n const num = Number(trimmed);\n if (Number.isFinite(num)) return num;\n }\n return undefined;\n}\n\nexport function resolveKakaoSenderKey(\n params: {\n providerId: string;\n config: AligoConfig;\n },\n ctx?: TemplateContext,\n): string {\n const senderKey =\n (typeof ctx?.kakaoChannelSenderKey === \"string\" &&\n ctx.kakaoChannelSenderKey.trim().length > 0\n ? ctx.kakaoChannelSenderKey.trim()\n : params.config.senderKey) || \"\";\n if (!senderKey) {\n throw new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"kakao channel senderKey is required (ctx.kakaoChannelSenderKey or config.senderKey)\",\n { providerId: params.providerId },\n );\n }\n return senderKey;\n}\n\nexport function toAligoTplButton(\n buttons: TemplateButton[] | undefined,\n): string | undefined {\n if (!Array.isArray(buttons) || buttons.length === 0) return undefined;\n\n const serializedButtons = JSON.parse(\n ButtonParser.serializeButtons(buttons),\n ) as unknown[];\n return JSON.stringify({ button: serializedButtons });\n}\n\nexport function mapAligoTemplateStatus(\n item: Record<string, unknown>,\n): Template[\"status\"] {\n const insp =\n typeof item.inspStatus === \"string\"\n ? item.inspStatus.trim().toUpperCase()\n : \"\";\n switch (insp) {\n case \"APR\":\n return \"APPROVED\";\n case \"REJ\":\n return \"REJECTED\";\n case \"REQ\":\n case \"REG\":\n return \"INSPECTION\";\n default:\n return \"PENDING\";\n }\n}\n\nexport function parseAligoDateTime(value: unknown): Date | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})\\s+(\\d{2}):(\\d{2}):(\\d{2})$/.exec(\n trimmed,\n );\n if (!match) return undefined;\n\n const year = Number(match[1]);\n const month = Number(match[2]);\n const day = Number(match[3]);\n const hour = Number(match[4]);\n const minute = Number(match[5]);\n const second = Number(match[6]);\n\n const date = new Date(year, month - 1, day, hour, minute, second);\n return Number.isNaN(date.getTime()) ? undefined : date;\n}\n\nexport function resolveAligoTemplateMessage(\n variables: Record<string, unknown> | undefined,\n templateContent?: string,\n): string {\n if (!variables) return \"\";\n const fullText = variables._full_text;\n if (fullText !== undefined && fullText !== null) return String(fullText);\n if (!templateContent) return Object.values(variables).map(String).join(\"\\n\");\n\n return interpolate(templateContent, variables);\n}\n",
11
- "import { fail, KMsgError, KMsgErrorCode, ok, type Result } from \"@k-msg/core\";\nimport { normalizeAligoKakaoCode } from \"./aligo.helpers\";\n\nexport async function requestAligo(params: {\n host: string;\n endpoint: string;\n data: Record<string, unknown>;\n providerId: string;\n}): Promise<Record<string, unknown>> {\n const formData = new FormData();\n for (const [key, value] of Object.entries(params.data)) {\n if (value !== undefined && value !== null) {\n formData.append(key, String(value));\n }\n }\n\n const response = await fetch(`${params.host}${params.endpoint}`, {\n method: \"POST\",\n body: formData,\n });\n\n if (!response.ok) {\n throw new KMsgError(\n KMsgErrorCode.NETWORK_ERROR,\n `HTTP error! status: ${response.status}`,\n { providerId: params.providerId },\n );\n }\n\n return (await response.json()) as Record<string, unknown>;\n}\n\nexport function ensureAligoKakaoOk(params: {\n providerId: string;\n response: Record<string, unknown>;\n fallbackMessage: string;\n}): Result<void, KMsgError> {\n const { providerId, response, fallbackMessage } = params;\n const rawCode = response.code;\n const code = normalizeAligoKakaoCode(rawCode);\n if (code === 0) return ok(undefined);\n\n const message =\n typeof response.message === \"string\" && response.message.length > 0\n ? response.message\n : fallbackMessage;\n const mapped =\n code === 509 || code === -99\n ? KMsgErrorCode.INVALID_REQUEST\n : KMsgErrorCode.PROVIDER_ERROR;\n return fail(\n new KMsgError(mapped, message, {\n providerId,\n originalCode: rawCode,\n raw: response,\n }),\n );\n}\n",
12
- "import {\n fail,\n KMsgError,\n KMsgErrorCode,\n ok,\n type Result,\n type SendOptions,\n type SendResult,\n} from \"@k-msg/core\";\nimport { mapAligoError } from \"./aligo.error\";\nimport {\n formatAligoDate,\n getAligoEndpoint,\n resolveAligoTemplateMessage,\n resolveImageRef,\n} from \"./aligo.helpers\";\nimport { requestAligo } from \"./aligo.http\";\nimport type {\n AligoMessageType,\n AligoRuntimeContext,\n} from \"./aligo.internal.types\";\nimport type { AligoResponse, AligoSMSRequest } from \"./types/aligo\";\n\nexport function collectSendWarnings(\n options: SendOptions,\n providerId: string,\n): SendResult[\"warnings\"] {\n if (options.type !== \"ALIMTALK\") return undefined;\n if (options.failover?.enabled !== true) return undefined;\n\n return [\n {\n code: \"FAILOVER_PARTIAL_PROVIDER\",\n message:\n \"Aligo failover mapping is partial. API-level fallback may be attempted for non-Kakao-user failures.\",\n details: {\n providerId,\n mappedFields: [\"failover\", \"fmessage_1\", \"fsubject_1\"],\n unsupportedFields: [\"fallbackChannel\"],\n },\n },\n ];\n}\n\nasync function sendSMS(\n ctx: AligoRuntimeContext,\n options: Extract<SendOptions, { type: \"SMS\" | \"LMS\" | \"MMS\" }>,\n): Promise<Result<SendResult, KMsgError>> {\n const sender = options.from || ctx.config.sender || \"\";\n if (!sender) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"from is required for SMS/LMS/MMS (options.from or config.sender)\",\n { providerId: ctx.providerId },\n ),\n );\n }\n\n const body: AligoSMSRequest = {\n key: ctx.config.apiKey,\n user_id: ctx.config.userId,\n sender,\n receiver: options.to,\n msg: options.text,\n msg_type: options.type,\n title: options.subject,\n testmode_yn: ctx.config.testMode ? \"Y\" : \"N\",\n };\n\n const scheduledAt = options.options?.scheduledAt;\n if (scheduledAt instanceof Date && !Number.isNaN(scheduledAt.getTime())) {\n const { date, time } = formatAligoDate(scheduledAt);\n body.rdate = date;\n body.rtime = time;\n }\n\n if (options.type === \"MMS\") {\n const imageRef = resolveImageRef({\n imageUrl: options.imageUrl,\n media: options.media,\n providerId: ctx.providerId,\n });\n if (!imageRef) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"image is required for MMS (options.imageUrl or options.media.image.ref)\",\n { providerId: ctx.providerId },\n ),\n );\n }\n body.image = imageRef;\n }\n\n const response = (await requestAligo({\n host: ctx.smsHost,\n endpoint: getAligoEndpoint(\"sendSMS\", ctx.config),\n data: body as unknown as Record<string, unknown>,\n providerId: ctx.providerId,\n })) as unknown as AligoResponse;\n\n if (response.result_code !== \"1\") {\n return fail(mapAligoError(response, ctx.providerId));\n }\n\n return ok({\n messageId: options.messageId || crypto.randomUUID(),\n providerId: ctx.providerId,\n providerMessageId: response.msg_id,\n status: \"PENDING\",\n type: options.type,\n to: options.to,\n raw: response,\n });\n}\n\nasync function sendAlimTalk(\n ctx: AligoRuntimeContext,\n options: Extract<SendOptions, { type: \"ALIMTALK\" }>,\n): Promise<Result<SendResult, KMsgError>> {\n const warnings = collectSendWarnings(options, ctx.providerId);\n const senderKey =\n (typeof options.kakao?.profileId === \"string\"\n ? options.kakao.profileId\n : ctx.config.senderKey) || \"\";\n if (!senderKey) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"kakao profileId is required (options.kakao.profileId or config.senderKey)\",\n { providerId: ctx.providerId },\n ),\n );\n }\n\n const sender = options.from || ctx.config.sender || \"\";\n if (!sender) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"from is required for ALIMTALK (options.from or config.sender)\",\n { providerId: ctx.providerId },\n ),\n );\n }\n\n const variables = options.variables as Record<string, unknown>;\n const templateId = options.templateId;\n if (!templateId || templateId.length === 0) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"templateId is required for ALIMTALK\",\n { providerId: ctx.providerId },\n ),\n );\n }\n const templateContent =\n typeof options.providerOptions?.templateContent === \"string\"\n ? options.providerOptions.templateContent\n : undefined;\n\n const body: Record<string, unknown> = {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n tpl_code: templateId,\n sender,\n receiver_1: options.to,\n subject_1: \"알림톡\",\n message_1: resolveAligoTemplateMessage(variables, templateContent),\n testMode: ctx.config.testMode ? \"Y\" : \"N\",\n };\n\n const failoverOverrideRaw =\n typeof options.providerOptions?.failover === \"string\"\n ? options.providerOptions.failover.trim().toUpperCase()\n : \"\";\n const failoverOverride =\n failoverOverrideRaw === \"Y\" || failoverOverrideRaw === \"N\"\n ? failoverOverrideRaw\n : undefined;\n const failoverFromOptions =\n options.failover?.enabled === true\n ? \"Y\"\n : options.failover?.enabled === false\n ? \"N\"\n : undefined;\n const failover = failoverOverride ?? failoverFromOptions;\n\n const fallbackTitle =\n typeof options.providerOptions?.fsubject_1 === \"string\" &&\n options.providerOptions.fsubject_1.trim().length > 0\n ? options.providerOptions.fsubject_1.trim()\n : typeof options.failover?.fallbackTitle === \"string\" &&\n options.failover.fallbackTitle.trim().length > 0\n ? options.failover.fallbackTitle.trim()\n : undefined;\n const fallbackContent =\n typeof options.providerOptions?.fmessage_1 === \"string\" &&\n options.providerOptions.fmessage_1.trim().length > 0\n ? options.providerOptions.fmessage_1.trim()\n : typeof options.failover?.fallbackContent === \"string\" &&\n options.failover.fallbackContent.trim().length > 0\n ? options.failover.fallbackContent.trim()\n : undefined;\n\n if (failover) {\n body.failover = failover;\n }\n if (fallbackTitle) {\n body.fsubject_1 = fallbackTitle;\n }\n if (fallbackContent) {\n body.fmessage_1 = fallbackContent;\n }\n\n const scheduledAt = options.options?.scheduledAt;\n if (scheduledAt instanceof Date && !Number.isNaN(scheduledAt.getTime())) {\n const { date, time } = formatAligoDate(scheduledAt);\n body.reserve = \"Y\";\n body.reserve_date = date;\n body.reserve_time = time;\n }\n\n const response = (await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: getAligoEndpoint(\"sendAlimTalk\", ctx.config),\n data: body,\n providerId: ctx.providerId,\n })) as unknown as AligoResponse;\n\n if (response.result_code !== \"0\") {\n return fail(mapAligoError(response, ctx.providerId));\n }\n\n return ok({\n messageId: options.messageId || crypto.randomUUID(),\n providerId: ctx.providerId,\n providerMessageId: response.msg_id,\n status: \"PENDING\",\n type: options.type,\n to: options.to,\n ...(Array.isArray(warnings) && warnings.length > 0 ? { warnings } : {}),\n raw: response,\n });\n}\n\nasync function sendFriendTalk(\n ctx: AligoRuntimeContext,\n options: Extract<SendOptions, { type: \"FRIENDTALK\" }>,\n): Promise<Result<SendResult, KMsgError>> {\n const senderKey =\n (typeof options.kakao?.profileId === \"string\"\n ? options.kakao.profileId\n : ctx.config.senderKey) || \"\";\n if (!senderKey) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"kakao profileId is required (options.kakao.profileId or config.senderKey)\",\n { providerId: ctx.providerId },\n ),\n );\n }\n\n const sender = options.from || ctx.config.sender || \"\";\n if (!sender) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"from is required for FRIENDTALK (options.from or config.sender)\",\n { providerId: ctx.providerId },\n ),\n );\n }\n\n const body: Record<string, unknown> = {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n sender,\n receiver_1: options.to,\n subject_1: \"친구톡\",\n message_1: options.text,\n testMode: ctx.config.testMode ? \"Y\" : \"N\",\n };\n\n const imageRef = resolveImageRef({\n imageUrl: options.imageUrl,\n media: options.media,\n providerId: ctx.providerId,\n });\n if (imageRef) {\n body.image_1 = imageRef;\n }\n\n const buttons = Array.isArray(options.kakao?.buttons)\n ? options.kakao.buttons\n : options.buttons;\n if (buttons) {\n body.button_1 = JSON.stringify(buttons);\n }\n\n const scheduledAt = options.options?.scheduledAt;\n if (scheduledAt instanceof Date && !Number.isNaN(scheduledAt.getTime())) {\n const { date, time } = formatAligoDate(scheduledAt);\n body.reserve = \"Y\";\n body.reserve_date = date;\n body.reserve_time = time;\n }\n\n const response = (await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: getAligoEndpoint(\"sendFriendTalk\", ctx.config),\n data: body,\n providerId: ctx.providerId,\n })) as unknown as AligoResponse;\n\n if (response.result_code !== \"0\") {\n return fail(mapAligoError(response, ctx.providerId));\n }\n\n return ok({\n messageId: options.messageId || crypto.randomUUID(),\n providerId: ctx.providerId,\n providerMessageId: response.msg_id,\n status: \"PENDING\",\n type: options.type,\n to: options.to,\n raw: response,\n });\n}\n\nexport async function sendWithAligo(\n ctx: AligoRuntimeContext,\n options: SendOptions,\n): Promise<Result<SendResult, KMsgError>> {\n try {\n switch (options.type as AligoMessageType) {\n case \"ALIMTALK\":\n return await sendAlimTalk(\n ctx,\n options as Extract<SendOptions, { type: \"ALIMTALK\" }>,\n );\n case \"FRIENDTALK\":\n return await sendFriendTalk(\n ctx,\n options as Extract<SendOptions, { type: \"FRIENDTALK\" }>,\n );\n case \"SMS\":\n case \"LMS\":\n case \"MMS\":\n return await sendSMS(\n ctx,\n options as Extract<SendOptions, { type: \"SMS\" | \"LMS\" | \"MMS\" }>,\n );\n default:\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n `AligoProvider does not support type ${options.type}`,\n { providerId: ctx.providerId, type: options.type },\n ),\n );\n }\n } catch (error) {\n return fail(mapAligoError(error, ctx.providerId));\n }\n}\n",
13
- "import {\n fail,\n KMsgError,\n KMsgErrorCode,\n ok,\n type Result,\n type Template,\n type TemplateContext,\n type TemplateCreateInput,\n type TemplateUpdateInput,\n} from \"@k-msg/core\";\nimport { validateTemplatePayload } from \"@k-msg/template\";\nimport { isObjectRecord } from \"../shared/type-guards\";\nimport { mapAligoKakaoError } from \"./aligo.error\";\nimport {\n mapAligoTemplateStatus,\n parseAligoDateTime,\n resolveKakaoSenderKey,\n toAligoTplButton,\n} from \"./aligo.helpers\";\nimport { ensureAligoKakaoOk, requestAligo } from \"./aligo.http\";\nimport type { AligoRuntimeContext } from \"./aligo.internal.types\";\n\nfunction withProviderContext(error: KMsgError, providerId: string): KMsgError {\n return new KMsgError(error.code, error.message, {\n providerId,\n ...(error.details ?? {}),\n });\n}\n\nexport async function createTemplate(\n ctx: AligoRuntimeContext,\n input: TemplateCreateInput,\n templateCtx?: TemplateContext,\n): Promise<Result<Template, KMsgError>> {\n try {\n const senderKey = resolveKakaoSenderKey(ctx, templateCtx);\n const payloadValidation = validateTemplatePayload(input, {\n requireName: true,\n requireContent: true,\n });\n if (payloadValidation.isFailure) {\n return fail(withProviderContext(payloadValidation.error, ctx.providerId));\n }\n\n const body: Record<string, unknown> = {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n tpl_name: payloadValidation.value.name ?? input.name,\n tpl_content: payloadValidation.value.content ?? input.content,\n };\n\n const tplButton = toAligoTplButton(payloadValidation.value.buttons);\n if (tplButton) body.tpl_button = tplButton;\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/template/add/\",\n data: body,\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"template create failed\",\n });\n if (okResult.isFailure) return okResult;\n\n const data = isObjectRecord(response.data) ? response.data : {};\n const code = String(data.templtCode ?? \"\");\n if (!code) {\n return fail(\n new KMsgError(\n KMsgErrorCode.PROVIDER_ERROR,\n \"template create did not return templtCode\",\n { providerId: ctx.providerId, raw: response },\n ),\n );\n }\n\n const createdAt = parseAligoDateTime(data.cdate) ?? new Date();\n const updatedAt =\n parseAligoDateTime(data.udate) ??\n parseAligoDateTime(data.cdate) ??\n createdAt;\n\n return ok({\n id: code,\n code,\n name: String(\n data.templtName ?? payloadValidation.value.name ?? input.name,\n ),\n content: String(\n data.templtContent ?? payloadValidation.value.content ?? input.content,\n ),\n category: input.category,\n status: mapAligoTemplateStatus(data),\n buttons: Array.isArray(data.buttons)\n ? data.buttons\n : payloadValidation.value.buttons,\n variables: input.variables,\n createdAt,\n updatedAt,\n });\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function getTemplate(\n ctx: AligoRuntimeContext,\n code: string,\n templateCtx?: TemplateContext,\n): Promise<Result<Template, KMsgError>> {\n try {\n const senderKey = resolveKakaoSenderKey(ctx, templateCtx);\n const templateCode = code.trim();\n if (!templateCode) {\n return fail(\n new KMsgError(KMsgErrorCode.INVALID_REQUEST, \"code is required\", {\n providerId: ctx.providerId,\n }),\n );\n }\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/template/list/\",\n data: {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n tpl_code: templateCode,\n },\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"template get failed\",\n });\n if (okResult.isFailure) return okResult;\n\n const listRaw = response.list;\n const list = Array.isArray(listRaw) ? listRaw : [];\n const first = list.find(isObjectRecord);\n if (!first) {\n return fail(\n new KMsgError(KMsgErrorCode.TEMPLATE_NOT_FOUND, \"Template not found\", {\n providerId: ctx.providerId,\n templateCode,\n }),\n );\n }\n\n const tplCode = String(first.templtCode ?? templateCode);\n const createdAt = parseAligoDateTime(first.cdate) ?? new Date();\n const updatedAt =\n parseAligoDateTime(first.udate) ??\n parseAligoDateTime(first.cdate) ??\n createdAt;\n\n return ok({\n id: tplCode,\n code: tplCode,\n name: String(first.templtName ?? \"\"),\n content: String(first.templtContent ?? \"\"),\n status: mapAligoTemplateStatus(first),\n buttons: Array.isArray(first.buttons) ? first.buttons : undefined,\n createdAt,\n updatedAt,\n });\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function updateTemplate(\n ctx: AligoRuntimeContext,\n code: string,\n patch: TemplateUpdateInput,\n templateCtx?: TemplateContext,\n): Promise<Result<Template, KMsgError>> {\n try {\n const senderKey = resolveKakaoSenderKey(ctx, templateCtx);\n const templateCode = code.trim();\n if (!templateCode) {\n return fail(\n new KMsgError(KMsgErrorCode.INVALID_REQUEST, \"code is required\", {\n providerId: ctx.providerId,\n }),\n );\n }\n\n const existingResult = await getTemplate(ctx, templateCode, {\n kakaoChannelSenderKey: senderKey,\n });\n if (existingResult.isFailure) return existingResult;\n const existing = existingResult.value;\n\n const nextName =\n typeof patch.name === \"string\" && patch.name.trim().length > 0\n ? patch.name.trim()\n : existing.name;\n const nextContent =\n typeof patch.content === \"string\" && patch.content.trim().length > 0\n ? patch.content\n : existing.content;\n const payloadValidation = validateTemplatePayload(\n {\n name: nextName,\n content: nextContent,\n buttons: patch.buttons !== undefined ? patch.buttons : existing.buttons,\n },\n {\n requireName: true,\n requireContent: true,\n },\n );\n if (payloadValidation.isFailure) {\n return fail(withProviderContext(payloadValidation.error, ctx.providerId));\n }\n\n const body: Record<string, unknown> = {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n tpl_code: templateCode,\n tpl_name: payloadValidation.value.name ?? nextName,\n tpl_content: payloadValidation.value.content ?? nextContent,\n };\n\n const tplButton = toAligoTplButton(payloadValidation.value.buttons);\n if (tplButton) body.tpl_button = tplButton;\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/template/modify/\",\n data: body,\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"template update failed\",\n });\n if (okResult.isFailure) return okResult;\n\n const refreshed = await getTemplate(ctx, templateCode, {\n kakaoChannelSenderKey: senderKey,\n });\n if (refreshed.isSuccess) return refreshed;\n\n return ok({\n ...existing,\n name: payloadValidation.value.name ?? nextName,\n content: payloadValidation.value.content ?? nextContent,\n ...(patch.category !== undefined ? { category: patch.category } : {}),\n ...(patch.variables !== undefined ? { variables: patch.variables } : {}),\n ...(patch.buttons !== undefined\n ? { buttons: payloadValidation.value.buttons }\n : {}),\n updatedAt: new Date(),\n });\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function deleteTemplate(\n ctx: AligoRuntimeContext,\n code: string,\n templateCtx?: TemplateContext,\n): Promise<Result<void, KMsgError>> {\n try {\n const senderKey = resolveKakaoSenderKey(ctx, templateCtx);\n const templateCode = code.trim();\n if (!templateCode) {\n return fail(\n new KMsgError(KMsgErrorCode.INVALID_REQUEST, \"code is required\", {\n providerId: ctx.providerId,\n }),\n );\n }\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/template/del/\",\n data: {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n tpl_code: templateCode,\n },\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"template delete failed\",\n });\n if (okResult.isFailure) return okResult;\n\n return ok(undefined);\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function listTemplates(\n ctx: AligoRuntimeContext,\n params?: { status?: string; page?: number; limit?: number },\n templateCtx?: TemplateContext,\n): Promise<Result<Template[], KMsgError>> {\n try {\n const senderKey = resolveKakaoSenderKey(ctx, templateCtx);\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/template/list/\",\n data: {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n },\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"template list failed\",\n });\n if (okResult.isFailure) return okResult;\n\n const listRaw = response.list;\n const list = Array.isArray(listRaw) ? listRaw : [];\n const templates = list\n .filter(isObjectRecord)\n .map((item) => {\n const tplCode = String(item.templtCode ?? \"\");\n const createdAt = parseAligoDateTime(item.cdate) ?? new Date();\n const updatedAt =\n parseAligoDateTime(item.udate) ??\n parseAligoDateTime(item.cdate) ??\n createdAt;\n\n return {\n id: tplCode,\n code: tplCode,\n name: String(item.templtName ?? \"\"),\n content: String(item.templtContent ?? \"\"),\n status: mapAligoTemplateStatus(item),\n buttons: Array.isArray(item.buttons) ? item.buttons : undefined,\n createdAt,\n updatedAt,\n } satisfies Template;\n })\n .filter((template) => template.code.length > 0);\n\n if (params?.status) {\n const status = params.status.trim().toUpperCase();\n return ok(templates.filter((template) => template.status === status));\n }\n\n return ok(templates);\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function requestTemplateInspection(\n ctx: AligoRuntimeContext,\n code: string,\n templateCtx?: TemplateContext,\n): Promise<Result<void, KMsgError>> {\n try {\n const senderKey = resolveKakaoSenderKey(ctx, templateCtx);\n const templateCode = code.trim();\n\n if (!templateCode) {\n return fail(\n new KMsgError(KMsgErrorCode.INVALID_REQUEST, \"code is required\", {\n providerId: ctx.providerId,\n }),\n );\n }\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/template/request/\",\n data: {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n tpl_code: templateCode,\n },\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"template inspection request failed\",\n });\n if (okResult.isFailure) return okResult;\n\n return ok(undefined);\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n"
14
- ],
15
- "mappings": "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",
16
- "debugId": "C790C7C50E6B04EA64756E2164756E21",
17
- "names": []
18
- }
@@ -1,18 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/aligo/provider.ts", "../src/onboarding/specs.ts", "../src/aligo/aligo.kakao.ts", "../src/shared/type-guards.ts", "../src/aligo/aligo.error.ts", "../src/aligo/aligo.helpers.ts", "../src/aligo/aligo.http.ts", "../src/aligo/aligo.send.ts", "../src/aligo/aligo.template.ts"],
4
- "sourcesContent": [
5
- "import {\n type KakaoChannel,\n type KakaoChannelCategories,\n type KakaoChannelProvider,\n type KMsgError,\n type MessageType,\n type Provider,\n type ProviderHealthStatus,\n type Result,\n readRuntimeEnv,\n type SendOptions,\n type SendResult,\n type Template,\n type TemplateContext,\n type TemplateCreateInput,\n type TemplateInspectionProvider,\n type TemplateProvider,\n type TemplateUpdateInput,\n} from \"@k-msg/core\";\nimport { getProviderOnboardingSpec } from \"../onboarding/specs\";\nimport type { AligoRuntimeContext } from \"./aligo.internal.types\";\nimport {\n addKakaoChannel,\n listKakaoChannelCategories,\n listKakaoChannels,\n requestKakaoChannelAuth,\n} from \"./aligo.kakao\";\nimport { sendWithAligo } from \"./aligo.send\";\nimport {\n createTemplate,\n deleteTemplate,\n getTemplate,\n listTemplates,\n requestTemplateInspection,\n updateTemplate,\n} from \"./aligo.template\";\nimport type { AligoConfig } from \"./types/aligo\";\n\nexport class AligoProvider\n implements\n Provider,\n TemplateProvider,\n TemplateInspectionProvider,\n KakaoChannelProvider\n{\n readonly id = \"aligo\";\n readonly name = \"Aligo Smart SMS\";\n readonly supportedTypes: readonly MessageType[] = [\n \"ALIMTALK\",\n \"FRIENDTALK\",\n \"SMS\",\n \"LMS\",\n \"MMS\",\n ];\n\n private readonly smsHost: string;\n private readonly alimtalkHost: string;\n\n getOnboardingSpec() {\n const spec = getProviderOnboardingSpec(this.id);\n if (!spec) {\n throw new Error(`Onboarding spec missing for provider: ${this.id}`);\n }\n return spec;\n }\n\n constructor(private readonly config: AligoConfig) {\n if (!config || typeof config !== \"object\") {\n throw new Error(\"AligoProvider requires a config object\");\n }\n if (!config.apiKey || config.apiKey.length === 0) {\n throw new Error(\"AligoProvider requires `apiKey`\");\n }\n if (!config.userId || config.userId.length === 0) {\n throw new Error(\"AligoProvider requires `userId`\");\n }\n\n this.smsHost = config.smsBaseUrl || \"https://apis.aligo.in\";\n this.alimtalkHost = config.alimtalkBaseUrl || \"https://kakaoapi.aligo.in\";\n }\n\n private getRuntimeContext(): AligoRuntimeContext {\n return {\n providerId: this.id,\n config: this.config,\n smsHost: this.smsHost,\n alimtalkHost: this.alimtalkHost,\n };\n }\n\n async healthCheck(): Promise<ProviderHealthStatus> {\n const start = Date.now();\n const issues: string[] = [];\n\n try {\n if (!this.config.apiKey) issues.push(\"Missing apiKey\");\n if (!this.config.userId) issues.push(\"Missing userId\");\n if (!this.config.sender) {\n issues.push(\"Missing sender (default from)\");\n }\n\n try {\n new URL(this.smsHost);\n } catch {\n issues.push(\"Invalid smsBaseUrl\");\n }\n\n try {\n new URL(this.alimtalkHost);\n } catch {\n issues.push(\"Invalid alimtalkBaseUrl\");\n }\n\n return {\n healthy: issues.length === 0,\n issues,\n latencyMs: Date.now() - start,\n data: {\n provider: this.id,\n smsBaseUrl: this.smsHost,\n alimtalkBaseUrl: this.alimtalkHost,\n },\n };\n } catch (error) {\n issues.push(error instanceof Error ? error.message : String(error));\n return { healthy: false, issues, latencyMs: Date.now() - start };\n }\n }\n\n async send(options: SendOptions): Promise<Result<SendResult, KMsgError>> {\n const messageId = options.messageId || crypto.randomUUID();\n const normalized = { ...options, messageId } as SendOptions;\n return sendWithAligo(this.getRuntimeContext(), normalized);\n }\n\n async listKakaoChannels(params?: {\n plusId?: string;\n senderKey?: string;\n }): Promise<Result<KakaoChannel[], KMsgError>> {\n return listKakaoChannels(this.getRuntimeContext(), params);\n }\n\n async listKakaoChannelCategories(): Promise<\n Result<KakaoChannelCategories, KMsgError>\n > {\n return listKakaoChannelCategories(this.getRuntimeContext());\n }\n\n async requestKakaoChannelAuth(params: {\n plusId: string;\n phoneNumber: string;\n }): Promise<Result<void, KMsgError>> {\n return requestKakaoChannelAuth(this.getRuntimeContext(), params);\n }\n\n async addKakaoChannel(params: {\n plusId: string;\n authNum: string;\n phoneNumber: string;\n categoryCode: string;\n }): Promise<Result<KakaoChannel, KMsgError>> {\n return addKakaoChannel(this.getRuntimeContext(), params);\n }\n\n async createTemplate(\n input: TemplateCreateInput,\n ctx?: TemplateContext,\n ): Promise<Result<Template, KMsgError>> {\n return createTemplate(this.getRuntimeContext(), input, ctx);\n }\n\n async updateTemplate(\n code: string,\n patch: TemplateUpdateInput,\n ctx?: TemplateContext,\n ): Promise<Result<Template, KMsgError>> {\n return updateTemplate(this.getRuntimeContext(), code, patch, ctx);\n }\n\n async deleteTemplate(\n code: string,\n ctx?: TemplateContext,\n ): Promise<Result<void, KMsgError>> {\n return deleteTemplate(this.getRuntimeContext(), code, ctx);\n }\n\n async getTemplate(\n code: string,\n ctx?: TemplateContext,\n ): Promise<Result<Template, KMsgError>> {\n return getTemplate(this.getRuntimeContext(), code, ctx);\n }\n\n async listTemplates(\n params?: { status?: string; page?: number; limit?: number },\n ctx?: TemplateContext,\n ): Promise<Result<Template[], KMsgError>> {\n return listTemplates(this.getRuntimeContext(), params, ctx);\n }\n\n async requestTemplateInspection(\n code: string,\n ctx?: TemplateContext,\n ): Promise<Result<void, KMsgError>> {\n return requestTemplateInspection(this.getRuntimeContext(), code, ctx);\n }\n}\n\nexport const createAligoProvider = (config: AligoConfig) =>\n new AligoProvider(config);\n\nexport const createDefaultAligoProvider = () => {\n const config: AligoConfig = {\n apiKey: readRuntimeEnv(\"ALIGO_API_KEY\") || \"\",\n userId: readRuntimeEnv(\"ALIGO_USER_ID\") || \"\",\n senderKey: readRuntimeEnv(\"ALIGO_SENDER_KEY\") || \"\",\n sender: readRuntimeEnv(\"ALIGO_SENDER\") || \"\",\n friendtalkEndpoint: readRuntimeEnv(\"ALIGO_FRIENDTALK_ENDPOINT\"),\n testMode: readRuntimeEnv(\"NODE_ENV\") !== \"production\",\n debug: readRuntimeEnv(\"NODE_ENV\") === \"development\",\n };\n\n if (!config.apiKey || !config.userId) {\n throw new Error(\"ALIGO_API_KEY and ALIGO_USER_ID are required\");\n }\n\n return new AligoProvider(config);\n};\n\n// biome-ignore lint/complexity/noStaticOnlyClass: kept as a factory for convenience\nexport class AligoProviderFactory {\n static create(config: AligoConfig): AligoProvider {\n return new AligoProvider(config);\n }\n\n static createDefault(): AligoProvider {\n return createDefaultAligoProvider();\n }\n}\n\nexport function initializeAligo(): void {}\n",
6
- "import type { ProviderOnboardingSpec } from \"@k-msg/core\";\n\nexport const providerOnboardingSpecs: Readonly<\n Record<string, ProviderOnboardingSpec>\n> = {\n iwinv: {\n providerId: \"iwinv\",\n providerName: \"IWINV Messaging Provider\",\n channelOnboarding: \"manual\",\n templateLifecycleApi: \"available\",\n plusIdPolicy: \"optional\",\n plusIdInference: \"unsupported\",\n liveTestSupport: \"supported\",\n checks: [\n {\n id: \"channel_registered_in_console\",\n title: \"Kakao channel is registered in IWINV console\",\n description:\n \"IWINV channel onboarding is manual. Confirm channel registration and approval in console.\",\n kind: \"manual\",\n severity: \"blocker\",\n scopes: [\"doctor\", \"preflight\"],\n },\n {\n id: \"iwinv_config_required\",\n title: \"IWINV config has required keys\",\n kind: \"config\",\n severity: \"blocker\",\n scopes: [\"doctor\", \"preflight\"],\n configKeys: [\"apiKey\"],\n },\n {\n id: \"template_capability_available\",\n title: \"Template lifecycle APIs are available\",\n kind: \"capability\",\n severity: \"warning\",\n scopes: [\"doctor\", \"preflight\"],\n capabilityMethods: [\n \"listTemplates\",\n \"getTemplate\",\n \"createTemplate\",\n \"updateTemplate\",\n \"deleteTemplate\",\n ],\n },\n {\n id: \"template_list_probe\",\n title: \"Template list API probe\",\n kind: \"api_probe\",\n severity: \"warning\",\n scopes: [\"doctor\", \"preflight\"],\n probeOperation: \"list_templates\",\n },\n ],\n notes: [\n \"Channel add/auth is not available via IWINV public API in current integration.\",\n \"Template APIs are available and can be probed.\",\n ],\n },\n aligo: {\n providerId: \"aligo\",\n providerName: \"Aligo Smart SMS\",\n channelOnboarding: \"api\",\n templateLifecycleApi: \"available\",\n plusIdPolicy: \"required_if_no_inference\",\n plusIdInference: \"supported\",\n liveTestSupport: \"supported\",\n checks: [\n {\n id: \"aligo_config_required\",\n title: \"Aligo config has required keys\",\n kind: \"config\",\n severity: \"blocker\",\n scopes: [\"doctor\", \"preflight\"],\n configKeys: [\"apiKey\", \"userId\"],\n },\n {\n id: \"channel_api_capability_available\",\n title: \"Kakao channel APIs are available\",\n kind: \"capability\",\n severity: \"warning\",\n scopes: [\"doctor\", \"preflight\"],\n capabilityMethods: [\n \"listKakaoChannels\",\n \"requestKakaoChannelAuth\",\n \"addKakaoChannel\",\n ],\n },\n {\n id: \"channel_list_probe\",\n title: \"Kakao channel list API probe\",\n kind: \"api_probe\",\n severity: \"warning\",\n scopes: [\"doctor\", \"preflight\"],\n probeOperation: \"list_kakao_channels\",\n },\n {\n id: \"template_list_probe\",\n title: \"Template list API probe\",\n kind: \"api_probe\",\n severity: \"warning\",\n scopes: [\"doctor\", \"preflight\"],\n probeOperation: \"list_templates\",\n },\n ],\n },\n solapi: {\n providerId: \"solapi\",\n providerName: \"SOLAPI Messaging Provider\",\n channelOnboarding: \"none\",\n templateLifecycleApi: \"unavailable\",\n plusIdPolicy: \"required_if_no_inference\",\n plusIdInference: \"unsupported\",\n liveTestSupport: \"partial\",\n checks: [\n {\n id: \"solapi_config_required\",\n title: \"SOLAPI config has required keys\",\n kind: \"config\",\n severity: \"blocker\",\n scopes: [\"doctor\", \"preflight\"],\n configKeys: [\"apiKey\", \"apiSecret\"],\n },\n ],\n notes: [\n \"SOLAPI ALIMTALK requires kakao profileId/pfId, but plusId inference is not available in current integration.\",\n ],\n },\n mock: {\n providerId: \"mock\",\n providerName: \"Mock Provider\",\n channelOnboarding: \"api\",\n templateLifecycleApi: \"available\",\n plusIdPolicy: \"optional\",\n plusIdInference: \"supported\",\n liveTestSupport: \"none\",\n checks: [\n {\n id: \"mock_template_capability_available\",\n title: \"Mock template APIs are available\",\n kind: \"capability\",\n severity: \"info\",\n scopes: [\"doctor\", \"preflight\"],\n capabilityMethods: [\"listTemplates\", \"getTemplate\", \"createTemplate\"],\n },\n ],\n },\n} as const;\n\nexport function getProviderOnboardingSpec(\n providerId: string,\n): ProviderOnboardingSpec | undefined {\n return providerOnboardingSpecs[providerId];\n}\n\nexport function listProviderOnboardingSpecs(): ProviderOnboardingSpec[] {\n return Object.values(providerOnboardingSpecs);\n}\n",
7
- "import {\n fail,\n type KakaoCategoryEntry,\n type KakaoChannel,\n type KakaoChannelCategories,\n KMsgError,\n KMsgErrorCode,\n ok,\n type Result,\n} from \"@k-msg/core\";\nimport { isObjectRecord } from \"../shared/type-guards\";\nimport { mapAligoKakaoError } from \"./aligo.error\";\nimport { parseAligoDateTime } from \"./aligo.helpers\";\nimport { ensureAligoKakaoOk, requestAligo } from \"./aligo.http\";\nimport type { AligoRuntimeContext } from \"./aligo.internal.types\";\n\nexport async function listKakaoChannels(\n ctx: AligoRuntimeContext,\n params?: {\n plusId?: string;\n senderKey?: string;\n },\n): Promise<Result<KakaoChannel[], KMsgError>> {\n try {\n const body: Record<string, unknown> = {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n ...(typeof params?.plusId === \"string\" && params.plusId.trim().length > 0\n ? { plusid: params.plusId.trim() }\n : {}),\n ...(typeof params?.senderKey === \"string\" &&\n params.senderKey.trim().length > 0\n ? { senderkey: params.senderKey.trim() }\n : {}),\n };\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/profile/list/\",\n data: body,\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"channel list failed\",\n });\n if (okResult.isFailure) return okResult;\n\n const listRaw = response.list;\n const list = Array.isArray(listRaw) ? listRaw : [];\n const channels: KakaoChannel[] = list\n .filter(isObjectRecord)\n .map((item) => ({\n providerId: ctx.providerId,\n senderKey: String(item.senderKey ?? \"\"),\n plusId: typeof item.uuid === \"string\" ? item.uuid : undefined,\n name: typeof item.name === \"string\" ? item.name : undefined,\n status: typeof item.status === \"string\" ? item.status : undefined,\n createdAt: parseAligoDateTime(item.cdate),\n updatedAt: parseAligoDateTime(item.udate),\n raw: item,\n }))\n .filter((channel) => channel.senderKey.length > 0);\n\n return ok(channels);\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function listKakaoChannelCategories(\n ctx: AligoRuntimeContext,\n): Promise<Result<KakaoChannelCategories, KMsgError>> {\n try {\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/category/\",\n data: {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n },\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"category list failed\",\n });\n if (okResult.isFailure) return okResult;\n\n const data = isObjectRecord(response.data) ? response.data : {};\n\n const mapEntries = (raw: unknown): KakaoCategoryEntry[] => {\n const arr = Array.isArray(raw) ? raw : [];\n return arr\n .filter(isObjectRecord)\n .map((entry) => ({\n code: String(entry.code ?? \"\"),\n name: String(entry.name ?? \"\"),\n parentCode:\n typeof entry.parentCode === \"string\" && entry.parentCode.length > 0\n ? entry.parentCode\n : undefined,\n }))\n .filter((entry) => entry.code.length > 0);\n };\n\n return ok({\n first: mapEntries(data.firstBusinessType),\n second: mapEntries(data.secondBusinessType),\n third: mapEntries(data.thirdBusinessType),\n });\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function requestKakaoChannelAuth(\n ctx: AligoRuntimeContext,\n params: {\n plusId: string;\n phoneNumber: string;\n },\n): Promise<Result<void, KMsgError>> {\n try {\n const plusId = params.plusId.trim();\n const phoneNumber = params.phoneNumber.trim();\n if (!plusId || !phoneNumber) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"plusId and phoneNumber are required\",\n { providerId: ctx.providerId },\n ),\n );\n }\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/profile/auth/\",\n data: {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n plusid: plusId,\n phonenumber: phoneNumber,\n },\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"channel auth failed\",\n });\n if (okResult.isFailure) return okResult;\n\n return ok(undefined);\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function addKakaoChannel(\n ctx: AligoRuntimeContext,\n params: {\n plusId: string;\n authNum: string;\n phoneNumber: string;\n categoryCode: string;\n },\n): Promise<Result<KakaoChannel, KMsgError>> {\n try {\n const plusId = params.plusId.trim();\n const authNum = params.authNum.trim();\n const phoneNumber = params.phoneNumber.trim();\n const categoryCode = params.categoryCode.trim();\n\n if (!plusId || !authNum || !phoneNumber || !categoryCode) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"plusId, authNum, phoneNumber, categoryCode are required\",\n { providerId: ctx.providerId },\n ),\n );\n }\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/profile/add/\",\n data: {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n plusid: plusId,\n authnum: authNum,\n phonenumber: phoneNumber,\n categorycode: categoryCode,\n },\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"channel add failed\",\n });\n if (okResult.isFailure) return okResult;\n\n const dataRaw = response.data;\n const data = Array.isArray(dataRaw)\n ? dataRaw.find(isObjectRecord)\n : isObjectRecord(dataRaw)\n ? dataRaw\n : undefined;\n\n if (!data) {\n return fail(\n new KMsgError(\n KMsgErrorCode.PROVIDER_ERROR,\n \"channel add returned empty data\",\n {\n providerId: ctx.providerId,\n raw: response,\n },\n ),\n );\n }\n\n const senderKey = String(data.senderKey ?? \"\");\n if (!senderKey) {\n return fail(\n new KMsgError(\n KMsgErrorCode.PROVIDER_ERROR,\n \"channel add did not return senderKey\",\n { providerId: ctx.providerId, raw: data },\n ),\n );\n }\n\n return ok({\n providerId: ctx.providerId,\n senderKey,\n plusId: typeof data.uuid === \"string\" ? data.uuid : plusId,\n name: typeof data.name === \"string\" ? data.name : undefined,\n status: typeof data.status === \"string\" ? data.status : undefined,\n createdAt: parseAligoDateTime(data.cdate),\n updatedAt: parseAligoDateTime(data.udate),\n raw: data,\n });\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n",
8
- "export function isObjectRecord(\n value: unknown,\n): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n",
9
- "import { KMsgError, KMsgErrorCode } from \"@k-msg/core\";\nimport { isObjectRecord } from \"../shared/type-guards\";\n\nexport function mapAligoKakaoError(\n error: unknown,\n providerId: string,\n): KMsgError {\n if (error instanceof KMsgError) return error;\n return new KMsgError(\n KMsgErrorCode.PROVIDER_ERROR,\n error instanceof Error ? error.message : String(error),\n { providerId },\n );\n}\n\nexport function mapAligoError(error: unknown, providerId: string): KMsgError {\n if (error instanceof KMsgError) return error;\n\n const record = isObjectRecord(error) ? error : {};\n const resultCodeRaw = record.result_code;\n const resultCode =\n resultCodeRaw !== undefined && resultCodeRaw !== null\n ? String(resultCodeRaw)\n : \"UNKNOWN\";\n\n const message =\n typeof record.message === \"string\" && record.message.length > 0\n ? record.message\n : typeof record.msg === \"string\" && record.msg.length > 0\n ? record.msg\n : error instanceof Error\n ? error.message\n : \"Unknown Aligo error\";\n\n let code: KMsgErrorCode = KMsgErrorCode.PROVIDER_ERROR;\n\n switch (resultCode) {\n case \"-100\":\n case \"-101\":\n code = KMsgErrorCode.AUTHENTICATION_FAILED;\n break;\n case \"-102\":\n case \"-201\":\n code = KMsgErrorCode.INSUFFICIENT_BALANCE;\n break;\n case \"-103\":\n case \"-105\":\n code = KMsgErrorCode.INVALID_REQUEST;\n break;\n case \"-501\":\n code = KMsgErrorCode.TEMPLATE_NOT_FOUND;\n break;\n default:\n code = KMsgErrorCode.PROVIDER_ERROR;\n }\n\n return new KMsgError(code, `${message} (code: ${resultCode})`, {\n providerId,\n resultCode,\n });\n}\n",
10
- "import {\n KMsgError,\n KMsgErrorCode,\n type MessageBinaryInput,\n type Template,\n type TemplateContext,\n} from \"@k-msg/core\";\nimport {\n ButtonParser,\n interpolate,\n type TemplateButton,\n} from \"@k-msg/template\";\nimport type { AligoConfig } from \"./types/aligo\";\n\nexport function resolveImageRef(options: {\n imageUrl?: string;\n media?: { image?: MessageBinaryInput };\n providerId: string;\n}): string | undefined {\n const imageUrl =\n typeof options.imageUrl === \"string\" && options.imageUrl.trim().length > 0\n ? options.imageUrl.trim()\n : undefined;\n if (imageUrl) return imageUrl;\n\n const image = options.media?.image;\n if (!image) return undefined;\n\n if (\"ref\" in image) {\n const ref = image.ref.trim();\n return ref.length > 0 ? ref : undefined;\n }\n\n throw new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"Aligo MMS/FriendTalk image requires `options.imageUrl` or `options.media.image.ref` (url/path).\",\n { providerId: options.providerId },\n );\n}\n\nexport function getAligoEndpoint(\n operation: \"sendSMS\" | \"sendAlimTalk\" | \"sendFriendTalk\",\n config: AligoConfig,\n): string {\n switch (operation) {\n case \"sendSMS\":\n return \"/send/\";\n case \"sendAlimTalk\":\n return \"/akv10/alimtalk/send/\";\n case \"sendFriendTalk\":\n return config.friendtalkEndpoint || \"/akv10/friendtalk/send/\";\n default:\n return \"/\";\n }\n}\n\nexport function formatAligoDate(date: Date): { date: string; time: string } {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, \"0\");\n const day = String(date.getDate()).padStart(2, \"0\");\n const hours = String(date.getHours()).padStart(2, \"0\");\n const minutes = String(date.getMinutes()).padStart(2, \"0\");\n\n return {\n date: `${year}${month}${day}`,\n time: `${hours}${minutes}`,\n };\n}\n\nexport function normalizeAligoKakaoCode(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n const num = Number(trimmed);\n if (Number.isFinite(num)) return num;\n }\n return undefined;\n}\n\nexport function resolveKakaoSenderKey(\n params: {\n providerId: string;\n config: AligoConfig;\n },\n ctx?: TemplateContext,\n): string {\n const senderKey =\n (typeof ctx?.kakaoChannelSenderKey === \"string\" &&\n ctx.kakaoChannelSenderKey.trim().length > 0\n ? ctx.kakaoChannelSenderKey.trim()\n : params.config.senderKey) || \"\";\n if (!senderKey) {\n throw new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"kakao channel senderKey is required (ctx.kakaoChannelSenderKey or config.senderKey)\",\n { providerId: params.providerId },\n );\n }\n return senderKey;\n}\n\nexport function toAligoTplButton(\n buttons: TemplateButton[] | undefined,\n): string | undefined {\n if (!Array.isArray(buttons) || buttons.length === 0) return undefined;\n\n const serializedButtons = JSON.parse(\n ButtonParser.serializeButtons(buttons),\n ) as unknown[];\n return JSON.stringify({ button: serializedButtons });\n}\n\nexport function mapAligoTemplateStatus(\n item: Record<string, unknown>,\n): Template[\"status\"] {\n const insp =\n typeof item.inspStatus === \"string\"\n ? item.inspStatus.trim().toUpperCase()\n : \"\";\n switch (insp) {\n case \"APR\":\n return \"APPROVED\";\n case \"REJ\":\n return \"REJECTED\";\n case \"REQ\":\n case \"REG\":\n return \"INSPECTION\";\n default:\n return \"PENDING\";\n }\n}\n\nexport function parseAligoDateTime(value: unknown): Date | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})\\s+(\\d{2}):(\\d{2}):(\\d{2})$/.exec(\n trimmed,\n );\n if (!match) return undefined;\n\n const year = Number(match[1]);\n const month = Number(match[2]);\n const day = Number(match[3]);\n const hour = Number(match[4]);\n const minute = Number(match[5]);\n const second = Number(match[6]);\n\n const date = new Date(year, month - 1, day, hour, minute, second);\n return Number.isNaN(date.getTime()) ? undefined : date;\n}\n\nexport function resolveAligoTemplateMessage(\n variables: Record<string, unknown> | undefined,\n templateContent?: string,\n): string {\n if (!variables) return \"\";\n const fullText = variables._full_text;\n if (fullText !== undefined && fullText !== null) return String(fullText);\n if (!templateContent) return Object.values(variables).map(String).join(\"\\n\");\n\n return interpolate(templateContent, variables);\n}\n",
11
- "import { fail, KMsgError, KMsgErrorCode, ok, type Result } from \"@k-msg/core\";\nimport { normalizeAligoKakaoCode } from \"./aligo.helpers\";\n\nexport async function requestAligo(params: {\n host: string;\n endpoint: string;\n data: Record<string, unknown>;\n providerId: string;\n}): Promise<Record<string, unknown>> {\n const formData = new FormData();\n for (const [key, value] of Object.entries(params.data)) {\n if (value !== undefined && value !== null) {\n formData.append(key, String(value));\n }\n }\n\n const response = await fetch(`${params.host}${params.endpoint}`, {\n method: \"POST\",\n body: formData,\n });\n\n if (!response.ok) {\n throw new KMsgError(\n KMsgErrorCode.NETWORK_ERROR,\n `HTTP error! status: ${response.status}`,\n { providerId: params.providerId },\n );\n }\n\n return (await response.json()) as Record<string, unknown>;\n}\n\nexport function ensureAligoKakaoOk(params: {\n providerId: string;\n response: Record<string, unknown>;\n fallbackMessage: string;\n}): Result<void, KMsgError> {\n const { providerId, response, fallbackMessage } = params;\n const rawCode = response.code;\n const code = normalizeAligoKakaoCode(rawCode);\n if (code === 0) return ok(undefined);\n\n const message =\n typeof response.message === \"string\" && response.message.length > 0\n ? response.message\n : fallbackMessage;\n const mapped =\n code === 509 || code === -99\n ? KMsgErrorCode.INVALID_REQUEST\n : KMsgErrorCode.PROVIDER_ERROR;\n return fail(\n new KMsgError(mapped, message, {\n providerId,\n originalCode: rawCode,\n raw: response,\n }),\n );\n}\n",
12
- "import {\n fail,\n KMsgError,\n KMsgErrorCode,\n ok,\n type Result,\n type SendOptions,\n type SendResult,\n} from \"@k-msg/core\";\nimport { mapAligoError } from \"./aligo.error\";\nimport {\n formatAligoDate,\n getAligoEndpoint,\n resolveAligoTemplateMessage,\n resolveImageRef,\n} from \"./aligo.helpers\";\nimport { requestAligo } from \"./aligo.http\";\nimport type {\n AligoMessageType,\n AligoRuntimeContext,\n} from \"./aligo.internal.types\";\nimport type { AligoResponse, AligoSMSRequest } from \"./types/aligo\";\n\nexport function collectSendWarnings(\n options: SendOptions,\n providerId: string,\n): SendResult[\"warnings\"] {\n if (options.type !== \"ALIMTALK\") return undefined;\n if (options.failover?.enabled !== true) return undefined;\n\n return [\n {\n code: \"FAILOVER_PARTIAL_PROVIDER\",\n message:\n \"Aligo failover mapping is partial. API-level fallback may be attempted for non-Kakao-user failures.\",\n details: {\n providerId,\n mappedFields: [\"failover\", \"fmessage_1\", \"fsubject_1\"],\n unsupportedFields: [\"fallbackChannel\"],\n },\n },\n ];\n}\n\nasync function sendSMS(\n ctx: AligoRuntimeContext,\n options: Extract<SendOptions, { type: \"SMS\" | \"LMS\" | \"MMS\" }>,\n): Promise<Result<SendResult, KMsgError>> {\n const sender = options.from || ctx.config.sender || \"\";\n if (!sender) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"from is required for SMS/LMS/MMS (options.from or config.sender)\",\n { providerId: ctx.providerId },\n ),\n );\n }\n\n const body: AligoSMSRequest = {\n key: ctx.config.apiKey,\n user_id: ctx.config.userId,\n sender,\n receiver: options.to,\n msg: options.text,\n msg_type: options.type,\n title: options.subject,\n testmode_yn: ctx.config.testMode ? \"Y\" : \"N\",\n };\n\n const scheduledAt = options.options?.scheduledAt;\n if (scheduledAt instanceof Date && !Number.isNaN(scheduledAt.getTime())) {\n const { date, time } = formatAligoDate(scheduledAt);\n body.rdate = date;\n body.rtime = time;\n }\n\n if (options.type === \"MMS\") {\n const imageRef = resolveImageRef({\n imageUrl: options.imageUrl,\n media: options.media,\n providerId: ctx.providerId,\n });\n if (!imageRef) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"image is required for MMS (options.imageUrl or options.media.image.ref)\",\n { providerId: ctx.providerId },\n ),\n );\n }\n body.image = imageRef;\n }\n\n const response = (await requestAligo({\n host: ctx.smsHost,\n endpoint: getAligoEndpoint(\"sendSMS\", ctx.config),\n data: body as unknown as Record<string, unknown>,\n providerId: ctx.providerId,\n })) as unknown as AligoResponse;\n\n if (response.result_code !== \"1\") {\n return fail(mapAligoError(response, ctx.providerId));\n }\n\n return ok({\n messageId: options.messageId || crypto.randomUUID(),\n providerId: ctx.providerId,\n providerMessageId: response.msg_id,\n status: \"PENDING\",\n type: options.type,\n to: options.to,\n raw: response,\n });\n}\n\nasync function sendAlimTalk(\n ctx: AligoRuntimeContext,\n options: Extract<SendOptions, { type: \"ALIMTALK\" }>,\n): Promise<Result<SendResult, KMsgError>> {\n const warnings = collectSendWarnings(options, ctx.providerId);\n const senderKey =\n (typeof options.kakao?.profileId === \"string\"\n ? options.kakao.profileId\n : ctx.config.senderKey) || \"\";\n if (!senderKey) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"kakao profileId is required (options.kakao.profileId or config.senderKey)\",\n { providerId: ctx.providerId },\n ),\n );\n }\n\n const sender = options.from || ctx.config.sender || \"\";\n if (!sender) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"from is required for ALIMTALK (options.from or config.sender)\",\n { providerId: ctx.providerId },\n ),\n );\n }\n\n const variables = options.variables as Record<string, unknown>;\n const templateId = options.templateId;\n if (!templateId || templateId.length === 0) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"templateId is required for ALIMTALK\",\n { providerId: ctx.providerId },\n ),\n );\n }\n const templateContent =\n typeof options.providerOptions?.templateContent === \"string\"\n ? options.providerOptions.templateContent\n : undefined;\n\n const body: Record<string, unknown> = {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n tpl_code: templateId,\n sender,\n receiver_1: options.to,\n subject_1: \"알림톡\",\n message_1: resolveAligoTemplateMessage(variables, templateContent),\n testMode: ctx.config.testMode ? \"Y\" : \"N\",\n };\n\n const failoverOverrideRaw =\n typeof options.providerOptions?.failover === \"string\"\n ? options.providerOptions.failover.trim().toUpperCase()\n : \"\";\n const failoverOverride =\n failoverOverrideRaw === \"Y\" || failoverOverrideRaw === \"N\"\n ? failoverOverrideRaw\n : undefined;\n const failoverFromOptions =\n options.failover?.enabled === true\n ? \"Y\"\n : options.failover?.enabled === false\n ? \"N\"\n : undefined;\n const failover = failoverOverride ?? failoverFromOptions;\n\n const fallbackTitle =\n typeof options.providerOptions?.fsubject_1 === \"string\" &&\n options.providerOptions.fsubject_1.trim().length > 0\n ? options.providerOptions.fsubject_1.trim()\n : typeof options.failover?.fallbackTitle === \"string\" &&\n options.failover.fallbackTitle.trim().length > 0\n ? options.failover.fallbackTitle.trim()\n : undefined;\n const fallbackContent =\n typeof options.providerOptions?.fmessage_1 === \"string\" &&\n options.providerOptions.fmessage_1.trim().length > 0\n ? options.providerOptions.fmessage_1.trim()\n : typeof options.failover?.fallbackContent === \"string\" &&\n options.failover.fallbackContent.trim().length > 0\n ? options.failover.fallbackContent.trim()\n : undefined;\n\n if (failover) {\n body.failover = failover;\n }\n if (fallbackTitle) {\n body.fsubject_1 = fallbackTitle;\n }\n if (fallbackContent) {\n body.fmessage_1 = fallbackContent;\n }\n\n const scheduledAt = options.options?.scheduledAt;\n if (scheduledAt instanceof Date && !Number.isNaN(scheduledAt.getTime())) {\n const { date, time } = formatAligoDate(scheduledAt);\n body.reserve = \"Y\";\n body.reserve_date = date;\n body.reserve_time = time;\n }\n\n const response = (await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: getAligoEndpoint(\"sendAlimTalk\", ctx.config),\n data: body,\n providerId: ctx.providerId,\n })) as unknown as AligoResponse;\n\n if (response.result_code !== \"0\") {\n return fail(mapAligoError(response, ctx.providerId));\n }\n\n return ok({\n messageId: options.messageId || crypto.randomUUID(),\n providerId: ctx.providerId,\n providerMessageId: response.msg_id,\n status: \"PENDING\",\n type: options.type,\n to: options.to,\n ...(Array.isArray(warnings) && warnings.length > 0 ? { warnings } : {}),\n raw: response,\n });\n}\n\nasync function sendFriendTalk(\n ctx: AligoRuntimeContext,\n options: Extract<SendOptions, { type: \"FRIENDTALK\" }>,\n): Promise<Result<SendResult, KMsgError>> {\n const senderKey =\n (typeof options.kakao?.profileId === \"string\"\n ? options.kakao.profileId\n : ctx.config.senderKey) || \"\";\n if (!senderKey) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"kakao profileId is required (options.kakao.profileId or config.senderKey)\",\n { providerId: ctx.providerId },\n ),\n );\n }\n\n const sender = options.from || ctx.config.sender || \"\";\n if (!sender) {\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n \"from is required for FRIENDTALK (options.from or config.sender)\",\n { providerId: ctx.providerId },\n ),\n );\n }\n\n const body: Record<string, unknown> = {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n sender,\n receiver_1: options.to,\n subject_1: \"친구톡\",\n message_1: options.text,\n testMode: ctx.config.testMode ? \"Y\" : \"N\",\n };\n\n const imageRef = resolveImageRef({\n imageUrl: options.imageUrl,\n media: options.media,\n providerId: ctx.providerId,\n });\n if (imageRef) {\n body.image_1 = imageRef;\n }\n\n const buttons = Array.isArray(options.kakao?.buttons)\n ? options.kakao.buttons\n : options.buttons;\n if (buttons) {\n body.button_1 = JSON.stringify(buttons);\n }\n\n const scheduledAt = options.options?.scheduledAt;\n if (scheduledAt instanceof Date && !Number.isNaN(scheduledAt.getTime())) {\n const { date, time } = formatAligoDate(scheduledAt);\n body.reserve = \"Y\";\n body.reserve_date = date;\n body.reserve_time = time;\n }\n\n const response = (await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: getAligoEndpoint(\"sendFriendTalk\", ctx.config),\n data: body,\n providerId: ctx.providerId,\n })) as unknown as AligoResponse;\n\n if (response.result_code !== \"0\") {\n return fail(mapAligoError(response, ctx.providerId));\n }\n\n return ok({\n messageId: options.messageId || crypto.randomUUID(),\n providerId: ctx.providerId,\n providerMessageId: response.msg_id,\n status: \"PENDING\",\n type: options.type,\n to: options.to,\n raw: response,\n });\n}\n\nexport async function sendWithAligo(\n ctx: AligoRuntimeContext,\n options: SendOptions,\n): Promise<Result<SendResult, KMsgError>> {\n try {\n switch (options.type as AligoMessageType) {\n case \"ALIMTALK\":\n return await sendAlimTalk(\n ctx,\n options as Extract<SendOptions, { type: \"ALIMTALK\" }>,\n );\n case \"FRIENDTALK\":\n return await sendFriendTalk(\n ctx,\n options as Extract<SendOptions, { type: \"FRIENDTALK\" }>,\n );\n case \"SMS\":\n case \"LMS\":\n case \"MMS\":\n return await sendSMS(\n ctx,\n options as Extract<SendOptions, { type: \"SMS\" | \"LMS\" | \"MMS\" }>,\n );\n default:\n return fail(\n new KMsgError(\n KMsgErrorCode.INVALID_REQUEST,\n `AligoProvider does not support type ${options.type}`,\n { providerId: ctx.providerId, type: options.type },\n ),\n );\n }\n } catch (error) {\n return fail(mapAligoError(error, ctx.providerId));\n }\n}\n",
13
- "import {\n fail,\n KMsgError,\n KMsgErrorCode,\n ok,\n type Result,\n type Template,\n type TemplateContext,\n type TemplateCreateInput,\n type TemplateUpdateInput,\n} from \"@k-msg/core\";\nimport { validateTemplatePayload } from \"@k-msg/template\";\nimport { isObjectRecord } from \"../shared/type-guards\";\nimport { mapAligoKakaoError } from \"./aligo.error\";\nimport {\n mapAligoTemplateStatus,\n parseAligoDateTime,\n resolveKakaoSenderKey,\n toAligoTplButton,\n} from \"./aligo.helpers\";\nimport { ensureAligoKakaoOk, requestAligo } from \"./aligo.http\";\nimport type { AligoRuntimeContext } from \"./aligo.internal.types\";\n\nfunction withProviderContext(error: KMsgError, providerId: string): KMsgError {\n return new KMsgError(error.code, error.message, {\n providerId,\n ...(error.details ?? {}),\n });\n}\n\nexport async function createTemplate(\n ctx: AligoRuntimeContext,\n input: TemplateCreateInput,\n templateCtx?: TemplateContext,\n): Promise<Result<Template, KMsgError>> {\n try {\n const senderKey = resolveKakaoSenderKey(ctx, templateCtx);\n const payloadValidation = validateTemplatePayload(input, {\n requireName: true,\n requireContent: true,\n });\n if (payloadValidation.isFailure) {\n return fail(withProviderContext(payloadValidation.error, ctx.providerId));\n }\n\n const body: Record<string, unknown> = {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n tpl_name: payloadValidation.value.name ?? input.name,\n tpl_content: payloadValidation.value.content ?? input.content,\n };\n\n const tplButton = toAligoTplButton(payloadValidation.value.buttons);\n if (tplButton) body.tpl_button = tplButton;\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/template/add/\",\n data: body,\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"template create failed\",\n });\n if (okResult.isFailure) return okResult;\n\n const data = isObjectRecord(response.data) ? response.data : {};\n const code = String(data.templtCode ?? \"\");\n if (!code) {\n return fail(\n new KMsgError(\n KMsgErrorCode.PROVIDER_ERROR,\n \"template create did not return templtCode\",\n { providerId: ctx.providerId, raw: response },\n ),\n );\n }\n\n const createdAt = parseAligoDateTime(data.cdate) ?? new Date();\n const updatedAt =\n parseAligoDateTime(data.udate) ??\n parseAligoDateTime(data.cdate) ??\n createdAt;\n\n return ok({\n id: code,\n code,\n name: String(\n data.templtName ?? payloadValidation.value.name ?? input.name,\n ),\n content: String(\n data.templtContent ?? payloadValidation.value.content ?? input.content,\n ),\n category: input.category,\n status: mapAligoTemplateStatus(data),\n buttons: Array.isArray(data.buttons)\n ? data.buttons\n : payloadValidation.value.buttons,\n variables: input.variables,\n createdAt,\n updatedAt,\n });\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function getTemplate(\n ctx: AligoRuntimeContext,\n code: string,\n templateCtx?: TemplateContext,\n): Promise<Result<Template, KMsgError>> {\n try {\n const senderKey = resolveKakaoSenderKey(ctx, templateCtx);\n const templateCode = code.trim();\n if (!templateCode) {\n return fail(\n new KMsgError(KMsgErrorCode.INVALID_REQUEST, \"code is required\", {\n providerId: ctx.providerId,\n }),\n );\n }\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/template/list/\",\n data: {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n tpl_code: templateCode,\n },\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"template get failed\",\n });\n if (okResult.isFailure) return okResult;\n\n const listRaw = response.list;\n const list = Array.isArray(listRaw) ? listRaw : [];\n const first = list.find(isObjectRecord);\n if (!first) {\n return fail(\n new KMsgError(KMsgErrorCode.TEMPLATE_NOT_FOUND, \"Template not found\", {\n providerId: ctx.providerId,\n templateCode,\n }),\n );\n }\n\n const tplCode = String(first.templtCode ?? templateCode);\n const createdAt = parseAligoDateTime(first.cdate) ?? new Date();\n const updatedAt =\n parseAligoDateTime(first.udate) ??\n parseAligoDateTime(first.cdate) ??\n createdAt;\n\n return ok({\n id: tplCode,\n code: tplCode,\n name: String(first.templtName ?? \"\"),\n content: String(first.templtContent ?? \"\"),\n status: mapAligoTemplateStatus(first),\n buttons: Array.isArray(first.buttons) ? first.buttons : undefined,\n createdAt,\n updatedAt,\n });\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function updateTemplate(\n ctx: AligoRuntimeContext,\n code: string,\n patch: TemplateUpdateInput,\n templateCtx?: TemplateContext,\n): Promise<Result<Template, KMsgError>> {\n try {\n const senderKey = resolveKakaoSenderKey(ctx, templateCtx);\n const templateCode = code.trim();\n if (!templateCode) {\n return fail(\n new KMsgError(KMsgErrorCode.INVALID_REQUEST, \"code is required\", {\n providerId: ctx.providerId,\n }),\n );\n }\n\n const existingResult = await getTemplate(ctx, templateCode, {\n kakaoChannelSenderKey: senderKey,\n });\n if (existingResult.isFailure) return existingResult;\n const existing = existingResult.value;\n\n const nextName =\n typeof patch.name === \"string\" && patch.name.trim().length > 0\n ? patch.name.trim()\n : existing.name;\n const nextContent =\n typeof patch.content === \"string\" && patch.content.trim().length > 0\n ? patch.content\n : existing.content;\n const payloadValidation = validateTemplatePayload(\n {\n name: nextName,\n content: nextContent,\n buttons: patch.buttons !== undefined ? patch.buttons : existing.buttons,\n },\n {\n requireName: true,\n requireContent: true,\n },\n );\n if (payloadValidation.isFailure) {\n return fail(withProviderContext(payloadValidation.error, ctx.providerId));\n }\n\n const body: Record<string, unknown> = {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n tpl_code: templateCode,\n tpl_name: payloadValidation.value.name ?? nextName,\n tpl_content: payloadValidation.value.content ?? nextContent,\n };\n\n const tplButton = toAligoTplButton(payloadValidation.value.buttons);\n if (tplButton) body.tpl_button = tplButton;\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/template/modify/\",\n data: body,\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"template update failed\",\n });\n if (okResult.isFailure) return okResult;\n\n const refreshed = await getTemplate(ctx, templateCode, {\n kakaoChannelSenderKey: senderKey,\n });\n if (refreshed.isSuccess) return refreshed;\n\n return ok({\n ...existing,\n name: payloadValidation.value.name ?? nextName,\n content: payloadValidation.value.content ?? nextContent,\n ...(patch.category !== undefined ? { category: patch.category } : {}),\n ...(patch.variables !== undefined ? { variables: patch.variables } : {}),\n ...(patch.buttons !== undefined\n ? { buttons: payloadValidation.value.buttons }\n : {}),\n updatedAt: new Date(),\n });\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function deleteTemplate(\n ctx: AligoRuntimeContext,\n code: string,\n templateCtx?: TemplateContext,\n): Promise<Result<void, KMsgError>> {\n try {\n const senderKey = resolveKakaoSenderKey(ctx, templateCtx);\n const templateCode = code.trim();\n if (!templateCode) {\n return fail(\n new KMsgError(KMsgErrorCode.INVALID_REQUEST, \"code is required\", {\n providerId: ctx.providerId,\n }),\n );\n }\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/template/del/\",\n data: {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n tpl_code: templateCode,\n },\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"template delete failed\",\n });\n if (okResult.isFailure) return okResult;\n\n return ok(undefined);\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function listTemplates(\n ctx: AligoRuntimeContext,\n params?: { status?: string; page?: number; limit?: number },\n templateCtx?: TemplateContext,\n): Promise<Result<Template[], KMsgError>> {\n try {\n const senderKey = resolveKakaoSenderKey(ctx, templateCtx);\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/template/list/\",\n data: {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n },\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"template list failed\",\n });\n if (okResult.isFailure) return okResult;\n\n const listRaw = response.list;\n const list = Array.isArray(listRaw) ? listRaw : [];\n const templates = list\n .filter(isObjectRecord)\n .map((item) => {\n const tplCode = String(item.templtCode ?? \"\");\n const createdAt = parseAligoDateTime(item.cdate) ?? new Date();\n const updatedAt =\n parseAligoDateTime(item.udate) ??\n parseAligoDateTime(item.cdate) ??\n createdAt;\n\n return {\n id: tplCode,\n code: tplCode,\n name: String(item.templtName ?? \"\"),\n content: String(item.templtContent ?? \"\"),\n status: mapAligoTemplateStatus(item),\n buttons: Array.isArray(item.buttons) ? item.buttons : undefined,\n createdAt,\n updatedAt,\n } satisfies Template;\n })\n .filter((template) => template.code.length > 0);\n\n if (params?.status) {\n const status = params.status.trim().toUpperCase();\n return ok(templates.filter((template) => template.status === status));\n }\n\n return ok(templates);\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n\nexport async function requestTemplateInspection(\n ctx: AligoRuntimeContext,\n code: string,\n templateCtx?: TemplateContext,\n): Promise<Result<void, KMsgError>> {\n try {\n const senderKey = resolveKakaoSenderKey(ctx, templateCtx);\n const templateCode = code.trim();\n\n if (!templateCode) {\n return fail(\n new KMsgError(KMsgErrorCode.INVALID_REQUEST, \"code is required\", {\n providerId: ctx.providerId,\n }),\n );\n }\n\n const response = await requestAligo({\n host: ctx.alimtalkHost,\n endpoint: \"/akv10/template/request/\",\n data: {\n apikey: ctx.config.apiKey,\n userid: ctx.config.userId,\n senderkey: senderKey,\n tpl_code: templateCode,\n },\n providerId: ctx.providerId,\n });\n\n const okResult = ensureAligoKakaoOk({\n providerId: ctx.providerId,\n response,\n fallbackMessage: \"template inspection request failed\",\n });\n if (okResult.isFailure) return okResult;\n\n return ok(undefined);\n } catch (error) {\n return fail(mapAligoKakaoError(error, ctx.providerId));\n }\n}\n"
14
- ],
15
- "mappings": "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",
16
- "debugId": "712B4D075ED82CEB64756E2164756E21",
17
- "names": []
18
- }