@crossdelta/platform-sdk 0.5.12 → 0.7.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.
@@ -56,6 +56,8 @@ jobs:
56
56
  mapfile -t dirs < <(find packages -mindepth 1 -maxdepth 1 -type d | sort)
57
57
  for dir in "${dirs[@]}"; do
58
58
  [ -f "$dir/package.json" ] || continue
59
+ is_private=$(jq -r '.private // false' "$dir/package.json")
60
+ [ "$is_private" = "true" ] && continue
59
61
  pkg_name=$(jq -r '.name // empty' "$dir/package.json")
60
62
  [ -n "$pkg_name" ] || continue
61
63
  slug=$(basename "$dir")
@@ -69,6 +71,8 @@ jobs:
69
71
  changed_dirs=$(git diff --name-only "$base" "$HEAD_SHA" -- 'packages/*' | cut -d/ -f1-2 | sort -u)
70
72
  while IFS= read -r dir; do
71
73
  [ -f "$dir/package.json" ] || continue
74
+ is_private=$(jq -r '.private // false' "$dir/package.json")
75
+ [ "$is_private" = "true" ] && continue
72
76
  pkg_name=$(jq -r '.name // empty' "$dir/package.json")
73
77
  [ -n "$pkg_name" ] && add_entry "$pkg_name" "$dir"
74
78
  done <<< "$changed_dirs"
@@ -98,11 +102,6 @@ jobs:
98
102
 
99
103
  - uses: oven-sh/setup-bun@v2
100
104
 
101
- - uses: actions/setup-node@v4
102
- with:
103
- node-version: '20'
104
- registry-url: https://registry.npmjs.org
105
-
106
105
  - name: Install dependencies
107
106
  run: bun install
108
107
 
@@ -137,8 +136,8 @@ jobs:
137
136
  - name: Publish
138
137
  working-directory: ${{ matrix.package.dir }}
139
138
  env:
140
- NODE_AUTH_TOKEN: ${{ secrets.NPMJS_TOKEN }}
141
- run: npm publish --access=public
139
+ NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
140
+ run: bun publish --access=public --provenance --tolerate-republish
142
141
 
143
142
  - name: Commit version bump
144
143
  if: steps.bump.outputs.bumped == 'true'
@@ -13,9 +13,27 @@
13
13
  },
14
14
  "pf": {
15
15
  "registry": "{{projectName}}/platform",
16
- "dev": {
17
- "watchDirs": ["infra/services"],
18
- "watchPackages": ["services", "apps"]
16
+ "commands": {
17
+ "pulumi": {
18
+ "cwd": "infra"
19
+ }
20
+ },
21
+ "paths": {
22
+ "services": {
23
+ "path": "services",
24
+ "watch": true
25
+ },
26
+ "apps": {
27
+ "path": "apps",
28
+ "watch": true
29
+ },
30
+ "packages": {
31
+ "path": "packages",
32
+ "watch": true
33
+ },
34
+ "contracts": {
35
+ "path": "packages/contracts"
36
+ }
19
37
  }
20
38
  },
21
39
  "devDependencies": {
@@ -0,0 +1,134 @@
1
+ # {{scope}}/contracts
2
+
3
+ Shared event contracts for cross-service event consumption.
4
+
5
+ ## Purpose
6
+
7
+ This package contains **shared event definitions** (contracts) for events that are consumed by multiple services. When an event is used by more than one service, define it here to ensure type consistency across the platform.
8
+
9
+ ## Structure
10
+
11
+ ```
12
+ src/
13
+ ├── events/ # Event contracts and mock data
14
+ │ ├── order-created.ts # Contract definition
15
+ │ ├── order-created.mock.json # Mock data for testing
16
+ │ └── index.ts # Re-exports
17
+ └── index.ts # Main exports
18
+ ```
19
+
20
+ **Contract files contain:**
21
+ - Zod schema definition
22
+ - Contract object (type + schema)
23
+ - TypeScript type inference
24
+ - Mock JSON for `pf event:publish`
25
+
26
+ ## Usage
27
+
28
+ ### In Event Handlers (Consumers)
29
+
30
+ ```ts
31
+ import { handleEvent } from '@crossdelta/cloudevents'
32
+ import { OrderCreatedContract, type OrderCreatedData } from '{{scope}}/contracts'
33
+
34
+ export default handleEvent(OrderCreatedContract, async (data: OrderCreatedData) => {
35
+ // data is fully typed from contract
36
+ console.log(data.orderId, data.customerId)
37
+ })
38
+ ```
39
+
40
+ ### In Publishers (REST APIs)
41
+
42
+ ```ts
43
+ import { publish } from '@crossdelta/cloudevents'
44
+ import { OrderCreatedContract } from '{{scope}}/contracts'
45
+
46
+ // Type-safe publishing with contract
47
+ await publish(OrderCreatedContract, {
48
+ orderId: 'order-123',
49
+ customerId: 'cust-456',
50
+ total: 99.99,
51
+ items: [...]
52
+ })
53
+ ```
54
+
55
+ ### In Use-Cases
56
+
57
+ ```ts
58
+ import type { OrderCreatedData } from '{{scope}}/contracts'
59
+
60
+ export const processOrder = async (data: OrderCreatedData) => {
61
+ // Use typed event data
62
+ }
63
+ ```
64
+
65
+ ## Adding New Contracts
66
+
67
+ Contracts are **auto-generated** when you create event handlers:
68
+
69
+ ```bash
70
+ # 1. Create service with event handler
71
+ pf new hono-micro notifications --ai -d "Sends emails on order.created events"
72
+
73
+ # 2. Generate contract (if missing) and mock data
74
+ pf event:generate services/notifications
75
+ ```
76
+
77
+ This creates:
78
+ - `packages/contracts/src/events/order-created.ts` (contract)
79
+ - `packages/contracts/src/events/order-created.mock.json` (mock)
80
+ - Updates `packages/contracts/src/index.ts` (exports)
81
+
82
+ ### Manual Contract Creation
83
+
84
+ ```ts
85
+ // packages/contracts/src/events/order-created.ts
86
+ import { createContract } from '@crossdelta/cloudevents'
87
+ import { z } from 'zod'
88
+
89
+ export const OrderCreatedSchema = z.object({
90
+ orderId: z.string(),
91
+ customerId: z.string(),
92
+ total: z.number(),
93
+ items: z.array(z.object({
94
+ productId: z.string(),
95
+ quantity: z.number(),
96
+ price: z.number(),
97
+ })),
98
+ })
99
+
100
+ export const OrderCreatedContract = createContract({
101
+ type: 'order.created',
102
+ schema: OrderCreatedSchema,
103
+ })
104
+
105
+ export type OrderCreatedData = z.infer<typeof OrderCreatedContract.schema>
106
+ ```
107
+
108
+ ## Testing with Mocks
109
+
110
+ ```bash
111
+ # List all available events
112
+ pf event:list
113
+
114
+ # Publish mock event
115
+ pf event:publish order.created
116
+
117
+ # Publish with custom data
118
+ pf event:publish order.created --data '{"orderId":"test-123"}'
119
+ ```
120
+
121
+ ## Guidelines
122
+
123
+ - ✅ Use contracts for **shared events** (multi-consumer)
124
+ - ✅ Export both contract and inferred type
125
+ - ✅ Keep contracts minimal and focused
126
+ - ✅ Generate mocks for all contracts
127
+ - ❌ Don't put business logic in contracts
128
+ - ❌ Don't include event handlers in this package
129
+
130
+ **Naming conventions:**
131
+ - Contracts: `OrderCreatedContract`
132
+ - Types: `OrderCreatedData`
133
+ - Files: `order-created.ts`
134
+ - Event types: `order.created` (dot notation)
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "{{scope}}/contracts",
3
+ "private": true,
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "types": "./src/index.ts",
8
+ "default": "./src/index.ts"
9
+ }
10
+ },
11
+ "dependencies": {
12
+ "@crossdelta/cloudevents": "workspace:*",
13
+ "zod": "^4.0.0"
14
+ },
15
+ "devDependencies": {
16
+ "@biomejs/biome": "^1.9.4",
17
+ "typescript": "^5.7.2"
18
+ }
19
+ }
@@ -0,0 +1,8 @@
1
+ // Export your event contracts and schemas here
2
+ // Example:
3
+ // export * from './events/order-created.schema'
4
+ // export * from './events/order-created.contract'
5
+
6
+ export * from './events/order-created'
7
+ export * from './events/user-updated'
8
+ export * from './events/order'
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src/**/*"]
8
+ }
package/install.sh ADDED
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ # Colors for output
5
+ RED='\033[0;31m'
6
+ GREEN='\033[0;32m'
7
+ YELLOW='\033[1;33m'
8
+ BLUE='\033[0;34m'
9
+ CYAN='\033[0;36m'
10
+ NC='\033[0m'
11
+
12
+ printf "${CYAN}"
13
+ cat << "EOF"
14
+ ______
15
+ / ____/
16
+ ____ / /_
17
+ / __ \ / __/
18
+ / /_/ // /
19
+ / .___//_/
20
+ /_/
21
+
22
+ @crossdelta/platform-sdk installer
23
+ EOF
24
+ printf "${NC}\n"
25
+
26
+ # Function to check if command exists
27
+ command_exists() {
28
+ command -v "$1" &> /dev/null
29
+ }
30
+
31
+ # Detect or install package manager
32
+ detect_or_install_package_manager() {
33
+ # Check for existing package managers
34
+ if command_exists bun; then
35
+ echo "bun"
36
+ return 0
37
+ elif command_exists pnpm; then
38
+ echo "pnpm"
39
+ return 0
40
+ elif command_exists yarn; then
41
+ echo "yarn"
42
+ return 0
43
+ elif command_exists npm; then
44
+ echo "npm"
45
+ return 0
46
+ fi
47
+
48
+ # No package manager found - ask user for permission
49
+ printf "${YELLOW}No package manager found (bun, pnpm, yarn, npm).${NC}\n"
50
+ printf "${YELLOW}To use @crossdelta/platform-sdk, we recommend installing Bun (fast JavaScript runtime).${NC}\n"
51
+ printf "\n"
52
+ read -p "Do you want to install Bun now? (y/n) " -n 1 -r
53
+ printf "\n"
54
+
55
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
56
+ printf "${RED}Installation cancelled. Please install Bun or another package manager manually.${NC}\n"
57
+ printf "${BLUE}Visit: https://bun.sh${NC}\n"
58
+ exit 1
59
+ fi
60
+
61
+ # Install Bun
62
+ printf "${BLUE}Installing Bun...${NC}\n"
63
+ curl -fsSL https://bun.sh/install | bash
64
+
65
+ # Load Bun into current shell
66
+ export BUN_INSTALL="$HOME/.bun"
67
+ export PATH="$BUN_INSTALL/bin:$PATH"
68
+
69
+ printf "${GREEN}✓${NC} Bun installed successfully\n"
70
+ echo "bun"
71
+ }
72
+
73
+ PM=$(detect_or_install_package_manager)
74
+
75
+ printf "${GREEN}✓${NC} Using package manager: ${BLUE}$PM${NC}\n"
76
+ printf "\n"
77
+
78
+ # Check if arguments were provided
79
+ if [ $# -eq 0 ]; then
80
+ # No arguments: Install pf globally
81
+ printf "${BLUE}Installing @crossdelta/platform-sdk CLI globally...${NC}\n"
82
+ printf "\n"
83
+
84
+ case $PM in
85
+ bun)
86
+ bun add -g @crossdelta/platform-sdk
87
+ ;;
88
+ pnpm)
89
+ pnpm add -g @crossdelta/platform-sdk
90
+ ;;
91
+ yarn)
92
+ yarn global add @crossdelta/platform-sdk
93
+ ;;
94
+ npm)
95
+ npm install -g @crossdelta/platform-sdk
96
+ ;;
97
+ esac
98
+
99
+ EXIT_CODE=$?
100
+
101
+ if [ $EXIT_CODE -eq 0 ]; then
102
+ printf "\n"
103
+ printf "${GREEN}✨ Installation successful!${NC}\n"
104
+ printf "\n"
105
+ printf "${CYAN}Next steps:${NC}\n"
106
+ printf " ${BLUE}pf new workspace my-platform${NC} # Create a new workspace\n"
107
+ printf " ${BLUE}pf --help${NC} # Show all available commands\n"
108
+ printf "\n"
109
+ else
110
+ printf "\n"
111
+ printf "${RED}✗ Installation failed${NC}\n"
112
+ exit $EXIT_CODE
113
+ fi
114
+ else
115
+ # Arguments provided: Run pf command directly
116
+ PF_ARGS=()
117
+
118
+ while [[ $# -gt 0 ]]; do
119
+ case $1 in
120
+ -h|--help)
121
+ echo "Usage: bash install.sh [COMMAND] [OPTIONS]"
122
+ echo ""
123
+ echo "Without arguments:"
124
+ echo " Installs pf CLI globally"
125
+ echo ""
126
+ echo "With arguments:"
127
+ echo " Runs 'pf [COMMAND] [OPTIONS]' directly (via bunx/npx)"
128
+ echo ""
129
+ echo "Examples:"
130
+ echo " bash install.sh # Install pf globally"
131
+ echo " bash install.sh new workspace my-platform # Run command directly"
132
+ echo " bash install.sh --help # Show pf help"
133
+ exit 0
134
+ ;;
135
+ *)
136
+ PF_ARGS+=("$1")
137
+ shift
138
+ ;;
139
+ esac
140
+ done
141
+
142
+ printf "${BLUE}Running: pf ${PF_ARGS[*]}${NC}\n"
143
+ printf "\n"
144
+
145
+ # Execute pf command via package runner
146
+ case $PM in
147
+ bun)
148
+ bunx @crossdelta/platform-sdk "${PF_ARGS[@]}"
149
+ ;;
150
+ pnpm)
151
+ pnpm dlx @crossdelta/platform-sdk "${PF_ARGS[@]}"
152
+ ;;
153
+ yarn)
154
+ yarn dlx @crossdelta/platform-sdk "${PF_ARGS[@]}"
155
+ ;;
156
+ npm)
157
+ npx @crossdelta/platform-sdk "${PF_ARGS[@]}"
158
+ ;;
159
+ esac
160
+ fi
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@crossdelta/platform-sdk",
3
- "version": "0.5.12",
4
- "description": "CLI toolkit for scaffolding Turborepo workspaces with Pulumi infrastructure and Hono/NestJS microservices",
3
+ "version": "0.7.0",
4
+ "description": "Your AI-powered platform engineer. Scaffold complete Turborepo workspaces, generate microservice boilerplate with natural language, and deploy to the cloud — all from one CLI.",
5
5
  "keywords": [
6
6
  "cli",
7
7
  "scaffolding",
@@ -35,7 +35,8 @@
35
35
  "dist/",
36
36
  "README.md",
37
37
  "logo.png",
38
- "schemas"
38
+ "schemas",
39
+ "install.sh"
39
40
  ],
40
41
  "exports": {
41
42
  "./schemas/event.schema.json": "./schemas/event.schema.json"
@@ -57,14 +58,15 @@
57
58
  "build": "npm run build:cli && npm run build:schematics && npm run build:cli:copy",
58
59
  "prepublishOnly": "npm run build",
59
60
  "lint": "biome lint --fix",
60
- "test": "vitest run",
61
- "test:watch": "vitest watch"
61
+ "test": "bun test",
62
+ "test:watch": "bun test --watch"
62
63
  },
63
64
  "schematics": "./dist/schematics/collection.json",
64
65
  "esbuild": {
65
66
  "external": [
66
67
  "@crossdelta/infrastructure",
67
68
  "@faker-js/faker",
69
+ "@anatine/zod-mock",
68
70
  "ai",
69
71
  "@ai-sdk/openai",
70
72
  "@ai-sdk/anthropic",
@@ -76,18 +78,22 @@
76
78
  "globby",
77
79
  "fs-extra",
78
80
  "chalk",
79
- "ora"
81
+ "ora",
82
+ "jiti",
83
+ "zod"
80
84
  ]
81
85
  },
82
86
  "dependencies": {
83
87
  "@ai-sdk/anthropic": "^2.0.53",
84
88
  "@ai-sdk/openai": "^2.0.79",
89
+ "@anatine/zod-mock": "^3.14.0",
85
90
  "@angular-devkit/core": "^21.0.0",
86
91
  "@faker-js/faker": "^9.8.0",
87
92
  "@inquirer/prompts": "^7.5.0",
88
93
  "@listr2/prompt-adapter-enquirer": "^2.0.15",
89
94
  "ai": "^5.0.108",
90
95
  "chalk": "^5.4.1",
96
+ "chokidar": "^5.0.0",
91
97
  "cli-table3": "^0.6.5",
92
98
  "commander": "^13.1.0",
93
99
  "dotenv": "^17.2.3",
@@ -96,6 +102,7 @@
96
102
  "fs-extra": "^11.3.0",
97
103
  "globby": "^14.1.0",
98
104
  "handlebars": "^4.7.8",
105
+ "jiti": "^2.6.1",
99
106
  "listr2": "^8.3.2",
100
107
  "ora": "^8.2.0",
101
108
  "os": "^0.1.2",
@@ -107,10 +114,25 @@
107
114
  "zx": "^8.5.3"
108
115
  },
109
116
  "peerDependencies": {
117
+ "@crossdelta/cloudevents": "*",
110
118
  "@crossdelta/infrastructure": "*",
111
119
  "@nestjs/schematics": "^11.0.5",
112
120
  "turbo": "^2.0.0"
113
121
  },
122
+ "peerDependenciesMeta": {
123
+ "@crossdelta/cloudevents": {
124
+ "optional": true
125
+ },
126
+ "@crossdelta/infrastructure": {
127
+ "optional": true
128
+ },
129
+ "@nestjs/schematics": {
130
+ "optional": true
131
+ },
132
+ "turbo": {
133
+ "optional": true
134
+ }
135
+ },
114
136
  "devDependencies": {
115
137
  "@angular-devkit/core": "^21.0.0",
116
138
  "@angular-devkit/schematics": "^21.0.0",
@@ -118,14 +140,12 @@
118
140
  "@eslint/js": "^9.22.0",
119
141
  "@nestjs/schematics": "^11.0.9",
120
142
  "@types/fs-extra": "^11.0.4",
121
- "@vitest/coverage-v8": "^3.1.2",
122
- "@vitest/ui": "^3.1.2",
123
143
  "biome": "^0.3.3",
144
+ "bun-types": "^1.3.4",
124
145
  "comment-json": "^4.4.1",
125
146
  "esbuild": "^0.25.3",
126
147
  "eslint": "^9.25.1",
127
148
  "typescript": "^5.8.3",
128
- "typescript-eslint": "^8.31.1",
129
- "vitest": "^3.1.2"
149
+ "typescript-eslint": "^8.31.1"
130
150
  }
131
151
  }