@walkeros/server-destination-aws 4.8.1-next-1792019907609 → 4.8.2
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/CHANGELOG.md +26 -3
- package/dist/dev.d.mts +7 -2
- package/dist/dev.d.ts +7 -2
- package/dist/dev.js +1 -1
- package/dist/dev.js.map +1 -1
- package/dist/dev.mjs +1 -1
- package/dist/dev.mjs.map +1 -1
- package/dist/examples/index.d.mts +7 -2
- package/dist/examples/index.d.ts +7 -2
- package/dist/examples/index.js +23 -6
- package/dist/examples/index.mjs +24 -7
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/schemas.js +1 -1
- package/dist/schemas.js.map +1 -1
- package/dist/schemas.mjs +1 -1
- package/dist/schemas.mjs.map +1 -1
- package/dist/walkerOS.json +407 -51
- package/package.json +6 -4
package/dist/dev.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/firehose/examples/index.ts","../src/firehose/examples/env.ts","../src/firehose/examples/step.ts","../src/lib/payload.ts","../src/firehose/lib/records.ts","../src/sns/examples/index.ts","../src/sns/examples/env.ts","../src/sns/examples/step.ts","../src/firehose/schemas/index.ts","../src/firehose/schemas/settings.ts","../src/firehose/schemas/mapping.ts","../src/sns/schemas/index.ts","../src/sns/schemas/settings.ts","../src/sns/schemas/mapping.ts","../src/sns/schemas/setup.ts","../src/schemas.ts","../src/examples/index.ts","../src/hints.ts","../src/dev.ts"],"sourcesContent":["export * as env from './env';\nexport * as step from './step';\n","import type { PutRecordBatchCommandInput } from '@aws-sdk/client-firehose';\nimport type { Env, SendClient } from '../types';\n\n/**\n * Example environment for the AWS Firehose destination.\n *\n * `push` is the mock env simulate injects: the client answers every `send`\n * locally, so nothing reaches AWS. Each command keeps its `input`, so a\n * recorded `send` shows the request.\n */\n\ninterface RecordsInput {\n Records: unknown[];\n}\n\nfunction hasRecords(value: unknown): value is RecordsInput {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'Records' in value &&\n Array.isArray(value.Records)\n );\n}\n\n// Mock FirehoseClient class: every record is accepted.\nclass MockFirehoseClient implements SendClient {\n config: unknown;\n\n constructor(config?: unknown) {\n this.config = config;\n }\n\n async send(command: object) {\n const input = 'input' in command ? command.input : undefined;\n const records = hasRecords(input) ? input.Records : [];\n return {\n FailedPutCount: 0,\n Encrypted: false,\n RequestResponses: records.map((_, index) => ({\n RecordId: `mock-record-id-${index}`,\n })),\n };\n }\n\n destroy(): void {}\n}\n\n// Mock PutRecordBatchCommand class. The build minifies class names; the tag\n// keeps the SDK command name in printed simulate output.\nclass MockPutRecordBatchCommand {\n readonly input: PutRecordBatchCommandInput;\n\n constructor(input: PutRecordBatchCommandInput) {\n this.input = input;\n }\n\n get [Symbol.toStringTag](): string {\n return 'PutRecordBatchCommand';\n }\n}\n\nexport const push: Env = {\n AWS: {\n FirehoseClient: MockFirehoseClient,\n PutRecordBatchCommand: MockPutRecordBatchCommand,\n },\n};\n\nexport const simulation = ['call:AWS.FirehoseClient.send'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport { toRecordData } from '../lib/records';\n\n/**\n * Firehose step examples. Each `out` is the recorded\n * `client.send(new PutRecordBatchCommand(input))` call. A record is the full\n * event as JSON plus a newline, or the mapped `data` when a mapping produced\n * an object.\n */\n\nconst STREAM = 'walkeros-events';\n\n/**\n * The copy-paste config: the stream, its region, and keys from `$secret`.\n * `init` builds one client from it, offline, with a per-attempt timeout of a\n * quarter of the collector's 10 s race, so the SDK's three attempts end\n * before the collector stops waiting.\n */\nexport const init: Flow.StepExample = {\n title: 'Initialization',\n description:\n 'Init builds one FirehoseClient for the stream region with the credentials from config.credentials and a 2500 ms per-attempt timeout. Nothing is sent until the first event.',\n in: {\n settings: { streamName: STREAM, region: 'eu-central-1' },\n credentials: {\n accessKeyId: '$secret.AWS_ACCESS_KEY_ID',\n secretAccessKey: '$secret.AWS_SECRET_ACCESS_KEY',\n },\n },\n out: [\n [\n 'new FirehoseClient',\n {\n region: 'eu-central-1',\n credentials: {\n accessKeyId: '$secret.AWS_ACCESS_KEY_ID',\n secretAccessKey: '$secret.AWS_SECRET_ACCESS_KEY',\n },\n requestHandler: { requestTimeout: 2500, throwOnRequestTimeout: true },\n },\n ],\n ],\n};\n\nconst pageEvent = getEvent('page view', {\n id: 'ev-1700001000',\n timestamp: 1700001000,\n data: { title: 'Home', url: 'https://example.com/' },\n source: { type: 'express', platform: 'server' },\n});\n\nconst orderEvt = getEvent('order complete', {\n id: 'ev-1700001001',\n timestamp: 1700001001,\n data: { id: 'ORD-400', total: 99.99, currency: 'EUR' },\n source: { type: 'express', platform: 'server' },\n});\n\nconst signupEvt = getEvent('user signup', {\n id: 'ev-1700001002',\n timestamp: 1700001002,\n data: { plan: 'pro', source: 'landing-page' },\n user: { id: 'usr-789', email: 'new@example.com' },\n source: { type: 'express', platform: 'server' },\n});\n\nfunction sent(payload: unknown): Flow.StepExample['out'] {\n return [\n [\n 'client.send',\n {\n DeliveryStreamName: STREAM,\n Records: [{ Data: toRecordData(payload) }],\n },\n ],\n ];\n}\n\nexport const firehoseRecord: Flow.StepExample = {\n title: 'Page view record',\n description:\n 'A page view is sent to Firehose as one record: the full event as JSON followed by a newline.',\n in: pageEvent,\n mapping: undefined,\n out: sent(pageEvent),\n};\n\nexport const orderEvent: Flow.StepExample = {\n title: 'Order record',\n description:\n 'An order complete event is serialized and delivered to Firehose as one newline-terminated record.',\n in: orderEvt,\n mapping: undefined,\n out: sent(orderEvt),\n};\n\nexport const userSignupEvent: Flow.StepExample = {\n title: 'User signup record',\n description:\n 'A user signup event including user fields is streamed to Firehose as a JSON record.',\n in: signupEvt,\n mapping: undefined,\n out: sent(signupEvt),\n};\n\nexport const mappedRecord: Flow.StepExample = {\n title: 'Mapped record',\n description:\n 'A mapping that produces an object sends that object as the record instead of the full event. Keep the event id in it for deduplication.',\n in: orderEvt,\n mapping: {\n data: {\n map: {\n id: 'id',\n name: 'name',\n order_id: 'data.id',\n total: 'data.total',\n },\n },\n },\n out: sent({\n id: 'ev-1700001001',\n name: 'order complete',\n order_id: 'ORD-400',\n total: 99.99,\n }),\n};\n","import type { WalkerOS } from '@walkeros/core';\nimport { isObject } from '@walkeros/core';\n\n/**\n * What one record or message carries: the mapped `data` when the mapping\n * produced an object, else the full event.\n */\nexport function toPayload(event: WalkerOS.Event, data?: unknown): object {\n return isObject(data) ? data : event;\n}\n","export { toPayload } from '../../lib/payload';\n\n/** Most records one `PutRecordBatch` call accepts. */\nexport const MAX_RECORDS_PER_CALL = 500;\n\n/**\n * Raw bytes per call, kept below the documented 4 MiB request limit with room\n * for the base64 encoding and the JSON envelope of the request.\n */\nexport const MAX_BYTES_PER_CALL = 2_900_000;\n\n/** Largest record Firehose accepts, newline included. */\nexport const MAX_RECORD_BYTES = 1_000_000;\n\n/** The record bytes: the payload as JSON, plus `\\n` unless `newline` is false. */\nexport function toRecordData(payload: unknown, newline = true): Buffer {\n const json = JSON.stringify(payload);\n if (typeof json !== 'string')\n throw new TypeError('The payload does not serialize to JSON.');\n return Buffer.from(newline ? `${json}\\n` : json);\n}\n\n/** One record on its way out, with its index in the delivery. */\nexport interface PlannedRecord {\n index: number;\n data: Buffer;\n}\n\n/** A record refused before sending; it is never sent. */\nexport interface RefusedRecord {\n index: number;\n code: 'RecordTooLarge' | 'InvalidRecord';\n detail: string;\n cause?: unknown;\n}\n\nexport interface Plan {\n chunks: PlannedRecord[][];\n refused: RefusedRecord[];\n}\n\n/**\n * Turns payloads into records and splits them into calls of at most\n * `MAX_RECORDS_PER_CALL` records and `MAX_BYTES_PER_CALL` bytes, in order.\n * A record that cannot be serialized or is too large is refused on its own,\n * so it never fails its neighbours.\n */\nexport function planChunks(\n payloads: readonly unknown[],\n newline: boolean,\n): Plan {\n const chunks: PlannedRecord[][] = [];\n const refused: RefusedRecord[] = [];\n let current: PlannedRecord[] = [];\n let currentBytes = 0;\n\n payloads.forEach((payload, index) => {\n let data: Buffer;\n try {\n data = toRecordData(payload, newline);\n } catch (error) {\n refused.push({\n index,\n code: 'InvalidRecord',\n detail: `Record ${index} does not serialize to JSON: ${error instanceof Error ? error.message : String(error)}`,\n cause: error,\n });\n return;\n }\n\n if (data.byteLength > MAX_RECORD_BYTES) {\n refused.push({\n index,\n code: 'RecordTooLarge',\n detail: `Record ${index} is ${data.byteLength} bytes, over the ${MAX_RECORD_BYTES} byte limit.`,\n });\n return;\n }\n\n if (\n current.length >= MAX_RECORDS_PER_CALL ||\n currentBytes + data.byteLength > MAX_BYTES_PER_CALL\n ) {\n chunks.push(current);\n current = [];\n currentBytes = 0;\n }\n\n current.push({ index, data });\n currentBytes += data.byteLength;\n });\n\n if (current.length > 0) chunks.push(current);\n return { chunks, refused };\n}\n","export * as env from './env';\nexport * as step from './step';\n","import type {\n CreateTopicCommandInput,\n GetTopicAttributesCommandInput,\n PublishCommandInput,\n SubscribeCommandInput,\n} from '@aws-sdk/client-sns';\nimport type { GetCallerIdentityCommandInput } from '@aws-sdk/client-sts';\nimport type { Env, SendClient } from '../types';\n\n/**\n * Example environment for the AWS SNS destination.\n *\n * `push` is the mock env simulate injects: the SNS and STS clients answer\n * every `send` locally, so nothing reaches AWS. Each command keeps its\n * `input`, so a recorded `send` shows the request (`Publish` per event).\n * Unit tests still substitute the SDK module-wide via\n * `jest.mock('@aws-sdk/client-sns')`.\n */\n\nconst TOPIC_ARN = 'arn:aws:sns:eu-central-1:123456789012:walkeros-events';\n\n// The build minifies class names; the tag keeps the SDK command name in\n// printed simulate output (`{\"PublishCommand\":{\"input\":...}}`).\nclass MockCommand<Input> {\n constructor(public readonly input: Input) {}\n}\n\nclass MockCreateTopicCommand extends MockCommand<CreateTopicCommandInput> {\n get [Symbol.toStringTag](): string {\n return 'CreateTopicCommand';\n }\n}\nclass MockPublishCommand extends MockCommand<PublishCommandInput> {\n get [Symbol.toStringTag](): string {\n return 'PublishCommand';\n }\n}\nclass MockGetTopicAttributesCommand extends MockCommand<GetTopicAttributesCommandInput> {\n get [Symbol.toStringTag](): string {\n return 'GetTopicAttributesCommand';\n }\n}\nclass MockSubscribeCommand extends MockCommand<SubscribeCommandInput> {\n get [Symbol.toStringTag](): string {\n return 'SubscribeCommand';\n }\n}\nclass MockGetCallerIdentityCommand extends MockCommand<GetCallerIdentityCommandInput> {\n get [Symbol.toStringTag](): string {\n return 'GetCallerIdentityCommand';\n }\n}\n\nclass MockSNSClient implements SendClient {\n constructor(public config?: object) {}\n async send(command: object): Promise<unknown> {\n if (command instanceof MockCreateTopicCommand)\n return { TopicArn: TOPIC_ARN };\n if (command instanceof MockPublishCommand)\n return { MessageId: 'mock-message-id' };\n return {};\n }\n destroy(): void {}\n}\n\nclass MockSTSClient implements SendClient {\n constructor(public config?: object) {}\n async send(): Promise<unknown> {\n return {\n Account: '123456789012',\n Arn: 'arn:aws:iam::123456789012:user/walkeros',\n };\n }\n destroy(): void {}\n}\n\nexport const push: Env = {\n AWS: {\n SNSClient: MockSNSClient,\n CreateTopicCommand: MockCreateTopicCommand,\n PublishCommand: MockPublishCommand,\n GetTopicAttributesCommand: MockGetTopicAttributesCommand,\n SubscribeCommand: MockSubscribeCommand,\n STSClient: MockSTSClient,\n GetCallerIdentityCommand: MockGetCallerIdentityCommand,\n },\n};\n\n/** Every request goes through `send`; the command in `args[0]` names it. */\nexport const simulation = ['call:AWS.SNSClient.send'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\n\n/**\n * SNS step examples. Each example's `out` is the array of recorded mock\n * calls produced by `push()`. The recording shape is:\n * ['client.send', commandInput]\n *\n * The destination JSON-stringifies the event (or the mapped `data` object)\n * into the Publish call's Message field. Mapping entries (messageGroupId,\n * messageDeduplicationId, messageAttributes) resolve per event via\n * getMappingValue. On a FIFO topic the deduplication id defaults to the\n * event id.\n */\n\nconst TOPIC_ARN = 'arn:aws:sns:eu-central-1:123456789012:walkeros-events';\nconst FIFO_ARN = 'arn:aws:sns:eu-central-1:123456789012:walkeros-events.fifo';\n\n/**\n * The copy-paste config: the topic ARN, which also names the region, and\n * keys from `$secret`. `init` builds one client from it, offline; nothing is\n * sent until the first event.\n */\nexport const init: Flow.StepExample = {\n title: 'Initialization',\n description:\n 'Init builds one SNSClient in the region of the topic ARN with the credentials from config.credentials and a 2500 ms per-attempt timeout. No topic is created and nothing is sent until the first event.',\n in: {\n settings: { topicArn: TOPIC_ARN },\n credentials: {\n accessKeyId: '$secret.AWS_ACCESS_KEY_ID',\n secretAccessKey: '$secret.AWS_SECRET_ACCESS_KEY',\n },\n },\n out: [\n [\n 'new SNSClient',\n {\n region: 'eu-central-1',\n credentials: {\n accessKeyId: '$secret.AWS_ACCESS_KEY_ID',\n secretAccessKey: '$secret.AWS_SECRET_ACCESS_KEY',\n },\n requestHandler: { requestTimeout: 2500, throwOnRequestTimeout: true },\n },\n ],\n ],\n};\n\nconst pageEvent = getEvent('page view', {\n id: 'ev-1700001000',\n timestamp: 1700001000,\n data: { title: 'Home', url: 'https://example.com/' },\n source: { type: 'express', platform: 'server' },\n});\n\nconst orderEvt = getEvent('order complete', {\n id: 'ev-1700001001',\n timestamp: 1700001001,\n data: { id: 'ORD-400', total: 99.99, currency: 'EUR' },\n user: { id: 'usr-789' },\n source: { type: 'express', platform: 'server' },\n});\n\nconst productViewEvt = getEvent('product view', {\n id: 'ev-1700001002',\n timestamp: 1700001002,\n data: { id: 'SKU-1', tenant_id: 'acme' },\n source: { type: 'express', platform: 'server' },\n});\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view publish',\n description:\n 'A page view event is JSON-stringified and published as the Message of an SNS Publish call.',\n in: pageEvent,\n mapping: undefined,\n out: [\n [\n 'client.send',\n {\n TopicArn: TOPIC_ARN,\n Message: JSON.stringify(pageEvent),\n },\n ],\n ],\n};\n\nexport const orderEvent: Flow.StepExample = {\n title: 'Order publish with FIFO group (path-resolved)',\n description:\n 'An order complete event is published to a FIFO topic with a messageGroupId resolved from the event via the mapping path \"user.id\". The deduplication id defaults to the event id.',\n in: orderEvt,\n mapping: { settings: { messageGroupId: 'user.id' } },\n out: [\n [\n 'client.send',\n {\n TopicArn: FIFO_ARN,\n Message: JSON.stringify(orderEvt),\n MessageGroupId: 'usr-789',\n MessageDeduplicationId: 'ev-1700001001',\n },\n ],\n ],\n};\n\nexport const attributedPublish: Flow.StepExample = {\n title: 'Publish with per-event message attributes',\n description:\n 'Demonstrates `messageAttributes` as `Mapping.Map`: each attribute value resolves per event. Operators express the SDK shape (`{ DataType, StringValue }`) per entry.',\n in: productViewEvt,\n mapping: {\n settings: {\n messageAttributes: {\n schema_version: { value: { DataType: 'String', StringValue: 'v4' } },\n tenant: { value: { DataType: 'String', StringValue: 'acme' } },\n },\n },\n },\n out: [\n [\n 'client.send',\n {\n TopicArn: TOPIC_ARN,\n Message: JSON.stringify(productViewEvt),\n MessageAttributes: {\n schema_version: { DataType: 'String', StringValue: 'v4' },\n tenant: { DataType: 'String', StringValue: 'acme' },\n },\n },\n ],\n ],\n};\n\nexport const mappedMessage: Flow.StepExample = {\n title: 'Mapped message',\n description:\n 'A mapping that produces an object publishes that object as the Message instead of the full event. Keep the event id in it for deduplication.',\n in: orderEvt,\n mapping: {\n data: {\n map: { id: 'id', name: 'name', order_id: 'data.id', total: 'data.total' },\n },\n },\n out: [\n [\n 'client.send',\n {\n TopicArn: TOPIC_ARN,\n Message: JSON.stringify({\n id: 'ev-1700001001',\n name: 'order complete',\n order_id: 'ORD-400',\n total: 99.99,\n }),\n },\n ],\n ],\n};\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema, FirehoseConfigSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport {\n SettingsSchema,\n type Settings,\n FirehoseConfigSchema,\n} from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n\n// Nested JSON Schema for Firehose subpage\nexport const firehose = zodToSchema(FirehoseConfigSchema);\n","import { z } from '@walkeros/core/dev';\n\nconst streamName = z\n .string()\n .min(1)\n .describe('Name of the Firehose stream (like walkeros-events). Required.')\n .optional();\n\nconst region = z\n .string()\n .describe(\n 'AWS region of the stream (like eu-central-1). Default: AWS_REGION or the active profile, else eu-central-1.',\n );\n\nconst client = z\n .any()\n .describe(\n 'A FirehoseClient of your own. Used as is and never closed by the destination.',\n );\n\nconst config = z\n .any()\n .describe(\n 'Raw FirehoseClient options passed to the SDK (like { endpoint, maxAttempts }). Put keys in config.credentials instead.',\n );\n\n/** @deprecated The nested form, still read as an alias of the flat fields. */\nexport const FirehoseConfigSchema = z.object({\n streamName,\n client: client.optional(),\n region: region.optional(),\n config: config.optional(),\n});\n\nexport const SettingsSchema = z.object({\n // Optional in the schema only so the deprecated alias still validates;\n // init throws when neither form names a stream.\n streamName,\n region: region.optional(),\n newline: z\n .boolean()\n .describe(\n 'Append a newline to every record (default true). Set false when the stream adds its own new line delimiter.',\n )\n .optional(),\n config: config.optional(),\n client: client.optional(),\n firehose: FirehoseConfigSchema.describe(\n 'Deprecated: use the flat fields streamName, region, config and client.',\n ).optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * AWS Firehose Mapping Schema\n * Firehose has no rule-level settings: a rule's `data` becomes the record.\n */\nexport const MappingSchema = z.object({});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\nimport { SetupSchema } from './setup';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\nexport {\n SetupSchema,\n SetupSubscriptionSchema,\n type Setup,\n type SetupSubscription,\n} from './setup';\n\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\nexport const setup = zodToSchema(SetupSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n topicArn: z\n .string()\n .describe(\n 'Topic ARN (like arn:aws:sns:eu-central-1:123456789012:walkeros-events). Region and topic name derive from it. Required unless topicName is set.',\n )\n .optional(),\n topicName: z\n .string()\n .min(1)\n .describe(\n 'Topic name (like walkeros-events). Used by walkeros setup; without topicArn the ARN is completed with the account id at the first publish.',\n )\n .optional(),\n region: z\n .string()\n .describe(\n 'AWS region (like eu-central-1). Default: the region in topicArn, AWS_REGION or the active profile, else eu-central-1.',\n )\n .optional(),\n client: z\n .any()\n .describe(\n 'An SNSClient of your own. Used as is and never closed by the destination.',\n )\n .optional(),\n config: z\n .any()\n .describe(\n 'Raw SNSClient options passed to the SDK. Put keys in config.credentials instead.',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * SNS Mapping Schema.\n *\n * `messageAttributes` is `Mapping.Map`: each value resolves per event to the\n * SDK's `{ DataType, StringValue }` shape. Schema accepts any structure;\n * runtime mapping resolution coerces shape via `getMappingValue`.\n *\n * `messageGroupId` and `messageDeduplicationId` are `Mapping.Value`: a string\n * path or a value-config object.\n */\nexport const MappingSchema = z.object({\n messageAttributes: z.record(z.string(), z.unknown()).optional(),\n messageGroupId: z.unknown().optional(),\n messageDeduplicationId: z.unknown().optional(),\n});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { z } from '@walkeros/core/dev';\n\nexport const SetupSubscriptionSchema = z.object({\n protocol: z.enum(['sqs', 'lambda', 'https', 'http', 'email', 'sms']),\n endpoint: z.string().min(1),\n rawMessageDelivery: z.boolean().optional(),\n filterPolicy: z.record(z.string(), z.unknown()).optional(),\n deadLetterTargetArn: z.string().optional(),\n});\n\nexport const SetupSchema = z.object({\n region: z.string().optional(),\n displayName: z.string().optional(),\n fifoTopic: z.boolean().optional(),\n kmsMasterKeyId: z.string().optional(),\n tags: z.record(z.string(), z.string()).optional(),\n subscriptions: z.array(SetupSubscriptionSchema).optional(),\n});\n\nexport type Setup = z.infer<typeof SetupSchema>;\nexport type SetupSubscription = z.infer<typeof SetupSubscriptionSchema>;\n","// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\n\nexport {\n settings as firehoseSettings,\n mapping as firehoseMapping,\n firehose,\n} from './firehose/schemas';\n\nexport {\n settings as snsSettings,\n mapping as snsMapping,\n setup as snsSetup,\n} from './sns/schemas';\n\n// Backwards-compatible aliases (firehose is the package's default sub-destination).\nexport { settings, mapping } from './firehose/schemas';\n","export * as firehose from '../firehose/examples';\nexport * as sns from '../sns/examples';\n// Re-export env at top level for env-loader compatibility (matches web pattern)\nexport * as env from '../firehose/examples/env';\nexport * as step from '../firehose/examples/step';\n","import type { Hint } from '@walkeros/core';\n\nexport const hints: Hint.Hints = {\n 'minimal-config': {\n text: 'Firehose needs settings.streamName (plus settings.region when the stream is not in AWS_REGION or eu-central-1). SNS needs settings.topicArn; region and topic name derive from it. Off AWS, add config.credentials. Nothing is sent and no credentials are loaded until the first event.',\n code: [\n {\n lang: 'json',\n code: '{ \"settings\": { \"streamName\": \"walkeros-events\", \"region\": \"eu-central-1\" }, \"credentials\": { \"accessKeyId\": \"$secret.AWS_ACCESS_KEY_ID\", \"secretAccessKey\": \"$secret.AWS_SECRET_ACCESS_KEY\" } }',\n },\n {\n lang: 'json',\n code: '{ \"settings\": { \"topicArn\": \"arn:aws:sns:eu-central-1:123456789012:walkeros-events\" } }',\n },\n ],\n },\n 'auth-credentials': {\n text: 'On AWS compute an attached IAM role needs no config at all. Elsewhere, config.credentials ({ accessKeyId, secretAccessKey, sessionToken? }, or the same as a JSON string) wins over settings.config.credentials, which wins over the AWS default chain (AWS_* variables, AWS_PROFILE, ECS, EC2 and web identity roles; Kubernetes can go keyless with AWS_ROLE_ARN plus AWS_WEB_IDENTITY_TOKEN_FILE). Back every value with $secret; never write a literal key. Credentials are shape-checked at init and loaded only at the first send.',\n code: [\n {\n lang: 'json',\n code: '{ \"credentials\": { \"accessKeyId\": \"$secret.AWS_ACCESS_KEY_ID\", \"secretAccessKey\": \"$secret.AWS_SECRET_ACCESS_KEY\" } }',\n },\n ],\n },\n 'firehose-records': {\n text: 'Each record is the mapped data object, or the full event when the mapping produced none, followed by a newline. Set settings.newline: false when the stream adds its own new line delimiter. Batching is on by default (500 records or 1 s); calls carry at most 500 records and 2,900,000 bytes, and a record over 1,000,000 bytes fails as RecordTooLarge without being sent.',\n },\n 'delivery-guarantee': {\n text: 'Delivery is at least once: deduplicate downstream on event.id, and keep id in mapped data. A record AWS rejects is reported as failed with code, status and retryable. There is no retry beyond the built-in AWS SDK retry: a rejected record goes to the in-memory dead letter queue of the collector, which nothing replays yet. On SNS FIFO topics MessageDeduplicationId defaults to event.id.',\n },\n 'troubleshoot-errors': {\n text: 'Every failure carries code, status and retryable, and its message names the stream or topic and the region. ResourceNotFoundException: wrong settings.streamName or region. AccessDeniedException / AuthorizationErrorException: the credentials lack firehose:PutRecordBatch or sns:Publish. UnrecognizedClientException, InvalidSignatureException, ExpiredTokenException or no credentials found: check config.credentials or the environment. SNS NotFoundException: the topic does not exist; run walkeros setup or set settings.topicArn. NULL rows in Athena: the stream adds its own new line delimiter too, so set newline: false. InvalidConfig at start: a missing or conflicting setting, named in the message.',\n },\n};\n","import * as firehoseExamplesNs from './firehose/examples';\nimport * as snsExamplesNs from './sns/examples';\nimport * as firehoseSchemasNs from './firehose/schemas';\nimport * as snsSchemasNs from './sns/schemas';\n\nexport * as schemas from './schemas';\nexport * as examples from './examples';\nexport { hints } from './hints';\n\n/** Dev examples per export, keyed by the export names in package.json. */\nexport const exportExamples = {\n destinationFirehose: firehoseExamplesNs,\n destinationSNS: snsExamplesNs,\n};\n\n/** Schemas per export, keyed by the export names in package.json. */\nexport const exportSchemas = {\n destinationFirehose: {\n settings: firehoseSchemasNs.settings,\n mapping: firehoseSchemasNs.mapping,\n },\n destinationSNS: {\n settings: snsSchemasNs.settings,\n mapping: snsSchemasNs.mapping,\n setup: snsSchemasNs.setup,\n },\n};\n"],"mappings":"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","names":["config","examples_exports","env_exports","step_exports","env_exports","push","simulation","config","step_exports","init","orderEvent","getEvent","TOPIC_ARN","pageEvent","orderEvt","z","zodToSchema","z","SettingsSchema","z","MappingSchema","z","settings","zodToSchema","SettingsSchema","mapping","MappingSchema","mapping","settings","examples_exports","examples_exports","settings","mapping"]}
|
|
1
|
+
{"version":3,"sources":["../src/firehose/examples/index.ts","../src/firehose/examples/env.ts","../src/firehose/examples/step.ts","../src/lib/payload.ts","../src/firehose/lib/records.ts","../src/sns/examples/index.ts","../src/sns/examples/env.ts","../src/sns/examples/step.ts","../src/firehose/schemas/index.ts","../src/firehose/schemas/settings.ts","../src/firehose/schemas/mapping.ts","../src/sns/schemas/index.ts","../src/sns/schemas/settings.ts","../src/sns/schemas/mapping.ts","../src/sns/schemas/setup.ts","../src/schemas.ts","../src/examples/index.ts","../src/hints.ts","../src/dev.ts"],"sourcesContent":["export * as env from './env';\nexport * as step from './step';\n","import type { PutRecordBatchCommandInput } from '@aws-sdk/client-firehose';\nimport type { Env, SendClient } from '../types';\n\n/**\n * Example environment for the AWS Firehose destination.\n *\n * `push` is the mock env simulate injects: the client answers every `send`\n * locally, so nothing reaches AWS. Each command keeps its `input`, so a\n * recorded `send` shows the request.\n */\n\ninterface RecordsInput {\n Records: unknown[];\n}\n\nfunction hasRecords(value: unknown): value is RecordsInput {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'Records' in value &&\n Array.isArray(value.Records)\n );\n}\n\n// Mock FirehoseClient class: every record is accepted.\nclass MockFirehoseClient implements SendClient {\n config: unknown;\n\n constructor(config?: unknown) {\n this.config = config;\n }\n\n async send(command: object) {\n const input = 'input' in command ? command.input : undefined;\n const records = hasRecords(input) ? input.Records : [];\n return {\n FailedPutCount: 0,\n Encrypted: false,\n RequestResponses: records.map((_, index) => ({\n RecordId: `mock-record-id-${index}`,\n })),\n };\n }\n\n destroy(): void {}\n}\n\n// Mock PutRecordBatchCommand class. The build minifies class names; the tag\n// keeps the SDK command name in printed simulate output.\nclass MockPutRecordBatchCommand {\n readonly input: PutRecordBatchCommandInput;\n\n constructor(input: PutRecordBatchCommandInput) {\n this.input = input;\n }\n\n get [Symbol.toStringTag](): string {\n return 'PutRecordBatchCommand';\n }\n}\n\nexport const push: Env = {\n AWS: {\n FirehoseClient: MockFirehoseClient,\n PutRecordBatchCommand: MockPutRecordBatchCommand,\n },\n};\n\nexport const simulation = ['call:AWS.FirehoseClient.send'];\n","import type { Flow } from '@walkeros/core';\nimport { createEvent, getEvent } from '@walkeros/core';\nimport { toRecordData } from '../lib/records';\n\n/**\n * Firehose step examples. Each `out` is the recorded\n * `client.send(new PutRecordBatchCommand(input))` call. A record is the full\n * event as JSON plus a newline, or the mapped `data` when a mapping produced\n * an object.\n */\n\nconst STREAM = 'walkeros-events';\n\n/**\n * The copy-paste config: the stream, its region, and keys from `$secret`.\n * `init` builds one client from it, offline, with a per-attempt timeout of a\n * quarter of the collector's 10 s race, so the SDK's three attempts end\n * before the collector stops waiting.\n */\nexport const init: Flow.StepExample = {\n title: 'Initialization',\n description:\n 'Init builds one FirehoseClient for the stream region with the credentials from config.credentials and a 2500 ms per-attempt timeout. Nothing is sent until the first event.',\n in: {\n settings: { streamName: STREAM, region: 'eu-central-1' },\n credentials: {\n accessKeyId: '$secret.AWS_ACCESS_KEY_ID',\n secretAccessKey: '$secret.AWS_SECRET_ACCESS_KEY',\n },\n },\n out: [\n [\n 'new FirehoseClient',\n {\n region: 'eu-central-1',\n credentials: {\n accessKeyId: '$secret.AWS_ACCESS_KEY_ID',\n secretAccessKey: '$secret.AWS_SECRET_ACCESS_KEY',\n },\n requestHandler: { requestTimeout: 2500, throwOnRequestTimeout: true },\n },\n ],\n ],\n};\n\nconst pageEvent = getEvent('page view', {\n id: 'ev-1700001000',\n timestamp: 1700001000,\n data: { title: 'Home', url: 'https://example.com/' },\n source: { type: 'express', platform: 'server' },\n});\n\nconst orderEvt = getEvent('order complete', {\n id: 'ev-1700001001',\n timestamp: 1700001001,\n data: { id: 'ORD-400', value: 99.99, currency: 'EUR' },\n source: { type: 'express', platform: 'server' },\n});\n\nconst signupEvt = createEvent({\n name: 'user signup',\n id: 'ev-1700001002',\n timestamp: 1700001002,\n data: { plan: 'pro', source: 'landing-page' },\n user: { id: 'usr-789', email: 'new@example.com' },\n source: { type: 'express', platform: 'server' },\n});\n\nfunction sent(payload: unknown): Flow.StepExample['out'] {\n return [\n [\n 'client.send',\n {\n DeliveryStreamName: STREAM,\n Records: [{ Data: toRecordData(payload) }],\n },\n ],\n ];\n}\n\nexport const firehoseRecord: Flow.StepExample = {\n title: 'Page view record',\n description:\n 'A page view is sent to Firehose as one record: the full event as JSON followed by a newline.',\n in: pageEvent,\n mapping: undefined,\n out: sent(pageEvent),\n};\n\nexport const orderEvent: Flow.StepExample = {\n title: 'Order record',\n description:\n 'An order complete event is serialized and delivered to Firehose as one newline-terminated record.',\n in: orderEvt,\n mapping: undefined,\n out: sent(orderEvt),\n};\n\nexport const userSignupEvent: Flow.StepExample = {\n title: 'User signup record',\n description:\n 'A user signup event including user fields is streamed to Firehose as a JSON record.',\n in: signupEvt,\n mapping: undefined,\n out: sent(signupEvt),\n};\n\nexport const mappedRecord: Flow.StepExample = {\n title: 'Mapped record',\n description:\n 'A mapping that produces an object sends that object as the record instead of the full event. Keep the event id in it for deduplication.',\n in: orderEvt,\n mapping: {\n data: {\n map: {\n id: 'id',\n name: 'name',\n order_id: 'data.id',\n total: 'data.value',\n },\n },\n },\n out: sent({\n id: 'ev-1700001001',\n name: 'order complete',\n order_id: 'ORD-400',\n total: 99.99,\n }),\n};\n\n/** A silent rule sends no record to Firehose. */\nexport const silentRule: Flow.StepExample = {\n public: false,\n description: 'A rule with silent: true sends no record to Firehose.',\n in: pageEvent,\n mapping: { silent: true },\n out: [],\n};\n","import type { WalkerOS } from '@walkeros/core';\nimport { isObject } from '@walkeros/core';\n\n/**\n * What one record or message carries: the mapped `data` when the mapping\n * produced an object, else the full event.\n */\nexport function toPayload(event: WalkerOS.Event, data?: unknown): object {\n return isObject(data) ? data : event;\n}\n","export { toPayload } from '../../lib/payload';\n\n/** Most records one `PutRecordBatch` call accepts. */\nexport const MAX_RECORDS_PER_CALL = 500;\n\n/**\n * Raw bytes per call, kept below the documented 4 MiB request limit with room\n * for the base64 encoding and the JSON envelope of the request.\n */\nexport const MAX_BYTES_PER_CALL = 2_900_000;\n\n/** Largest record Firehose accepts, newline included. */\nexport const MAX_RECORD_BYTES = 1_000_000;\n\n/** The record bytes: the payload as JSON, plus `\\n` unless `newline` is false. */\nexport function toRecordData(payload: unknown, newline = true): Buffer {\n const json = JSON.stringify(payload);\n if (typeof json !== 'string')\n throw new TypeError('The payload does not serialize to JSON.');\n return Buffer.from(newline ? `${json}\\n` : json);\n}\n\n/** One record on its way out, with its index in the delivery. */\nexport interface PlannedRecord {\n index: number;\n data: Buffer;\n}\n\n/** A record refused before sending; it is never sent. */\nexport interface RefusedRecord {\n index: number;\n code: 'RecordTooLarge' | 'InvalidRecord';\n detail: string;\n cause?: unknown;\n}\n\nexport interface Plan {\n chunks: PlannedRecord[][];\n refused: RefusedRecord[];\n}\n\n/**\n * Turns payloads into records and splits them into calls of at most\n * `MAX_RECORDS_PER_CALL` records and `MAX_BYTES_PER_CALL` bytes, in order.\n * A record that cannot be serialized or is too large is refused on its own,\n * so it never fails its neighbours.\n */\nexport function planChunks(\n payloads: readonly unknown[],\n newline: boolean,\n): Plan {\n const chunks: PlannedRecord[][] = [];\n const refused: RefusedRecord[] = [];\n let current: PlannedRecord[] = [];\n let currentBytes = 0;\n\n payloads.forEach((payload, index) => {\n let data: Buffer;\n try {\n data = toRecordData(payload, newline);\n } catch (error) {\n refused.push({\n index,\n code: 'InvalidRecord',\n detail: `Record ${index} does not serialize to JSON.`,\n cause: error,\n });\n return;\n }\n\n if (data.byteLength > MAX_RECORD_BYTES) {\n refused.push({\n index,\n code: 'RecordTooLarge',\n detail: `Record ${index} is ${data.byteLength} bytes, over the ${MAX_RECORD_BYTES} byte limit.`,\n });\n return;\n }\n\n if (\n current.length >= MAX_RECORDS_PER_CALL ||\n currentBytes + data.byteLength > MAX_BYTES_PER_CALL\n ) {\n chunks.push(current);\n current = [];\n currentBytes = 0;\n }\n\n current.push({ index, data });\n currentBytes += data.byteLength;\n });\n\n if (current.length > 0) chunks.push(current);\n return { chunks, refused };\n}\n","export * as env from './env';\nexport * as step from './step';\n","import type {\n CreateTopicCommandInput,\n GetTopicAttributesCommandInput,\n PublishCommandInput,\n SubscribeCommandInput,\n} from '@aws-sdk/client-sns';\nimport type { GetCallerIdentityCommandInput } from '@aws-sdk/client-sts';\nimport type { Env, SendClient } from '../types';\n\n/**\n * Example environment for the AWS SNS destination.\n *\n * `push` is the mock env simulate injects: the SNS and STS clients answer\n * every `send` locally, so nothing reaches AWS. Each command keeps its\n * `input`, so a recorded `send` shows the request (`Publish` per event).\n * Unit tests still substitute the SDK module-wide via\n * `jest.mock('@aws-sdk/client-sns')`.\n */\n\nconst TOPIC_ARN = 'arn:aws:sns:eu-central-1:123456789012:walkeros-events';\n\n// The build minifies class names; the tag keeps the SDK command name in\n// printed simulate output (`{\"PublishCommand\":{\"input\":...}}`).\nclass MockCommand<Input> {\n constructor(public readonly input: Input) {}\n}\n\nclass MockCreateTopicCommand extends MockCommand<CreateTopicCommandInput> {\n get [Symbol.toStringTag](): string {\n return 'CreateTopicCommand';\n }\n}\nclass MockPublishCommand extends MockCommand<PublishCommandInput> {\n get [Symbol.toStringTag](): string {\n return 'PublishCommand';\n }\n}\nclass MockGetTopicAttributesCommand extends MockCommand<GetTopicAttributesCommandInput> {\n get [Symbol.toStringTag](): string {\n return 'GetTopicAttributesCommand';\n }\n}\nclass MockSubscribeCommand extends MockCommand<SubscribeCommandInput> {\n get [Symbol.toStringTag](): string {\n return 'SubscribeCommand';\n }\n}\nclass MockGetCallerIdentityCommand extends MockCommand<GetCallerIdentityCommandInput> {\n get [Symbol.toStringTag](): string {\n return 'GetCallerIdentityCommand';\n }\n}\n\nclass MockSNSClient implements SendClient {\n constructor(public config?: object) {}\n async send(command: object): Promise<unknown> {\n if (command instanceof MockCreateTopicCommand)\n return { TopicArn: TOPIC_ARN };\n if (command instanceof MockPublishCommand)\n return { MessageId: 'mock-message-id' };\n return {};\n }\n destroy(): void {}\n}\n\nclass MockSTSClient implements SendClient {\n constructor(public config?: object) {}\n async send(): Promise<unknown> {\n return {\n Account: '123456789012',\n Arn: 'arn:aws:iam::123456789012:user/walkeros',\n };\n }\n destroy(): void {}\n}\n\nexport const push: Env = {\n AWS: {\n SNSClient: MockSNSClient,\n CreateTopicCommand: MockCreateTopicCommand,\n PublishCommand: MockPublishCommand,\n GetTopicAttributesCommand: MockGetTopicAttributesCommand,\n SubscribeCommand: MockSubscribeCommand,\n STSClient: MockSTSClient,\n GetCallerIdentityCommand: MockGetCallerIdentityCommand,\n },\n};\n\n/** Every request goes through `send`; the command in `args[0]` names it. */\nexport const simulation = ['call:AWS.SNSClient.send'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\n\n/**\n * SNS step examples. Each example's `out` is the array of recorded mock\n * calls produced by `push()`. The recording shape is:\n * ['client.send', commandInput]\n *\n * The destination JSON-stringifies the event (or the mapped `data` object)\n * into the Publish call's Message field. Mapping entries (messageGroupId,\n * messageDeduplicationId, messageAttributes) resolve per event via\n * getMappingValue. On a FIFO topic the deduplication id defaults to the\n * event id.\n */\n\nconst TOPIC_ARN = 'arn:aws:sns:eu-central-1:123456789012:walkeros-events';\nconst FIFO_ARN = 'arn:aws:sns:eu-central-1:123456789012:walkeros-events.fifo';\n\n/**\n * The copy-paste config: the topic ARN, which also names the region, and\n * keys from `$secret`. `init` builds one client from it, offline; nothing is\n * sent until the first event.\n */\nexport const init: Flow.StepExample = {\n title: 'Initialization',\n description:\n 'Init builds one SNSClient in the region of the topic ARN with the credentials from config.credentials and a 2500 ms per-attempt timeout. No topic is created and nothing is sent until the first event.',\n in: {\n settings: { topicArn: TOPIC_ARN },\n credentials: {\n accessKeyId: '$secret.AWS_ACCESS_KEY_ID',\n secretAccessKey: '$secret.AWS_SECRET_ACCESS_KEY',\n },\n },\n out: [\n [\n 'new SNSClient',\n {\n region: 'eu-central-1',\n credentials: {\n accessKeyId: '$secret.AWS_ACCESS_KEY_ID',\n secretAccessKey: '$secret.AWS_SECRET_ACCESS_KEY',\n },\n requestHandler: { requestTimeout: 2500, throwOnRequestTimeout: true },\n },\n ],\n ],\n};\n\nconst pageEvent = getEvent('page view', {\n id: 'ev-1700001000',\n timestamp: 1700001000,\n data: { title: 'Home', url: 'https://example.com/' },\n source: { type: 'express', platform: 'server' },\n});\n\nconst orderEvt = getEvent('order complete', {\n id: 'ev-1700001001',\n timestamp: 1700001001,\n data: { id: 'ORD-400', value: 99.99, currency: 'EUR' },\n user: { id: 'usr-789' },\n source: { type: 'express', platform: 'server' },\n});\n\nconst productViewEvt = getEvent('product view', {\n id: 'ev-1700001002',\n timestamp: 1700001002,\n data: { id: 'SKU-1', tenant_id: 'acme' },\n source: { type: 'express', platform: 'server' },\n});\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view publish',\n description:\n 'A page view event is JSON-stringified and published as the Message of an SNS Publish call.',\n in: pageEvent,\n mapping: undefined,\n out: [\n [\n 'client.send',\n {\n TopicArn: TOPIC_ARN,\n Message: JSON.stringify(pageEvent),\n },\n ],\n ],\n};\n\nexport const orderEvent: Flow.StepExample = {\n title: 'Order publish with FIFO group (path-resolved)',\n description:\n 'An order complete event is published to a FIFO topic with a messageGroupId resolved from the event via the mapping path \"user.id\". The deduplication id defaults to the event id.',\n in: orderEvt,\n mapping: { settings: { messageGroupId: 'user.id' } },\n out: [\n [\n 'client.send',\n {\n TopicArn: FIFO_ARN,\n Message: JSON.stringify(orderEvt),\n MessageGroupId: 'usr-789',\n MessageDeduplicationId: 'ev-1700001001',\n },\n ],\n ],\n};\n\nexport const attributedPublish: Flow.StepExample = {\n title: 'Publish with per-event message attributes',\n description:\n 'Demonstrates `messageAttributes` as `Mapping.Map`: each attribute value resolves per event. Operators express the SDK shape (`{ DataType, StringValue }`) per entry.',\n in: productViewEvt,\n mapping: {\n settings: {\n messageAttributes: {\n schema_version: { value: { DataType: 'String', StringValue: 'v4' } },\n tenant: { value: { DataType: 'String', StringValue: 'acme' } },\n },\n },\n },\n out: [\n [\n 'client.send',\n {\n TopicArn: TOPIC_ARN,\n Message: JSON.stringify(productViewEvt),\n MessageAttributes: {\n schema_version: { DataType: 'String', StringValue: 'v4' },\n tenant: { DataType: 'String', StringValue: 'acme' },\n },\n },\n ],\n ],\n};\n\nexport const mappedMessage: Flow.StepExample = {\n title: 'Mapped message',\n description:\n 'A mapping that produces an object publishes that object as the Message instead of the full event. Keep the event id in it for deduplication.',\n in: orderEvt,\n mapping: {\n data: {\n map: { id: 'id', name: 'name', order_id: 'data.id', total: 'data.value' },\n },\n },\n out: [\n [\n 'client.send',\n {\n TopicArn: TOPIC_ARN,\n Message: JSON.stringify({\n id: 'ev-1700001001',\n name: 'order complete',\n order_id: 'ORD-400',\n total: 99.99,\n }),\n },\n ],\n ],\n};\n\n/** A silent rule publishes no message to SNS. */\nexport const silentRule: Flow.StepExample = {\n public: false,\n description: 'A rule with silent: true publishes no message to SNS.',\n in: pageEvent,\n mapping: { silent: true },\n out: [],\n};\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema, FirehoseConfigSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport {\n SettingsSchema,\n type Settings,\n FirehoseConfigSchema,\n} from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n\n// Nested JSON Schema for Firehose subpage\nexport const firehose = zodToSchema(FirehoseConfigSchema);\n","import { z } from '@walkeros/core/dev';\n\nconst streamName = z\n .string()\n .min(1)\n .describe('Name of the Firehose stream (like walkeros-events). Required.')\n .optional();\n\nconst region = z\n .string()\n .describe(\n 'AWS region of the stream (like eu-central-1). Default: AWS_REGION or the active profile, else eu-central-1.',\n );\n\nconst client = z\n .any()\n .describe(\n 'A FirehoseClient of your own. Used as is and never closed by the destination.',\n );\n\nconst config = z\n .any()\n .describe(\n 'Raw FirehoseClient options passed to the SDK (like { endpoint, maxAttempts }). Put keys in config.credentials instead.',\n );\n\n/** @deprecated The nested form, still read as an alias of the flat fields. */\nexport const FirehoseConfigSchema = z.object({\n streamName,\n client: client.optional(),\n region: region.optional(),\n config: config.optional(),\n});\n\nexport const SettingsSchema = z\n .object({\n // Optional in the schema only so the deprecated alias still validates;\n // init throws when neither form names a stream.\n streamName,\n region: region.optional(),\n newline: z\n .boolean()\n .describe(\n 'Append a newline to every record (default true). Set false when the stream adds its own new line delimiter.',\n )\n .optional(),\n config: config.optional(),\n client: client.optional(),\n firehose: FirehoseConfigSchema.describe(\n 'Deprecated: use the flat fields streamName, region, config and client.',\n ).optional(),\n })\n .refine(\n (settings) =>\n settings.streamName !== undefined ||\n settings.firehose?.streamName !== undefined,\n { message: 'Set settings.streamName' },\n )\n // The same rule in JSON Schema: the stream is named in one of both forms.\n .meta({\n anyOf: [\n { required: ['streamName'] },\n {\n required: ['firehose'],\n properties: { firehose: { required: ['streamName'] } },\n },\n ],\n });\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * AWS Firehose Mapping Schema\n * Firehose has no rule-level settings: a rule's `data` becomes the record.\n */\nexport const MappingSchema = z.object({});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\nimport { SetupSchema } from './setup';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\nexport {\n SetupSchema,\n SetupSubscriptionSchema,\n type Setup,\n type SetupSubscription,\n} from './setup';\n\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\nexport const setup = zodToSchema(SetupSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z\n .object({\n topicArn: z\n .string()\n .describe(\n 'Topic ARN (like arn:aws:sns:eu-central-1:123456789012:walkeros-events). Region and topic name derive from it. Required unless topicName is set.',\n )\n .optional(),\n topicName: z\n .string()\n .min(1)\n .describe(\n 'Topic name (like walkeros-events). Used by walkeros setup; without topicArn the ARN is completed with the account id at the first publish.',\n )\n .optional(),\n region: z\n .string()\n .describe(\n 'AWS region (like eu-central-1). Default: the region in topicArn, AWS_REGION or the active profile, else eu-central-1.',\n )\n .optional(),\n client: z\n .any()\n .describe(\n 'An SNSClient of your own. Used as is and never closed by the destination.',\n )\n .optional(),\n config: z\n .any()\n .describe(\n 'Raw SNSClient options passed to the SDK. Put keys in config.credentials instead.',\n )\n .optional(),\n })\n .refine(\n (settings) =>\n settings.topicArn !== undefined || settings.topicName !== undefined,\n { message: 'Set settings.topicArn or settings.topicName' },\n )\n // The same rule in JSON Schema: one of both names the topic.\n .meta({\n anyOf: [{ required: ['topicArn'] }, { required: ['topicName'] }],\n });\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * SNS Mapping Schema.\n *\n * `messageAttributes` is `Mapping.Map`: each value resolves per event to the\n * SDK's `{ DataType, StringValue }` shape. Schema accepts any structure;\n * runtime mapping resolution coerces shape via `getMappingValue`.\n *\n * `messageGroupId` and `messageDeduplicationId` are `Mapping.Value`: a string\n * path or a value-config object.\n */\nexport const MappingSchema = z.object({\n messageAttributes: z.record(z.string(), z.unknown()).optional(),\n messageGroupId: z.unknown().optional(),\n messageDeduplicationId: z.unknown().optional(),\n});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { z } from '@walkeros/core/dev';\n\nexport const SetupSubscriptionSchema = z.object({\n protocol: z.enum(['sqs', 'lambda', 'https', 'http', 'email', 'sms']),\n endpoint: z.string().min(1),\n rawMessageDelivery: z.boolean().optional(),\n filterPolicy: z.record(z.string(), z.unknown()).optional(),\n deadLetterTargetArn: z.string().optional(),\n});\n\nexport const SetupSchema = z.object({\n region: z.string().optional(),\n displayName: z.string().optional(),\n fifoTopic: z.boolean().optional(),\n kmsMasterKeyId: z.string().optional(),\n tags: z.record(z.string(), z.string()).optional(),\n subscriptions: z.array(SetupSubscriptionSchema).optional(),\n});\n\nexport type Setup = z.infer<typeof SetupSchema>;\nexport type SetupSubscription = z.infer<typeof SetupSubscriptionSchema>;\n","// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\n\nexport {\n settings as firehoseSettings,\n mapping as firehoseMapping,\n firehose,\n} from './firehose/schemas';\n\nexport {\n settings as snsSettings,\n mapping as snsMapping,\n setup as snsSetup,\n} from './sns/schemas';\n\n// Backwards-compatible aliases (firehose is the package's default sub-destination).\nexport { settings, mapping } from './firehose/schemas';\n","export * as firehose from '../firehose/examples';\nexport * as sns from '../sns/examples';\n// Re-export env at top level for env-loader compatibility (matches web pattern)\nexport * as env from '../firehose/examples/env';\nexport * as step from '../firehose/examples/step';\n","import type { Hint } from '@walkeros/core';\n\nexport const hints: Hint.Hints = {\n 'minimal-config': {\n text: 'Firehose needs settings.streamName (plus settings.region when the stream is not in AWS_REGION or eu-central-1). SNS needs settings.topicArn; region and topic name derive from it. Off AWS, add config.credentials. Nothing is sent and no credentials are loaded until the first event.',\n code: [\n {\n lang: 'json',\n code: '{ \"settings\": { \"streamName\": \"walkeros-events\", \"region\": \"eu-central-1\" }, \"credentials\": { \"accessKeyId\": \"$secret.AWS_ACCESS_KEY_ID\", \"secretAccessKey\": \"$secret.AWS_SECRET_ACCESS_KEY\" } }',\n },\n {\n lang: 'json',\n code: '{ \"settings\": { \"topicArn\": \"arn:aws:sns:eu-central-1:123456789012:walkeros-events\" } }',\n },\n ],\n },\n 'auth-credentials': {\n text: 'On AWS compute an attached IAM role needs no config at all. Elsewhere, config.credentials ({ accessKeyId, secretAccessKey, sessionToken? }, or the same as a JSON string) wins over settings.config.credentials, which wins over the AWS default chain (AWS_* variables, AWS_PROFILE, ECS, EC2 and web identity roles; Kubernetes can go keyless with AWS_ROLE_ARN plus AWS_WEB_IDENTITY_TOKEN_FILE). Back every value with $secret; never write a literal key. Credentials are shape-checked at init and loaded only at the first send.',\n code: [\n {\n lang: 'json',\n code: '{ \"credentials\": { \"accessKeyId\": \"$secret.AWS_ACCESS_KEY_ID\", \"secretAccessKey\": \"$secret.AWS_SECRET_ACCESS_KEY\" } }',\n },\n ],\n },\n 'firehose-records': {\n text: 'Each record is the mapped data object, or the full event when the mapping produced none, followed by a newline. Set settings.newline: false when the stream adds its own new line delimiter. Batching is on by default (500 records or 1 s); calls carry at most 500 records and 2,900,000 bytes, and a record over 1,000,000 bytes fails as RecordTooLarge without being sent.',\n },\n 'delivery-guarantee': {\n text: 'Delivery is at least once: deduplicate downstream on event.id, and keep id in mapped data. A record AWS rejects is reported as failed with code, status and retryable. There is no retry beyond the built-in AWS SDK retry: a rejected record goes to the in-memory dead letter queue of the collector, which nothing replays yet. On SNS FIFO topics MessageDeduplicationId defaults to event.id.',\n },\n 'troubleshoot-errors': {\n text: 'Every failure carries code, status and retryable, and its message names the stream or topic and the region; the AWS error itself stays on the error as its cause. ResourceNotFoundException: wrong settings.streamName or region. AccessDeniedException / AuthorizationErrorException: the credentials lack firehose:PutRecordBatch or sns:Publish. UnrecognizedClientException, InvalidSignatureException, ExpiredTokenException or no credentials found: check config.credentials or the environment. SNS NotFoundException: the topic does not exist; run walkeros setup or set settings.topicArn. NULL rows in Athena: the stream adds its own new line delimiter too, so set newline: false. Code config at start: a missing or conflicting setting, named in the message.',\n },\n};\n","import * as firehoseExamplesNs from './firehose/examples';\nimport * as snsExamplesNs from './sns/examples';\nimport * as firehoseSchemasNs from './firehose/schemas';\nimport * as snsSchemasNs from './sns/schemas';\n\nexport * as schemas from './schemas';\nexport * as examples from './examples';\nexport { hints } from './hints';\n\n/** Dev examples per export, keyed by the export names in package.json. */\nexport const exportExamples = {\n destinationFirehose: firehoseExamplesNs,\n destinationSNS: snsExamplesNs,\n};\n\n/** Schemas per export, keyed by the export names in package.json. */\nexport const exportSchemas = {\n destinationFirehose: {\n settings: firehoseSchemasNs.settings,\n mapping: firehoseSchemasNs.mapping,\n },\n destinationSNS: {\n settings: snsSchemasNs.settings,\n mapping: snsSchemasNs.mapping,\n setup: snsSchemasNs.setup,\n },\n};\n"],"mappings":"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","names":["config","examples_exports","env_exports","step_exports","env_exports","push","simulation","config","step_exports","init","orderEvent","silentRule","getEvent","TOPIC_ARN","pageEvent","orderEvt","settings","z","zodToSchema","z","SettingsSchema","settings","z","MappingSchema","z","settings","zodToSchema","SettingsSchema","mapping","MappingSchema","mapping","settings","examples_exports","examples_exports","settings","mapping"]}
|
|
@@ -47,12 +47,14 @@ declare const firehoseRecord: Flow.StepExample;
|
|
|
47
47
|
declare const orderEvent$1: Flow.StepExample;
|
|
48
48
|
declare const userSignupEvent: Flow.StepExample;
|
|
49
49
|
declare const mappedRecord: Flow.StepExample;
|
|
50
|
+
/** A silent rule sends no record to Firehose. */
|
|
51
|
+
declare const silentRule$1: Flow.StepExample;
|
|
50
52
|
|
|
51
53
|
declare const step$1_firehoseRecord: typeof firehoseRecord;
|
|
52
54
|
declare const step$1_mappedRecord: typeof mappedRecord;
|
|
53
55
|
declare const step$1_userSignupEvent: typeof userSignupEvent;
|
|
54
56
|
declare namespace step$1 {
|
|
55
|
-
export { step$1_firehoseRecord as firehoseRecord, init$1 as init, step$1_mappedRecord as mappedRecord, orderEvent$1 as orderEvent, step$1_userSignupEvent as userSignupEvent };
|
|
57
|
+
export { step$1_firehoseRecord as firehoseRecord, init$1 as init, step$1_mappedRecord as mappedRecord, orderEvent$1 as orderEvent, silentRule$1 as silentRule, step$1_userSignupEvent as userSignupEvent };
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
declare namespace index$1 {
|
|
@@ -99,14 +101,17 @@ declare const pageView: Flow.StepExample;
|
|
|
99
101
|
declare const orderEvent: Flow.StepExample;
|
|
100
102
|
declare const attributedPublish: Flow.StepExample;
|
|
101
103
|
declare const mappedMessage: Flow.StepExample;
|
|
104
|
+
/** A silent rule publishes no message to SNS. */
|
|
105
|
+
declare const silentRule: Flow.StepExample;
|
|
102
106
|
|
|
103
107
|
declare const step_attributedPublish: typeof attributedPublish;
|
|
104
108
|
declare const step_init: typeof init;
|
|
105
109
|
declare const step_mappedMessage: typeof mappedMessage;
|
|
106
110
|
declare const step_orderEvent: typeof orderEvent;
|
|
107
111
|
declare const step_pageView: typeof pageView;
|
|
112
|
+
declare const step_silentRule: typeof silentRule;
|
|
108
113
|
declare namespace step {
|
|
109
|
-
export { step_attributedPublish as attributedPublish, step_init as init, step_mappedMessage as mappedMessage, step_orderEvent as orderEvent, step_pageView as pageView };
|
|
114
|
+
export { step_attributedPublish as attributedPublish, step_init as init, step_mappedMessage as mappedMessage, step_orderEvent as orderEvent, step_pageView as pageView, step_silentRule as silentRule };
|
|
110
115
|
}
|
|
111
116
|
|
|
112
117
|
declare const index_env: typeof env;
|
package/dist/examples/index.d.ts
CHANGED
|
@@ -47,12 +47,14 @@ declare const firehoseRecord: Flow.StepExample;
|
|
|
47
47
|
declare const orderEvent$1: Flow.StepExample;
|
|
48
48
|
declare const userSignupEvent: Flow.StepExample;
|
|
49
49
|
declare const mappedRecord: Flow.StepExample;
|
|
50
|
+
/** A silent rule sends no record to Firehose. */
|
|
51
|
+
declare const silentRule$1: Flow.StepExample;
|
|
50
52
|
|
|
51
53
|
declare const step$1_firehoseRecord: typeof firehoseRecord;
|
|
52
54
|
declare const step$1_mappedRecord: typeof mappedRecord;
|
|
53
55
|
declare const step$1_userSignupEvent: typeof userSignupEvent;
|
|
54
56
|
declare namespace step$1 {
|
|
55
|
-
export { step$1_firehoseRecord as firehoseRecord, init$1 as init, step$1_mappedRecord as mappedRecord, orderEvent$1 as orderEvent, step$1_userSignupEvent as userSignupEvent };
|
|
57
|
+
export { step$1_firehoseRecord as firehoseRecord, init$1 as init, step$1_mappedRecord as mappedRecord, orderEvent$1 as orderEvent, silentRule$1 as silentRule, step$1_userSignupEvent as userSignupEvent };
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
declare namespace index$1 {
|
|
@@ -99,14 +101,17 @@ declare const pageView: Flow.StepExample;
|
|
|
99
101
|
declare const orderEvent: Flow.StepExample;
|
|
100
102
|
declare const attributedPublish: Flow.StepExample;
|
|
101
103
|
declare const mappedMessage: Flow.StepExample;
|
|
104
|
+
/** A silent rule publishes no message to SNS. */
|
|
105
|
+
declare const silentRule: Flow.StepExample;
|
|
102
106
|
|
|
103
107
|
declare const step_attributedPublish: typeof attributedPublish;
|
|
104
108
|
declare const step_init: typeof init;
|
|
105
109
|
declare const step_mappedMessage: typeof mappedMessage;
|
|
106
110
|
declare const step_orderEvent: typeof orderEvent;
|
|
107
111
|
declare const step_pageView: typeof pageView;
|
|
112
|
+
declare const step_silentRule: typeof silentRule;
|
|
108
113
|
declare namespace step {
|
|
109
|
-
export { step_attributedPublish as attributedPublish, step_init as init, step_mappedMessage as mappedMessage, step_orderEvent as orderEvent, step_pageView as pageView };
|
|
114
|
+
export { step_attributedPublish as attributedPublish, step_init as init, step_mappedMessage as mappedMessage, step_orderEvent as orderEvent, step_pageView as pageView, step_silentRule as silentRule };
|
|
110
115
|
}
|
|
111
116
|
|
|
112
117
|
declare const index_env: typeof env;
|
package/dist/examples/index.js
CHANGED
|
@@ -86,6 +86,7 @@ __export(step_exports, {
|
|
|
86
86
|
init: () => init,
|
|
87
87
|
mappedRecord: () => mappedRecord,
|
|
88
88
|
orderEvent: () => orderEvent,
|
|
89
|
+
silentRule: () => silentRule,
|
|
89
90
|
userSignupEvent: () => userSignupEvent
|
|
90
91
|
});
|
|
91
92
|
var import_core2 = require("@walkeros/core");
|
|
@@ -137,10 +138,11 @@ var pageEvent = (0, import_core2.getEvent)("page view", {
|
|
|
137
138
|
var orderEvt = (0, import_core2.getEvent)("order complete", {
|
|
138
139
|
id: "ev-1700001001",
|
|
139
140
|
timestamp: 1700001001,
|
|
140
|
-
data: { id: "ORD-400",
|
|
141
|
+
data: { id: "ORD-400", value: 99.99, currency: "EUR" },
|
|
141
142
|
source: { type: "express", platform: "server" }
|
|
142
143
|
});
|
|
143
|
-
var signupEvt = (0, import_core2.
|
|
144
|
+
var signupEvt = (0, import_core2.createEvent)({
|
|
145
|
+
name: "user signup",
|
|
144
146
|
id: "ev-1700001002",
|
|
145
147
|
timestamp: 1700001002,
|
|
146
148
|
data: { plan: "pro", source: "landing-page" },
|
|
@@ -189,7 +191,7 @@ var mappedRecord = {
|
|
|
189
191
|
id: "id",
|
|
190
192
|
name: "name",
|
|
191
193
|
order_id: "data.id",
|
|
192
|
-
total: "data.
|
|
194
|
+
total: "data.value"
|
|
193
195
|
}
|
|
194
196
|
}
|
|
195
197
|
},
|
|
@@ -200,6 +202,13 @@ var mappedRecord = {
|
|
|
200
202
|
total: 99.99
|
|
201
203
|
})
|
|
202
204
|
};
|
|
205
|
+
var silentRule = {
|
|
206
|
+
public: false,
|
|
207
|
+
description: "A rule with silent: true sends no record to Firehose.",
|
|
208
|
+
in: pageEvent,
|
|
209
|
+
mapping: { silent: true },
|
|
210
|
+
out: []
|
|
211
|
+
};
|
|
203
212
|
|
|
204
213
|
// src/sns/examples/index.ts
|
|
205
214
|
var examples_exports2 = {};
|
|
@@ -295,7 +304,8 @@ __export(step_exports2, {
|
|
|
295
304
|
init: () => init2,
|
|
296
305
|
mappedMessage: () => mappedMessage,
|
|
297
306
|
orderEvent: () => orderEvent2,
|
|
298
|
-
pageView: () => pageView
|
|
307
|
+
pageView: () => pageView,
|
|
308
|
+
silentRule: () => silentRule2
|
|
299
309
|
});
|
|
300
310
|
var import_core3 = require("@walkeros/core");
|
|
301
311
|
var TOPIC_ARN2 = "arn:aws:sns:eu-central-1:123456789012:walkeros-events";
|
|
@@ -333,7 +343,7 @@ var pageEvent2 = (0, import_core3.getEvent)("page view", {
|
|
|
333
343
|
var orderEvt2 = (0, import_core3.getEvent)("order complete", {
|
|
334
344
|
id: "ev-1700001001",
|
|
335
345
|
timestamp: 1700001001,
|
|
336
|
-
data: { id: "ORD-400",
|
|
346
|
+
data: { id: "ORD-400", value: 99.99, currency: "EUR" },
|
|
337
347
|
user: { id: "usr-789" },
|
|
338
348
|
source: { type: "express", platform: "server" }
|
|
339
349
|
});
|
|
@@ -407,7 +417,7 @@ var mappedMessage = {
|
|
|
407
417
|
in: orderEvt2,
|
|
408
418
|
mapping: {
|
|
409
419
|
data: {
|
|
410
|
-
map: { id: "id", name: "name", order_id: "data.id", total: "data.
|
|
420
|
+
map: { id: "id", name: "name", order_id: "data.id", total: "data.value" }
|
|
411
421
|
}
|
|
412
422
|
},
|
|
413
423
|
out: [
|
|
@@ -425,6 +435,13 @@ var mappedMessage = {
|
|
|
425
435
|
]
|
|
426
436
|
]
|
|
427
437
|
};
|
|
438
|
+
var silentRule2 = {
|
|
439
|
+
public: false,
|
|
440
|
+
description: "A rule with silent: true publishes no message to SNS.",
|
|
441
|
+
in: pageEvent2,
|
|
442
|
+
mapping: { silent: true },
|
|
443
|
+
out: []
|
|
444
|
+
};
|
|
428
445
|
// Annotate the CommonJS export names for ESM import in node:
|
|
429
446
|
0 && (module.exports = {
|
|
430
447
|
env,
|
package/dist/examples/index.mjs
CHANGED
|
@@ -63,9 +63,10 @@ __export(step_exports, {
|
|
|
63
63
|
init: () => init,
|
|
64
64
|
mappedRecord: () => mappedRecord,
|
|
65
65
|
orderEvent: () => orderEvent,
|
|
66
|
+
silentRule: () => silentRule,
|
|
66
67
|
userSignupEvent: () => userSignupEvent
|
|
67
68
|
});
|
|
68
|
-
import { getEvent } from "@walkeros/core";
|
|
69
|
+
import { createEvent, getEvent } from "@walkeros/core";
|
|
69
70
|
|
|
70
71
|
// src/lib/payload.ts
|
|
71
72
|
import { isObject } from "@walkeros/core";
|
|
@@ -114,10 +115,11 @@ var pageEvent = getEvent("page view", {
|
|
|
114
115
|
var orderEvt = getEvent("order complete", {
|
|
115
116
|
id: "ev-1700001001",
|
|
116
117
|
timestamp: 1700001001,
|
|
117
|
-
data: { id: "ORD-400",
|
|
118
|
+
data: { id: "ORD-400", value: 99.99, currency: "EUR" },
|
|
118
119
|
source: { type: "express", platform: "server" }
|
|
119
120
|
});
|
|
120
|
-
var signupEvt =
|
|
121
|
+
var signupEvt = createEvent({
|
|
122
|
+
name: "user signup",
|
|
121
123
|
id: "ev-1700001002",
|
|
122
124
|
timestamp: 1700001002,
|
|
123
125
|
data: { plan: "pro", source: "landing-page" },
|
|
@@ -166,7 +168,7 @@ var mappedRecord = {
|
|
|
166
168
|
id: "id",
|
|
167
169
|
name: "name",
|
|
168
170
|
order_id: "data.id",
|
|
169
|
-
total: "data.
|
|
171
|
+
total: "data.value"
|
|
170
172
|
}
|
|
171
173
|
}
|
|
172
174
|
},
|
|
@@ -177,6 +179,13 @@ var mappedRecord = {
|
|
|
177
179
|
total: 99.99
|
|
178
180
|
})
|
|
179
181
|
};
|
|
182
|
+
var silentRule = {
|
|
183
|
+
public: false,
|
|
184
|
+
description: "A rule with silent: true sends no record to Firehose.",
|
|
185
|
+
in: pageEvent,
|
|
186
|
+
mapping: { silent: true },
|
|
187
|
+
out: []
|
|
188
|
+
};
|
|
180
189
|
|
|
181
190
|
// src/sns/examples/index.ts
|
|
182
191
|
var examples_exports2 = {};
|
|
@@ -272,7 +281,8 @@ __export(step_exports2, {
|
|
|
272
281
|
init: () => init2,
|
|
273
282
|
mappedMessage: () => mappedMessage,
|
|
274
283
|
orderEvent: () => orderEvent2,
|
|
275
|
-
pageView: () => pageView
|
|
284
|
+
pageView: () => pageView,
|
|
285
|
+
silentRule: () => silentRule2
|
|
276
286
|
});
|
|
277
287
|
import { getEvent as getEvent2 } from "@walkeros/core";
|
|
278
288
|
var TOPIC_ARN2 = "arn:aws:sns:eu-central-1:123456789012:walkeros-events";
|
|
@@ -310,7 +320,7 @@ var pageEvent2 = getEvent2("page view", {
|
|
|
310
320
|
var orderEvt2 = getEvent2("order complete", {
|
|
311
321
|
id: "ev-1700001001",
|
|
312
322
|
timestamp: 1700001001,
|
|
313
|
-
data: { id: "ORD-400",
|
|
323
|
+
data: { id: "ORD-400", value: 99.99, currency: "EUR" },
|
|
314
324
|
user: { id: "usr-789" },
|
|
315
325
|
source: { type: "express", platform: "server" }
|
|
316
326
|
});
|
|
@@ -384,7 +394,7 @@ var mappedMessage = {
|
|
|
384
394
|
in: orderEvt2,
|
|
385
395
|
mapping: {
|
|
386
396
|
data: {
|
|
387
|
-
map: { id: "id", name: "name", order_id: "data.id", total: "data.
|
|
397
|
+
map: { id: "id", name: "name", order_id: "data.id", total: "data.value" }
|
|
388
398
|
}
|
|
389
399
|
},
|
|
390
400
|
out: [
|
|
@@ -402,6 +412,13 @@ var mappedMessage = {
|
|
|
402
412
|
]
|
|
403
413
|
]
|
|
404
414
|
};
|
|
415
|
+
var silentRule2 = {
|
|
416
|
+
public: false,
|
|
417
|
+
description: "A rule with silent: true publishes no message to SNS.",
|
|
418
|
+
in: pageEvent2,
|
|
419
|
+
mapping: { silent: true },
|
|
420
|
+
out: []
|
|
421
|
+
};
|
|
405
422
|
export {
|
|
406
423
|
env_exports as env,
|
|
407
424
|
examples_exports as firehose,
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var mod,__defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropNames=Object.getOwnPropertyNames,__hasOwnProp=Object.prototype.hasOwnProperty,index_exports={};((target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})})(index_exports,{DestinationFirehose:()=>types_exports,DestinationSNS:()=>types_exports2,default:()=>destinationFirehose,destinationFirehose:()=>destinationFirehose,destinationSNS:()=>destinationSNS}),module.exports=(mod=index_exports,((to,from,except,desc)=>{if(from&&"object"==typeof from||"function"==typeof from)for(let key of __getOwnPropNames(from))__hasOwnProp.call(to,key)||key===except||__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to})(__defProp({},"__esModule",{value:!0}),mod));var import_client_firehose=require("@aws-sdk/client-firehose"),import_core2=require("@walkeros/core"),import_config=require("@smithy/core/config");function isHandlerInstance(handler){return"object"==typeof handler&&null!==handler&&"handle"in handler&&"function"==typeof handler.handle}function resolveTimeout(timeout){return void 0===timeout||!Number.isFinite(timeout)||timeout<=0?1e4:timeout}function requestHandlerOptions(timeout){return{requestTimeout:Math.floor(.25*resolveTimeout(timeout)),throwOnRequestTimeout:!0}}function parseTopicArn(arn){const parts=arn.split(":");if(6!==parts.length)return;const[prefix,partition,service,region,accountId,name]=parts;return"arn"===prefix&&partition&&"sns"===service&®ion&&accountId&&name?{region:region,accountId:accountId,name:name}:void 0}async function loadSdkRegion(){try{const region=await(0,import_config.loadConfig)(import_config.NODE_REGION_CONFIG_OPTIONS,import_config.NODE_REGION_CONFIG_FILE_OPTIONS)();return"string"==typeof region&®ion.length>0?region:void 0}catch{return}}function firstString(...candidates){return candidates.find(candidate=>"string"==typeof candidate&&candidate.length>0)}var InFlight=class{pending=new Set;track(promise){this.pending.add(promise);const remove=()=>{this.pending.delete(promise)};return promise.then(remove,remove),promise}get size(){return this.pending.size}async settle(){for(;this.pending.size>0;)await Promise.allSettled([...this.pending])}},import_core=require("@walkeros/core"),import_retry=require("@smithy/core/retry"),AwsDeliveryError=class extends Error{code;status;retryable;constructor(message,options){super(message,{cause:options.cause}),this.name="AwsDeliveryError",this.code=options.code,this.status=options.status,this.retryable=options.retryable}};function formatMessage(target,code,text){const hint=function(code,target){switch(code){case"ResourceNotFoundException":return"Firehose"===target.service?"Check settings.streamName and settings.region.":"Check settings.topicArn and settings.region.";case"AccessDeniedException":case"AuthorizationErrorException":return"Firehose"===target.service?"Allow firehose:PutRecordBatch on the stream for these credentials.":"Allow sns:Publish on the topic for these credentials.";case"UnrecognizedClientException":case"InvalidSignatureException":case"ExpiredTokenException":case"CredentialsProviderError":return"Check config.credentials or the AWS credentials in the environment.";case"NotFoundException":return"SNS"===target.service?`Run "walkeros setup destination.${target.id??"<id>"}" or set settings.topicArn.`:void 0;default:return}}(code,target),base=`${function(target){const kind="Firehose"===target.service?"stream":"topic";return`${target.service} ${kind} "${target.resource}" (${target.region})`}(target)}: ${code}: ${text}`;return hint?`${base} ${hint}`:base}function fromSdkError(error,target){if(error instanceof AwsDeliveryError)return error;if(!function(error){return error instanceof Error}(error))return new AwsDeliveryError(formatMessage(target,"UnknownError",String(error)),{code:"UnknownError",retryable:!1,cause:error});const code=function(error){if("Error"!==error.name)return error.name;const code=Reflect.get(error,"code");return"string"==typeof code&&code.length>0?code:error.name}(error),retryable=(0,import_retry.isThrottlingError)(error)||(0,import_retry.isTransientError)(error)||(0,import_retry.isServerError)(error);return new AwsDeliveryError(formatMessage(target,code,error.message),{code:code,status:error.$metadata?.httpStatusCode,retryable:retryable,cause:error})}function recordError(target,code,text,status){return new AwsDeliveryError(formatMessage(target,code,text),{code:code,status:status,retryable:!0})}function localError(target,code,text,cause){return new AwsDeliveryError(formatMessage(target,code,text),{code:code,retryable:"InvalidResponse"===code,cause:cause})}function configError(message){return new AwsDeliveryError(message,{code:"InvalidConfig",retryable:!1})}function nonEmpty(value){return"string"==typeof value&&value.length>0}function parseCredentials(input){if(null==input||""===input)return;let value=input;if("string"==typeof input)try{value=JSON.parse(input)}catch{throw configError('config.credentials is not valid JSON. Expected {"accessKeyId", "secretAccessKey", "sessionToken"?}.')}if(!(0,import_core.isObject)(value))throw configError("config.credentials must be an object with accessKeyId and secretAccessKey.");const{accessKeyId:accessKeyId,secretAccessKey:secretAccessKey,sessionToken:sessionToken}=value;for(const[field,fieldValue]of[["accessKeyId",accessKeyId],["secretAccessKey",secretAccessKey]])if(!nonEmpty(fieldValue))throw configError(`config.credentials.${field} is missing or empty. Set it from a $secret.`);if(void 0!==sessionToken&&!nonEmpty(sessionToken))throw configError("config.credentials.sessionToken must be a non-empty string when set.");const credentials={accessKeyId:String(accessKeyId),secretAccessKey:String(secretAccessKey)};return void 0!==sessionToken&&(credentials.sessionToken=sessionToken),credentials}var STREAM_NAME_PATTERN=/^[a-zA-Z0-9_.-]{1,64}$/;function sameValue(a,b){if(a===b)return!0;if(Array.isArray(a)&&Array.isArray(b))return a.length===b.length&&a.every((v,i)=>sameValue(v,b[i]));if(!(0,import_core2.isObject)(a)||!(0,import_core2.isObject)(b))return!1;if(!isPlain(a)||!isPlain(b))return!1;const keys=Object.keys(a);return keys.length===Object.keys(b).length&&keys.every(key=>key in b&&sameValue(a[key],b[key]))}function isPlain(value){const proto=Object.getPrototypeOf(value);return proto===Object.prototype||null===proto}function pick(key,flat,alias){if(void 0!==flat&&void 0!==alias&&!sameValue(flat,alias))throw configError(`Firehose: settings.${key} and settings.firehose.${key} are both set and differ. Remove settings.firehose.`);return flat??alias}async function getConfig(partialConfig={},env,logger){const input=partialConfig.settings??{},alias=input.firehose??{},streamName=pick("streamName",input.streamName,alias.streamName),sdkConfig=pick("config",input.config,alias.config),userClient=pick("client",input.client,alias.client),regionSetting=pick("region",input.region,alias.region);if(!streamName)throw configError("Firehose: settings.streamName is missing. Set it to the name of your Firehose stream.");if(!STREAM_NAME_PATTERN.test(streamName))throw configError(`Firehose: settings.streamName "${streamName}" is not a valid stream name. Use 1 to 64 letters, digits, "_", "." or "-".`);const region=firstString(regionSetting,"string"==typeof sdkConfig?.region?sdkConfig.region:void 0,await loadSdkRegion())??"eu-central-1",credentials=parseCredentials(partialConfig.credentials),credentialSource=userClient?"client":credentials?"config.credentials":void 0!==sdkConfig?.credentials?"settings.config.credentials":"default chain",client=userClient??function(Client,options){const clientConfig2={...options.config,region:options.region};return options.credentials&&(clientConfig2.credentials=options.credentials),void 0===clientConfig2.requestHandler&&(clientConfig2.requestHandler=requestHandlerOptions(options.timeout)),new Client(clientConfig2)}(env?.AWS?.FirehoseClient??import_client_firehose.FirehoseClient,{region:region,config:sdkConfig,credentials:credentials,timeout:partialConfig.timeout}),settings={streamName:streamName,region:region,newline:!1!==input.newline,client:client,runtime:{ownsClient:!userClient&&!isHandlerInstance(sdkConfig?.requestHandler),inflight:new InFlight,credentialSource:credentialSource}};return sdkConfig&&(settings.config=sdkConfig),logger.debug("Firehose client ready",{stream:streamName,region:region,credentials:credentialSource}),{...partialConfig,settings:settings}}function resolveSettings(settings){const{streamName:streamName,region:region,client:client,runtime:runtime}=settings??{};if(!(streamName&®ion&&client&&runtime))throw configError("Firehose: the destination was not initialized.");return{streamName:streamName,region:region,newline:!1!==settings?.newline,client:client,runtime:runtime}}var import_client_firehose2=require("@aws-sdk/client-firehose"),import_core3=require("@walkeros/core");function toPayload(event,data){return(0,import_core3.isObject)(data)?data:event}function planChunks(payloads,newline){const chunks=[],refused=[];let current=[],currentBytes=0;return payloads.forEach((payload,index)=>{let data;try{data=function(payload,newline=!0){const json=JSON.stringify(payload);if("string"!=typeof json)throw new TypeError("The payload does not serialize to JSON.");return Buffer.from(newline?`${json}\n`:json)}(payload,newline)}catch(error){return void refused.push({index:index,code:"InvalidRecord",detail:`Record ${index} does not serialize to JSON: ${error instanceof Error?error.message:String(error)}`,cause:error})}data.byteLength>1e6?refused.push({index:index,code:"RecordTooLarge",detail:`Record ${index} is ${data.byteLength} bytes, over the 1000000 byte limit.`}):((current.length>=500||currentBytes+data.byteLength>29e5)&&(chunks.push(current),current=[],currentBytes=0),current.push({index:index,data:data}),currentBytes+=data.byteLength)}),current.length>0&&chunks.push(current),{chunks:chunks,refused:refused}}function isRecord(value){return"object"==typeof value&&null!==value}function readMetadata(value){if(!isRecord(value))return{};const metadata=value.$metadata;if(!isRecord(metadata))return{};const{httpStatusCode:httpStatusCode,attempts:attempts}=metadata;return{status:"number"==typeof httpStatusCode?httpStatusCode:void 0,attempts:"number"==typeof attempts?attempts:void 0}}async function deliver(items,settings,env,logger){const target={service:"Firehose",resource:settings.streamName,region:settings.region},Command=env?.AWS?.PutRecordBatchCommand??import_client_firehose2.PutRecordBatchCommand,plan=planChunks(items.map(({event:event,data:data})=>toPayload(event,data)),settings.newline),failures=plan.refused.map(({index:index,code:code,detail:detail,cause:cause})=>({index:index,error:localError(target,code,detail,cause)})),results=await Promise.all(plan.chunks.map(async chunk=>{const started=Date.now(),bytes=chunk.reduce((sum,record)=>sum+record.data.byteLength,0),command=new Command({DeliveryStreamName:settings.streamName,Records:chunk.map(({data:data})=>({Data:data}))});let result,attempts;try{const response=function(value){const response=readMetadata(value);return isRecord(value)?("number"==typeof value.FailedPutCount&&(response.failedPutCount=value.FailedPutCount),Array.isArray(value.RequestResponses)&&(response.responses=value.RequestResponses.map(entry=>{if(!isRecord(entry))return{};const{ErrorCode:ErrorCode,ErrorMessage:ErrorMessage}=entry;return{errorCode:"string"==typeof ErrorCode&&ErrorCode.length>0?ErrorCode:void 0,errorMessage:"string"==typeof ErrorMessage?ErrorMessage:void 0}})),response):response}(await settings.runtime.inflight.track(settings.client.send(command)));attempts=response.attempts,result=function(chunk,response,target){const{responses:responses,failedPutCount:failedPutCount,status:status}=response;if(responses&&responses.length===chunk.length){const failures=[];if(responses.forEach((entry,local)=>{entry.errorCode&&failures.push({index:chunk[local].index,error:recordError(target,entry.errorCode,entry.errorMessage??"Record rejected.",status)})}),void 0===failedPutCount||failures.length===failedPutCount)return failures}else if(0===failedPutCount)return[];const error=localError(target,"InvalidResponse",`PutRecordBatch answered without per-record results that match its FailedPutCount for ${chunk.length} records (FailedPutCount ${failedPutCount??"missing"}).`);return chunk.map(({index:index})=>({index:index,error:error}))}(chunk,response,target)}catch(thrown){attempts=readMetadata(thrown).attempts;const error=fromSdkError(thrown,target);result=chunk.map(({index:index})=>({index:index,error:error}))}return logger.debug("Firehose PutRecordBatch",{stream:settings.streamName,records:chunk.length,bytes:bytes,failed:result.length,attempts:attempts,ms:Date.now()-started}),result}));for(const result of results)failures.push(...result);return failures.sort((a,b)=>a.index-b.index)}function toOutcome(total,failures){if(0!==failures.length){if(failures.length>=total)throw function(failures){const first=failures[0].error;if(failures.every(({error:error})=>error===first))return first;const byCode=new Map;for(const{error:error}of failures){const entry=byCode.get(error.code);entry?entry.count+=1:byCode.set(error.code,{count:1,sample:error})}let dominant={count:0,sample:first};for(const entry of byCode.values())entry.count>dominant.count&&(dominant=entry);const counts=[...byCode.entries()].map(([code,{count:count}])=>`${count} ${code}`).join(", ");return new AwsDeliveryError(`${dominant.sample.message} (all ${failures.length} records failed: ${counts})`,{code:dominant.sample.code,status:dominant.sample.status,retryable:failures.every(({error:error})=>error.retryable),cause:dominant.sample})}(failures);return{failed:failures.map(({index:index,error:error})=>({index:index,error:error}))}}}var types_exports={},destinationFirehose={type:"aws-firehose",config:{batch:{size:500,age:1e3}},init:async({config:config,env:env,logger:logger})=>getConfig(config,env,logger),push:async function(event,context){const{config:config,data:data,env:env,logger:logger}=context,settings=resolveSettings(config.settings),[failure]=await deliver([{event:event,data:data}],settings,env,logger);if(failure)throw failure.error},pushBatch:async(batch,context)=>{const{config:config,env:env,logger:logger}=context;if(0===batch.entries.length)return;const settings=resolveSettings(config.settings),failures=await deliver(batch.entries.map(({event:event,data:data})=>({event:event,data:data})),settings,env,logger);return toOutcome(batch.entries.length,failures)},async destroy({config:config,logger:logger}){const runtime=config.settings?.runtime;runtime&&(await runtime.inflight.settle(),runtime.ownsClient&&(runtime.ownsClient=!1,config.settings?.client?.destroy?.(),logger.debug("Firehose client closed")))}},import_client_sns=require("@aws-sdk/client-sns"),import_client_sts=require("@aws-sdk/client-sts"),import_core4=require("@walkeros/core");function createSnsClient(env,options){return new(env?.AWS?.SNSClient??import_client_sns.SNSClient)(function(options){const resolved={...options.config,region:options.region};return options.credentials&&(resolved.credentials=options.credentials),void 0===resolved.requestHandler&&(resolved.requestHandler=requestHandlerOptions(options.timeout)),resolved}(options))}function createStsClient(env,options){const Client=env?.AWS?.STSClient??import_client_sts.STSClient,config={region:options.region},credentials=options.credentials??options.config?.credentials;credentials&&(config.credentials=credentials);const userHandler=options.config?.requestHandler;return config.requestHandler=void 0===userHandler||isHandlerInstance(userHandler)?requestHandlerOptions(options.timeout):userHandler,config.maxAttempts=1,new Client(config)}async function getCallerIdentity(client,env,target){const Command=env?.AWS?.GetCallerIdentityCommand??import_client_sts.GetCallerIdentityCommand;let response;try{response=await client.send(new Command({}))}catch(error){throw fromSdkError(error,target)}if(!(0,import_core4.isObject)(response)||"string"!=typeof response.Account)throw fromSdkError(new Error("STS GetCallerIdentity returned no Account."),target);const partition=("string"==typeof response.Arn?response.Arn:"").split(":")[1]||"aws";return{accountId:response.Account,partition:partition}}function topicArnResolver(topicArn,topicName,target,stsClient,env){if(topicArn)return async()=>topicArn;let pending;return()=>(pending??=(async()=>{const client=stsClient();try{const{accountId:accountId,partition:partition}=await getCallerIdentity(client,env,target);return`arn:${partition}:sns:${target.region}:${accountId}:${topicName}`}finally{client.destroy?.()}})().catch(error=>{throw pending=void 0,error}),pending)}var import_client_sns2=require("@aws-sdk/client-sns"),import_core5=require("@walkeros/core");function isMessageAttribute(value){return(0,import_core5.isObject)(value)&&"string"==typeof value.DataType}async function resolveStringMappingValue(event,value,collector){const resolved=await(0,import_core5.getMappingValue)(event,value,{collector:collector});return"string"==typeof resolved&&resolved.length>0?resolved:null!=resolved?String(resolved):void 0}function readAttempts(value){if("object"!=typeof value||null===value||!("$metadata"in value))return;const metadata=value.$metadata;return"object"==typeof metadata&&null!==metadata&&"attempts"in metadata&&"number"==typeof metadata.attempts?metadata.attempts:void 0}var import_client_sns3=require("@aws-sdk/client-sns"),import_core6=require("@walkeros/core"),DEFAULT_SETUP={fifoTopic:!1},identityCache=new Map;function buildSubscribeAttributes(sub){const attrs={};return void 0!==sub.rawMessageDelivery&&(attrs.RawMessageDelivery=String(sub.rawMessageDelivery)),void 0!==sub.filterPolicy&&(attrs.FilterPolicy=JSON.stringify(sub.filterPolicy)),void 0!==sub.deadLetterTargetArn&&(attrs.RedrivePolicy=JSON.stringify({deadLetterTargetArn:sub.deadLetterTargetArn})),Object.keys(attrs).length>0?attrs:void 0}var types_exports2={},destinationSNS={type:"aws-sns",config:{},setup:async function(ctx){const{config:config,env:env,logger:logger}=ctx,merged=(0,import_core6.resolveSetup)(config.setup,DEFAULT_SETUP);if(!merged)return void logger.debug("setup: skipped (config.setup is false or unset)");const settings=config.settings??{},arn=settings.topicArn?parseTopicArn(settings.topicArn):void 0,topicName=settings.topicName??arn?.name;if(!topicName)return void logger.throw("setup: settings.topicName (or settings.topicArn) is required. There is no safe default for the SNS topic name.");const sdkRegion="string"==typeof settings.config?.region?settings.config.region:void 0,region=firstString(merged.region,settings.region,arn?.region,sdkRegion,await loadSdkRegion())??"eu-central-1",fifo=merged.fifoTopic??!1,finalName=function(name,fifo){if(fifo)return name.endsWith(".fifo")?name:`${name}.fifo`;if(name.endsWith(".fifo"))throw new Error(`FIFO suffix '.fifo' on standard topic name '${name}'. Set setup.fifoTopic: true or rename the topic.`);return name}(topicName,fifo);fifo&&finalName!==topicName&&logger.info(`setup: appended .fifo suffix to FIFO topic name '${topicName}' -> '${finalName}'`);const options={region:region,config:settings.config,credentials:parseCredentials(config.credentials),timeout:config.timeout},client=settings.client??createSnsClient(env,options),closesClient=!settings.client&&!isHandlerInstance(settings.config?.requestHandler);try{const{accountId:accountId,partition:partition}=await async function(env,options,target){const cached=identityCache.get(options.region);if(cached)return cached;const stsClient=createStsClient(env,options);try{const identity=await getCallerIdentity(stsClient,env,target);return identityCache.set(options.region,identity),identity}finally{stsClient.destroy?.()}}(env,options,{service:"SNS",resource:finalName,region:region,id:ctx.id}),candidateArn=`arn:${partition}:sns:${region}:${accountId}:${finalName}`;let topicCreated=!1;try{const Command=env?.AWS?.GetTopicAttributesCommand??import_client_sns3.GetTopicAttributesCommand;await client.send(new Command({TopicArn:candidateArn}))}catch(err){if(!function(err){return!(!function(err){return"object"==typeof err&&null!==err}(err)||"NotFoundException"!==err.name&&"NotFound"!==err.name&&(!err.$metadata||404!==err.$metadata.httpStatusCode))}(err))throw err;topicCreated=!0}const attributes={};fifo&&(attributes.FifoTopic="true",attributes.ContentBasedDeduplication="true"),void 0!==merged.displayName&&(attributes.DisplayName=merged.displayName),void 0!==merged.kmsMasterKeyId&&(attributes.KmsMasterKeyId=merged.kmsMasterKeyId);const tagEntries=merged.tags?Object.entries(merged.tags).map(([Key,Value])=>({Key:Key,Value:Value})):void 0,createInput={Name:finalName};Object.keys(attributes).length>0&&(createInput.Attributes=attributes),tagEntries&&tagEntries.length>0&&(createInput.Tags=tagEntries);const CreateCommand=env?.AWS?.CreateTopicCommand??import_client_sns3.CreateTopicCommand,topicArn=function(res){if("object"==typeof(v=res)&&null!==v&&"string"==typeof res.TopicArn)return res.TopicArn;var v;throw new Error("SNS CreateTopic returned no TopicArn")}(await client.send(new CreateCommand(createInput)));topicCreated?logger.info("setup: topic created",{topicArn:topicArn,region:region}):logger.debug("setup: topic exists; declared state re-applied",{topicArn:topicArn,region:region});const subscriptionsCreated=await async function(client,env,topicArn,declared){let count=0;for(const sub of declared){const input={TopicArn:topicArn,Protocol:sub.protocol,Endpoint:sub.endpoint},attrs=buildSubscribeAttributes(sub);attrs&&(input.Attributes=attrs);const Command=env?.AWS?.SubscribeCommand??import_client_sns3.SubscribeCommand;await client.send(new Command(input)),count+=1}return count}(client,env,topicArn,merged.subscriptions??[]);return{topicArn:topicArn,topicCreated:topicCreated,tagsApplied:merged.tags?Object.keys(merged.tags).length:0,subscriptionsCreated:subscriptionsCreated}}finally{closesClient&&client.destroy?.()}},init:async({config:config,env:env,logger:logger,id:id})=>async function(partialConfig={},env,logger,id){const input=partialConfig.settings??{},{topicArn:topicArn,config:sdkConfig,client:userClient}=input,arn=topicArn?parseTopicArn(topicArn):void 0;if(topicArn&&!arn)throw configError(`SNS: settings.topicArn "${topicArn}" is not an SNS topic ARN (arn:aws:sns:<region>:<account>:<name>).`);if(!arn&&!input.topicName)throw configError("SNS: settings.topicArn is missing. Set it to the ARN of your topic (or set settings.topicName).");if(arn&&input.region&&input.region!==arn.region)throw configError(`SNS: settings.region "${input.region}" differs from the region "${arn.region}" in settings.topicArn. Remove settings.region.`);if(arn&&input.topicName&&input.topicName!==arn.name)throw configError(`SNS: settings.topicName "${input.topicName}" differs from the name "${arn.name}" in settings.topicArn. Remove settings.topicName.`);const sdkRegion="string"==typeof sdkConfig?.region?sdkConfig.region:void 0,region=firstString(input.region,arn?.region,sdkRegion,await loadSdkRegion())??"eu-central-1",topicName=input.topicName??arn?.name;void 0!==partialConfig.batch&&logger.warn("SNS publishes one message per event and does not batch. Remove config.batch from this destination.");const credentials=parseCredentials(partialConfig.credentials),clientOptions={region:region,config:sdkConfig,credentials:credentials,timeout:partialConfig.timeout},settings={region:region,client:userClient??createSnsClient(env,clientOptions),runtime:{ownsClient:!userClient&&!isHandlerInstance(sdkConfig?.requestHandler),inflight:new InFlight,topicArn:topicArnResolver(topicArn,topicName,{service:"SNS",resource:topicName??"",region:region,id:id},()=>createStsClient(env,clientOptions),env)}};return topicArn&&(settings.topicArn=topicArn),topicName&&(settings.topicName=topicName),sdkConfig&&(settings.config=sdkConfig),logger.debug("SNS client ready",{topic:topicArn??topicName,region:region,credentials:userClient?"client":credentials?"config.credentials":void 0!==sdkConfig?.credentials?"settings.config.credentials":"default chain"}),{...partialConfig,settings:settings}}(config,env,logger,id),push:async function(event,context){const{config:config,data:data,env:env,rule:rule,collector:collector,logger:logger,id:id}=context,settings=function(settings){const{region:region,client:client,runtime:runtime}=settings??{};if(!region||!client||!runtime)throw configError("SNS: the destination was not initialized.");return{topicArn:settings?.topicArn,topicName:settings?.topicName,region:region,client:client,runtime:runtime}}(config.settings),{runtime:runtime}=settings,topicArn=await runtime.inflight.track(runtime.topicArn()),target={service:"SNS",resource:topicArn,region:settings.region,id:id},ruleSettings=(value=rule?.settings,"object"==typeof value&&null!==value?rule.settings:{});var value;const messageGroupId=void 0!==ruleSettings.messageGroupId?await resolveStringMappingValue(event,ruleSettings.messageGroupId,collector):void 0,fifo=topicArn.endsWith(".fifo"),messageDeduplicationId=(void 0!==ruleSettings.messageDeduplicationId?await resolveStringMappingValue(event,ruleSettings.messageDeduplicationId,collector):void 0)??(fifo&&event.id?event.id:void 0),messageAttributes=await async function(event,source,collector){if(!source)return;const result={};let touched=!1;for(const[key,value]of Object.entries(source)){const resolved=await(0,import_core5.getMappingValue)(event,value,{collector:collector});isMessageAttribute(resolved)?(result[key]=resolved,touched=!0):"string"==typeof resolved&&resolved.length>0?(result[key]={DataType:"String",StringValue:resolved},touched=!0):null!=resolved&&(result[key]={DataType:"String",StringValue:String(resolved)},touched=!0)}return touched?result:void 0}(event,ruleSettings.messageAttributes,collector);let message;try{message=JSON.stringify(toPayload(event,data))}catch(error){throw localError(target,"InvalidRecord",`The message does not serialize to JSON: ${error instanceof Error?error.message:String(error)}`,error)}const input={TopicArn:topicArn,Message:message};messageGroupId&&(input.MessageGroupId=messageGroupId),messageDeduplicationId&&(input.MessageDeduplicationId=messageDeduplicationId),messageAttributes&&(input.MessageAttributes=messageAttributes);const Command=env?.AWS?.PublishCommand??import_client_sns2.PublishCommand,started=Date.now();let attempts;try{attempts=readAttempts(await runtime.inflight.track(settings.client.send(new Command(input))))}catch(error){throw attempts=readAttempts(error),fromSdkError(error,target)}finally{logger.debug("SNS Publish",{topicArn:topicArn,fifo:fifo,event:event.name,attempts:attempts,ms:Date.now()-started})}},async destroy({config:config,logger:logger}){const runtime=config.settings?.runtime;runtime&&(await runtime.inflight.settle(),runtime.ownsClient&&(runtime.ownsClient=!1,config.settings?.client?.destroy?.(),logger.debug("SNS client closed")))}};//# sourceMappingURL=index.js.map
|
|
1
|
+
"use strict";var mod,__defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropNames=Object.getOwnPropertyNames,__hasOwnProp=Object.prototype.hasOwnProperty,index_exports={};((target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})})(index_exports,{DestinationFirehose:()=>types_exports,DestinationSNS:()=>types_exports2,default:()=>destinationFirehose,destinationFirehose:()=>destinationFirehose,destinationSNS:()=>destinationSNS}),module.exports=(mod=index_exports,((to,from,except,desc)=>{if(from&&"object"==typeof from||"function"==typeof from)for(let key of __getOwnPropNames(from))__hasOwnProp.call(to,key)||key===except||__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to})(__defProp({},"__esModule",{value:!0}),mod));var import_client_firehose=require("@aws-sdk/client-firehose"),import_core3=require("@walkeros/core"),import_config=require("@smithy/core/config");function isHandlerInstance(handler){return"object"==typeof handler&&null!==handler&&"handle"in handler&&"function"==typeof handler.handle}function resolveTimeout(timeout){return void 0===timeout||!Number.isFinite(timeout)||timeout<=0?1e4:timeout}function requestHandlerOptions(timeout){return{requestTimeout:Math.floor(.25*resolveTimeout(timeout)),throwOnRequestTimeout:!0}}function parseTopicArn(arn){const parts=arn.split(":");if(6!==parts.length)return;const[prefix,partition,service,region,accountId,name]=parts;return"arn"===prefix&&partition&&"sns"===service&®ion&&accountId&&name?{region:region,accountId:accountId,name:name}:void 0}async function loadSdkRegion(){try{const region=await(0,import_config.loadConfig)(import_config.NODE_REGION_CONFIG_OPTIONS,import_config.NODE_REGION_CONFIG_FILE_OPTIONS)();return"string"==typeof region&®ion.length>0?region:void 0}catch{return}}function firstString(...candidates){return candidates.find(candidate=>"string"==typeof candidate&&candidate.length>0)}var InFlight=class{pending=new Set;track(promise){this.pending.add(promise);const remove=()=>{this.pending.delete(promise)};return promise.then(remove,remove),promise}get size(){return this.pending.size}async settle(){for(;this.pending.size>0;)await Promise.allSettled([...this.pending])}},import_core2=require("@walkeros/core"),import_retry=require("@smithy/core/retry"),import_core=require("@walkeros/core");function describe(target){const kind="Firehose"===target.service?"stream":"topic";return`${target.service} ${kind} "${target.resource}" (${target.region})`}function formatMessage(target,code,detail){const hint=function(code,target){switch(code){case"ResourceNotFoundException":return"Firehose"===target.service?"Check settings.streamName and settings.region.":"Check settings.topicArn and settings.region.";case"AccessDeniedException":case"AuthorizationErrorException":return"Firehose"===target.service?"Allow firehose:PutRecordBatch on the stream for these credentials.":"Allow sns:Publish on the topic for these credentials.";case"UnrecognizedClientException":case"InvalidSignatureException":case"ExpiredTokenException":case"CredentialsProviderError":return"Check config.credentials or the AWS credentials in the environment.";case"NotFoundException":return"SNS"===target.service?`Run "walkeros setup destination.${target.id??"<id>"}" or set settings.topicArn.`:void 0;default:return}}(code,target),base=detail?`${describe(target)}: ${code}: ${detail}`:`${describe(target)}: ${code}`;return hint?`${base} ${hint}`:base}var PROVIDER_ERRORS=["ProviderError","CredentialsProviderError","TokenProviderError"];function fromSdkError(error,target){if(error instanceof import_core.StepError)return error;if(!function(error){return error instanceof Error}(error))return new import_core.StepError(formatMessage(target,"UnknownError"),{code:"UnknownError",retryable:!1,cause:error});const code=function(error){if("Error"!==error.name)return error.name;const code=Reflect.get(error,"code");return"string"==typeof code&&code.length>0?code:error.name}(error),status=error.$metadata?.httpStatusCode,retryable=(0,import_retry.isThrottlingError)(error)||(0,import_retry.isTransientError)(error)||(0,import_retry.isServerError)(error)||void 0===status&&!PROVIDER_ERRORS.includes(code);return new import_core.StepError(formatMessage(target,code),{code:code,status:status,retryable:retryable,cause:error})}function recordError(target,code,status,body){return new import_core.StepError(formatMessage(target,code),{code:code,status:status,retryable:!0,body:body})}function localError(target,code,detail,cause){return new import_core.StepError(formatMessage(target,code,detail),{code:code,retryable:"InvalidResponse"===code,cause:cause})}function configError(message){return new import_core.StepError(message,{code:"config"})}function nonEmpty(value){return"string"==typeof value&&value.length>0}function parseCredentials(input){if(null==input||""===input)return;let value=input;if("string"==typeof input)try{value=JSON.parse(input)}catch{throw configError('config.credentials is not valid JSON. Expected {"accessKeyId", "secretAccessKey", "sessionToken"?}.')}if(!(0,import_core2.isObject)(value))throw configError("config.credentials must be an object with accessKeyId and secretAccessKey.");const{accessKeyId:accessKeyId,secretAccessKey:secretAccessKey,sessionToken:sessionToken}=value;for(const[field,fieldValue]of[["accessKeyId",accessKeyId],["secretAccessKey",secretAccessKey]])if(!nonEmpty(fieldValue))throw configError(`config.credentials.${field} is missing or empty. Set it from a $secret.`);if(void 0!==sessionToken&&!nonEmpty(sessionToken))throw configError("config.credentials.sessionToken must be a non-empty string when set.");const credentials={accessKeyId:String(accessKeyId),secretAccessKey:String(secretAccessKey)};return void 0!==sessionToken&&(credentials.sessionToken=sessionToken),credentials}var STREAM_NAME_PATTERN=/^[a-zA-Z0-9_.-]{1,64}$/;function sameValue(a,b){if(a===b)return!0;if(Array.isArray(a)&&Array.isArray(b))return a.length===b.length&&a.every((v,i)=>sameValue(v,b[i]));if(!(0,import_core3.isObject)(a)||!(0,import_core3.isObject)(b))return!1;if(!isPlain(a)||!isPlain(b))return!1;const keys=Object.keys(a);return keys.length===Object.keys(b).length&&keys.every(key=>key in b&&sameValue(a[key],b[key]))}function isPlain(value){const proto=Object.getPrototypeOf(value);return proto===Object.prototype||null===proto}function pick(key,flat,alias){if(void 0!==flat&&void 0!==alias&&!sameValue(flat,alias))throw configError(`Firehose: settings.${key} and settings.firehose.${key} are both set and differ. Remove settings.firehose.`);return flat??alias}async function getConfig(partialConfig={},env,logger){const input=partialConfig.settings??{},alias=input.firehose??{},streamName=pick("streamName",input.streamName,alias.streamName),sdkConfig=pick("config",input.config,alias.config),userClient=pick("client",input.client,alias.client),regionSetting=pick("region",input.region,alias.region);if(!streamName)throw configError("Firehose: settings.streamName is missing. Set it to the name of your Firehose stream (settings.firehose.streamName is the deprecated form).");if(!STREAM_NAME_PATTERN.test(streamName))throw configError(`Firehose: settings.streamName "${streamName}" is not a valid stream name. Use 1 to 64 letters, digits, "_", "." or "-".`);const region=firstString(regionSetting,"string"==typeof sdkConfig?.region?sdkConfig.region:void 0,await loadSdkRegion())??"eu-central-1",credentials=parseCredentials(partialConfig.credentials),credentialSource=userClient?"client":credentials?"config.credentials":void 0!==sdkConfig?.credentials?"settings.config.credentials":"default chain",client=userClient??function(Client,options){const clientConfig2={...options.config,region:options.region};return options.credentials&&(clientConfig2.credentials=options.credentials),void 0===clientConfig2.requestHandler&&(clientConfig2.requestHandler=requestHandlerOptions(options.timeout)),new Client(clientConfig2)}(env?.AWS?.FirehoseClient??import_client_firehose.FirehoseClient,{region:region,config:sdkConfig,credentials:credentials,timeout:partialConfig.timeout}),settings={streamName:streamName,region:region,newline:!1!==input.newline,client:client,runtime:{ownsClient:!userClient&&!isHandlerInstance(sdkConfig?.requestHandler),inflight:new InFlight,credentialSource:credentialSource}};return sdkConfig&&(settings.config=sdkConfig),logger.debug("Firehose client ready",{stream:streamName,region:region,credentials:credentialSource}),{...partialConfig,settings:settings}}function resolveSettings(settings){const{streamName:streamName,region:region,client:client,runtime:runtime}=settings??{};if(!(streamName&®ion&&client&&runtime))throw new import_core3.StepError("Firehose: the destination was not initialized.",{code:"not-ready"});return{streamName:streamName,region:region,newline:!1!==settings?.newline,client:client,runtime:runtime}}var import_client_firehose2=require("@aws-sdk/client-firehose"),import_core4=require("@walkeros/core");function toPayload(event,data){return(0,import_core4.isObject)(data)?data:event}function planChunks(payloads,newline){const chunks=[],refused=[];let current=[],currentBytes=0;return payloads.forEach((payload,index)=>{let data;try{data=function(payload,newline=!0){const json=JSON.stringify(payload);if("string"!=typeof json)throw new TypeError("The payload does not serialize to JSON.");return Buffer.from(newline?`${json}\n`:json)}(payload,newline)}catch(error){return void refused.push({index:index,code:"InvalidRecord",detail:`Record ${index} does not serialize to JSON.`,cause:error})}data.byteLength>1e6?refused.push({index:index,code:"RecordTooLarge",detail:`Record ${index} is ${data.byteLength} bytes, over the 1000000 byte limit.`}):((current.length>=500||currentBytes+data.byteLength>29e5)&&(chunks.push(current),current=[],currentBytes=0),current.push({index:index,data:data}),currentBytes+=data.byteLength)}),current.length>0&&chunks.push(current),{chunks:chunks,refused:refused}}function isRecord(value){return"object"==typeof value&&null!==value}function readMetadata(value){if(!isRecord(value))return{};const metadata=value.$metadata;if(!isRecord(metadata))return{};const{httpStatusCode:httpStatusCode,attempts:attempts}=metadata;return{status:"number"==typeof httpStatusCode?httpStatusCode:void 0,attempts:"number"==typeof attempts?attempts:void 0}}async function deliver(items,settings,env,logger){const target={service:"Firehose",resource:settings.streamName,region:settings.region},Command=env?.AWS?.PutRecordBatchCommand??import_client_firehose2.PutRecordBatchCommand,plan=planChunks(items.map(({event:event,data:data})=>toPayload(event,data)),settings.newline),failures=plan.refused.map(({index:index,code:code,detail:detail,cause:cause})=>({index:index,error:localError(target,code,detail,cause)})),results=await Promise.all(plan.chunks.map(async chunk=>{const started=Date.now(),bytes=chunk.reduce((sum,record)=>sum+record.data.byteLength,0),command=new Command({DeliveryStreamName:settings.streamName,Records:chunk.map(({data:data})=>({Data:data}))});let result,attempts;try{const response=function(value){const response=readMetadata(value);return isRecord(value)?("number"==typeof value.FailedPutCount&&(response.failedPutCount=value.FailedPutCount),Array.isArray(value.RequestResponses)&&(response.responses=value.RequestResponses.map(entry=>{if(!isRecord(entry))return{};const{ErrorCode:ErrorCode,ErrorMessage:ErrorMessage}=entry;return{errorCode:"string"==typeof ErrorCode&&ErrorCode.length>0?ErrorCode:void 0,errorMessage:"string"==typeof ErrorMessage?ErrorMessage:void 0}})),response):response}(await settings.runtime.inflight.track(settings.client.send(command)));attempts=response.attempts,result=function(chunk,response,target){const{responses:responses,failedPutCount:failedPutCount,status:status}=response;if(responses&&responses.length===chunk.length){const failures=[];if(responses.forEach((entry,local)=>{entry.errorCode&&failures.push({index:chunk[local].index,error:recordError(target,entry.errorCode,status,entry)})}),void 0===failedPutCount||failures.length===failedPutCount)return failures}else if(0===failedPutCount)return[];const error=localError(target,"InvalidResponse",`PutRecordBatch answered without per-record results that match its FailedPutCount for ${chunk.length} records (FailedPutCount ${failedPutCount??"missing"}).`);return chunk.map(({index:index})=>({index:index,error:error}))}(chunk,response,target)}catch(thrown){attempts=readMetadata(thrown).attempts;const error=fromSdkError(thrown,target);result=chunk.map(({index:index})=>({index:index,error:error}))}return logger.debug("Firehose PutRecordBatch",{stream:settings.streamName,records:chunk.length,bytes:bytes,failed:result.length,attempts:attempts,ms:Date.now()-started}),result}));for(const result of results)failures.push(...result);return failures.sort((a,b)=>a.index-b.index)}var import_server_core=require("@walkeros/server-core"),types_exports={},destinationFirehose={type:"aws-firehose",config:{batch:{size:500,age:1e3}},init:async({config:config,env:env,logger:logger})=>getConfig(config,env,logger),push:async function(event,context){const{config:config,data:data,env:env,logger:logger,rule:rule}=context,settings=resolveSettings(config.settings);if(!rule?.silent){const[failure]=await deliver([{event:event,data:data}],settings,env,logger);if(failure)throw failure.error}},pushBatch:async(batch,context)=>{const{config:config,env:env,logger:logger}=context,settings=resolveSettings(config.settings),sending=batch.entries.map((entry,index)=>({entry:entry,index:index})).filter(({entry:entry})=>!entry.rule?.silent),failures=sending.length?await deliver(sending.map(({entry:{event:event,data:data}})=>({event:event,data:data})),settings,env,logger):[];return(0,import_server_core.batchOutcome)(batch.entries.length,failures.map(({index:index,error:error})=>({index:sending[index].index,error:error})))},async destroy({config:config,logger:logger}){const runtime=config.settings?.runtime;runtime&&(await runtime.inflight.settle(),runtime.ownsClient&&(runtime.ownsClient=!1,config.settings?.client?.destroy?.(),logger.debug("Firehose client closed")))}},import_core6=require("@walkeros/core"),import_client_sns=require("@aws-sdk/client-sns"),import_client_sts=require("@aws-sdk/client-sts"),import_core5=require("@walkeros/core");function createSnsClient(env,options){return new(env?.AWS?.SNSClient??import_client_sns.SNSClient)(function(options){const resolved={...options.config,region:options.region};return options.credentials&&(resolved.credentials=options.credentials),void 0===resolved.requestHandler&&(resolved.requestHandler=requestHandlerOptions(options.timeout)),resolved}(options))}function createStsClient(env,options){const Client=env?.AWS?.STSClient??import_client_sts.STSClient,config={region:options.region},credentials=options.credentials??options.config?.credentials;credentials&&(config.credentials=credentials);const userHandler=options.config?.requestHandler;return config.requestHandler=void 0===userHandler||isHandlerInstance(userHandler)?requestHandlerOptions(options.timeout):userHandler,config.maxAttempts=1,new Client(config)}async function getCallerIdentity(client,env,target){const Command=env?.AWS?.GetCallerIdentityCommand??import_client_sts.GetCallerIdentityCommand;let response;try{response=await client.send(new Command({}))}catch(error){throw fromSdkError(error,target)}if(!(0,import_core5.isObject)(response)||"string"!=typeof response.Account)throw localError(target,"InvalidResponse","STS GetCallerIdentity returned no Account.");const partition=("string"==typeof response.Arn?response.Arn:"").split(":")[1]||"aws";return{accountId:response.Account,partition:partition}}function topicArnResolver(topicArn,topicName,target,stsClient,env){if(topicArn)return async()=>topicArn;let pending;return()=>(pending??=(async()=>{const client=stsClient();try{const{accountId:accountId,partition:partition}=await getCallerIdentity(client,env,target);return`arn:${partition}:sns:${target.region}:${accountId}:${topicName}`}finally{client.destroy?.()}})().catch(error=>{throw pending=void 0,error}),pending)}var import_client_sns2=require("@aws-sdk/client-sns"),import_core7=require("@walkeros/core");function isMessageAttribute(value){return(0,import_core7.isObject)(value)&&"string"==typeof value.DataType}async function resolveStringMappingValue(event,value,collector){const resolved=await(0,import_core7.getMappingValue)(event,value,{collector:collector});return"string"==typeof resolved&&resolved.length>0?resolved:null!=resolved?String(resolved):void 0}var publish=async function(event,context){const{config:config,data:data,env:env,rule:rule,collector:collector,logger:logger,id:id}=context,settings=function(settings){const{region:region,client:client,runtime:runtime}=settings??{};if(!region||!client||!runtime)throw new import_core6.StepError("SNS: the destination was not initialized.",{code:"not-ready"});return{topicArn:settings?.topicArn,topicName:settings?.topicName,region:region,client:client,runtime:runtime}}(config.settings),{runtime:runtime}=settings,topicArn=await runtime.inflight.track(runtime.topicArn()),target={service:"SNS",resource:topicArn,region:settings.region,id:id},ruleSettings=(value=rule?.settings,"object"==typeof value&&null!==value?rule.settings:{});var value;const messageGroupId=void 0!==ruleSettings.messageGroupId?await resolveStringMappingValue(event,ruleSettings.messageGroupId,collector):void 0,fifo=topicArn.endsWith(".fifo"),messageDeduplicationId=(void 0!==ruleSettings.messageDeduplicationId?await resolveStringMappingValue(event,ruleSettings.messageDeduplicationId,collector):void 0)??(fifo&&event.id?event.id:void 0),messageAttributes=await async function(event,source,collector){if(!source)return;const result={};let touched=!1;for(const[key,value]of Object.entries(source)){const resolved=await(0,import_core7.getMappingValue)(event,value,{collector:collector});isMessageAttribute(resolved)?(result[key]=resolved,touched=!0):"string"==typeof resolved&&resolved.length>0?(result[key]={DataType:"String",StringValue:resolved},touched=!0):null!=resolved&&(result[key]={DataType:"String",StringValue:String(resolved)},touched=!0)}return touched?result:void 0}(event,ruleSettings.messageAttributes,collector);let message;try{message=JSON.stringify(toPayload(event,data))}catch(error){throw localError(target,"InvalidRecord","The message does not serialize to JSON.",error)}const input={TopicArn:topicArn,Message:message};messageGroupId&&(input.MessageGroupId=messageGroupId),messageDeduplicationId&&(input.MessageDeduplicationId=messageDeduplicationId),messageAttributes&&(input.MessageAttributes=messageAttributes);const Command=env?.AWS?.PublishCommand??import_client_sns2.PublishCommand,started=Date.now();let attempts;try{attempts=readAttempts(await runtime.inflight.track(settings.client.send(new Command(input))))}catch(error){throw attempts=readAttempts(error),fromSdkError(error,target)}finally{logger.debug("SNS Publish",{topicArn:topicArn,fifo:fifo,event:event.name,attempts:attempts,ms:Date.now()-started})}};function readAttempts(value){if("object"!=typeof value||null===value||!("$metadata"in value))return;const metadata=value.$metadata;return"object"==typeof metadata&&null!==metadata&&"attempts"in metadata&&"number"==typeof metadata.attempts?metadata.attempts:void 0}var import_client_sns3=require("@aws-sdk/client-sns"),import_core8=require("@walkeros/core"),DEFAULT_SETUP={fifoTopic:!1},identityCache=new Map;function buildSubscribeAttributes(sub){const attrs={};return void 0!==sub.rawMessageDelivery&&(attrs.RawMessageDelivery=String(sub.rawMessageDelivery)),void 0!==sub.filterPolicy&&(attrs.FilterPolicy=JSON.stringify(sub.filterPolicy)),void 0!==sub.deadLetterTargetArn&&(attrs.RedrivePolicy=JSON.stringify({deadLetterTargetArn:sub.deadLetterTargetArn})),Object.keys(attrs).length>0?attrs:void 0}var types_exports2={},destinationSNS={type:"aws-sns",config:{},setup:async function(ctx){const{config:config,env:env,logger:logger}=ctx,merged=(0,import_core8.resolveSetup)(config.setup,DEFAULT_SETUP);if(!merged)return void logger.debug("setup: skipped (config.setup is false or unset)");const settings=config.settings??{},arn=settings.topicArn?parseTopicArn(settings.topicArn):void 0,topicName=settings.topicName??arn?.name;if(!topicName)return void logger.throw("setup: settings.topicName (or settings.topicArn) is required. There is no safe default for the SNS topic name.");const sdkRegion="string"==typeof settings.config?.region?settings.config.region:void 0,region=firstString(merged.region,settings.region,arn?.region,sdkRegion,await loadSdkRegion())??"eu-central-1",fifo=merged.fifoTopic??!1,finalName=function(name,fifo){if(fifo)return name.endsWith(".fifo")?name:`${name}.fifo`;if(name.endsWith(".fifo"))throw new Error(`FIFO suffix '.fifo' on standard topic name '${name}'. Set setup.fifoTopic: true or rename the topic.`);return name}(topicName,fifo);fifo&&finalName!==topicName&&logger.info(`setup: appended .fifo suffix to FIFO topic name '${topicName}' -> '${finalName}'`);const options={region:region,config:settings.config,credentials:parseCredentials(config.credentials),timeout:config.timeout},client=settings.client??createSnsClient(env,options),closesClient=!settings.client&&!isHandlerInstance(settings.config?.requestHandler);try{const{accountId:accountId,partition:partition}=await async function(env,options,target){const cached=identityCache.get(options.region);if(cached)return cached;const stsClient=createStsClient(env,options);try{const identity=await getCallerIdentity(stsClient,env,target);return identityCache.set(options.region,identity),identity}finally{stsClient.destroy?.()}}(env,options,{service:"SNS",resource:finalName,region:region,id:ctx.id}),candidateArn=`arn:${partition}:sns:${region}:${accountId}:${finalName}`;let topicCreated=!1;try{const Command=env?.AWS?.GetTopicAttributesCommand??import_client_sns3.GetTopicAttributesCommand;await client.send(new Command({TopicArn:candidateArn}))}catch(err){if(!function(err){return!(!function(err){return"object"==typeof err&&null!==err}(err)||"NotFoundException"!==err.name&&"NotFound"!==err.name&&(!err.$metadata||404!==err.$metadata.httpStatusCode))}(err))throw err;topicCreated=!0}const attributes={};fifo&&(attributes.FifoTopic="true",attributes.ContentBasedDeduplication="true"),void 0!==merged.displayName&&(attributes.DisplayName=merged.displayName),void 0!==merged.kmsMasterKeyId&&(attributes.KmsMasterKeyId=merged.kmsMasterKeyId);const tagEntries=merged.tags?Object.entries(merged.tags).map(([Key,Value])=>({Key:Key,Value:Value})):void 0,createInput={Name:finalName};Object.keys(attributes).length>0&&(createInput.Attributes=attributes),tagEntries&&tagEntries.length>0&&(createInput.Tags=tagEntries);const CreateCommand=env?.AWS?.CreateTopicCommand??import_client_sns3.CreateTopicCommand,topicArn=function(res){if("object"==typeof(v=res)&&null!==v&&"string"==typeof res.TopicArn)return res.TopicArn;var v;throw new Error("SNS CreateTopic returned no TopicArn")}(await client.send(new CreateCommand(createInput)));topicCreated?logger.info("setup: topic created",{topicArn:topicArn,region:region}):logger.debug("setup: topic exists; declared state re-applied",{topicArn:topicArn,region:region});const subscriptionsCreated=await async function(client,env,topicArn,declared){let count=0;for(const sub of declared){const input={TopicArn:topicArn,Protocol:sub.protocol,Endpoint:sub.endpoint},attrs=buildSubscribeAttributes(sub);attrs&&(input.Attributes=attrs);const Command=env?.AWS?.SubscribeCommand??import_client_sns3.SubscribeCommand;await client.send(new Command(input)),count+=1}return count}(client,env,topicArn,merged.subscriptions??[]);return{topicArn:topicArn,topicCreated:topicCreated,tagsApplied:merged.tags?Object.keys(merged.tags).length:0,subscriptionsCreated:subscriptionsCreated}}finally{closesClient&&client.destroy?.()}},init:async({config:config,env:env,logger:logger,id:id})=>async function(partialConfig={},env,logger,id){const input=partialConfig.settings??{},{topicArn:topicArn,config:sdkConfig,client:userClient}=input,arn=topicArn?parseTopicArn(topicArn):void 0;if(topicArn&&!arn)throw configError(`SNS: settings.topicArn "${topicArn}" is not an SNS topic ARN (arn:aws:sns:<region>:<account>:<name>).`);if(!arn&&!input.topicName)throw configError("SNS: settings.topicArn is missing. Set it to the ARN of your topic (or set settings.topicName).");if(arn&&input.region&&input.region!==arn.region)throw configError(`SNS: settings.region "${input.region}" differs from the region "${arn.region}" in settings.topicArn. Remove settings.region.`);if(arn&&input.topicName&&input.topicName!==arn.name)throw configError(`SNS: settings.topicName "${input.topicName}" differs from the name "${arn.name}" in settings.topicArn. Remove settings.topicName.`);const sdkRegion="string"==typeof sdkConfig?.region?sdkConfig.region:void 0,region=firstString(input.region,arn?.region,sdkRegion,await loadSdkRegion())??"eu-central-1",topicName=input.topicName??arn?.name;void 0!==partialConfig.batch&&logger.warn("SNS publishes one message per event and does not batch. Remove config.batch from this destination.");const credentials=parseCredentials(partialConfig.credentials),clientOptions={region:region,config:sdkConfig,credentials:credentials,timeout:partialConfig.timeout},settings={region:region,client:userClient??createSnsClient(env,clientOptions),runtime:{ownsClient:!userClient&&!isHandlerInstance(sdkConfig?.requestHandler),inflight:new InFlight,topicArn:topicArnResolver(topicArn,topicName,{service:"SNS",resource:topicName??"",region:region,id:id},()=>createStsClient(env,clientOptions),env)}};return topicArn&&(settings.topicArn=topicArn),topicName&&(settings.topicName=topicName),sdkConfig&&(settings.config=sdkConfig),logger.debug("SNS client ready",{topic:topicArn??topicName,region:region,credentials:userClient?"client":credentials?"config.credentials":void 0!==sdkConfig?.credentials?"settings.config.credentials":"default chain"}),{...partialConfig,settings:settings}}(config,env,logger,id),push:async function(event,context){context.rule?.silent||await publish(event,context)},async destroy({config:config,logger:logger}){const runtime=config.settings?.runtime;runtime&&(await runtime.inflight.settle(),runtime.ownsClient&&(runtime.ownsClient=!1,config.settings?.client?.destroy?.(),logger.debug("SNS client closed")))}};//# sourceMappingURL=index.js.map
|