@gaganref/confect-alchemy 0.0.0-stage → 10.3.1-fork.2

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 (113) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +22 -2
  3. package/dist/Backend.d.ts +45 -0
  4. package/dist/Backend.d.ts.map +1 -0
  5. package/dist/Backend.js +38 -0
  6. package/dist/Backend.js.map +1 -0
  7. package/dist/Code.d.ts +80 -0
  8. package/dist/Code.d.ts.map +1 -0
  9. package/dist/Code.js +29 -0
  10. package/dist/Code.js.map +1 -0
  11. package/dist/Confect.d.ts +2 -0
  12. package/dist/Confect.d.ts.map +1 -0
  13. package/dist/Confect.js +8 -0
  14. package/dist/Confect.js.map +1 -0
  15. package/dist/Convex.d.ts +7 -0
  16. package/dist/Convex.d.ts.map +1 -0
  17. package/dist/Convex.js +21 -0
  18. package/dist/Convex.js.map +1 -0
  19. package/dist/ConvexClient.d.ts +215 -0
  20. package/dist/ConvexClient.d.ts.map +1 -0
  21. package/dist/ConvexClient.js +224 -0
  22. package/dist/ConvexClient.js.map +1 -0
  23. package/dist/DeployKey.d.ts +120 -0
  24. package/dist/DeployKey.d.ts.map +1 -0
  25. package/dist/DeployKey.js +151 -0
  26. package/dist/DeployKey.js.map +1 -0
  27. package/dist/Deployment.d.ts +113 -0
  28. package/dist/Deployment.d.ts.map +1 -0
  29. package/dist/Deployment.js +160 -0
  30. package/dist/Deployment.js.map +1 -0
  31. package/dist/EnvironmentVariables.d.ts +155 -0
  32. package/dist/EnvironmentVariables.d.ts.map +1 -0
  33. package/dist/EnvironmentVariables.js +135 -0
  34. package/dist/EnvironmentVariables.js.map +1 -0
  35. package/dist/Project.d.ts +100 -0
  36. package/dist/Project.d.ts.map +1 -0
  37. package/dist/Project.js +123 -0
  38. package/dist/Project.js.map +1 -0
  39. package/dist/Providers.d.ts +17 -0
  40. package/dist/Providers.d.ts.map +1 -0
  41. package/dist/Providers.js +46 -0
  42. package/dist/Providers.js.map +1 -0
  43. package/dist/_virtual/_rolldown/runtime.js +13 -0
  44. package/dist/index.d.ts +3 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +3 -0
  47. package/dist/internal/CodeDeployment.d.ts +17 -0
  48. package/dist/internal/CodeDeployment.d.ts.map +1 -0
  49. package/dist/internal/CodeDeployment.js +53 -0
  50. package/dist/internal/CodeDeployment.js.map +1 -0
  51. package/dist/internal/CommandRunner.d.ts +55 -0
  52. package/dist/internal/CommandRunner.d.ts.map +1 -0
  53. package/dist/internal/CommandRunner.js +126 -0
  54. package/dist/internal/CommandRunner.js.map +1 -0
  55. package/dist/internal/FileLock.d.ts +30 -0
  56. package/dist/internal/FileLock.d.ts.map +1 -0
  57. package/dist/internal/FileLock.js +83 -0
  58. package/dist/internal/FileLock.js.map +1 -0
  59. package/dist/internal/Lifecycle.d.ts +11 -0
  60. package/dist/internal/Lifecycle.d.ts.map +1 -0
  61. package/dist/internal/Lifecycle.js +45 -0
  62. package/dist/internal/Lifecycle.js.map +1 -0
  63. package/dist/internal/LocalBackend.d.ts +63 -0
  64. package/dist/internal/LocalBackend.d.ts.map +1 -0
  65. package/dist/internal/LocalBackend.js +333 -0
  66. package/dist/internal/LocalBackend.js.map +1 -0
  67. package/dist/internal/LocalSidecar.d.ts +3 -0
  68. package/dist/internal/LocalSidecar.d.ts.map +1 -0
  69. package/dist/internal/LocalSidecar.js +7 -0
  70. package/dist/internal/LocalSidecar.js.map +1 -0
  71. package/dist/internal/Loopback.d.ts +18 -0
  72. package/dist/internal/Loopback.d.ts.map +1 -0
  73. package/dist/internal/Loopback.js +31 -0
  74. package/dist/internal/Loopback.js.map +1 -0
  75. package/dist/internal/PushLock.d.ts +36 -0
  76. package/dist/internal/PushLock.d.ts.map +1 -0
  77. package/dist/internal/PushLock.js +61 -0
  78. package/dist/internal/PushLock.js.map +1 -0
  79. package/dist/internal/ResourceIdentity.d.ts +3 -0
  80. package/dist/internal/ResourceIdentity.d.ts.map +1 -0
  81. package/dist/internal/ResourceIdentity.js +10 -0
  82. package/dist/internal/ResourceIdentity.js.map +1 -0
  83. package/dist/internal/UserCache.d.ts +12 -0
  84. package/dist/internal/UserCache.d.ts.map +1 -0
  85. package/dist/internal/UserCache.js +25 -0
  86. package/dist/internal/UserCache.js.map +1 -0
  87. package/dist/internal/Zip.d.ts +15 -0
  88. package/dist/internal/Zip.d.ts.map +1 -0
  89. package/dist/internal/Zip.js +65 -0
  90. package/dist/internal/Zip.js.map +1 -0
  91. package/package.json +65 -3
  92. package/src/Backend.ts +101 -0
  93. package/src/Code.ts +55 -0
  94. package/src/Confect.ts +1 -0
  95. package/src/Convex.ts +18 -0
  96. package/src/ConvexClient.ts +544 -0
  97. package/src/DeployKey.ts +256 -0
  98. package/src/Deployment.ts +277 -0
  99. package/src/EnvironmentVariables.ts +254 -0
  100. package/src/Project.ts +205 -0
  101. package/src/Providers.ts +67 -0
  102. package/src/index.ts +2 -0
  103. package/src/internal/CodeDeployment.ts +81 -0
  104. package/src/internal/CommandRunner.ts +251 -0
  105. package/src/internal/FileLock.ts +136 -0
  106. package/src/internal/Lifecycle.ts +49 -0
  107. package/src/internal/LocalBackend.ts +492 -0
  108. package/src/internal/LocalSidecar.ts +9 -0
  109. package/src/internal/Loopback.ts +34 -0
  110. package/src/internal/PushLock.ts +99 -0
  111. package/src/internal/ResourceIdentity.ts +20 -0
  112. package/src/internal/UserCache.ts +25 -0
  113. package/src/internal/Zip.ts +108 -0
@@ -0,0 +1,100 @@
1
+ import { OwnedBySomeoneElse } from "alchemy/AdoptPolicy";
2
+ import * as Provider from "alchemy/Provider";
3
+ import { Resource } from "alchemy/Resource";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Schema from "effect/Schema";
6
+ import { ConvexClient } from "./ConvexClient";
7
+ import type { Providers } from "./Providers";
8
+ export interface ProjectProps {
9
+ readonly teamId: number;
10
+ readonly name?: string;
11
+ }
12
+ export interface ProjectAttributes {
13
+ readonly projectId: number;
14
+ readonly teamId: number;
15
+ readonly name: string;
16
+ readonly slug: string;
17
+ }
18
+ export type Project = Resource<"Convex.Project", ProjectProps, ProjectAttributes, never, Providers>;
19
+ export declare const Project: import("alchemy/Resource").ResourceClass<Project>;
20
+ declare const ProjectTeamChange_base: Schema.Class<ProjectTeamChange, Schema.TaggedStruct<"ProjectTeamChange", {
21
+ readonly projectId: Schema.Finite;
22
+ readonly teamId: Schema.Finite;
23
+ readonly requestedTeamId: Schema.Finite;
24
+ }>, import("effect/Cause").YieldableError>;
25
+ export declare class ProjectTeamChange extends ProjectTeamChange_base {
26
+ }
27
+ declare const AmbiguousProject_base: Schema.Class<AmbiguousProject, Schema.TaggedStruct<"AmbiguousProject", {
28
+ readonly teamId: Schema.Finite;
29
+ readonly name: Schema.String;
30
+ readonly projectIds: Schema.$Array<Schema.Finite>;
31
+ }>, import("effect/Cause").YieldableError>;
32
+ export declare class AmbiguousProject extends AmbiguousProject_base {
33
+ }
34
+ export declare const provider: Effect.Effect<{
35
+ diff: (args_0: {
36
+ id: string;
37
+ fqn: string;
38
+ instanceId: string;
39
+ olds: ProjectProps;
40
+ news: import("alchemy/Input").Input<ProjectProps>;
41
+ oldBindings: import("alchemy/Resource").ResourceBinding<never>[];
42
+ newBindings: import("alchemy/Input").Input<import("alchemy/Resource").ResourceBinding<never>[]>;
43
+ output: ProjectAttributes | undefined;
44
+ }) => Effect.Effect<{
45
+ action: "update";
46
+ } | undefined, import("./ConvexClient").ConvexApiError | import("./ConvexClient").ConvexConflict | ProjectTeamChange, never>;
47
+ read: (args_0: {
48
+ id: string;
49
+ fqn: string;
50
+ instanceId: string;
51
+ olds: ProjectProps;
52
+ output: ProjectAttributes | undefined;
53
+ }) => Effect.Effect<ProjectAttributes | undefined, AmbiguousProject | import("./ConvexClient").ConvexApiError | import("./ConvexClient").ConvexConflict | import("./ConvexClient").ConvexNotFound, never>;
54
+ reconcile: (args_0: {
55
+ id: string;
56
+ fqn: string;
57
+ instanceId: string;
58
+ news: ProjectProps;
59
+ olds: ProjectProps | undefined;
60
+ output: ProjectAttributes | undefined;
61
+ session: import("alchemy/Report").ScopedPlanStatusSession;
62
+ bindings: import("alchemy/Resource").ResourceBinding<never>[];
63
+ }) => Effect.Effect<ProjectAttributes, AmbiguousProject | import("./ConvexClient").ConvexApiError | import("./ConvexClient").ConvexConflict | import("./ConvexClient").ConvexNotFound | import("./internal/Lifecycle").LifecycleStateError | OwnedBySomeoneElse | ProjectTeamChange | import("alchemy/State/State").StateStoreError, never>;
64
+ delete: (args_0: {
65
+ id: string;
66
+ fqn: string;
67
+ instanceId: string;
68
+ olds: ProjectProps;
69
+ output: ProjectAttributes;
70
+ session: import("alchemy/Report").ScopedPlanStatusSession;
71
+ bindings: import("alchemy/Resource").ResourceBinding<never>[];
72
+ force?: boolean;
73
+ }) => Effect.Effect<void, import("./ConvexClient").ConvexApiError | import("./ConvexClient").ConvexConflict, never>;
74
+ }, never, ConvexClient>;
75
+ /**
76
+ * Under `alchemy dev` a project needs no Convex account: it is a fixed local
77
+ * identity that local deployments ignore.
78
+ */
79
+ export declare const localProvider: Effect.Effect<{
80
+ reconcile: (args_0: {
81
+ id: string;
82
+ fqn: string;
83
+ instanceId: string;
84
+ news: ProjectProps;
85
+ olds: ProjectProps | undefined;
86
+ output: ProjectAttributes | undefined;
87
+ session: import("alchemy/Report").ScopedPlanStatusSession;
88
+ bindings: import("alchemy/Resource").ResourceBinding<never>[];
89
+ }) => Effect.Effect<{
90
+ projectId: number;
91
+ teamId: number;
92
+ name: string;
93
+ slug: string;
94
+ }, never, never>;
95
+ delete: () => Effect.Effect<void, never, never>;
96
+ }, never, never>;
97
+ export declare const layer: import("effect/Layer").Layer<Provider.Provider<Project>, never, ConvexClient>;
98
+ export declare const localLayer: import("effect/Layer").Layer<Provider.Provider<Project>, never, never>;
99
+ export {};
100
+ //# sourceMappingURL=Project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Project.d.ts","sourceRoot":"","sources":["../src/Project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAW,MAAM,qBAAqB,CAAC;AAElE,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAI7C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,OAAO,GAAG,QAAQ,CAC5B,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,KAAK,EACL,SAAS,CACV,CAAC;AACF,eAAO,MAAM,OAAO,mDAElB,CAAC;;;;;;AAEH,qBAAa,iBAAkB,SAAQ,sBAOtC;CAAG;;;;;;AAEJ,qBAAa,gBAAiB,SAAQ,qBAOrC;CAAG;AAEJ,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBA+HnB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;gBAeyB,CAAC;AAEpD,eAAO,MAAM,KAAK,+EAAqC,CAAC;AACxD,eAAO,MAAM,UAAU,wEAA0C,CAAC"}
@@ -0,0 +1,123 @@
1
+ import { ConvexClient } from "./ConvexClient.js";
2
+ import { checkpointCreate, shouldAdopt } from "./internal/Lifecycle.js";
3
+ import { resourceName } from "./internal/ResourceIdentity.js";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Provider from "alchemy/Provider";
6
+ import { Resource } from "alchemy/Resource";
7
+ import * as Schema from "effect/Schema";
8
+ import { OwnedBySomeoneElse, Unowned } from "alchemy/AdoptPolicy";
9
+ import { isResolved } from "alchemy/Diff";
10
+ //#region src/Project.ts
11
+ const Project = Resource("Convex.Project", { defaultRemovalPolicy: "retain" });
12
+ var ProjectTeamChange = class extends Schema.TaggedError()("ProjectTeamChange", {
13
+ projectId: Schema.Finite,
14
+ teamId: Schema.Finite,
15
+ requestedTeamId: Schema.Finite
16
+ }) {};
17
+ var AmbiguousProject = class extends Schema.TaggedError()("AmbiguousProject", {
18
+ teamId: Schema.Finite,
19
+ name: Schema.String,
20
+ projectIds: Schema.Array(Schema.Finite)
21
+ }) {};
22
+ const provider = Effect.gen(function* () {
23
+ const client = yield* ConvexClient;
24
+ const attributes = (project) => ({
25
+ projectId: project.id,
26
+ teamId: project.teamId,
27
+ name: project.name,
28
+ slug: project.slug
29
+ });
30
+ const find = Effect.fn("Project.find")(function* (teamId, name) {
31
+ const matches = (yield* client.listProjects(teamId)).filter((project) => project.name === name);
32
+ if (matches.length > 1) return yield* new AmbiguousProject({
33
+ teamId,
34
+ name,
35
+ projectIds: matches.map((project) => project.id)
36
+ });
37
+ return matches[0];
38
+ });
39
+ return {
40
+ diff: Effect.fn("Project.diff")(function* ({ news, output }) {
41
+ if (!isResolved(news) || !output) return;
42
+ if (output.teamId !== news.teamId) return yield* new ProjectTeamChange({
43
+ projectId: output.projectId,
44
+ teamId: output.teamId,
45
+ requestedTeamId: news.teamId
46
+ });
47
+ const project = yield* client.getProject(output.projectId).pipe(Effect.catchTag("ConvexNotFound", () => Effect.void));
48
+ if (!project) return { action: "update" };
49
+ if (project.teamId !== news.teamId) return yield* new ProjectTeamChange({
50
+ projectId: project.id,
51
+ teamId: project.teamId,
52
+ requestedTeamId: news.teamId
53
+ });
54
+ if ((news.name ?? output.name) !== project.name) return { action: "update" };
55
+ }),
56
+ read: Effect.fn("Project.read")(function* ({ fqn, instanceId, olds, output }) {
57
+ if (output) {
58
+ const project = yield* client.getProject(output.projectId).pipe(Effect.catchTag("ConvexNotFound", () => Effect.void));
59
+ return project ? attributes(project) : void 0;
60
+ }
61
+ if (olds.teamId === void 0) return;
62
+ const project = yield* find(olds.teamId, olds.name ?? (yield* resourceName("project", fqn, instanceId)));
63
+ return project ? Unowned(attributes(project)) : void 0;
64
+ }),
65
+ reconcile: Effect.fn("Project.reconcile")(function* ({ fqn, instanceId, news, output }) {
66
+ if (!output) yield* checkpointCreate(fqn, instanceId, news);
67
+ if (output && output.teamId !== news.teamId) return yield* new ProjectTeamChange({
68
+ projectId: output.projectId,
69
+ teamId: output.teamId,
70
+ requestedTeamId: news.teamId
71
+ });
72
+ let project = output ? yield* client.getProject(output.projectId).pipe(Effect.catchTag("ConvexNotFound", () => Effect.void)) : void 0;
73
+ const name = news.name ?? output?.name ?? (yield* resourceName("project", fqn, instanceId));
74
+ if (!project) {
75
+ const existing = yield* find(news.teamId, name);
76
+ if (existing && !(yield* shouldAdopt(fqn))) return yield* new OwnedBySomeoneElse({
77
+ message: "An existing project requires explicit adoption.",
78
+ resourceType: Project.Type,
79
+ physicalName: name
80
+ });
81
+ if (existing) {
82
+ project = existing;
83
+ yield* checkpointCreate(fqn, instanceId, news, attributes(existing));
84
+ } else {
85
+ const created = yield* client.createProject(news.teamId, { projectName: name });
86
+ project = yield* client.getProject(created.id);
87
+ }
88
+ }
89
+ if (project.teamId !== news.teamId) return yield* new ProjectTeamChange({
90
+ projectId: project.id,
91
+ teamId: project.teamId,
92
+ requestedTeamId: news.teamId
93
+ });
94
+ if (project.name !== name) project = yield* client.updateProject(project.id, { name });
95
+ return attributes(project);
96
+ }),
97
+ delete: Effect.fn("Project.delete")(function* ({ output }) {
98
+ yield* client.deleteProject(output.projectId).pipe(Effect.catchTag("ConvexNotFound", () => Effect.void));
99
+ })
100
+ };
101
+ });
102
+ /**
103
+ * Under `alchemy dev` a project needs no Convex account: it is a fixed local
104
+ * identity that local deployments ignore.
105
+ */
106
+ const localProvider = Effect.succeed({
107
+ reconcile: Effect.fn("Project.localReconcile")(function* ({ fqn, instanceId, news }) {
108
+ const name = news.name ?? (yield* resourceName("project", fqn, instanceId));
109
+ return {
110
+ projectId: 0,
111
+ teamId: news.teamId,
112
+ name,
113
+ slug: name
114
+ };
115
+ }),
116
+ delete: () => Effect.void
117
+ });
118
+ const layer = Provider.effect(Project, provider);
119
+ const localLayer = Provider.effect(Project, localProvider);
120
+ //#endregion
121
+ export { AmbiguousProject, Project, ProjectTeamChange, layer, localLayer, localProvider, provider };
122
+
123
+ //# sourceMappingURL=Project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Project.js","names":[],"sources":["../src/Project.ts"],"sourcesContent":["import { OwnedBySomeoneElse, Unowned } from \"alchemy/AdoptPolicy\";\nimport { isResolved } from \"alchemy/Diff\";\nimport * as Provider from \"alchemy/Provider\";\nimport { Resource } from \"alchemy/Resource\";\nimport * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\n\nimport { ConvexClient } from \"./ConvexClient\";\nimport type { Providers } from \"./Providers\";\nimport { resourceName } from \"./internal/ResourceIdentity\";\nimport { checkpointCreate, shouldAdopt } from \"./internal/Lifecycle\";\n\nexport interface ProjectProps {\n readonly teamId: number;\n readonly name?: string;\n}\n\nexport interface ProjectAttributes {\n readonly projectId: number;\n readonly teamId: number;\n readonly name: string;\n readonly slug: string;\n}\n\nexport type Project = Resource<\n \"Convex.Project\",\n ProjectProps,\n ProjectAttributes,\n never,\n Providers\n>;\nexport const Project = Resource<Project>(\"Convex.Project\", {\n defaultRemovalPolicy: \"retain\",\n});\n\nexport class ProjectTeamChange extends Schema.TaggedError<ProjectTeamChange>()(\n \"ProjectTeamChange\",\n {\n projectId: Schema.Finite,\n teamId: Schema.Finite,\n requestedTeamId: Schema.Finite,\n },\n) {}\n\nexport class AmbiguousProject extends Schema.TaggedError<AmbiguousProject>()(\n \"AmbiguousProject\",\n {\n teamId: Schema.Finite,\n name: Schema.String,\n projectIds: Schema.Array(Schema.Finite),\n },\n) {}\n\nexport const provider = Effect.gen(function* () {\n const client = yield* ConvexClient;\n const attributes = (project: {\n id: number;\n teamId: number;\n name: string;\n slug: string;\n }): ProjectAttributes => ({\n projectId: project.id,\n teamId: project.teamId,\n name: project.name,\n slug: project.slug,\n });\n const find = Effect.fn(\"Project.find\")(function* (\n teamId: number,\n name: string,\n ) {\n const matches = (yield* client.listProjects(teamId)).filter(\n (project) => project.name === name,\n );\n if (matches.length > 1)\n return yield* new AmbiguousProject({\n teamId,\n name,\n projectIds: matches.map((project) => project.id),\n });\n return matches[0];\n });\n return {\n diff: Effect.fn(\"Project.diff\")(function* ({ news, output }) {\n if (!isResolved(news) || !output) return;\n if (output.teamId !== news.teamId)\n return yield* new ProjectTeamChange({\n projectId: output.projectId,\n teamId: output.teamId,\n requestedTeamId: news.teamId,\n });\n const project = yield* client\n .getProject(output.projectId)\n .pipe(Effect.catchTag(\"ConvexNotFound\", () => Effect.void));\n if (!project) return { action: \"update\" };\n if (project.teamId !== news.teamId)\n return yield* new ProjectTeamChange({\n projectId: project.id,\n teamId: project.teamId,\n requestedTeamId: news.teamId,\n });\n if ((news.name ?? output.name) !== project.name)\n return { action: \"update\" };\n }),\n read: Effect.fn(\"Project.read\")(function* ({\n fqn,\n instanceId,\n olds,\n output,\n }) {\n if (output) {\n const project = yield* client\n .getProject(output.projectId)\n .pipe(Effect.catchTag(\"ConvexNotFound\", () => Effect.void));\n return project ? attributes(project) : undefined;\n }\n if (olds.teamId === undefined) return;\n const project = yield* find(\n olds.teamId,\n olds.name ?? (yield* resourceName(\"project\", fqn, instanceId)),\n );\n return project ? Unowned(attributes(project)) : undefined;\n }),\n reconcile: Effect.fn(\"Project.reconcile\")(function* ({\n fqn,\n instanceId,\n news,\n output,\n }) {\n if (!output) yield* checkpointCreate(fqn, instanceId, news);\n if (output && output.teamId !== news.teamId)\n return yield* new ProjectTeamChange({\n projectId: output.projectId,\n teamId: output.teamId,\n requestedTeamId: news.teamId,\n });\n let project = output\n ? yield* client\n .getProject(output.projectId)\n .pipe(Effect.catchTag(\"ConvexNotFound\", () => Effect.void))\n : undefined;\n const name =\n news.name ??\n output?.name ??\n (yield* resourceName(\"project\", fqn, instanceId));\n if (!project) {\n const existing = yield* find(news.teamId, name);\n if (existing && !(yield* shouldAdopt(fqn)))\n return yield* new OwnedBySomeoneElse({\n message: \"An existing project requires explicit adoption.\",\n resourceType: Project.Type,\n physicalName: name,\n });\n if (existing) {\n project = existing;\n yield* checkpointCreate(fqn, instanceId, news, attributes(existing));\n } else {\n const created = yield* client.createProject(news.teamId, {\n projectName: name,\n });\n project = yield* client.getProject(created.id);\n }\n }\n if (project.teamId !== news.teamId)\n return yield* new ProjectTeamChange({\n projectId: project.id,\n teamId: project.teamId,\n requestedTeamId: news.teamId,\n });\n if (project.name !== name)\n project = yield* client.updateProject(project.id, {\n name,\n });\n return attributes(project);\n }),\n delete: Effect.fn(\"Project.delete\")(function* ({ output }) {\n yield* client\n .deleteProject(output.projectId)\n .pipe(Effect.catchTag(\"ConvexNotFound\", () => Effect.void));\n }),\n } satisfies Provider.ProviderServiceInput<Project>;\n});\n\n/**\n * Under `alchemy dev` a project needs no Convex account: it is a fixed local\n * identity that local deployments ignore.\n */\nexport const localProvider = Effect.succeed({\n reconcile: Effect.fn(\"Project.localReconcile\")(function* ({\n fqn,\n instanceId,\n news,\n }) {\n const name = news.name ?? (yield* resourceName(\"project\", fqn, instanceId));\n return {\n projectId: 0,\n teamId: news.teamId,\n name,\n slug: name,\n } satisfies ProjectAttributes;\n }),\n delete: () => Effect.void,\n} satisfies Provider.ProviderServiceInput<Project>);\n\nexport const layer = Provider.effect(Project, provider);\nexport const localLayer = Provider.effect(Project, localProvider);\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import * as Provider from "alchemy/Provider";
2
+ import type * as Redacted from "effect/Redacted";
3
+ import * as Layer from "effect/Layer";
4
+ declare const Providers_base: Provider.ProviderCollection<Providers, "@confect/alchemy/Providers">;
5
+ export declare class Providers extends Providers_base {
6
+ }
7
+ /**
8
+ * Register Convex resources without eagerly resolving management credentials.
9
+ * `alchemy deploy` resolves each resource to its cloud provider; `alchemy dev`
10
+ * resolves the same resources to local providers backed by a local Convex
11
+ * backend, so one stack definition serves both.
12
+ */
13
+ export declare const providers: (options?: {
14
+ readonly token?: Redacted.Redacted<string>;
15
+ }) => Layer.Layer<Providers, never, import("alchemy/AlchemyContext").AlchemyContext | import("alchemy/Artifacts").ArtifactStore | import("effect/process/ChildProcessSpawner").ChildProcessSpawner | import("effect/Crypto").Crypto | import("effect/FileSystem").FileSystem | import("effect/http/HttpClient").HttpClient | import("effect/Path").Path | import("alchemy/Stack").Stack>;
16
+ export {};
17
+ //# sourceMappingURL=Providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Providers.d.ts","sourceRoot":"","sources":["../src/Providers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;;AAWtC,qBAAa,SAAU,SAAQ,cAE9B;CAAG;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,SAAS,aAAc;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC5C,uXAwCE,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { layer } from "./internal/CommandRunner.js";
2
+ import { layer as layer$1 } from "./internal/PushLock.js";
3
+ import { Code, layer as layer$2, localLayer } from "./Code.js";
4
+ import { layer as layer$3 } from "./ConvexClient.js";
5
+ import { EnvironmentVariables, layer as layer$4, localLayer as localLayer$1 } from "./EnvironmentVariables.js";
6
+ import { Project, layer as layer$5, localLayer as localLayer$2 } from "./Project.js";
7
+ import { Deployment, layer as layer$6, localLayer as localLayer$3 } from "./Deployment.js";
8
+ import { DeployKey, layer as layer$7, localLayer as localLayer$4 } from "./DeployKey.js";
9
+ import * as Provider from "alchemy/Provider";
10
+ import * as Layer from "effect/Layer";
11
+ import * as FetchHttpClient from "effect/http/FetchHttpClient";
12
+ import * as ProviderLayer from "alchemy/Local/ProviderLayer";
13
+ //#region src/Providers.ts
14
+ var Providers = class extends Provider.ProviderCollection()("@confect/alchemy/Providers") {};
15
+ /**
16
+ * Register Convex resources without eagerly resolving management credentials.
17
+ * `alchemy deploy` resolves each resource to its cloud provider; `alchemy dev`
18
+ * resolves the same resources to local providers backed by a local Convex
19
+ * backend, so one stack definition serves both.
20
+ */
21
+ const providers = (options) => Layer.effect(Providers, Provider.collection([
22
+ Project,
23
+ Deployment,
24
+ DeployKey,
25
+ EnvironmentVariables,
26
+ Code
27
+ ])).pipe(Layer.provide(Layer.mergeAll(ProviderLayer.dual(Project, {
28
+ live: () => layer$5,
29
+ local: () => localLayer$2
30
+ }), ProviderLayer.dual(Deployment, {
31
+ live: () => layer$6,
32
+ local: () => localLayer$3
33
+ }), ProviderLayer.dual(DeployKey, {
34
+ live: () => layer$7,
35
+ local: () => localLayer$4
36
+ }), ProviderLayer.dual(EnvironmentVariables, {
37
+ live: () => layer$4,
38
+ local: () => localLayer$1
39
+ }), ProviderLayer.dual(Code, {
40
+ live: () => layer$2,
41
+ local: () => localLayer
42
+ }))), Layer.provide(layer$3(options).pipe(Layer.provide(FetchHttpClient.layer))), Layer.provide(layer), Layer.provide(layer$1()));
43
+ //#endregion
44
+ export { Providers, providers };
45
+
46
+ //# sourceMappingURL=Providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Providers.js","names":["Project.Project","Deployment.Deployment","DeployKey.DeployKey","EnvironmentVariables.EnvironmentVariables","Code.Code","Project.layer","Project.localLayer","Deployment.layer","Deployment.localLayer","DeployKey.layer","DeployKey.localLayer","EnvironmentVariables.layer","EnvironmentVariables.localLayer","Code.layer","Code.localLayer","ConvexClient.layer","CommandRunner.layer","PushLock.layer"],"sources":["../src/Providers.ts"],"sourcesContent":["import * as ProviderLayer from \"alchemy/Local/ProviderLayer\";\nimport * as Provider from \"alchemy/Provider\";\nimport type * as Redacted from \"effect/Redacted\";\nimport * as Layer from \"effect/Layer\";\nimport * as FetchHttpClient from \"effect/http/FetchHttpClient\";\nimport * as Code from \"./Code\";\nimport * as ConvexClient from \"./ConvexClient\";\nimport * as Deployment from \"./Deployment\";\nimport * as DeployKey from \"./DeployKey\";\nimport * as EnvironmentVariables from \"./EnvironmentVariables\";\nimport * as Project from \"./Project\";\nimport * as CommandRunner from \"./internal/CommandRunner\";\nimport * as PushLock from \"./internal/PushLock\";\n\nexport class Providers extends Provider.ProviderCollection<Providers>()(\n \"@confect/alchemy/Providers\",\n) {}\n\n/**\n * Register Convex resources without eagerly resolving management credentials.\n * `alchemy deploy` resolves each resource to its cloud provider; `alchemy dev`\n * resolves the same resources to local providers backed by a local Convex\n * backend, so one stack definition serves both.\n */\nexport const providers = (options?: {\n readonly token?: Redacted.Redacted<string>;\n}) =>\n Layer.effect(\n Providers,\n Provider.collection([\n Project.Project,\n Deployment.Deployment,\n DeployKey.DeployKey,\n EnvironmentVariables.EnvironmentVariables,\n Code.Code,\n ]),\n ).pipe(\n Layer.provide(\n Layer.mergeAll(\n ProviderLayer.dual(Project.Project, {\n live: () => Project.layer,\n local: () => Project.localLayer,\n }),\n ProviderLayer.dual(Deployment.Deployment, {\n live: () => Deployment.layer,\n local: () => Deployment.localLayer,\n }),\n ProviderLayer.dual(DeployKey.DeployKey, {\n live: () => DeployKey.layer,\n local: () => DeployKey.localLayer,\n }),\n ProviderLayer.dual(EnvironmentVariables.EnvironmentVariables, {\n live: () => EnvironmentVariables.layer,\n local: () => EnvironmentVariables.localLayer,\n }),\n ProviderLayer.dual(Code.Code, {\n live: () => Code.layer,\n local: () => Code.localLayer,\n }),\n ),\n ),\n Layer.provide(\n ConvexClient.layer(options).pipe(Layer.provide(FetchHttpClient.layer)),\n ),\n Layer.provide(CommandRunner.layer),\n Layer.provide(PushLock.layer()),\n );\n"],"mappings":";;;;;;;;;;;;;AAcA,IAAa,YAAb,cAA+B,SAAS,mBAA8B,CAAC,CACrE,4BACF,CAAC,CAAC,CAAC;;;;;;;AAQH,MAAa,aAAa,YAGxB,MAAM,OACJ,WACA,SAAS,WAAW;CAClBA;CACAC;CACAC;CACAC;CACAC;AACF,CAAC,CACH,CAAC,CAAC,KACA,MAAM,QACJ,MAAM,SACJ,cAAc,KAAKJ,SAAiB;CAClC,YAAYK;CACZ,aAAaC;AACf,CAAC,GACD,cAAc,KAAKL,YAAuB;CACxC,YAAYM;CACZ,aAAaC;AACf,CAAC,GACD,cAAc,KAAKN,WAAqB;CACtC,YAAYO;CACZ,aAAaC;AACf,CAAC,GACD,cAAc,KAAKP,sBAA2C;CAC5D,YAAYQ;CACZ,aAAaC;AACf,CAAC,GACD,cAAc,KAAKR,MAAW;CAC5B,YAAYS;CACZ,aAAaC;AACf,CAAC,CACH,CACF,GACA,MAAM,QACJC,QAAmB,OAAO,CAAC,CAAC,KAAK,MAAM,QAAQ,gBAAgB,KAAK,CAAC,CACvE,GACA,MAAM,QAAQC,KAAmB,GACjC,MAAM,QAAQC,QAAe,CAAC,CAChC"}
@@ -0,0 +1,13 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true
8
+ });
9
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
+ return target;
11
+ };
12
+ //#endregion
13
+ export { __exportAll };
@@ -0,0 +1,3 @@
1
+ export * as Convex from "./Convex";
2
+ export * as Confect from "./Confect";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,OAAO,KAAK,OAAO,MAAM,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import { Confect_exports } from "./Confect.js";
2
+ import { Convex_exports } from "./Convex.js";
3
+ export { Confect_exports as Confect, Convex_exports as Convex };
@@ -0,0 +1,17 @@
1
+ import type { ProviderMode } from "alchemy/ProviderMode";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Schema from "effect/Schema";
4
+ import type { CodeProps } from "../Code";
5
+ import { CommandRunner } from "./CommandRunner";
6
+ import { PushLock } from "./PushLock";
7
+ declare const InvalidDeploymentTarget_base: Schema.Class<InvalidDeploymentTarget, Schema.TaggedStruct<"InvalidDeploymentTarget", {
8
+ readonly reason: Schema.Literals<readonly ["deployment", "deployKey"]>;
9
+ }>, import("effect/Cause").YieldableError>;
10
+ export declare class InvalidDeploymentTarget extends InvalidDeploymentTarget_base {
11
+ }
12
+ export declare const deploy: (props: CodeProps, mode?: ProviderMode | undefined) => Effect.Effect<{
13
+ name: string;
14
+ url: string;
15
+ }, import("./CommandRunner").CommandError | InvalidDeploymentTarget | import("./PushLock").PushLockError, CommandRunner | PushLock>;
16
+ export {};
17
+ //# sourceMappingURL=CodeDeployment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeDeployment.d.ts","sourceRoot":"","sources":["../../src/internal/CodeDeployment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAGxC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,aAAa,EAAmB,MAAM,iBAAiB,CAAC;AAEjE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;;;;AAEtC,qBAAa,uBAAwB,SAAQ,4BAG5C;CAAG;AAoDJ,eAAO,MAAM,MAAM;;;mIAejB,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { CommandRunner } from "./CommandRunner.js";
2
+ import { isOrigin } from "./Loopback.js";
3
+ import { PushLock } from "./PushLock.js";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Redacted from "effect/Redacted";
6
+ import * as Result from "effect/Result";
7
+ import * as Schema from "effect/Schema";
8
+ //#region src/internal/CodeDeployment.ts
9
+ var InvalidDeploymentTarget = class extends Schema.TaggedError()("InvalidDeploymentTarget", { reason: Schema.Literals(["deployment", "deployKey"]) }) {};
10
+ const deploymentName = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
11
+ const cloudTarget = (props) => {
12
+ const { name, url } = props.deployment;
13
+ if (!deploymentName.test(name) || !new RegExp(`^https://${name}(?:\\.[a-z]{2}-[a-z]+-[0-9]+)?\\.convex\\.cloud$`).test(url)) return Result.fail(new InvalidDeploymentTarget({ reason: "deployment" }));
14
+ const key = /^(?:dev|prod|preview|custom):([a-z0-9]+(?:-[a-z0-9]+)*)\|[a-zA-Z0-9+/=_-]+$/.exec(Redacted.value(props.deployKey));
15
+ if (!key || key[1] !== name) return Result.fail(new InvalidDeploymentTarget({ reason: "deployKey" }));
16
+ return Result.succeed({
17
+ _tag: "Cloud",
18
+ deploymentName: name,
19
+ deployKey: props.deployKey
20
+ });
21
+ };
22
+ const localTarget = (props) => {
23
+ const { name, url } = props.deployment;
24
+ if (!deploymentName.test(name) || !isOrigin(url)) return Result.fail(new InvalidDeploymentTarget({ reason: "deployment" }));
25
+ const key = /^([a-z0-9]+(?:-[a-z0-9]+)*)\|[0-9a-f]+$/.exec(Redacted.value(props.deployKey));
26
+ if (!key || key[1] !== name) return Result.fail(new InvalidDeploymentTarget({ reason: "deployKey" }));
27
+ return Result.succeed({
28
+ _tag: "SelfHosted",
29
+ deploymentName: name,
30
+ url,
31
+ adminKey: props.deployKey
32
+ });
33
+ };
34
+ const targets = {
35
+ live: cloudTarget,
36
+ local: localTarget
37
+ };
38
+ const deploy = Effect.fn("Code.deploy")(function* (props, mode = "live") {
39
+ const target = yield* Effect.fromResult(targets[mode](props));
40
+ const runner = yield* CommandRunner;
41
+ yield* (yield* PushLock).withLock(target.deploymentName, Effect.gen(function* () {
42
+ if (props.prepare) yield* runner.prepare(props.prepare, props.cwd);
43
+ yield* runner.deploy(target, props.cwd);
44
+ }));
45
+ return {
46
+ name: props.deployment.name,
47
+ url: props.deployment.url
48
+ };
49
+ });
50
+ //#endregion
51
+ export { InvalidDeploymentTarget, deploy };
52
+
53
+ //# sourceMappingURL=CodeDeployment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeDeployment.js","names":["Loopback.isOrigin"],"sources":["../../src/internal/CodeDeployment.ts"],"sourcesContent":["import type { ProviderMode } from \"alchemy/ProviderMode\";\nimport * as Effect from \"effect/Effect\";\nimport * as Redacted from \"effect/Redacted\";\nimport * as Result from \"effect/Result\";\nimport * as Schema from \"effect/Schema\";\nimport type { CodeProps } from \"../Code\";\nimport { CommandRunner, type PushTarget } from \"./CommandRunner\";\nimport * as Loopback from \"./Loopback\";\nimport { PushLock } from \"./PushLock\";\n\nexport class InvalidDeploymentTarget extends Schema.TaggedError<InvalidDeploymentTarget>()(\n \"InvalidDeploymentTarget\",\n { reason: Schema.Literals([\"deployment\", \"deployKey\"]) },\n) {}\n\nconst deploymentName = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\nconst cloudTarget = (\n props: CodeProps,\n): Result.Result<PushTarget, InvalidDeploymentTarget> => {\n const { name, url } = props.deployment;\n if (\n !deploymentName.test(name) ||\n !new RegExp(\n `^https://${name}(?:\\\\.[a-z]{2}-[a-z]+-[0-9]+)?\\\\.convex\\\\.cloud$`,\n ).test(url)\n )\n return Result.fail(new InvalidDeploymentTarget({ reason: \"deployment\" }));\n const key =\n /^(?:dev|prod|preview|custom):([a-z0-9]+(?:-[a-z0-9]+)*)\\|[a-zA-Z0-9+/=_-]+$/.exec(\n Redacted.value(props.deployKey),\n );\n if (!key || key[1] !== name)\n return Result.fail(new InvalidDeploymentTarget({ reason: \"deployKey\" }));\n return Result.succeed({\n _tag: \"Cloud\",\n deploymentName: name,\n deployKey: props.deployKey,\n });\n};\n\nconst localTarget = (\n props: CodeProps,\n): Result.Result<PushTarget, InvalidDeploymentTarget> => {\n const { name, url } = props.deployment;\n if (!deploymentName.test(name) || !Loopback.isOrigin(url))\n return Result.fail(new InvalidDeploymentTarget({ reason: \"deployment\" }));\n const key = /^([a-z0-9]+(?:-[a-z0-9]+)*)\\|[0-9a-f]+$/.exec(\n Redacted.value(props.deployKey),\n );\n if (!key || key[1] !== name)\n return Result.fail(new InvalidDeploymentTarget({ reason: \"deployKey\" }));\n return Result.succeed({\n _tag: \"SelfHosted\",\n deploymentName: name,\n url,\n adminKey: props.deployKey,\n });\n};\n\nconst targets = { live: cloudTarget, local: localTarget } satisfies Record<\n ProviderMode,\n (props: CodeProps) => Result.Result<PushTarget, InvalidDeploymentTarget>\n>;\n\nexport const deploy = Effect.fn(\"Code.deploy\")(function* (\n props: CodeProps,\n mode: ProviderMode = \"live\",\n) {\n const target = yield* Effect.fromResult(targets[mode](props));\n const runner = yield* CommandRunner;\n const lock = yield* PushLock;\n yield* lock.withLock(\n target.deploymentName,\n Effect.gen(function* () {\n if (props.prepare) yield* runner.prepare(props.prepare, props.cwd);\n yield* runner.deploy(target, props.cwd);\n }),\n );\n return { name: props.deployment.name, url: props.deployment.url };\n});\n"],"mappings":";;;;;;;;AAUA,IAAa,0BAAb,cAA6C,OAAO,YAAqC,CAAC,CACxF,2BACA,EAAE,QAAQ,OAAO,SAAS,CAAC,cAAc,WAAW,CAAC,EAAE,CACzD,CAAC,CAAC,CAAC;AAEH,MAAM,iBAAiB;AAEvB,MAAM,eACJ,UACuD;CACvD,MAAM,EAAE,MAAM,QAAQ,MAAM;CAC5B,IACE,CAAC,eAAe,KAAK,IAAI,KACzB,CAAC,IAAI,OACH,YAAY,KAAK,iDACnB,CAAC,CAAC,KAAK,GAAG,GAEV,OAAO,OAAO,KAAK,IAAI,wBAAwB,EAAE,QAAQ,aAAa,CAAC,CAAC;CAC1E,MAAM,MACJ,8EAA8E,KAC5E,SAAS,MAAM,MAAM,SAAS,CAChC;CACF,IAAI,CAAC,OAAO,IAAI,OAAO,MACrB,OAAO,OAAO,KAAK,IAAI,wBAAwB,EAAE,QAAQ,YAAY,CAAC,CAAC;CACzE,OAAO,OAAO,QAAQ;EACpB,MAAM;EACN,gBAAgB;EAChB,WAAW,MAAM;CACnB,CAAC;AACH;AAEA,MAAM,eACJ,UACuD;CACvD,MAAM,EAAE,MAAM,QAAQ,MAAM;CAC5B,IAAI,CAAC,eAAe,KAAK,IAAI,KAAK,CAACA,SAAkB,GAAG,GACtD,OAAO,OAAO,KAAK,IAAI,wBAAwB,EAAE,QAAQ,aAAa,CAAC,CAAC;CAC1E,MAAM,MAAM,0CAA0C,KACpD,SAAS,MAAM,MAAM,SAAS,CAChC;CACA,IAAI,CAAC,OAAO,IAAI,OAAO,MACrB,OAAO,OAAO,KAAK,IAAI,wBAAwB,EAAE,QAAQ,YAAY,CAAC,CAAC;CACzE,OAAO,OAAO,QAAQ;EACpB,MAAM;EACN,gBAAgB;EAChB;EACA,UAAU,MAAM;CAClB,CAAC;AACH;AAEA,MAAM,UAAU;CAAE,MAAM;CAAa,OAAO;AAAY;AAKxD,MAAa,SAAS,OAAO,GAAG,aAAa,CAAC,CAAC,WAC7C,OACA,OAAqB,QACrB;CACA,MAAM,SAAS,OAAO,OAAO,WAAW,QAAQ,KAAK,CAAC,KAAK,CAAC;CAC5D,MAAM,SAAS,OAAO;CAEtB,QAAO,OADa,SAAA,CACR,SACV,OAAO,gBACP,OAAO,IAAI,aAAa;EACtB,IAAI,MAAM,SAAS,OAAO,OAAO,QAAQ,MAAM,SAAS,MAAM,GAAG;EACjE,OAAO,OAAO,OAAO,QAAQ,MAAM,GAAG;CACxC,CAAC,CACH;CACA,OAAO;EAAE,MAAM,MAAM,WAAW;EAAM,KAAK,MAAM,WAAW;CAAI;AAClE,CAAC"}
@@ -0,0 +1,55 @@
1
+ import * as Config from "effect/Config";
2
+ import * as Context from "effect/Context";
3
+ import * as Effect from "effect/Effect";
4
+ import * as FileSystem from "effect/FileSystem";
5
+ import * as Layer from "effect/Layer";
6
+ import * as Path from "effect/Path";
7
+ import * as Redacted from "effect/Redacted";
8
+ import * as Schema from "effect/Schema";
9
+ import { ChildProcessSpawner } from "effect/process";
10
+ export interface PrepareCommand {
11
+ readonly command: string;
12
+ readonly args: ReadonlyArray<string>;
13
+ }
14
+ /**
15
+ * Where a push goes: a cloud deployment through its deploy key, or a local
16
+ * backend through the CLI's self-hosted target and its admin key.
17
+ */
18
+ export type PushTarget = {
19
+ readonly _tag: "Cloud";
20
+ readonly deploymentName: string;
21
+ readonly deployKey: Redacted.Redacted<string>;
22
+ } | {
23
+ readonly _tag: "SelfHosted";
24
+ readonly deploymentName: string;
25
+ readonly url: string;
26
+ readonly adminKey: Redacted.Redacted<string>;
27
+ };
28
+ declare const CommandError_base: Schema.Class<CommandError, Schema.TaggedStruct<"CommandError", {
29
+ readonly operation: Schema.Literals<readonly ["prepare", "deploy"]>;
30
+ readonly reason: Schema.Literals<readonly ["configuration", "spawn", "exit"]>;
31
+ readonly exitCode: Schema.optionalKey<Schema.Finite>;
32
+ }>, import("effect/Cause").YieldableError>;
33
+ export declare class CommandError extends CommandError_base {
34
+ }
35
+ declare const CommandRunner_base: Context.ServiceClass<CommandRunner, "@confect/alchemy/internal/CommandRunner", {
36
+ readonly prepare: (command: PrepareCommand, cwd?: string) => Effect.Effect<void, CommandError>;
37
+ readonly deploy: (target: PushTarget, cwd?: string) => Effect.Effect<void, CommandError>;
38
+ }>;
39
+ export declare class CommandRunner extends CommandRunner_base {
40
+ }
41
+ /**
42
+ * The ambient variables a child process needs to run on every platform; the
43
+ * rest of the parent environment, credentials included, is withheld.
44
+ */
45
+ export declare const processEnvironment: Config.Config<{
46
+ PATH: string;
47
+ HOME: string;
48
+ USERPROFILE: string;
49
+ SystemRoot: string;
50
+ TMPDIR: string;
51
+ TEMP: string;
52
+ }>;
53
+ export declare const layer: Layer.Layer<CommandRunner, never, ChildProcessSpawner.ChildProcessSpawner | FileSystem.FileSystem | Path.Path>;
54
+ export {};
55
+ //# sourceMappingURL=CommandRunner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandRunner.d.ts","sourceRoot":"","sources":["../../src/internal/CommandRunner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,IAAI,MAAM,aAAa,CAAC;AACpC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAgB,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAEnE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACtC;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,GAClB;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC/C,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC9C,CAAC;;;;;;AAON,qBAAa,YAAa,SAAQ,iBAOjC;CAAG;;sBAKkB,CAChB,OAAO,EAAE,cAAc,EACvB,GAAG,CAAC,EAAE,MAAM,KACT,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC;qBACrB,CACf,MAAM,EAAE,UAAU,EAClB,GAAG,CAAC,EAAE,MAAM,KACT,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC;;AAV1C,qBAAa,aAAc,SAAQ,kBAYW;CAAG;AAEjD;;;GAGG;AACH,eAAO,MAAM,kBAAkB;;;;;;;EAa7B,CAAC;AAiDH,eAAO,MAAM,KAAK,gHA4HjB,CAAC"}
@@ -0,0 +1,126 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as Redacted from "effect/Redacted";
3
+ import * as Schema from "effect/Schema";
4
+ import * as Config from "effect/Config";
5
+ import * as Context from "effect/Context";
6
+ import * as FileSystem from "effect/FileSystem";
7
+ import * as Layer from "effect/Layer";
8
+ import * as Path from "effect/Path";
9
+ import { ChildProcess, ChildProcessSpawner } from "effect/process";
10
+ //#region src/internal/CommandRunner.ts
11
+ const selection = (target) => target._tag === "Cloud" ? `CONVEX_DEPLOY_KEY=${Redacted.value(target.deployKey)}\n` : `CONVEX_SELF_HOSTED_URL=${target.url}\nCONVEX_SELF_HOSTED_ADMIN_KEY=${Redacted.value(target.adminKey)}\n`;
12
+ var CommandError = class extends Schema.TaggedError()("CommandError", {
13
+ operation: Schema.Literals(["prepare", "deploy"]),
14
+ reason: Schema.Literals([
15
+ "configuration",
16
+ "spawn",
17
+ "exit"
18
+ ]),
19
+ exitCode: Schema.optionalKey(Schema.Finite)
20
+ }) {};
21
+ var CommandRunner = class extends Context.Service()("@confect/alchemy/internal/CommandRunner") {};
22
+ /**
23
+ * The ambient variables a child process needs to run on every platform; the
24
+ * rest of the parent environment, credentials included, is withheld.
25
+ */
26
+ const processEnvironment = Config.all({
27
+ PATH: Config.String("PATH").pipe(Config.orElse(() => Config.String("Path")), Config.withDefault("")),
28
+ HOME: Config.String("HOME").pipe(Config.withDefault("")),
29
+ USERPROFILE: Config.String("USERPROFILE").pipe(Config.withDefault("")),
30
+ SystemRoot: Config.String("SystemRoot").pipe(Config.orElse(() => Config.String("SYSTEMROOT")), Config.withDefault("")),
31
+ TMPDIR: Config.String("TMPDIR").pipe(Config.withDefault("")),
32
+ TEMP: Config.String("TEMP").pipe(Config.withDefault(""))
33
+ });
34
+ const packageBin = Effect.fn("CommandRunner.packageBin")(function* (fs, path, cwd, packageName, binName) {
35
+ const invalid = () => new CommandError({
36
+ operation: packageName === "convex" ? "deploy" : "prepare",
37
+ reason: "configuration"
38
+ });
39
+ let directory = cwd;
40
+ while (true) {
41
+ const manifestPath = path.join(directory, "node_modules", packageName, "package.json");
42
+ if (yield* fs.exists(manifestPath).pipe(Effect.mapError(invalid))) {
43
+ const manifest = yield* fs.readFileString(manifestPath).pipe(Effect.flatMap(Schema.decodeEffect(Schema.fromJsonString(Schema.Struct({ bin: Schema.Union([Schema.String, Schema.Record(Schema.String, Schema.String)]) })))), Effect.mapError(invalid));
44
+ const relative = typeof manifest.bin === "string" ? manifest.bin : manifest.bin[binName];
45
+ if (!relative) return yield* invalid();
46
+ return path.resolve(path.dirname(manifestPath), relative);
47
+ }
48
+ const parent = path.dirname(directory);
49
+ if (parent === directory) return yield* invalid();
50
+ directory = parent;
51
+ }
52
+ });
53
+ const layer = Layer.effect(CommandRunner, Effect.gen(function* () {
54
+ const fs = yield* FileSystem.FileSystem;
55
+ const path = yield* Path.Path;
56
+ const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
57
+ const run = Effect.fn("CommandRunner.run")(function* (operation, command, args, cwd, env) {
58
+ const code = yield* spawner.exitCode(ChildProcess.make(command, args, {
59
+ cwd,
60
+ env,
61
+ extendEnv: false,
62
+ stdin: "ignore",
63
+ stdout: "ignore",
64
+ stderr: "ignore"
65
+ })).pipe(Effect.mapError(() => new CommandError({
66
+ operation,
67
+ reason: "spawn"
68
+ })));
69
+ if (code !== 0) return yield* new CommandError({
70
+ operation,
71
+ reason: "exit",
72
+ exitCode: Number(code)
73
+ });
74
+ });
75
+ const environment = processEnvironment.pipe(Effect.map((env) => ({
76
+ ...env,
77
+ CI: "true",
78
+ DO_NOT_TRACK: "1"
79
+ })));
80
+ return CommandRunner.of({
81
+ prepare: Effect.fn("CommandRunner.prepare")(function* (command, cwd = process.cwd()) {
82
+ const directory = path.resolve(cwd);
83
+ const env = yield* environment.pipe(Effect.mapError(() => new CommandError({
84
+ operation: "prepare",
85
+ reason: "configuration"
86
+ })));
87
+ if (command.command === "confect") {
88
+ const bin = yield* packageBin(fs, path, directory, "@confect/cli", "confect");
89
+ yield* run("prepare", process.execPath, [bin, ...command.args], directory, env);
90
+ } else yield* run("prepare", command.command, command.args, directory, env);
91
+ }),
92
+ deploy: Effect.fn("CommandRunner.deploy")(function* (target, cwd = process.cwd()) {
93
+ const directory = path.resolve(cwd);
94
+ const bin = yield* packageBin(fs, path, directory, "convex", "convex");
95
+ const env = yield* environment.pipe(Effect.mapError(() => new CommandError({
96
+ operation: "deploy",
97
+ reason: "configuration"
98
+ })));
99
+ yield* Effect.scoped(Effect.gen(function* () {
100
+ const temp = yield* fs.makeTempDirectoryScoped({ prefix: "confect-deploy-" });
101
+ const envFile = path.join(temp, "deployment.env");
102
+ yield* fs.writeFileString(envFile, selection(target), { mode: 384 });
103
+ yield* run("deploy", process.execPath, [
104
+ bin,
105
+ "deploy",
106
+ "--yes",
107
+ "--env-file",
108
+ envFile
109
+ ], directory, {
110
+ ...env,
111
+ HOME: temp,
112
+ USERPROFILE: temp,
113
+ LOCALAPPDATA: temp,
114
+ XDG_CONFIG_HOME: temp
115
+ });
116
+ }).pipe(Effect.mapError((error) => Schema.is(CommandError)(error) ? error : new CommandError({
117
+ operation: "deploy",
118
+ reason: "configuration"
119
+ }))));
120
+ })
121
+ });
122
+ }));
123
+ //#endregion
124
+ export { CommandError, CommandRunner, layer, processEnvironment };
125
+
126
+ //# sourceMappingURL=CommandRunner.js.map