@theholocron/holocron-plugin-neon 2.0.0-alpha.49 → 2.0.0-alpha.50
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/dist/index.d.mts +7 -13
- package/dist/index.mjs +28 -45
- package/package.json +10 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,25 +1,19 @@
|
|
|
1
|
-
import { AuthError, ConnectionStringOptions, ResolveTokenInput,
|
|
1
|
+
import { AuthError, ConnectionStringOptions, ResolveTokenInput, Storage, StorageBranch } from "@theholocron/cli";
|
|
2
|
+
import { NeonClient, NeonClient as NeonClient$1, createNeonClient } from "@theholocron/neon-client";
|
|
2
3
|
|
|
3
4
|
//#region src/auth.d.ts
|
|
4
5
|
declare const resolveToken: (input?: import("@theholocron/http-client").ResolveTokenInput) => string;
|
|
5
6
|
//#endregion
|
|
6
|
-
//#region src/rest.d.ts
|
|
7
|
-
declare function createNeonRestClient(opts: {
|
|
8
|
-
token: string;
|
|
9
|
-
baseUrl?: string;
|
|
10
|
-
fetch?: typeof fetch;
|
|
11
|
-
}): RestClient$1;
|
|
12
|
-
//#endregion
|
|
13
7
|
//#region src/capabilities/storage.d.ts
|
|
14
8
|
interface StorageOptions {
|
|
15
9
|
projectId: string;
|
|
16
10
|
}
|
|
17
11
|
declare class NeonStorage implements Storage {
|
|
18
|
-
private readonly
|
|
12
|
+
private readonly client;
|
|
13
|
+
private readonly opts;
|
|
19
14
|
readonly key: "storage";
|
|
20
15
|
readonly providerName = "neon";
|
|
21
|
-
|
|
22
|
-
constructor(rest: RestClient, opts: StorageOptions);
|
|
16
|
+
constructor(client: NeonClient$1, opts: StorageOptions);
|
|
23
17
|
getConnectionString(scope: string, options?: ConnectionStringOptions): Promise<string>;
|
|
24
18
|
listBranches(): Promise<StorageBranch[]>;
|
|
25
19
|
createBranch(input: {
|
|
@@ -76,7 +70,7 @@ interface NeonPluginOptions extends ResolveTokenInput {
|
|
|
76
70
|
}
|
|
77
71
|
interface PluginContext {
|
|
78
72
|
options: NeonPluginOptions;
|
|
79
|
-
|
|
73
|
+
client: NeonClient;
|
|
80
74
|
}
|
|
81
75
|
declare function createContext(options: NeonPluginOptions): PluginContext;
|
|
82
76
|
declare function storage(ctx: PluginContext): Storage;
|
|
@@ -94,4 +88,4 @@ declare function createPlugin(options: NeonPluginOptions): {
|
|
|
94
88
|
*/
|
|
95
89
|
declare const AUTH_HINT: string;
|
|
96
90
|
//#endregion
|
|
97
|
-
export { AUTH_HINT, AuthError, NeonPluginOptions, NeonStorage, PluginContext, type ResolveTokenInput, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, createContext,
|
|
91
|
+
export { AUTH_HINT, AuthError, type NeonClient, NeonPluginOptions, NeonStorage, PluginContext, type ResolveTokenInput, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, createContext, createNeonClient, createPlugin, resolveToken, storage, verifyToken };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { AuthError, ProviderApiError, createResolveToken
|
|
1
|
+
import { AuthError, ProviderApiError, createResolveToken } from "@theholocron/cli";
|
|
2
|
+
import { createNeonClient } from "@theholocron/neon-client";
|
|
2
3
|
//#region src/auth.ts
|
|
3
4
|
const resolveToken = createResolveToken({
|
|
4
5
|
envName: "HOLOCRON_NEON_API_KEY",
|
|
@@ -27,55 +28,46 @@ const resolveToken = createResolveToken({
|
|
|
27
28
|
* via `projectId` in options.
|
|
28
29
|
*/
|
|
29
30
|
var NeonStorage = class {
|
|
30
|
-
|
|
31
|
+
client;
|
|
32
|
+
opts;
|
|
31
33
|
key = "storage";
|
|
32
34
|
providerName = "neon";
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
this.
|
|
35
|
+
constructor(client, opts) {
|
|
36
|
+
this.client = client;
|
|
37
|
+
this.opts = opts;
|
|
36
38
|
if (!opts.projectId) throw new Error("NeonStorage requires `projectId` in options");
|
|
37
|
-
this.base = `/projects/${opts.projectId}`;
|
|
38
39
|
}
|
|
39
40
|
async getConnectionString(scope, options = {}) {
|
|
40
41
|
const db = await this.firstDatabase(scope);
|
|
41
|
-
const
|
|
42
|
+
const { uri } = await this.client.connection.uri(this.opts.projectId, {
|
|
42
43
|
branch_id: scope,
|
|
43
44
|
database_name: db.name,
|
|
44
45
|
role_name: db.owner_name,
|
|
45
46
|
pooled: options.pooled ? "true" : "false"
|
|
46
|
-
};
|
|
47
|
-
return
|
|
47
|
+
});
|
|
48
|
+
return uri;
|
|
48
49
|
}
|
|
49
50
|
async listBranches() {
|
|
50
|
-
|
|
51
|
+
const { branches } = await this.client.branches.list(this.opts.projectId);
|
|
52
|
+
return branches.map(mapBranch);
|
|
51
53
|
}
|
|
52
54
|
async createBranch(input) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
},
|
|
60
|
-
endpoints: [{ type: "read_write" }]
|
|
61
|
-
}
|
|
62
|
-
})).branch);
|
|
55
|
+
const { branch } = await this.client.branches.create(this.opts.projectId, {
|
|
56
|
+
name: input.name,
|
|
57
|
+
...input.from ? { parent_id: input.from } : {},
|
|
58
|
+
endpoints: [{ type: "read_write" }]
|
|
59
|
+
});
|
|
60
|
+
return mapBranch(branch);
|
|
63
61
|
}
|
|
64
62
|
async destroyBranch(branch) {
|
|
65
|
-
await this.
|
|
63
|
+
await this.client.branches.destroy(this.opts.projectId, branch);
|
|
66
64
|
}
|
|
67
65
|
async resetBranch(input) {
|
|
68
|
-
await this.
|
|
69
|
-
method: "POST",
|
|
70
|
-
body: { source_branch_id: input.from }
|
|
71
|
-
});
|
|
66
|
+
await this.client.branches.restore(this.opts.projectId, input.branch, input.from);
|
|
72
67
|
}
|
|
73
68
|
async enableExtension(input) {
|
|
74
69
|
const db = await this.firstDatabase(input.branch);
|
|
75
|
-
await this.
|
|
76
|
-
method: "POST",
|
|
77
|
-
body: { query: `CREATE EXTENSION IF NOT EXISTS "${input.extension}"` }
|
|
78
|
-
});
|
|
70
|
+
await this.client.databases.runSql(this.opts.projectId, input.branch, db.name, `CREATE EXTENSION IF NOT EXISTS "${input.extension}"`);
|
|
79
71
|
}
|
|
80
72
|
/**
|
|
81
73
|
* The first database on a branch — the "default" for connection-string
|
|
@@ -83,7 +75,8 @@ var NeonStorage = class {
|
|
|
83
75
|
* means it was created without an endpoint and needs initialization).
|
|
84
76
|
*/
|
|
85
77
|
async firstDatabase(branchId) {
|
|
86
|
-
const
|
|
78
|
+
const { databases } = await this.client.databases.list(this.opts.projectId, branchId);
|
|
79
|
+
const db = databases[0];
|
|
87
80
|
if (!db) throw new ProviderApiError(`Neon branch ${branchId} has no databases — initialize the branch first`, 404, void 0);
|
|
88
81
|
return db;
|
|
89
82
|
}
|
|
@@ -97,16 +90,6 @@ function mapBranch(raw) {
|
|
|
97
90
|
};
|
|
98
91
|
}
|
|
99
92
|
//#endregion
|
|
100
|
-
//#region src/rest.ts
|
|
101
|
-
function createNeonRestClient(opts) {
|
|
102
|
-
return createRestClient({
|
|
103
|
-
baseUrl: opts.baseUrl ?? "https://console.neon.tech/api/v2",
|
|
104
|
-
token: opts.token,
|
|
105
|
-
vendor: "Neon",
|
|
106
|
-
fetch: opts.fetch
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
//#endregion
|
|
110
93
|
//#region src/verify-token.ts
|
|
111
94
|
/**
|
|
112
95
|
* `verifyToken` — plugin-level export used by `holocron auth set` +
|
|
@@ -115,13 +98,13 @@ function createNeonRestClient(opts) {
|
|
|
115
98
|
* shape.
|
|
116
99
|
*/
|
|
117
100
|
async function verifyToken(token, opts = {}) {
|
|
118
|
-
const
|
|
101
|
+
const client = createNeonClient({
|
|
119
102
|
token,
|
|
120
103
|
baseUrl: opts.baseUrl,
|
|
121
104
|
fetch: opts.fetch
|
|
122
105
|
});
|
|
123
106
|
try {
|
|
124
|
-
const me = await
|
|
107
|
+
const me = await client.users.me();
|
|
125
108
|
return {
|
|
126
109
|
ok: true,
|
|
127
110
|
subject: `user @ ${me?.email ?? me?.login ?? me?.name ?? me?.id ?? "unknown"}`
|
|
@@ -139,7 +122,7 @@ function createContext(options) {
|
|
|
139
122
|
if (!options.projectId) throw new Error("@theholocron/holocron-plugin-neon requires `projectId` in options");
|
|
140
123
|
return {
|
|
141
124
|
options,
|
|
142
|
-
|
|
125
|
+
client: createNeonClient({
|
|
143
126
|
token: resolveToken(options),
|
|
144
127
|
baseUrl: options.baseUrl,
|
|
145
128
|
fetch: options.fetch
|
|
@@ -147,7 +130,7 @@ function createContext(options) {
|
|
|
147
130
|
};
|
|
148
131
|
}
|
|
149
132
|
function storage(ctx) {
|
|
150
|
-
return new NeonStorage(ctx.
|
|
133
|
+
return new NeonStorage(ctx.client, { projectId: ctx.options.projectId });
|
|
151
134
|
}
|
|
152
135
|
function createPlugin(options) {
|
|
153
136
|
const ctx = createContext(options);
|
|
@@ -164,4 +147,4 @@ function createPlugin(options) {
|
|
|
164
147
|
*/
|
|
165
148
|
const AUTH_HINT = "generate a Neon API key at https://console.neon.tech/app/settings/api-keys, then run: holocron auth set neon <KEY>";
|
|
166
149
|
//#endregion
|
|
167
|
-
export { AUTH_HINT, AuthError, NeonStorage, createContext,
|
|
150
|
+
export { AUTH_HINT, AuthError, NeonStorage, createContext, createNeonClient, createPlugin, resolveToken, storage, verifyToken };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theholocron/holocron-plugin-neon",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.50",
|
|
4
4
|
"description": "Holocron plugin for Neon. Implements the storage capability against Neon's REST API — branch ops, connection strings, extensions.",
|
|
5
5
|
"homepage": "https://github.com/theholocron/holocron/tree/main/packages/holocron-plugin-neon#readme",
|
|
6
6
|
"bugs": "https://github.com/theholocron/holocron/issues",
|
|
@@ -21,9 +21,16 @@
|
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
-
"@theholocron/
|
|
24
|
+
"@theholocron/neon-client": "^0.7.0",
|
|
25
|
+
"@theholocron/cli": "2.0.0-alpha.50"
|
|
26
|
+
},
|
|
27
|
+
"peerDependenciesMeta": {
|
|
28
|
+
"@theholocron/neon-client": {
|
|
29
|
+
"optional": false
|
|
30
|
+
}
|
|
25
31
|
},
|
|
26
32
|
"devDependencies": {
|
|
33
|
+
"@theholocron/neon-client": "^0.7.0",
|
|
27
34
|
"@types/node": "^26",
|
|
28
35
|
"@theholocron/eslint-config": "^5.2.0",
|
|
29
36
|
"@theholocron/tsconfig": "^6.0.0",
|
|
@@ -37,7 +44,7 @@
|
|
|
37
44
|
"tsx": "^4.22.4",
|
|
38
45
|
"typescript": "^5.9.3",
|
|
39
46
|
"vitest": "^4.1.10",
|
|
40
|
-
"@theholocron/cli": "2.0.0-alpha.
|
|
47
|
+
"@theholocron/cli": "2.0.0-alpha.50"
|
|
41
48
|
},
|
|
42
49
|
"publishConfig": {
|
|
43
50
|
"access": "public"
|