vyft 0.4.0-alpha → 0.4.2-alpha

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 (189) hide show
  1. package/LICENSE +191 -21
  2. package/README.md +3 -49
  3. package/dist/commands/context/add.d.ts +4 -0
  4. package/dist/commands/context/add.d.ts.map +1 -0
  5. package/dist/commands/context/add.js +98 -0
  6. package/dist/commands/context/add.js.map +1 -0
  7. package/dist/commands/context/index.d.ts +4 -0
  8. package/dist/commands/context/index.d.ts.map +1 -0
  9. package/dist/commands/context/index.js +12 -0
  10. package/dist/commands/context/index.js.map +1 -0
  11. package/dist/commands/context/list.d.ts +4 -0
  12. package/dist/commands/context/list.d.ts.map +1 -0
  13. package/dist/commands/context/list.js +25 -0
  14. package/dist/commands/context/list.js.map +1 -0
  15. package/dist/commands/context/remove.d.ts +4 -0
  16. package/dist/commands/context/remove.d.ts.map +1 -0
  17. package/dist/commands/context/remove.js +36 -0
  18. package/dist/commands/context/remove.js.map +1 -0
  19. package/dist/commands/context/use.d.ts +4 -0
  20. package/dist/commands/context/use.d.ts.map +1 -0
  21. package/dist/commands/context/use.js +32 -0
  22. package/dist/commands/context/use.js.map +1 -0
  23. package/dist/commands/deploy.d.ts +4 -0
  24. package/dist/commands/deploy.d.ts.map +1 -0
  25. package/dist/commands/deploy.js +55 -0
  26. package/dist/commands/deploy.js.map +1 -0
  27. package/dist/commands/destroy.d.ts +4 -0
  28. package/dist/commands/destroy.d.ts.map +1 -0
  29. package/dist/commands/destroy.js +70 -0
  30. package/dist/commands/destroy.js.map +1 -0
  31. package/dist/commands/diff.d.ts +4 -0
  32. package/dist/commands/diff.d.ts.map +1 -0
  33. package/dist/commands/diff.js +52 -0
  34. package/dist/commands/diff.js.map +1 -0
  35. package/dist/commands/init.d.ts +4 -0
  36. package/dist/commands/init.d.ts.map +1 -0
  37. package/dist/commands/init.js +92 -0
  38. package/dist/commands/init.js.map +1 -0
  39. package/dist/commands/local/detect.d.ts +7 -0
  40. package/dist/commands/local/detect.d.ts.map +1 -0
  41. package/dist/commands/local/detect.js +146 -0
  42. package/dist/commands/local/detect.js.map +1 -0
  43. package/dist/commands/local/dev.d.ts +4 -0
  44. package/dist/commands/local/dev.d.ts.map +1 -0
  45. package/dist/commands/local/dev.js +387 -0
  46. package/dist/commands/local/dev.js.map +1 -0
  47. package/dist/commands/local/down.d.ts +4 -0
  48. package/dist/commands/local/down.d.ts.map +1 -0
  49. package/dist/commands/local/down.js +61 -0
  50. package/dist/commands/local/down.js.map +1 -0
  51. package/dist/commands/local/index.d.ts +4 -0
  52. package/dist/commands/local/index.d.ts.map +1 -0
  53. package/dist/commands/local/index.js +12 -0
  54. package/dist/commands/local/index.js.map +1 -0
  55. package/dist/commands/local/reset.d.ts +4 -0
  56. package/dist/commands/local/reset.d.ts.map +1 -0
  57. package/dist/commands/local/reset.js +67 -0
  58. package/dist/commands/local/reset.js.map +1 -0
  59. package/dist/commands/local/up.d.ts +4 -0
  60. package/dist/commands/local/up.d.ts.map +1 -0
  61. package/dist/commands/local/up.js +58 -0
  62. package/dist/commands/local/up.js.map +1 -0
  63. package/dist/commands/refresh.d.ts +4 -0
  64. package/dist/commands/refresh.d.ts.map +1 -0
  65. package/dist/commands/refresh.js +39 -0
  66. package/dist/commands/refresh.js.map +1 -0
  67. package/dist/config.d.ts +8 -0
  68. package/dist/config.d.ts.map +1 -0
  69. package/dist/config.js +65 -0
  70. package/dist/config.js.map +1 -0
  71. package/dist/contexts.d.ts +21 -0
  72. package/dist/contexts.d.ts.map +1 -0
  73. package/dist/contexts.js +72 -0
  74. package/dist/contexts.js.map +1 -0
  75. package/dist/index.d.ts +2 -9
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +23 -7
  78. package/dist/index.js.map +1 -0
  79. package/dist/lib.d.ts +7 -0
  80. package/dist/lib.d.ts.map +1 -0
  81. package/dist/lib.js +6 -0
  82. package/dist/lib.js.map +1 -0
  83. package/dist/providers.d.ts +9 -0
  84. package/dist/providers.d.ts.map +1 -0
  85. package/dist/providers.js +41 -0
  86. package/dist/providers.js.map +1 -0
  87. package/dist/runtime.d.ts +18 -15
  88. package/dist/runtime.d.ts.map +1 -0
  89. package/dist/runtime.js +154 -0
  90. package/dist/runtime.js.map +1 -0
  91. package/dist/runtime.test.d.ts +2 -0
  92. package/dist/runtime.test.d.ts.map +1 -0
  93. package/dist/runtime.test.js +119 -0
  94. package/dist/runtime.test.js.map +1 -0
  95. package/dist/utils/fs.d.ts +4 -0
  96. package/dist/utils/fs.d.ts.map +1 -0
  97. package/dist/utils/fs.js +33 -0
  98. package/dist/utils/fs.js.map +1 -0
  99. package/dist/utils/pm.d.ts +3 -0
  100. package/dist/utils/pm.d.ts.map +1 -0
  101. package/dist/utils/pm.js +17 -0
  102. package/dist/utils/pm.js.map +1 -0
  103. package/dist/utils/prompts.d.ts +2 -0
  104. package/dist/utils/prompts.d.ts.map +1 -0
  105. package/dist/utils/prompts.js +6 -0
  106. package/dist/utils/prompts.js.map +1 -0
  107. package/dist/utils/templates.d.ts +3 -0
  108. package/dist/utils/templates.d.ts.map +1 -0
  109. package/dist/utils/templates.js +48 -0
  110. package/dist/utils/templates.js.map +1 -0
  111. package/package.json +31 -48
  112. package/templates/bun/index.ts +8 -0
  113. package/templates/bun/package.json +15 -0
  114. package/templates/bun/tsconfig.json +15 -0
  115. package/templates/bun/vyft.config.ts +3 -0
  116. package/dist/build.d.ts +0 -12
  117. package/dist/build.js +0 -44
  118. package/dist/cli.d.ts +0 -2
  119. package/dist/cli.js +0 -842
  120. package/dist/context.d.ts +0 -39
  121. package/dist/context.js +0 -101
  122. package/dist/docker.d.ts +0 -69
  123. package/dist/docker.js +0 -958
  124. package/dist/exec.d.ts +0 -2
  125. package/dist/exec.js +0 -28
  126. package/dist/init.d.ts +0 -1
  127. package/dist/init.js +0 -117
  128. package/dist/interpolate.d.ts +0 -13
  129. package/dist/interpolate.js +0 -19
  130. package/dist/local/dev.d.ts +0 -31
  131. package/dist/local/dev.js +0 -109
  132. package/dist/local/index.d.ts +0 -2
  133. package/dist/local/index.js +0 -2
  134. package/dist/local/runtime.d.ts +0 -61
  135. package/dist/local/runtime.js +0 -391
  136. package/dist/logger.d.ts +0 -2
  137. package/dist/logger.js +0 -10
  138. package/dist/proxy.d.ts +0 -16
  139. package/dist/proxy.js +0 -0
  140. package/dist/resource.d.ts +0 -181
  141. package/dist/resource.js +0 -45
  142. package/dist/services/index.d.ts +0 -26
  143. package/dist/services/index.js +0 -35
  144. package/dist/services/minio.d.ts +0 -36
  145. package/dist/services/minio.js +0 -53
  146. package/dist/services/mongo.d.ts +0 -28
  147. package/dist/services/mongo.js +0 -45
  148. package/dist/services/mysql.d.ts +0 -28
  149. package/dist/services/mysql.js +0 -44
  150. package/dist/services/nats.d.ts +0 -26
  151. package/dist/services/nats.js +0 -38
  152. package/dist/services/postgres.d.ts +0 -28
  153. package/dist/services/postgres.js +0 -45
  154. package/dist/services/rabbitmq.d.ts +0 -28
  155. package/dist/services/rabbitmq.js +0 -44
  156. package/dist/services/redis.d.ts +0 -28
  157. package/dist/services/redis.js +0 -49
  158. package/dist/services/storage.d.ts +0 -39
  159. package/dist/services/storage.js +0 -94
  160. package/dist/swarm/factories.d.ts +0 -16
  161. package/dist/swarm/factories.js +0 -63
  162. package/dist/swarm/index.d.ts +0 -20
  163. package/dist/swarm/index.js +0 -5
  164. package/dist/swarm/proxy.d.ts +0 -24
  165. package/dist/swarm/proxy.js +0 -339
  166. package/dist/swarm/types.d.ts +0 -26
  167. package/dist/swarm/types.js +0 -0
  168. package/dist/symbols.d.ts +0 -15
  169. package/dist/symbols.js +0 -4
  170. package/templates/fullstack/apps/api/Dockerfile +0 -22
  171. package/templates/fullstack/apps/api/package.json +0 -26
  172. package/templates/fullstack/apps/api/src/auth.ts +0 -21
  173. package/templates/fullstack/apps/api/src/db.ts +0 -16
  174. package/templates/fullstack/apps/api/src/index.ts +0 -17
  175. package/templates/fullstack/apps/api/src/router.ts +0 -11
  176. package/templates/fullstack/apps/api/src/schema.ts +0 -11
  177. package/templates/fullstack/apps/api/tsconfig.json +0 -8
  178. package/templates/fullstack/apps/web/index.html +0 -12
  179. package/templates/fullstack/apps/web/package.json +0 -21
  180. package/templates/fullstack/apps/web/src/app.tsx +0 -8
  181. package/templates/fullstack/apps/web/src/main.tsx +0 -9
  182. package/templates/fullstack/apps/web/tsconfig.json +0 -7
  183. package/templates/fullstack/apps/web/vite.config.ts +0 -14
  184. package/templates/fullstack/dockerignore +0 -7
  185. package/templates/fullstack/gitignore +0 -3
  186. package/templates/fullstack/package.json +0 -14
  187. package/templates/fullstack/pnpm-workspace.yaml +0 -2
  188. package/templates/fullstack/tsconfig.json +0 -11
  189. package/templates/fullstack/vyft.config.ts +0 -22
package/dist/runtime.js CHANGED
@@ -0,0 +1,154 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { confirm, isCancel, log, password } from "@clack/prompts";
6
+ import { Cipher, generateSalt } from "@vyft/core";
7
+ import { LocalBackend, Store } from "@vyft/store";
8
+ import { platforms, runtimes } from "./providers.js";
9
+ const VYFT_DIR = ".vyft";
10
+ export function resolveStateDir(cwd, context, project, stage = "production") {
11
+ return path.join(cwd, VYFT_DIR, "context", context, project, stage);
12
+ }
13
+ export function resolveLocalStateDir(cwd, project) {
14
+ return path.join(cwd, VYFT_DIR, "local", project);
15
+ }
16
+ function passphraseConfigPath(project) {
17
+ return path.join(os.homedir(), ".config", "vyft", project, "passphrase");
18
+ }
19
+ async function readPersistedPassphrase(project) {
20
+ try {
21
+ const data = await fs.readFile(passphraseConfigPath(project), "utf8");
22
+ // trim() strips trailing newlines from manually-edited files; whitespace-only content is treated as absent
23
+ return data.trim() || null;
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ }
29
+ async function persistPassphrase(project, passphrase) {
30
+ const filePath = passphraseConfigPath(project);
31
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
32
+ await fs.writeFile(filePath, passphrase, { mode: 0o600 });
33
+ }
34
+ export async function resolvePassphrase(project, mode) {
35
+ const env = process.env["VYFT_PASSPHRASE"];
36
+ if (env)
37
+ return env;
38
+ const persisted = await readPersistedPassphrase(project);
39
+ if (persisted)
40
+ return persisted;
41
+ if (mode === "local") {
42
+ const generated = crypto.randomBytes(32).toString("hex");
43
+ await persistPassphrase(project, generated);
44
+ log.info(`Generated passphrase saved to ${passphraseConfigPath(project)}`);
45
+ return generated;
46
+ }
47
+ const value = await password({ message: "Enter passphrase:" });
48
+ if (isCancel(value))
49
+ process.exit(1);
50
+ if (mode === "deploy") {
51
+ const save = await confirm({
52
+ message: "Save passphrase locally for future use?",
53
+ });
54
+ // Cancelling the save prompt is treated as "no" — passphrase is returned without saving
55
+ if (!isCancel(save) && save) {
56
+ await persistPassphrase(project, value);
57
+ log.info(`Passphrase saved to ${passphraseConfigPath(project)}`);
58
+ }
59
+ }
60
+ return value;
61
+ }
62
+ export async function loadSalt(stateDir) {
63
+ const saltPath = path.join(stateDir, "salt");
64
+ try {
65
+ return await fs.readFile(saltPath);
66
+ }
67
+ catch {
68
+ const salt = generateSalt();
69
+ await fs.mkdir(stateDir, { recursive: true });
70
+ await fs.writeFile(saltPath, salt);
71
+ return salt;
72
+ }
73
+ }
74
+ export async function openStore(stateDir) {
75
+ await fs.mkdir(stateDir, { recursive: true });
76
+ return Store.open(new LocalBackend(stateDir));
77
+ }
78
+ export function buildCurrentState(store) {
79
+ const entries = {};
80
+ for (const [key, value] of store.entries()) {
81
+ const data = value;
82
+ if (data["status"] === "committed") {
83
+ const entry = {
84
+ urn: key,
85
+ input: data["input"] ?? {},
86
+ };
87
+ const output = data["output"];
88
+ if (output) {
89
+ entry.output = output;
90
+ }
91
+ const externalId = data["externalId"];
92
+ if (externalId) {
93
+ entry.externalId = externalId;
94
+ }
95
+ entries[key] = entry;
96
+ }
97
+ }
98
+ return { entries };
99
+ }
100
+ export function createArtifacts(stateDir) {
101
+ return (urn) => {
102
+ const dir = path.join(stateDir, "artifacts", urn);
103
+ return {
104
+ async write(name, data) {
105
+ await fs.mkdir(dir, { recursive: true });
106
+ await fs.writeFile(path.join(dir, name), data);
107
+ return { key: name };
108
+ },
109
+ async read(ref) {
110
+ return fs.readFile(path.join(dir, ref.key));
111
+ },
112
+ async exists(ref) {
113
+ try {
114
+ await fs.access(path.join(dir, ref.key));
115
+ return true;
116
+ }
117
+ catch {
118
+ return false;
119
+ }
120
+ },
121
+ async delete(ref) {
122
+ await fs.rm(path.join(dir, ref.key), { force: true });
123
+ },
124
+ };
125
+ };
126
+ }
127
+ export function createCipher(passphrase, salt) {
128
+ return new Cipher(passphrase, salt);
129
+ }
130
+ export function buildContext(store, cipher, providers, stateDir) {
131
+ return {
132
+ store,
133
+ cipher,
134
+ providers,
135
+ createArtifacts: createArtifacts(stateDir),
136
+ };
137
+ }
138
+ export function resolveRuntimeProvider(runtime, project, stage) {
139
+ const factory = runtimes.get(runtime);
140
+ if (!factory) {
141
+ const supported = [...runtimes.keys()].join(", ");
142
+ throw new Error(`Unknown runtime: "${runtime}". Supported: ${supported}`);
143
+ }
144
+ return factory({ project, stage });
145
+ }
146
+ export function resolvePlatformProvider(platform, project, stage) {
147
+ const factory = platforms.get(platform);
148
+ if (!factory) {
149
+ const supported = [...platforms.keys()].join(", ");
150
+ throw new Error(`Unknown platform: "${platform}". Supported: ${supported}`);
151
+ }
152
+ return factory({ project, stage });
153
+ }
154
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=runtime.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.test.d.ts","sourceRoot":"","sources":["../src/runtime.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,119 @@
1
+ import assert from "node:assert/strict";
2
+ import fs from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { afterEach, describe, it } from "node:test";
6
+ import { resolvePassphrase } from "./runtime.js";
7
+ function configPath(project) {
8
+ return path.join(os.homedir(), ".config", "vyft", project, "passphrase");
9
+ }
10
+ async function cleanupProject(project) {
11
+ try {
12
+ await fs.rm(path.join(os.homedir(), ".config", "vyft", project), {
13
+ recursive: true,
14
+ });
15
+ }
16
+ catch {
17
+ // ignore
18
+ }
19
+ }
20
+ describe("resolvePassphrase", () => {
21
+ const savedEnv = process.env["VYFT_PASSPHRASE"];
22
+ afterEach(() => {
23
+ if (savedEnv === undefined) {
24
+ delete process.env["VYFT_PASSPHRASE"];
25
+ }
26
+ else {
27
+ process.env["VYFT_PASSPHRASE"] = savedEnv;
28
+ }
29
+ });
30
+ it("returns VYFT_PASSPHRASE env var when set", async () => {
31
+ process.env["VYFT_PASSPHRASE"] = "env-secret";
32
+ const result = await resolvePassphrase("any-project", "deploy");
33
+ assert.equal(result, "env-secret");
34
+ });
35
+ it("returns persisted passphrase when file exists (deploy mode)", async () => {
36
+ delete process.env["VYFT_PASSPHRASE"];
37
+ const project = `test-${Date.now()}`;
38
+ const filePath = configPath(project);
39
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
40
+ await fs.writeFile(filePath, "stored-secret", { mode: 0o600 });
41
+ try {
42
+ const result = await resolvePassphrase(project, "deploy");
43
+ assert.equal(result, "stored-secret");
44
+ }
45
+ finally {
46
+ await cleanupProject(project);
47
+ }
48
+ });
49
+ it("trims trailing newlines from persisted passphrase file", async () => {
50
+ delete process.env["VYFT_PASSPHRASE"];
51
+ const project = `test-trim-${Date.now()}`;
52
+ const filePath = configPath(project);
53
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
54
+ await fs.writeFile(filePath, "my-passphrase\n", { mode: 0o600 });
55
+ try {
56
+ const result = await resolvePassphrase(project, "deploy");
57
+ assert.equal(result, "my-passphrase");
58
+ }
59
+ finally {
60
+ await cleanupProject(project);
61
+ }
62
+ });
63
+ it("treats whitespace-only passphrase file as absent", async () => {
64
+ delete process.env["VYFT_PASSPHRASE"];
65
+ const project = `test-whitespace-${Date.now()}`;
66
+ const filePath = configPath(project);
67
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
68
+ await fs.writeFile(filePath, " \n", { mode: 0o600 });
69
+ try {
70
+ // local mode: should generate a new passphrase since file content is empty after trim
71
+ const result = await resolvePassphrase(project, "local");
72
+ assert.ok(result.length > 0);
73
+ assert.notEqual(result.trim(), "");
74
+ }
75
+ finally {
76
+ await cleanupProject(project);
77
+ }
78
+ });
79
+ it("generates and persists a passphrase in local mode", async () => {
80
+ delete process.env["VYFT_PASSPHRASE"];
81
+ const project = `test-local-${Date.now()}`;
82
+ try {
83
+ const result = await resolvePassphrase(project, "local");
84
+ assert.ok(result.length > 0);
85
+ const saved = await fs.readFile(configPath(project), "utf8");
86
+ assert.equal(saved, result);
87
+ }
88
+ finally {
89
+ await cleanupProject(project);
90
+ }
91
+ });
92
+ it("returns same generated passphrase on subsequent local calls", async () => {
93
+ delete process.env["VYFT_PASSPHRASE"];
94
+ const project = `test-idempotent-${Date.now()}`;
95
+ try {
96
+ const first = await resolvePassphrase(project, "local");
97
+ const second = await resolvePassphrase(project, "local");
98
+ assert.equal(first, second);
99
+ }
100
+ finally {
101
+ await cleanupProject(project);
102
+ }
103
+ });
104
+ it("env var takes precedence over persisted passphrase", async () => {
105
+ const project = `test-priority-${Date.now()}`;
106
+ const filePath = configPath(project);
107
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
108
+ await fs.writeFile(filePath, "file-secret", { mode: 0o600 });
109
+ process.env["VYFT_PASSPHRASE"] = "env-wins";
110
+ try {
111
+ const result = await resolvePassphrase(project, "deploy");
112
+ assert.equal(result, "env-wins");
113
+ }
114
+ finally {
115
+ await cleanupProject(project);
116
+ }
117
+ });
118
+ });
119
+ //# sourceMappingURL=runtime.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.test.js","sourceRoot":"","sources":["../src/runtime.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function fileExists(filePath: string): Promise<boolean>;
2
+ export declare function isEmptyDir(dir: string): Promise<boolean>;
3
+ export declare function addGitignoreEntry(dir: string): Promise<void>;
4
+ //# sourceMappingURL=fs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":"AAEA,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO9D;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,iBAWlD"}
@@ -0,0 +1,33 @@
1
+ import fs from "node:fs/promises";
2
+ export async function fileExists(filePath) {
3
+ try {
4
+ await fs.access(filePath);
5
+ return true;
6
+ }
7
+ catch {
8
+ return false;
9
+ }
10
+ }
11
+ export async function isEmptyDir(dir) {
12
+ try {
13
+ const entries = await fs.readdir(dir);
14
+ return entries.length === 0;
15
+ }
16
+ catch {
17
+ return true;
18
+ }
19
+ }
20
+ export async function addGitignoreEntry(dir) {
21
+ const path = await import("node:path");
22
+ const gitignorePath = path.join(dir, ".gitignore");
23
+ try {
24
+ const content = await fs.readFile(gitignorePath, "utf8");
25
+ if (!content.includes(".vyft")) {
26
+ await fs.appendFile(gitignorePath, "\n.vyft/\n");
27
+ }
28
+ }
29
+ catch {
30
+ await fs.writeFile(gitignorePath, ".vyft/\n");
31
+ }
32
+ }
33
+ //# sourceMappingURL=fs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAElC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW;IAC1C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACtC,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,GAAW;IACjD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IACvC,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,MAAM,EAAE,CAAC,UAAU,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;IAChD,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ export type PackageManager = "pnpm" | "yarn" | "bun" | "npm";
2
+ export declare function detectPackageManager(cwd: string): Promise<PackageManager>;
3
+ //# sourceMappingURL=pm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pm.d.ts","sourceRoot":"","sources":["../../src/utils/pm.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;AAU7D,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,CAAC,CAKzB"}
@@ -0,0 +1,17 @@
1
+ import path from "node:path";
2
+ import { fileExists } from "./fs.js";
3
+ const LOCK_FILES = [
4
+ ["pnpm-lock.yaml", "pnpm"],
5
+ ["bun.lock", "bun"],
6
+ ["bun.lockb", "bun"],
7
+ ["yarn.lock", "yarn"],
8
+ ["package-lock.json", "npm"],
9
+ ];
10
+ export async function detectPackageManager(cwd) {
11
+ for (const [file, pm] of LOCK_FILES) {
12
+ if (await fileExists(path.join(cwd, file)))
13
+ return pm;
14
+ }
15
+ return "npm";
16
+ }
17
+ //# sourceMappingURL=pm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pm.js","sourceRoot":"","sources":["../../src/utils/pm.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAIrC,MAAM,UAAU,GAA+B;IAC7C,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAC1B,CAAC,UAAU,EAAE,KAAK,CAAC;IACnB,CAAC,WAAW,EAAE,KAAK,CAAC;IACpB,CAAC,WAAW,EAAE,MAAM,CAAC;IACrB,CAAC,mBAAmB,EAAE,KAAK,CAAC;CAC7B,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,GAAW;IAEX,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC;QACpC,IAAI,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC;IACxD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function cancel(msg?: string): never;
2
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/utils/prompts.ts"],"names":[],"mappings":"AAEA,wBAAgB,MAAM,CAAC,GAAG,SAAe,GAAG,KAAK,CAGhD"}
@@ -0,0 +1,6 @@
1
+ import { log } from "@clack/prompts";
2
+ export function cancel(msg = "Cancelled.") {
3
+ log.warn(msg);
4
+ process.exit(0);
5
+ }
6
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/utils/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAErC,MAAM,UAAU,MAAM,CAAC,GAAG,GAAG,YAAY;IACvC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACd,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function listTemplates(): Promise<string[]>;
2
+ export declare function copyTemplate(template: string, dest: string): Promise<void>;
3
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/utils/templates.ts"],"names":[],"mappings":"AAkBA,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAGvD;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,iBA2BhE"}
@@ -0,0 +1,48 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ function templatesDir() {
4
+ return path.resolve(import.meta.dirname, "..", "..", "templates");
5
+ }
6
+ async function fetchLatestVersion(pkg) {
7
+ try {
8
+ const res = await fetch(`https://registry.npmjs.org/${pkg}/latest`);
9
+ if (!res.ok)
10
+ return null;
11
+ const data = (await res.json());
12
+ return data.version ?? null;
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
18
+ export async function listTemplates() {
19
+ const entries = await fs.readdir(templatesDir(), { withFileTypes: true });
20
+ return entries.filter((e) => e.isDirectory()).map((e) => e.name);
21
+ }
22
+ export async function copyTemplate(template, dest) {
23
+ const src = path.join(templatesDir(), template);
24
+ const entries = await fs.readdir(src, { withFileTypes: true });
25
+ for (const entry of entries) {
26
+ if (!entry.isFile())
27
+ continue;
28
+ const srcFile = path.join(src, entry.name);
29
+ const destFile = path.join(dest, entry.name);
30
+ if (entry.name === "package.json") {
31
+ const raw = await fs.readFile(srcFile, "utf8");
32
+ const pkg = JSON.parse(raw);
33
+ pkg["name"] = path.basename(dest);
34
+ const vyftVersion = await fetchLatestVersion("vyft");
35
+ if (vyftVersion) {
36
+ const deps = pkg["dependencies"];
37
+ if (deps?.["vyft"]) {
38
+ deps["vyft"] = `^${vyftVersion}`;
39
+ }
40
+ }
41
+ await fs.writeFile(destFile, `${JSON.stringify(pkg, null, 2)}\n`);
42
+ }
43
+ else {
44
+ await fs.copyFile(srcFile, destFile);
45
+ }
46
+ }
47
+ }
48
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/utils/templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,SAAS,YAAY;IACnB,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;AACpE,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,GAAW;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,8BAA8B,GAAG,SAAS,CAAC,CAAC;QACpE,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QACzB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAyB,CAAC;QACxD,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1E,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB,EAAE,IAAY;IAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,QAAQ,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAE/D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,SAAS;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAE7C,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAClC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;YACvD,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAElC,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;YACrD,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,IAAI,GAAG,GAAG,CAAC,cAAc,CAAuC,CAAC;gBACvE,IAAI,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;oBACnB,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC;gBACnC,CAAC;YACH,CAAC;YAED,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QACpE,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,67 +1,50 @@
1
1
  {
2
2
  "name": "vyft",
3
- "version": "0.4.0-alpha",
4
- "description": "Deploy apps to Docker Swarm with TypeScript",
5
- "type": "module",
6
- "license": "MIT",
7
- "bin": {
8
- "vyft": "./dist/cli.js"
3
+ "version": "0.4.2-alpha",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "https://github.com/vyftlabs/vyft",
7
+ "directory": "packages/vyft"
9
8
  },
10
- "main": "./dist/index.js",
11
- "types": "./dist/index.d.ts",
9
+ "type": "module",
12
10
  "exports": {
13
11
  ".": {
12
+ "types": "./dist/lib.d.ts",
13
+ "default": "./dist/lib.js"
14
+ },
15
+ "./services": {
16
+ "types": "./dist/services.d.ts",
17
+ "default": "./dist/services.js"
18
+ },
19
+ "./cli": {
14
20
  "types": "./dist/index.d.ts",
15
- "import": "./dist/index.js"
21
+ "default": "./dist/index.js"
16
22
  }
17
23
  },
24
+ "bin": {
25
+ "vyft": "./dist/index.js"
26
+ },
18
27
  "files": [
19
28
  "dist",
20
29
  "templates"
21
30
  ],
22
- "keywords": [
23
- "docker",
24
- "swarm",
25
- "deploy",
26
- "infrastructure",
27
- "devops",
28
- "typescript"
29
- ],
30
- "repository": {
31
- "type": "git",
32
- "url": "git+https://github.com/vyftlabs/vyft.git"
33
- },
34
- "bugs": {
35
- "url": "https://github.com/vyftlabs/vyft/issues"
36
- },
37
- "homepage": "https://github.com/vyftlabs/vyft#readme",
38
- "devDependencies": {
39
- "@biomejs/biome": "^2.4.4",
40
- "@types/dockerode": "^4.0.1",
41
- "@types/node": "^25.3.1",
42
- "@types/ssh2": "^1.15.5",
43
- "@types/tar-fs": "^2.0.4",
44
- "tsx": "^4.21.0",
45
- "typescript": "^5.9.3",
46
- "vitest": "^4.0.18"
47
- },
48
31
  "dependencies": {
49
- "@clack/prompts": "^1.0.1",
32
+ "@clack/prompts": "^1.1.0",
50
33
  "commander": "^14.0.3",
51
- "dockerode": "^4.0.9",
52
- "picocolors": "^1.1.1",
53
- "pino": "^10.3.1",
54
- "ssh2": "^1.17.0",
55
- "tar-fs": "^3.1.1"
56
- },
57
- "engines": {
58
- "node": ">=22"
34
+ "jiti": "^2.6.1",
35
+ "@vyft/core": "0.4.2-alpha",
36
+ "@vyft/provider": "0.4.2-alpha",
37
+ "@vyft/docker": "0.4.2-alpha",
38
+ "@vyft/engine": "0.4.2-alpha",
39
+ "@vyft/local": "0.4.2-alpha",
40
+ "@vyft/platform": "0.4.2-alpha",
41
+ "@vyft/runtime": "0.4.2-alpha",
42
+ "@vyft/store": "0.4.2-alpha",
43
+ "@vyft/std": "0.4.2-alpha"
59
44
  },
60
45
  "scripts": {
61
46
  "build": "tsc",
62
- "lint": "biome check src/",
63
- "format:check": "biome format src/",
64
- "test": "vitest run",
65
- "test:watch": "vitest"
47
+ "test": "node --test 'src/**/*.test.ts'",
48
+ "lint": "biome check ."
66
49
  }
67
50
  }
@@ -0,0 +1,8 @@
1
+ const server = Bun.serve({
2
+ port: process.env.PORT ?? 3000,
3
+ fetch() {
4
+ return new Response("Hello from Vyft!");
5
+ },
6
+ });
7
+
8
+ console.log(`Listening on ${server.url}`);
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "my-vyft-app",
3
+ "description": "A Bun app deployed with Vyft",
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "bun run --watch index.ts"
7
+ },
8
+ "dependencies": {
9
+ "vyft": "latest"
10
+ },
11
+ "devDependencies": {
12
+ "@types/bun": "latest",
13
+ "typescript": "^5.9.3"
14
+ }
15
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ESNext"],
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "skipLibCheck": true,
10
+ "isolatedModules": true,
11
+ "resolveJsonModule": true,
12
+ "noUncheckedIndexedAccess": true
13
+ },
14
+ "include": ["**/*.ts"]
15
+ }
@@ -0,0 +1,3 @@
1
+ import { service } from "vyft";
2
+
3
+ export const app = service("app");
package/dist/build.d.ts DELETED
@@ -1,12 +0,0 @@
1
- import type { Logger } from "pino";
2
- export interface BuildResult {
3
- outputPath: string;
4
- }
5
- type BuildOptions = {
6
- output?: string;
7
- command?: string;
8
- env?: Record<string, string>;
9
- silent?: boolean;
10
- };
11
- export declare function buildStatic(context: string, options: BuildOptions, log?: Logger): Promise<BuildResult>;
12
- export {};