@alchemy.run/turso 2.0.0-beta.84 → 2.0.0-beta.85

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 (49) hide show
  1. package/lib/ApiToken.d.ts +9 -0
  2. package/lib/ApiToken.d.ts.map +1 -1
  3. package/lib/ApiToken.js +10 -2
  4. package/lib/ApiToken.js.map +1 -1
  5. package/lib/AuthProvider.d.ts +1 -1
  6. package/lib/AuthProvider.d.ts.map +1 -1
  7. package/lib/AuthProvider.js +1 -1
  8. package/lib/AuthProvider.js.map +1 -1
  9. package/lib/Contributions.d.ts +1 -1
  10. package/lib/Credentials.d.ts +1 -1
  11. package/lib/Credentials.d.ts.map +1 -1
  12. package/lib/Credentials.js +11 -15
  13. package/lib/Credentials.js.map +1 -1
  14. package/lib/Database.d.ts +9 -0
  15. package/lib/Database.d.ts.map +1 -1
  16. package/lib/Database.js +26 -20
  17. package/lib/Database.js.map +1 -1
  18. package/lib/DatabaseToken.d.ts +9 -0
  19. package/lib/DatabaseToken.d.ts.map +1 -1
  20. package/lib/DatabaseToken.js +6 -1
  21. package/lib/DatabaseToken.js.map +1 -1
  22. package/lib/Group.d.ts +9 -0
  23. package/lib/Group.d.ts.map +1 -1
  24. package/lib/Group.js +14 -5
  25. package/lib/Group.js.map +1 -1
  26. package/lib/GroupToken.d.ts +9 -0
  27. package/lib/GroupToken.d.ts.map +1 -1
  28. package/lib/GroupToken.js +6 -1
  29. package/lib/GroupToken.js.map +1 -1
  30. package/lib/Hrana.d.ts.map +1 -1
  31. package/lib/Hrana.js +5 -1
  32. package/lib/Hrana.js.map +1 -1
  33. package/lib/ManageDatabases.js +1 -1
  34. package/lib/ManageDatabases.js.map +1 -1
  35. package/lib/OrganizationMember.js +1 -1
  36. package/lib/OrganizationMember.js.map +1 -1
  37. package/lib/Providers.d.ts +1 -1
  38. package/lib/Providers.d.ts.map +1 -1
  39. package/package.json +8 -8
  40. package/src/ApiToken.ts +12 -2
  41. package/src/AuthProvider.ts +1 -1
  42. package/src/Credentials.ts +22 -49
  43. package/src/Database.ts +38 -23
  44. package/src/DatabaseToken.ts +11 -1
  45. package/src/Group.ts +18 -5
  46. package/src/GroupToken.ts +9 -1
  47. package/src/Hrana.ts +3 -1
  48. package/src/ManageDatabases.ts +1 -1
  49. package/src/OrganizationMember.ts +1 -1
package/src/Group.ts CHANGED
@@ -4,10 +4,16 @@ import { deepEqual, isResolved } from "alchemy/Diff";
4
4
  import { createPhysicalName } from "alchemy/PhysicalName";
5
5
  import * as Provider from "alchemy/Provider";
6
6
  import { Resource } from "alchemy/Resource";
7
+ import * as Data from "effect/Data";
7
8
  import * as Effect from "effect/Effect";
8
9
  import { organization } from "./Credentials.ts";
9
10
  import type { Providers } from "./Providers.ts";
10
11
 
12
+ export class GroupUnexpectedResponse extends Data.TaggedError("GroupUnexpectedResponse")<{
13
+ readonly message: string;
14
+ readonly cause?: unknown;
15
+ }> {}
16
+
11
17
  /**
12
18
  * A Turso location code, e.g. `"aws-us-east-1"`. List the locations
13
19
  * available to your organization with `turso db locations`.
@@ -125,7 +131,7 @@ export const GroupProvider = () =>
125
131
  const observe = (org: string, name: string) =>
126
132
  turso.getGroup({ organizationSlug: org, groupName: name }).pipe(
127
133
  Effect.map((res) => res.group),
128
- Effect.catchTag("NotFound", () => Effect.succeed(undefined)),
134
+ Effect.catchTag("NotFound", () => Effect.undefined),
129
135
  );
130
136
 
131
137
  const toAttrs = (
@@ -157,15 +163,20 @@ export const GroupProvider = () =>
157
163
  return { action: "replace", deleteFirst: news.name !== undefined } as const;
158
164
  }
159
165
  }),
160
- read: Effect.fn(function* ({ id, olds, output }) {
166
+ read: Effect.fn(function* ({ id, olds, output, previous }) {
161
167
  const org = output?.organization ?? (yield* organization);
162
168
  const name = output?.name ?? (yield* groupName(id, olds?.name));
163
169
  const group = yield* observe(org, name);
164
170
  if (!group) return undefined;
165
171
  const attrs = toAttrs(org, group, group.delete_protection ?? false);
166
172
  // Turso has no tags: a group found under an explicit, user-chosen
167
- // name without prior state may belong to someone else.
168
- return output === undefined && olds?.name !== undefined ? Unowned(attrs) : attrs;
173
+ // name without prior state may belong to someone else — unless it
174
+ // is the generation a delete-first replacement is about to free.
175
+ const ours =
176
+ output !== undefined ||
177
+ olds?.name === undefined ||
178
+ (previous?.organization === org && previous.name === name);
179
+ return ours ? attrs : Unowned(attrs);
169
180
  }),
170
181
  reconcile: Effect.fn(function* ({ id, news, output, session }) {
171
182
  const org = output?.organization ?? (yield* organization);
@@ -190,7 +201,9 @@ export const GroupProvider = () =>
190
201
  Effect.catchTag("Conflict", () => observe(org, name)),
191
202
  );
192
203
  if (!group) {
193
- return yield* Effect.fail(new Error(`Turso group ${name} vanished after create`));
204
+ return yield* new GroupUnexpectedResponse({
205
+ message: `Turso group ${name} vanished after create`,
206
+ });
194
207
  }
195
208
  }
196
209
 
package/src/GroupToken.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as turso from "@distilled.cloud/turso/turso";
2
2
  import * as Provider from "alchemy/Provider";
3
3
  import { Resource } from "alchemy/Resource";
4
+ import * as Data from "effect/Data";
4
5
  import * as Effect from "effect/Effect";
5
6
  import { organization } from "./Credentials.ts";
6
7
  import {
@@ -12,6 +13,11 @@ import {
12
13
  } from "./DatabaseToken.ts";
13
14
  import type { Providers } from "./Providers.ts";
14
15
 
16
+ export class GroupTokenUnexpectedResponse extends Data.TaggedError("GroupTokenUnexpectedResponse")<{
17
+ readonly message: string;
18
+ readonly cause?: unknown;
19
+ }> {}
20
+
15
21
  export interface GroupTokenProps extends SqlTokenProps {
16
22
  /** Name of the group whose databases the token grants access to. */
17
23
  group: string;
@@ -101,7 +107,9 @@ export const GroupTokenProvider = () =>
101
107
  : undefined,
102
108
  });
103
109
  if (!jwt) {
104
- return yield* Effect.fail(new Error(`Turso returned no token for group ${news.group}`));
110
+ return yield* new GroupTokenUnexpectedResponse({
111
+ message: `Turso returned no token for group ${news.group}`,
112
+ });
105
113
  }
106
114
  return {
107
115
  token: jwt,
package/src/Hrana.ts CHANGED
@@ -61,7 +61,9 @@ const toHranaValue = (value: unknown): HranaValue => {
61
61
  if (value instanceof Uint8Array) {
62
62
  return { type: "blob", base64: Buffer.from(value).toString("base64") };
63
63
  }
64
- return { type: "text", value: String(value) };
64
+ if (typeof value === "string") return { type: "text", value };
65
+ if (value instanceof Date) return { type: "text", value: value.toISOString() };
66
+ return { type: "text", value: JSON.stringify(value) };
65
67
  };
66
68
 
67
69
  const fromHranaValue = (value: HranaValue): unknown => {
@@ -159,7 +159,7 @@ export const ManageDatabasesHttp = Layer.effect(
159
159
  return database && database.group === (yield* groupName)
160
160
  ? toManaged(database)
161
161
  : undefined;
162
- }).pipe(Effect.catchTag("NotFound", () => Effect.succeed(undefined))),
162
+ }).pipe(Effect.catchTag("NotFound", () => Effect.undefined)),
163
163
  ),
164
164
  list: () =>
165
165
  authorize(
@@ -64,7 +64,7 @@ export const OrganizationMemberProvider = () =>
64
64
  const observe = (org: string, username: string) =>
65
65
  turso.getOrganizationMember({ organizationSlug: org, username }).pipe(
66
66
  Effect.map(({ member }) => member),
67
- Effect.catchTag("NotFound", () => Effect.succeed(undefined)),
67
+ Effect.catchTag("NotFound", () => Effect.undefined),
68
68
  );
69
69
 
70
70
  return {