@alchemy.run/turso 0.0.0 → 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.
- package/LICENSE +201 -0
- package/README.md +68 -4
- package/lib/ApiToken.d.ts +82 -0
- package/lib/ApiToken.d.ts.map +1 -0
- package/lib/ApiToken.js +128 -0
- package/lib/ApiToken.js.map +1 -0
- package/lib/AuthProvider.d.ts +36 -0
- package/lib/AuthProvider.d.ts.map +1 -0
- package/lib/AuthProvider.js +85 -0
- package/lib/AuthProvider.js.map +1 -0
- package/lib/Connect.d.ts +79 -0
- package/lib/Connect.d.ts.map +1 -0
- package/lib/Connect.js +22 -0
- package/lib/Connect.js.map +1 -0
- package/lib/Contributions.d.ts +7 -0
- package/lib/Contributions.d.ts.map +1 -0
- package/lib/Contributions.js +6 -0
- package/lib/Contributions.js.map +1 -0
- package/lib/Credentials.d.ts +39 -0
- package/lib/Credentials.d.ts.map +1 -0
- package/lib/Credentials.js +76 -0
- package/lib/Credentials.js.map +1 -0
- package/lib/Database.d.ts +226 -0
- package/lib/Database.d.ts.map +1 -0
- package/lib/Database.js +277 -0
- package/lib/Database.js.map +1 -0
- package/lib/DatabaseToken.d.ts +104 -0
- package/lib/DatabaseToken.d.ts.map +1 -0
- package/lib/DatabaseToken.js +133 -0
- package/lib/DatabaseToken.js.map +1 -0
- package/lib/Group.d.ts +102 -0
- package/lib/Group.d.ts.map +1 -0
- package/lib/Group.js +171 -0
- package/lib/Group.js.map +1 -0
- package/lib/GroupToken.d.ts +57 -0
- package/lib/GroupToken.d.ts.map +1 -0
- package/lib/GroupToken.js +88 -0
- package/lib/GroupToken.js.map +1 -0
- package/lib/Hrana.d.ts +42 -0
- package/lib/Hrana.d.ts.map +1 -0
- package/lib/Hrana.js +109 -0
- package/lib/Hrana.js.map +1 -0
- package/lib/ManageDatabases.d.ts +73 -0
- package/lib/ManageDatabases.d.ts.map +1 -0
- package/lib/ManageDatabases.js +81 -0
- package/lib/ManageDatabases.js.map +1 -0
- package/lib/OrganizationInvite.d.ts +46 -0
- package/lib/OrganizationInvite.d.ts.map +1 -0
- package/lib/OrganizationInvite.js +72 -0
- package/lib/OrganizationInvite.js.map +1 -0
- package/lib/OrganizationMember.d.ts +47 -0
- package/lib/OrganizationMember.d.ts.map +1 -0
- package/lib/OrganizationMember.js +81 -0
- package/lib/OrganizationMember.js.map +1 -0
- package/lib/OrganizationSettings.d.ts +52 -0
- package/lib/OrganizationSettings.d.ts.map +1 -0
- package/lib/OrganizationSettings.js +93 -0
- package/lib/OrganizationSettings.js.map +1 -0
- package/lib/Providers.d.ts +24 -0
- package/lib/Providers.d.ts.map +1 -0
- package/lib/Providers.js +42 -0
- package/lib/Providers.js.map +1 -0
- package/lib/index.d.ts +14 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +14 -0
- package/lib/index.js.map +1 -0
- package/package.json +54 -3
- package/src/ApiToken.ts +207 -0
- package/src/AuthProvider.ts +113 -0
- package/src/Connect.ts +103 -0
- package/src/Contributions.ts +9 -0
- package/src/Credentials.ts +112 -0
- package/src/Database.ts +519 -0
- package/src/DatabaseToken.ts +213 -0
- package/src/Group.ts +269 -0
- package/src/GroupToken.ts +127 -0
- package/src/Hrana.ts +184 -0
- package/src/ManageDatabases.ts +195 -0
- package/src/OrganizationInvite.ts +118 -0
- package/src/OrganizationMember.ts +122 -0
- package/src/OrganizationSettings.ts +145 -0
- package/src/Providers.ts +67 -0
- package/src/index.ts +20 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import * as turso from "@distilled.cloud/turso/turso";
|
|
2
|
+
import * as Provider from "alchemy/Provider";
|
|
3
|
+
import { Resource } from "alchemy/Resource";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import * as Schedule from "effect/Schedule";
|
|
6
|
+
import { organization } from "./Credentials.ts";
|
|
7
|
+
import type { Providers } from "./Providers.ts";
|
|
8
|
+
|
|
9
|
+
export interface OrganizationSettingsProps {
|
|
10
|
+
/** Allow usage beyond the plan's quota to be billed as overages. */
|
|
11
|
+
overages?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Require every member to enable multi-factor authentication. The
|
|
14
|
+
* deploying user must have MFA enabled first.
|
|
15
|
+
*/
|
|
16
|
+
requireMfa?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Keep deleted databases and groups recoverable. Requires an admin or
|
|
19
|
+
* owner.
|
|
20
|
+
*/
|
|
21
|
+
restoreEnabled?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface Settings {
|
|
25
|
+
overages: boolean;
|
|
26
|
+
requireMfa: boolean;
|
|
27
|
+
restoreEnabled: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface OrganizationSettingsAttributes extends Settings {
|
|
31
|
+
/** The organization slug. */
|
|
32
|
+
organization: string;
|
|
33
|
+
/** Settings observed before Alchemy first changed them; restored on destroy. */
|
|
34
|
+
original: Settings;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type OrganizationSettings = Resource<
|
|
38
|
+
"Turso.OrganizationSettings",
|
|
39
|
+
OrganizationSettingsProps,
|
|
40
|
+
OrganizationSettingsAttributes,
|
|
41
|
+
never,
|
|
42
|
+
Providers
|
|
43
|
+
>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Settings of the Turso organization your credentials act on. Only the
|
|
47
|
+
* settings you set are managed; destroying the resource restores the values
|
|
48
|
+
* observed before Alchemy first changed them.
|
|
49
|
+
* @see https://docs.turso.tech/api-reference/organizations/update
|
|
50
|
+
*
|
|
51
|
+
* ### Configuring the Organization
|
|
52
|
+
* **Example:** Enable overages and require MFA
|
|
53
|
+
* ```typescript
|
|
54
|
+
* yield* Turso.OrganizationSettings("Org", {
|
|
55
|
+
* overages: true,
|
|
56
|
+
* requireMfa: true,
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @resource
|
|
61
|
+
* @product Organization
|
|
62
|
+
*/
|
|
63
|
+
export const OrganizationSettings = Resource<OrganizationSettings>("Turso.OrganizationSettings");
|
|
64
|
+
|
|
65
|
+
const toSettings = (org: turso.Organization | undefined): Settings => ({
|
|
66
|
+
overages: org?.overages ?? false,
|
|
67
|
+
requireMfa: org?.require_mfa ?? false,
|
|
68
|
+
restoreEnabled: org?.restore_enabled ?? false,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
export const OrganizationSettingsProvider = () =>
|
|
72
|
+
Provider.effect(
|
|
73
|
+
OrganizationSettings,
|
|
74
|
+
Effect.gen(function* () {
|
|
75
|
+
const observe = (slug: string) =>
|
|
76
|
+
turso
|
|
77
|
+
.getOrganization({ organizationSlug: slug })
|
|
78
|
+
.pipe(Effect.map(({ organization }) => toSettings(organization)));
|
|
79
|
+
|
|
80
|
+
// `restore_enabled` must be updated on its own (per the API).
|
|
81
|
+
const apply = (slug: string, observed: Settings, desired: Partial<Settings>) =>
|
|
82
|
+
Effect.gen(function* () {
|
|
83
|
+
const patch: { overages?: boolean; require_mfa?: boolean } = {};
|
|
84
|
+
if (desired.overages !== undefined && desired.overages !== observed.overages) {
|
|
85
|
+
patch.overages = desired.overages;
|
|
86
|
+
}
|
|
87
|
+
if (desired.requireMfa !== undefined && desired.requireMfa !== observed.requireMfa) {
|
|
88
|
+
patch.require_mfa = desired.requireMfa;
|
|
89
|
+
}
|
|
90
|
+
if (Object.keys(patch).length > 0) {
|
|
91
|
+
yield* turso.updateOrganization({ organizationSlug: slug, ...patch });
|
|
92
|
+
}
|
|
93
|
+
if (
|
|
94
|
+
desired.restoreEnabled !== undefined &&
|
|
95
|
+
desired.restoreEnabled !== observed.restoreEnabled
|
|
96
|
+
) {
|
|
97
|
+
yield* turso.updateOrganization({
|
|
98
|
+
organizationSlug: slug,
|
|
99
|
+
restore_enabled: desired.restoreEnabled,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
stables: ["organization", "original"],
|
|
106
|
+
read: Effect.fn(function* ({ output }) {
|
|
107
|
+
if (!output) return undefined;
|
|
108
|
+
return { ...output, ...(yield* observe(output.organization)) };
|
|
109
|
+
}),
|
|
110
|
+
reconcile: Effect.fn(function* ({ news, output }) {
|
|
111
|
+
const slug = output?.organization ?? (yield* organization);
|
|
112
|
+
const observed = yield* observe(slug);
|
|
113
|
+
yield* apply(slug, observed, news);
|
|
114
|
+
// Organization reads can briefly lag a PATCH; wait until the
|
|
115
|
+
// settings we set are visible.
|
|
116
|
+
const settled = yield* observe(slug).pipe(
|
|
117
|
+
Effect.repeat({
|
|
118
|
+
schedule: Schedule.spaced("1 second"),
|
|
119
|
+
until: (current) =>
|
|
120
|
+
(news.overages === undefined || current.overages === news.overages) &&
|
|
121
|
+
(news.requireMfa === undefined || current.requireMfa === news.requireMfa) &&
|
|
122
|
+
(news.restoreEnabled === undefined ||
|
|
123
|
+
current.restoreEnabled === news.restoreEnabled),
|
|
124
|
+
times: 10,
|
|
125
|
+
}),
|
|
126
|
+
);
|
|
127
|
+
return {
|
|
128
|
+
organization: slug,
|
|
129
|
+
original: output?.original ?? observed,
|
|
130
|
+
...settled,
|
|
131
|
+
};
|
|
132
|
+
}),
|
|
133
|
+
delete: Effect.fn(function* ({ olds, output }) {
|
|
134
|
+
const observed = yield* observe(output.organization);
|
|
135
|
+
// Restore only the settings this resource managed.
|
|
136
|
+
yield* apply(output.organization, observed, {
|
|
137
|
+
overages: olds.overages !== undefined ? output.original.overages : undefined,
|
|
138
|
+
requireMfa: olds.requireMfa !== undefined ? output.original.requireMfa : undefined,
|
|
139
|
+
restoreEnabled:
|
|
140
|
+
olds.restoreEnabled !== undefined ? output.original.restoreEnabled : undefined,
|
|
141
|
+
});
|
|
142
|
+
}),
|
|
143
|
+
};
|
|
144
|
+
}),
|
|
145
|
+
);
|
package/src/Providers.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { CredentialsStoreLive } from "alchemy/Auth/Credentials";
|
|
2
|
+
import { ProfileStoreLive } from "alchemy/Auth/Profile";
|
|
3
|
+
import * as Provider from "alchemy/Provider";
|
|
4
|
+
import * as FetchHttpClient from "effect/http/FetchHttpClient";
|
|
5
|
+
import * as Layer from "effect/Layer";
|
|
6
|
+
import { ApiToken, ApiTokenProvider } from "./ApiToken.ts";
|
|
7
|
+
import { TursoAuth } from "./AuthProvider.ts";
|
|
8
|
+
import * as Credentials from "./Credentials.ts";
|
|
9
|
+
import { Database, DatabaseProvider } from "./Database.ts";
|
|
10
|
+
import { DatabaseToken, DatabaseTokenProvider } from "./DatabaseToken.ts";
|
|
11
|
+
import { Group, GroupProvider } from "./Group.ts";
|
|
12
|
+
import { GroupToken, GroupTokenProvider } from "./GroupToken.ts";
|
|
13
|
+
import { OrganizationInvite, OrganizationInviteProvider } from "./OrganizationInvite.ts";
|
|
14
|
+
import { OrganizationMember, OrganizationMemberProvider } from "./OrganizationMember.ts";
|
|
15
|
+
import { OrganizationSettings, OrganizationSettingsProvider } from "./OrganizationSettings.ts";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Service tag bundling all Turso providers + auth + credentials. Use
|
|
19
|
+
* `Turso.providers()` to materialize the full layer.
|
|
20
|
+
*/
|
|
21
|
+
export class Providers extends Provider.ProviderCollection<Providers>()("Turso") {}
|
|
22
|
+
|
|
23
|
+
export type ProviderRequirements = Layer.Services<ReturnType<typeof providers>>;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Build the complete Turso providers Layer: every Turso resource, the
|
|
27
|
+
* Turso AuthProvider registration (so `alchemy profile edit` can configure
|
|
28
|
+
* it), and credential resolution.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* Alchemy.Stack("App", { providers: Turso.providers() }, ...)
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export const providers = () =>
|
|
36
|
+
Layer.effect(
|
|
37
|
+
Providers,
|
|
38
|
+
Provider.collection([
|
|
39
|
+
ApiToken,
|
|
40
|
+
Database,
|
|
41
|
+
DatabaseToken,
|
|
42
|
+
Group,
|
|
43
|
+
GroupToken,
|
|
44
|
+
OrganizationInvite,
|
|
45
|
+
OrganizationMember,
|
|
46
|
+
OrganizationSettings,
|
|
47
|
+
]),
|
|
48
|
+
).pipe(
|
|
49
|
+
Layer.provide(
|
|
50
|
+
Layer.mergeAll(
|
|
51
|
+
ApiTokenProvider(),
|
|
52
|
+
DatabaseProvider(),
|
|
53
|
+
DatabaseTokenProvider(),
|
|
54
|
+
GroupProvider(),
|
|
55
|
+
GroupTokenProvider(),
|
|
56
|
+
OrganizationInviteProvider(),
|
|
57
|
+
OrganizationMemberProvider(),
|
|
58
|
+
OrganizationSettingsProvider(),
|
|
59
|
+
),
|
|
60
|
+
),
|
|
61
|
+
Layer.provideMerge(Credentials.fromAuthProvider()),
|
|
62
|
+
Layer.provideMerge(FetchHttpClient.layer),
|
|
63
|
+
Layer.provideMerge(TursoAuth),
|
|
64
|
+
Layer.provideMerge(ProfileStoreLive),
|
|
65
|
+
Layer.provideMerge(CredentialsStoreLive),
|
|
66
|
+
Layer.orDie,
|
|
67
|
+
);
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export * from "./ApiToken.ts";
|
|
2
|
+
export * from "./AuthProvider.ts";
|
|
3
|
+
export * from "./Connect.ts";
|
|
4
|
+
export {
|
|
5
|
+
Credentials,
|
|
6
|
+
CredentialsFromEnv,
|
|
7
|
+
DEFAULT_API_BASE_URL,
|
|
8
|
+
fromAuthProvider,
|
|
9
|
+
fromToken,
|
|
10
|
+
Organization,
|
|
11
|
+
} from "./Credentials.ts";
|
|
12
|
+
export * from "./Database.ts";
|
|
13
|
+
export * from "./DatabaseToken.ts";
|
|
14
|
+
export * from "./Group.ts";
|
|
15
|
+
export * from "./GroupToken.ts";
|
|
16
|
+
export * from "./ManageDatabases.ts";
|
|
17
|
+
export * from "./OrganizationInvite.ts";
|
|
18
|
+
export * from "./OrganizationMember.ts";
|
|
19
|
+
export * from "./OrganizationSettings.ts";
|
|
20
|
+
export * from "./Providers.ts";
|