create-step-func-emailer 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +96 -0
- package/dist/index.js.map +1 -0
- package/package.json +29 -0
- package/template/.env.example +15 -0
- package/template/CLAUDE.md +17 -0
- package/template/_gitignore +10 -0
- package/template/bin/app.ts +53 -0
- package/template/cdk.json +1 -0
- package/template/package.json +19 -0
- package/template/pnpm-workspace.yaml +2 -0
- package/template/sequences/.gitkeep +0 -0
- package/template/tsconfig.base.json +18 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
/* eslint-disable no-console */
|
|
38
|
+
const fs = __importStar(require("node:fs"));
|
|
39
|
+
const path = __importStar(require("node:path"));
|
|
40
|
+
const node_child_process_1 = require("node:child_process");
|
|
41
|
+
const projectName = process.argv[2];
|
|
42
|
+
if (!projectName) {
|
|
43
|
+
console.error("Usage: npx create-step-func-emailer <project-name>");
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
const targetDir = path.resolve(process.cwd(), projectName);
|
|
47
|
+
if (fs.existsSync(targetDir)) {
|
|
48
|
+
console.error(`Directory ${projectName} already exists.`);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
const templateDir = path.join(__dirname, "../template");
|
|
52
|
+
function copyDir(src, dest) {
|
|
53
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
54
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
55
|
+
const srcPath = path.join(src, entry.name);
|
|
56
|
+
// Rename _gitignore → .gitignore (npm strips dotfiles)
|
|
57
|
+
const destName = entry.name === "_gitignore" ? ".gitignore" : entry.name;
|
|
58
|
+
const destPath = path.join(dest, destName);
|
|
59
|
+
if (entry.isDirectory()) {
|
|
60
|
+
copyDir(srcPath, destPath);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
fs.copyFileSync(srcPath, destPath);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
console.log(`Creating ${projectName}...`);
|
|
68
|
+
copyDir(templateDir, targetDir);
|
|
69
|
+
// Install dependencies
|
|
70
|
+
console.log("\nInstalling dependencies...");
|
|
71
|
+
try {
|
|
72
|
+
(0, node_child_process_1.execSync)("pnpm install", { cwd: targetDir, stdio: "inherit" });
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
console.log("pnpm not found, trying npm...");
|
|
76
|
+
(0, node_child_process_1.execSync)("npm install", { cwd: targetDir, stdio: "inherit" });
|
|
77
|
+
}
|
|
78
|
+
// Git init + initial commit
|
|
79
|
+
console.log("\nInitializing git repository...");
|
|
80
|
+
(0, node_child_process_1.execSync)("git init", { cwd: targetDir, stdio: "inherit" });
|
|
81
|
+
(0, node_child_process_1.execSync)("git add -A", { cwd: targetDir, stdio: "inherit" });
|
|
82
|
+
(0, node_child_process_1.execSync)('git commit -m "Initial project scaffold"', {
|
|
83
|
+
cwd: targetDir,
|
|
84
|
+
stdio: "inherit",
|
|
85
|
+
});
|
|
86
|
+
console.log(`
|
|
87
|
+
Done! Created ${projectName}
|
|
88
|
+
|
|
89
|
+
Next steps:
|
|
90
|
+
cd ${projectName}
|
|
91
|
+
claude # Open Claude Code
|
|
92
|
+
/setup-env # Configure AWS environment
|
|
93
|
+
/create-sequence # Create your first email sequence
|
|
94
|
+
/deploy # Deploy to AWS
|
|
95
|
+
`);
|
|
96
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-step-func-emailer",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Create a new step-func-emailer project",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"bin": {
|
|
8
|
+
"create-step-func-emailer": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"template"
|
|
13
|
+
],
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/mdwt/step-func-emailer.git",
|
|
20
|
+
"directory": "packages/create"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"typescript": "^5.9.0"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsc",
|
|
27
|
+
"typecheck": "tsc --noEmit"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
AWS_PROFILE=default
|
|
2
|
+
ACCOUNT=123456789012
|
|
3
|
+
REGION=us-east-1
|
|
4
|
+
STACK_NAME=StepFuncEmailer
|
|
5
|
+
TABLE_NAME=StepFuncEmailer
|
|
6
|
+
EVENTS_TABLE_NAME=StepFuncEmailer-events
|
|
7
|
+
TEMPLATE_BUCKET_NAME=step-func-emailer-templates-mycompany
|
|
8
|
+
EVENT_BUS_NAME=step-func-emailer-bus
|
|
9
|
+
SES_CONFIG_SET_NAME=step-func-emailer-config
|
|
10
|
+
SNS_TOPIC_NAME=step-func-emailer-ses-notifications
|
|
11
|
+
DEFAULT_FROM_EMAIL=hello@example.com
|
|
12
|
+
DEFAULT_FROM_NAME=MyCompany
|
|
13
|
+
REPLY_TO_EMAIL=support@example.com
|
|
14
|
+
UNSUBSCRIBE_SECRET=replace-with-a-real-secret
|
|
15
|
+
SSM_PREFIX=/step-func-emailer
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Email Sequences Project
|
|
2
|
+
|
|
3
|
+
Built with [step-func-emailer](https://github.com/mdwt/step-func-emailer).
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
- `pnpm build` — build all sequences
|
|
8
|
+
- `pnpm deploy` — deploy to AWS
|
|
9
|
+
- `/create-sequence` — create a new email sequence
|
|
10
|
+
- `/setup-env` — configure AWS environment
|
|
11
|
+
- `/deploy` — build and deploy
|
|
12
|
+
|
|
13
|
+
## Structure
|
|
14
|
+
|
|
15
|
+
- `sequences/` — email sequences (auto-discovered by CDK)
|
|
16
|
+
- `bin/app.ts` — CDK entry point
|
|
17
|
+
- `.env` — AWS configuration
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "source-map-support/register";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import * as fs from "node:fs";
|
|
5
|
+
import * as cdk from "aws-cdk-lib";
|
|
6
|
+
import type { StepFuncEmailerConfig } from "@step-func-emailer/shared";
|
|
7
|
+
import { StepFuncEmailerStack } from "@step-func-emailer/cdk";
|
|
8
|
+
import { loadSequenceConfigs } from "@step-func-emailer/cdk/load-sequences";
|
|
9
|
+
|
|
10
|
+
// Load .env from project root
|
|
11
|
+
const envPath = path.join(__dirname, "../.env");
|
|
12
|
+
if (fs.existsSync(envPath)) {
|
|
13
|
+
for (const line of fs.readFileSync(envPath, "utf-8").split("\n")) {
|
|
14
|
+
const trimmed = line.trim();
|
|
15
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
16
|
+
const idx = trimmed.indexOf("=");
|
|
17
|
+
if (idx === -1) continue;
|
|
18
|
+
const key = trimmed.slice(0, idx);
|
|
19
|
+
const value = trimmed.slice(idx + 1);
|
|
20
|
+
if (!(key in process.env)) process.env[key] = value;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function required(name: string): string {
|
|
25
|
+
const val = process.env[name];
|
|
26
|
+
if (!val) throw new Error(`Missing env var ${name}. Run /setup-env in Claude Code.`);
|
|
27
|
+
return val;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const config: StepFuncEmailerConfig = {
|
|
31
|
+
account: required("ACCOUNT"),
|
|
32
|
+
region: required("REGION"),
|
|
33
|
+
stackName: required("STACK_NAME"),
|
|
34
|
+
tableName: required("TABLE_NAME"),
|
|
35
|
+
eventsTableName: required("EVENTS_TABLE_NAME"),
|
|
36
|
+
templateBucketName: required("TEMPLATE_BUCKET_NAME"),
|
|
37
|
+
eventBusName: required("EVENT_BUS_NAME"),
|
|
38
|
+
sesConfigSetName: required("SES_CONFIG_SET_NAME"),
|
|
39
|
+
snsTopicName: required("SNS_TOPIC_NAME"),
|
|
40
|
+
defaultFromEmail: required("DEFAULT_FROM_EMAIL"),
|
|
41
|
+
defaultFromName: required("DEFAULT_FROM_NAME"),
|
|
42
|
+
replyToEmail: process.env.REPLY_TO_EMAIL || undefined,
|
|
43
|
+
unsubscribeSecret: required("UNSUBSCRIBE_SECRET"),
|
|
44
|
+
ssmPrefix: required("SSM_PREFIX"),
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const definitions = loadSequenceConfigs();
|
|
48
|
+
const app = new cdk.App();
|
|
49
|
+
new StepFuncEmailerStack(app, config.stackName, {
|
|
50
|
+
env: { account: config.account, region: config.region },
|
|
51
|
+
config,
|
|
52
|
+
definitions,
|
|
53
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "app": "npx tsx bin/app.ts" }
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"private": true,
|
|
3
|
+
"scripts": {
|
|
4
|
+
"build": "pnpm -r build",
|
|
5
|
+
"synth": "npx cdk synth",
|
|
6
|
+
"deploy": "npx cdk deploy --require-approval never",
|
|
7
|
+
"typecheck": "pnpm -r typecheck"
|
|
8
|
+
},
|
|
9
|
+
"devDependencies": {
|
|
10
|
+
"@step-func-emailer/cdk": "^0.1.0",
|
|
11
|
+
"@step-func-emailer/shared": "^0.1.0",
|
|
12
|
+
"aws-cdk": "^2.1111.0",
|
|
13
|
+
"aws-cdk-lib": "^2.243.0",
|
|
14
|
+
"constructs": "^10.5.1",
|
|
15
|
+
"source-map-support": "^0.5.21",
|
|
16
|
+
"tsx": "^4.21.0",
|
|
17
|
+
"typescript": "^5.9.0"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "Node16",
|
|
5
|
+
"moduleResolution": "Node16",
|
|
6
|
+
"lib": ["ES2022"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"sourceMap": true,
|
|
15
|
+
"outDir": "dist",
|
|
16
|
+
"rootDir": "src"
|
|
17
|
+
}
|
|
18
|
+
}
|