@mesh-tech/mesh-cli 0.1.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.
Files changed (140) hide show
  1. package/dist/bin/mesh.d.ts +16 -0
  2. package/dist/bin/mesh.d.ts.map +1 -0
  3. package/dist/bin/mesh.js +40 -0
  4. package/dist/bin/mesh.js.map +1 -0
  5. package/dist/src/commands/create-app.d.ts +10 -0
  6. package/dist/src/commands/create-app.d.ts.map +1 -0
  7. package/dist/src/commands/create-app.js +176 -0
  8. package/dist/src/commands/create-app.js.map +1 -0
  9. package/dist/src/commands/db/connect.d.ts +13 -0
  10. package/dist/src/commands/db/connect.d.ts.map +1 -0
  11. package/dist/src/commands/db/connect.js +68 -0
  12. package/dist/src/commands/db/connect.js.map +1 -0
  13. package/dist/src/commands/db/credentials.d.ts +16 -0
  14. package/dist/src/commands/db/credentials.d.ts.map +1 -0
  15. package/dist/src/commands/db/credentials.js +56 -0
  16. package/dist/src/commands/db/credentials.js.map +1 -0
  17. package/dist/src/commands/db/env.d.ts +15 -0
  18. package/dist/src/commands/db/env.d.ts.map +1 -0
  19. package/dist/src/commands/db/env.js +50 -0
  20. package/dist/src/commands/db/env.js.map +1 -0
  21. package/dist/src/commands/db/exec.d.ts +54 -0
  22. package/dist/src/commands/db/exec.d.ts.map +1 -0
  23. package/dist/src/commands/db/exec.js +331 -0
  24. package/dist/src/commands/db/exec.js.map +1 -0
  25. package/dist/src/commands/db/index.d.ts +12 -0
  26. package/dist/src/commands/db/index.d.ts.map +1 -0
  27. package/dist/src/commands/db/index.js +62 -0
  28. package/dist/src/commands/db/index.js.map +1 -0
  29. package/dist/src/commands/db/psql.d.ts +16 -0
  30. package/dist/src/commands/db/psql.d.ts.map +1 -0
  31. package/dist/src/commands/db/psql.js +133 -0
  32. package/dist/src/commands/db/psql.js.map +1 -0
  33. package/dist/src/commands/deploy.d.ts +24 -0
  34. package/dist/src/commands/deploy.d.ts.map +1 -0
  35. package/dist/src/commands/deploy.js +228 -0
  36. package/dist/src/commands/deploy.js.map +1 -0
  37. package/dist/src/commands/dev.d.ts +17 -0
  38. package/dist/src/commands/dev.d.ts.map +1 -0
  39. package/dist/src/commands/dev.js +1248 -0
  40. package/dist/src/commands/dev.js.map +1 -0
  41. package/dist/src/commands/devbox.d.ts +22 -0
  42. package/dist/src/commands/devbox.d.ts.map +1 -0
  43. package/dist/src/commands/devbox.js +463 -0
  44. package/dist/src/commands/devbox.js.map +1 -0
  45. package/dist/src/commands/login.d.ts +47 -0
  46. package/dist/src/commands/login.d.ts.map +1 -0
  47. package/dist/src/commands/login.js +344 -0
  48. package/dist/src/commands/login.js.map +1 -0
  49. package/dist/src/commands/registry.d.ts +20 -0
  50. package/dist/src/commands/registry.d.ts.map +1 -0
  51. package/dist/src/commands/registry.js +336 -0
  52. package/dist/src/commands/registry.js.map +1 -0
  53. package/dist/src/commands/secrets/exec.d.ts +17 -0
  54. package/dist/src/commands/secrets/exec.d.ts.map +1 -0
  55. package/dist/src/commands/secrets/exec.js +132 -0
  56. package/dist/src/commands/secrets/exec.js.map +1 -0
  57. package/dist/src/commands/secrets/index.d.ts +10 -0
  58. package/dist/src/commands/secrets/index.d.ts.map +1 -0
  59. package/dist/src/commands/secrets/index.js +35 -0
  60. package/dist/src/commands/secrets/index.js.map +1 -0
  61. package/dist/src/commands/secrets/set.d.ts +22 -0
  62. package/dist/src/commands/secrets/set.d.ts.map +1 -0
  63. package/dist/src/commands/secrets/set.js +234 -0
  64. package/dist/src/commands/secrets/set.js.map +1 -0
  65. package/dist/src/commands/stack.d.ts +17 -0
  66. package/dist/src/commands/stack.d.ts.map +1 -0
  67. package/dist/src/commands/stack.js +175 -0
  68. package/dist/src/commands/stack.js.map +1 -0
  69. package/dist/src/commands/tunnel/index.d.ts +14 -0
  70. package/dist/src/commands/tunnel/index.d.ts.map +1 -0
  71. package/dist/src/commands/tunnel/index.js +217 -0
  72. package/dist/src/commands/tunnel/index.js.map +1 -0
  73. package/dist/src/index.d.ts +7 -0
  74. package/dist/src/index.d.ts.map +1 -0
  75. package/dist/src/index.js +7 -0
  76. package/dist/src/index.js.map +1 -0
  77. package/dist/src/utils/bastion.d.ts +43 -0
  78. package/dist/src/utils/bastion.d.ts.map +1 -0
  79. package/dist/src/utils/bastion.js +77 -0
  80. package/dist/src/utils/bastion.js.map +1 -0
  81. package/dist/src/utils/context.d.ts +29 -0
  82. package/dist/src/utils/context.d.ts.map +1 -0
  83. package/dist/src/utils/context.js +132 -0
  84. package/dist/src/utils/context.js.map +1 -0
  85. package/dist/src/utils/credentials.d.ts +61 -0
  86. package/dist/src/utils/credentials.d.ts.map +1 -0
  87. package/dist/src/utils/credentials.js +145 -0
  88. package/dist/src/utils/credentials.js.map +1 -0
  89. package/dist/src/utils/index.d.ts +9 -0
  90. package/dist/src/utils/index.d.ts.map +1 -0
  91. package/dist/src/utils/index.js +9 -0
  92. package/dist/src/utils/index.js.map +1 -0
  93. package/dist/src/utils/log.d.ts +8 -0
  94. package/dist/src/utils/log.d.ts.map +1 -0
  95. package/dist/src/utils/log.js +17 -0
  96. package/dist/src/utils/log.js.map +1 -0
  97. package/dist/src/utils/pulumi.d.ts +24 -0
  98. package/dist/src/utils/pulumi.d.ts.map +1 -0
  99. package/dist/src/utils/pulumi.js +63 -0
  100. package/dist/src/utils/pulumi.js.map +1 -0
  101. package/package.json +50 -0
  102. package/templates/api-web-db/api/.dockerignore +2 -0
  103. package/templates/api-web-db/api/Dockerfile +16 -0
  104. package/templates/api-web-db/api/package.json.hbs +21 -0
  105. package/templates/api-web-db/api/src/index.ts.hbs +123 -0
  106. package/templates/api-web-db/api/tsconfig.json +13 -0
  107. package/templates/api-web-db/package.json.hbs +27 -0
  108. package/templates/api-web-db/sst.config.ts.hbs +151 -0
  109. package/templates/api-web-db/tsconfig.json +11 -0
  110. package/templates/api-web-db/web/.dockerignore +3 -0
  111. package/templates/api-web-db/web/Dockerfile +17 -0
  112. package/templates/api-web-db/web/app/lib/db.server.ts +36 -0
  113. package/templates/api-web-db/web/app/root.tsx +29 -0
  114. package/templates/api-web-db/web/app/routes/home.tsx.hbs +114 -0
  115. package/templates/api-web-db/web/app/routes.ts +3 -0
  116. package/templates/api-web-db/web/package.json.hbs +30 -0
  117. package/templates/api-web-db/web/prisma/schema.prisma +25 -0
  118. package/templates/api-web-db/web/prisma.config.ts +18 -0
  119. package/templates/api-web-db/web/react-router.config.ts +5 -0
  120. package/templates/api-web-db/web/tsconfig.json +19 -0
  121. package/templates/api-web-db/web/vite.config.ts +9 -0
  122. package/templates/temporal-api-worker/README.md.hbs +133 -0
  123. package/templates/temporal-api-worker/api/.dockerignore +4 -0
  124. package/templates/temporal-api-worker/api/Dockerfile +13 -0
  125. package/templates/temporal-api-worker/api/package.json.hbs +23 -0
  126. package/templates/temporal-api-worker/api/src/encryption-codec.ts +133 -0
  127. package/templates/temporal-api-worker/api/src/index.ts.hbs +145 -0
  128. package/templates/temporal-api-worker/api/tsconfig.json +14 -0
  129. package/templates/temporal-api-worker/package.json.hbs +29 -0
  130. package/templates/temporal-api-worker/sst.config.ts.hbs +161 -0
  131. package/templates/temporal-api-worker/tsconfig.json +10 -0
  132. package/templates/temporal-api-worker/worker/.dockerignore +4 -0
  133. package/templates/temporal-api-worker/worker/Dockerfile +11 -0
  134. package/templates/temporal-api-worker/worker/package.json.hbs +25 -0
  135. package/templates/temporal-api-worker/worker/src/activities.ts.hbs +49 -0
  136. package/templates/temporal-api-worker/worker/src/bundle-workflows.ts +38 -0
  137. package/templates/temporal-api-worker/worker/src/encryption-codec.ts +156 -0
  138. package/templates/temporal-api-worker/worker/src/worker.ts.hbs +93 -0
  139. package/templates/temporal-api-worker/worker/src/workflows.ts.hbs +60 -0
  140. package/templates/temporal-api-worker/worker/tsconfig.json +14 -0
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Temporal Payload Encryption Codec
3
+ *
4
+ * Encrypts workflow payloads using AES-256-GCM following Temporal's
5
+ * recommended pattern: serialize the entire payload with Protobuf,
6
+ * then encrypt.
7
+ *
8
+ * Reference: https://github.com/temporalio/samples-typescript/blob/main/encryption/src/encryption-codec.ts
9
+ */
10
+
11
+ import { webcrypto as crypto } from "node:crypto";
12
+ import {
13
+ METADATA_ENCODING_KEY,
14
+ Payload,
15
+ PayloadCodec,
16
+ ValueError,
17
+ } from "@temporalio/common";
18
+ import proto from "@temporalio/proto";
19
+
20
+ const { temporal } = proto;
21
+
22
+ const ENCODING = "binary/encrypted";
23
+ const METADATA_ENCRYPTION_KEY_ID = "encryption-key-id";
24
+ const IV_LENGTH = 12;
25
+
26
+ /**
27
+ * Derive a CryptoKey from an encoding key string using SHA-256
28
+ */
29
+ async function deriveKey(encodingKey: string): Promise<crypto.CryptoKey> {
30
+ const keyData = await crypto.subtle.digest(
31
+ "SHA-256",
32
+ new TextEncoder().encode(encodingKey)
33
+ );
34
+ return crypto.subtle.importKey("raw", keyData, { name: "AES-GCM" }, false, [
35
+ "encrypt",
36
+ "decrypt",
37
+ ]);
38
+ }
39
+
40
+ /**
41
+ * Encrypt data using AES-256-GCM
42
+ * Output: IV (12 bytes) + Ciphertext+AuthTag (WebCrypto format)
43
+ */
44
+ async function encrypt(
45
+ data: Uint8Array,
46
+ key: crypto.CryptoKey
47
+ ): Promise<Uint8Array> {
48
+ const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH));
49
+ const encrypted = await crypto.subtle.encrypt(
50
+ { name: "AES-GCM", iv },
51
+ key,
52
+ data
53
+ );
54
+ // Prepend IV to ciphertext+authTag
55
+ const result = new Uint8Array(IV_LENGTH + encrypted.byteLength);
56
+ result.set(iv, 0);
57
+ result.set(new Uint8Array(encrypted), IV_LENGTH);
58
+ return result;
59
+ }
60
+
61
+ /**
62
+ * Decrypt data using AES-256-GCM
63
+ * Input: IV (12 bytes) + Ciphertext+AuthTag
64
+ */
65
+ async function decrypt(
66
+ data: Uint8Array,
67
+ key: crypto.CryptoKey
68
+ ): Promise<Uint8Array> {
69
+ const iv = data.slice(0, IV_LENGTH);
70
+ const ciphertextWithTag = data.slice(IV_LENGTH);
71
+ const decrypted = await crypto.subtle.decrypt(
72
+ { name: "AES-GCM", iv },
73
+ key,
74
+ ciphertextWithTag
75
+ );
76
+ return new Uint8Array(decrypted);
77
+ }
78
+
79
+ /**
80
+ * Payload codec that encrypts/decrypts payloads using AES-256-GCM.
81
+ *
82
+ * Uses Protobuf serialization for the entire payload (data + metadata)
83
+ * following Temporal's recommended pattern.
84
+ */
85
+ export class EncryptionCodec implements PayloadCodec {
86
+ private constructor(
87
+ private readonly key: crypto.CryptoKey,
88
+ private readonly keyId: string
89
+ ) {}
90
+
91
+ static async create(encodingKey: string): Promise<EncryptionCodec> {
92
+ const key = await deriveKey(encodingKey);
93
+ // Use truncated hash as key ID for identification
94
+ const keyIdData = await crypto.subtle.digest(
95
+ "SHA-256",
96
+ new TextEncoder().encode(encodingKey)
97
+ );
98
+ const keyId = Buffer.from(keyIdData).toString("hex").slice(0, 16);
99
+ return new EncryptionCodec(key, keyId);
100
+ }
101
+
102
+ async encode(payloads: Payload[]): Promise<Payload[]> {
103
+ return Promise.all(
104
+ payloads.map(async (payload) => ({
105
+ metadata: {
106
+ [METADATA_ENCODING_KEY]: new TextEncoder().encode(ENCODING),
107
+ [METADATA_ENCRYPTION_KEY_ID]: new TextEncoder().encode(this.keyId),
108
+ },
109
+ // Serialize entire payload with Protobuf, then encrypt
110
+ data: await encrypt(
111
+ temporal.api.common.v1.Payload.encode(payload).finish(),
112
+ this.key
113
+ ),
114
+ }))
115
+ );
116
+ }
117
+
118
+ async decode(payloads: Payload[]): Promise<Payload[]> {
119
+ return Promise.all(
120
+ payloads.map(async (payload) => {
121
+ // Check if encrypted
122
+ const encoding = payload.metadata?.[METADATA_ENCODING_KEY];
123
+ if (!encoding) {
124
+ return payload;
125
+ }
126
+
127
+ const encodingStr = new TextDecoder().decode(encoding);
128
+ if (encodingStr !== ENCODING) {
129
+ return payload;
130
+ }
131
+
132
+ if (!payload.data) {
133
+ throw new ValueError("Payload data is missing");
134
+ }
135
+
136
+ // Decrypt and deserialize with Protobuf
137
+ const decryptedBytes = await decrypt(payload.data, this.key);
138
+ return temporal.api.common.v1.Payload.decode(decryptedBytes);
139
+ })
140
+ );
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Creates an encryption codec from TEMPORAL_ENCODING_KEY env var.
146
+ * Returns undefined if not set.
147
+ */
148
+ export async function createEncryptionCodec(): Promise<EncryptionCodec | undefined> {
149
+ const encodingKey = process.env.TEMPORAL_ENCODING_KEY;
150
+ if (!encodingKey) {
151
+ console.log("[Encryption] No TEMPORAL_ENCODING_KEY set, payloads will not be encrypted");
152
+ return undefined;
153
+ }
154
+ console.log("[Encryption] Payload encryption enabled");
155
+ return EncryptionCodec.create(encodingKey);
156
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * {{titleCase name}} Temporal Worker
3
+ *
4
+ * Environment variables:
5
+ * - TEMPORAL_ADDRESS: Temporal server address (default: localhost:7233)
6
+ * - TEMPORAL_NAMESPACE: Temporal namespace (required)
7
+ * - TEMPORAL_TASK_QUEUE: Task queue name (required)
8
+ * - TEMPORAL_ENCODING_KEY: Encoding key for payload encryption (optional)
9
+ */
10
+
11
+ import * as fs from "fs";
12
+ import * as path from "path";
13
+ import { fileURLToPath } from "url";
14
+ import { NativeConnection, Worker, WorkerOptions, bundleWorkflowCode } from "@temporalio/worker";
15
+ import * as activities from "./activities.js";
16
+ import { createEncryptionCodec } from "./encryption-codec.js";
17
+
18
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
19
+
20
+ const TEMPORAL_ADDRESS = process.env.TEMPORAL_ADDRESS ?? "localhost:7233";
21
+
22
+ function requireEnv(name: string): string {
23
+ const value = process.env[name];
24
+ if (!value) {
25
+ throw new Error(`${name} environment variable is required`);
26
+ }
27
+ return value;
28
+ }
29
+
30
+ const TEMPORAL_NAMESPACE = requireEnv("TEMPORAL_NAMESPACE");
31
+ const TEMPORAL_TASK_QUEUE = requireEnv("TEMPORAL_TASK_QUEUE");
32
+
33
+ /**
34
+ * Load workflows - uses pre-bundled code in production, source files in dev
35
+ */
36
+ async function getWorkflowOptions(): Promise<
37
+ Pick<WorkerOptions, "workflowBundle" | "workflowsPath">
38
+ > {
39
+ const bundlePath = path.join(__dirname, "workflows-bundle.js");
40
+
41
+ if (fs.existsSync(bundlePath)) {
42
+ console.log("[Worker] Loading pre-bundled workflows...");
43
+ return {
44
+ workflowBundle: { code: fs.readFileSync(bundlePath, "utf-8") },
45
+ };
46
+ }
47
+
48
+ console.log("[Worker] Bundling workflows from source...");
49
+ return {
50
+ workflowBundle: await bundleWorkflowCode({
51
+ workflowsPath: new URL("./workflows.js", import.meta.url).pathname,
52
+ }),
53
+ };
54
+ }
55
+
56
+ async function run() {
57
+ console.log(`[Worker] Connecting to Temporal at ${TEMPORAL_ADDRESS}...`);
58
+
59
+ const connection = await NativeConnection.connect({
60
+ address: TEMPORAL_ADDRESS,
61
+ });
62
+
63
+ console.log(`[Worker] Connected. Namespace: ${TEMPORAL_NAMESPACE}`);
64
+
65
+ const workflowOptions = await getWorkflowOptions();
66
+
67
+ // Set up payload encryption if encoding key is available
68
+ const encryptionCodec = await createEncryptionCodec();
69
+ const dataConverter = encryptionCodec
70
+ ? { payloadCodecs: [encryptionCodec] }
71
+ : undefined;
72
+
73
+ if (encryptionCodec) {
74
+ console.log("[Worker] Payload encryption enabled");
75
+ }
76
+
77
+ const worker = await Worker.create({
78
+ connection,
79
+ namespace: TEMPORAL_NAMESPACE,
80
+ taskQueue: TEMPORAL_TASK_QUEUE,
81
+ ...workflowOptions,
82
+ activities,
83
+ dataConverter,
84
+ });
85
+
86
+ console.log(`[Worker] Starting on task queue: ${TEMPORAL_TASK_QUEUE}`);
87
+ await worker.run();
88
+ }
89
+
90
+ run().catch((err) => {
91
+ console.error("[Worker] Fatal error:", err);
92
+ process.exit(1);
93
+ });
@@ -0,0 +1,60 @@
1
+ /**
2
+ * {{titleCase name}} Workflows
3
+ *
4
+ * Define your workflow logic here. Workflows are deterministic functions
5
+ * that orchestrate activities and other workflows.
6
+ *
7
+ * Rules for workflows:
8
+ * - Must be deterministic (same inputs = same outputs)
9
+ * - Cannot use Date.now(), Math.random(), or other non-deterministic APIs
10
+ * - Use sleep() instead of setTimeout()
11
+ * - Use proxyActivities() to call activities
12
+ */
13
+
14
+ import { proxyActivities, sleep } from "@temporalio/workflow";
15
+ import type * as activities from "./activities.js";
16
+
17
+ // Configure activity retries and timeouts
18
+ const { greet, processTask } = proxyActivities<typeof activities>({
19
+ startToCloseTimeout: "30 seconds",
20
+ retry: {
21
+ maximumAttempts: 3,
22
+ },
23
+ });
24
+
25
+ /**
26
+ * Simple greeting workflow
27
+ *
28
+ * @param name - Name to greet
29
+ * @returns Greeting message
30
+ */
31
+ export async function greetingWorkflow(name: string): Promise<string> {
32
+ return await greet(name);
33
+ }
34
+
35
+ /**
36
+ * Task processing workflow with notification
37
+ *
38
+ * @param taskId - Task identifier
39
+ * @param userId - User who owns the task
40
+ * @returns Task status
41
+ */
42
+ export async function taskWorkflow(
43
+ taskId: string,
44
+ userId: string
45
+ ): Promise<{ status: string; taskId: string }> {
46
+ console.log(`[Workflow] Processing task ${taskId} for user ${userId}`);
47
+
48
+ // Process the task
49
+ const result = await processTask(taskId);
50
+
51
+ // Wait before completing (demonstrates durable timers)
52
+ await sleep("2 seconds");
53
+
54
+ console.log(`[Workflow] Task ${taskId} completed with status: ${result}`);
55
+
56
+ return {
57
+ status: result,
58
+ taskId,
59
+ };
60
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "declaration": true
12
+ },
13
+ "include": ["src/**/*"]
14
+ }