-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a test number which when called says hello, world!
- Loading branch information
Showing
6 changed files
with
255 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import { | ||
ContactFlow as BaseContactFlow, | ||
ContactFlowArgs, | ||
} from '@pulumi/aws/connect/index.js'; | ||
import { | ||
all, | ||
ComponentResource, | ||
ComponentResourceOptions, | ||
Input, | ||
} from '@pulumi/pulumi'; | ||
|
||
import { Err, Ok, Result } from '#root/ts/result.js'; | ||
|
||
interface ActionBase { | ||
Identifier: string; | ||
Type: string; | ||
Parameters: unknown; | ||
Transitions?: { | ||
NextAction?: string; | ||
Errors?: string[]; | ||
Conditions?: string[]; | ||
}; | ||
} | ||
|
||
export interface EndFlowExecutionAction extends ActionBase { | ||
Type: 'DisconnectParticipant'; | ||
Parameters: Record<string, never>; | ||
Transitions?: Record<string, never>; | ||
} | ||
|
||
export interface MessageParticipantAction extends ActionBase { | ||
Type: 'MessageParticipant'; | ||
Parameters: { | ||
/** | ||
* A prompt ID or prompt ARN to play to the participant along with gathering input. May not be specified if Text or SSML is also specified. | ||
* Must be specified either statically or as a single valid JSONPath identifier | ||
*/ | ||
PromptId?: string; | ||
/** | ||
* An optional string that defines text to send to the participant along with gathering input. | ||
* May not be specified if PromptId or SSML is also specified. May be specified statically or dynamically. | ||
*/ | ||
Text?: string; | ||
/** | ||
* An optional string that defines SSML to send to the participant along with gathering input. May not be specified if Text or | ||
* PromptId is also specified May be specified statically or dynamically. | ||
*/ | ||
SSML?: string; | ||
media?: { | ||
uri: string; | ||
SourceType: 'S3'; | ||
MediaType: 'Audio'; | ||
}; | ||
}; | ||
Transitions: { | ||
NextAction: string; | ||
}; | ||
} | ||
|
||
export type ContactFlowAction = | ||
| MessageParticipantAction | ||
| EndFlowExecutionAction; | ||
|
||
export interface ContactFlowLanguage { | ||
Version: '2019-10-30'; | ||
StartAction: string; | ||
Actions: ContactFlowAction[]; | ||
} | ||
|
||
export interface Args extends Omit<ContactFlowArgs, 'content'> { | ||
content: Input<ContactFlowLanguage>; | ||
} | ||
|
||
/** | ||
* Creates a ContactFlowModule, but it's typechecked. | ||
*/ | ||
export class ContactFlow extends ComponentResource { | ||
readonly value: BaseContactFlow; | ||
constructor( | ||
name: string, | ||
{ content, ...args }: Args, | ||
opts?: ComponentResourceOptions | ||
) { | ||
super('ts:pulumi:lib:ContactFlowModule', name, args, opts); | ||
|
||
void ContactFlow.validate(content).then(v => { | ||
if (v instanceof Error) throw v; | ||
}); | ||
|
||
this.value = new BaseContactFlow( | ||
`${name}_contact_flow_module`, | ||
{ | ||
...args, | ||
content: all([content]).apply(([v]) => JSON.stringify(v)), | ||
}, | ||
{ parent: this } | ||
); | ||
} | ||
|
||
private static async validateEntryPointSet( | ||
flow: ContactFlowLanguage | ||
): Promise<Result<void, Error>> { | ||
if (!flow.Actions.some(v => v.Identifier == flow.StartAction)) | ||
return { | ||
[Err]: new Error(`Missing entry point ${flow.StartAction}`), | ||
}; | ||
|
||
return { [Ok]: undefined }; | ||
} | ||
|
||
private static async validate( | ||
v: Input<ContactFlowLanguage> | ||
): Promise<Result<void, Error>> { | ||
const flow = await new Promise<ContactFlowLanguage>(ok => | ||
all([v]).apply(([flow]) => ok(flow!)) | ||
); | ||
|
||
return ContactFlow.validateEntryPointSet(flow); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import * as aws from '@pulumi/aws'; | ||
import * as Pulumi from '@pulumi/pulumi'; | ||
import { RandomPet } from '@pulumi/random'; | ||
|
||
import { | ||
ContactFlow, | ||
ContactFlowAction, | ||
ContactFlowLanguage, | ||
} from '#root/ts/pulumi/lib/contact_flow.js'; | ||
import { mergeTags, tagTrue } from '#root/ts/pulumi/lib/tags.js'; | ||
|
||
export interface Args { | ||
tags?: Pulumi.Input<Record<string, Pulumi.Input<string>>>; | ||
} | ||
|
||
export class Voice extends Pulumi.ComponentResource { | ||
phoneNumber: Pulumi.Output<string>; | ||
constructor( | ||
name: string, | ||
args: Args, | ||
opts?: Pulumi.ComponentResourceOptions | ||
) { | ||
super('ts:pulumi:voice', name, args, opts); | ||
const tag = name; | ||
const tags = mergeTags(args.tags, tagTrue(tag)); | ||
|
||
/* | ||
new CostAllocationTag( | ||
`${name}_cost_tag`, | ||
{ | ||
status: 'Active', | ||
tagKey: tag, | ||
}, | ||
{ parent: this } | ||
); | ||
*/ | ||
|
||
const connectInstance = new aws.connect.Instance( | ||
`${name}_connect_instance`, | ||
{ | ||
inboundCallsEnabled: true, | ||
outboundCallsEnabled: true, | ||
identityManagementType: 'CONNECT_MANAGED', | ||
instanceAlias: `${name}_connect_instance`.replaceAll( | ||
/[^a-z]/g, | ||
'' | ||
), | ||
}, | ||
{ parent: this } | ||
); | ||
|
||
const disconnectAction = new RandomPet( | ||
`${name}_disconnect_flow_id`, | ||
{}, | ||
{ parent: this } | ||
).id.apply( | ||
id => | ||
({ | ||
Identifier: id, | ||
Type: 'DisconnectParticipant', | ||
Parameters: {}, | ||
}) satisfies ContactFlowAction | ||
); | ||
|
||
const action = Pulumi.all([ | ||
new RandomPet(`${name}_flow_id`, {}, { parent: this }).id, | ||
disconnectAction, | ||
]).apply( | ||
([Identifier, disconnectAction]) => | ||
({ | ||
Identifier, | ||
Type: 'MessageParticipant', | ||
Parameters: { | ||
Text: 'Hello, world!', | ||
}, | ||
Transitions: { | ||
NextAction: disconnectAction.Identifier, | ||
}, | ||
}) satisfies ContactFlowAction | ||
); | ||
|
||
const flow: Pulumi.Input<ContactFlowLanguage> = Pulumi.all([ | ||
action, | ||
disconnectAction, | ||
]).apply( | ||
([action, disconnectAction]) => | ||
({ | ||
Version: '2019-10-30', | ||
StartAction: action!.Identifier, | ||
Actions: [action!, disconnectAction], | ||
}) satisfies ContactFlowLanguage | ||
); | ||
|
||
new ContactFlow( | ||
`${name}_contact_flow`, | ||
{ | ||
instanceId: connectInstance.id, | ||
name: 'Hello world flow', | ||
type: 'CONTACT_FLOW', | ||
content: flow, | ||
}, | ||
{ parent: this } | ||
); | ||
|
||
const phone = new aws.connect.PhoneNumber( | ||
`${name}_phone_number`, | ||
{ | ||
countryCode: 'US', | ||
type: 'DID', | ||
targetArn: connectInstance.arn, | ||
tags, | ||
}, | ||
{ parent: this } | ||
); | ||
|
||
this.phoneNumber = phone.phoneNumber; | ||
} | ||
} |