@ductape/cli 0.2.23 → 0.3.0

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 (101) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +7 -0
  3. package/dist/commands/migrate-codebase.d.ts +176 -0
  4. package/dist/commands/migrate-codebase.js +753 -0
  5. package/dist/commands/migration-artifact.d.ts +32 -0
  6. package/dist/commands/migration-artifact.js +48 -0
  7. package/dist/commands/migration-assurance.d.ts +10 -0
  8. package/dist/commands/migration-assurance.js +120 -0
  9. package/dist/commands/migration-database.d.ts +21 -0
  10. package/dist/commands/migration-database.js +162 -0
  11. package/dist/commands/migration-e2e.d.ts +68 -0
  12. package/dist/commands/migration-e2e.js +189 -0
  13. package/dist/commands/migration-environments.d.ts +20 -0
  14. package/dist/commands/migration-environments.js +58 -0
  15. package/dist/commands/migration-generated.d.ts +68 -0
  16. package/dist/commands/migration-generated.js +217 -0
  17. package/dist/commands/migration-portfolio.d.ts +88 -0
  18. package/dist/commands/migration-portfolio.js +223 -0
  19. package/dist/commands/migration-products.d.ts +23 -0
  20. package/dist/commands/migration-products.js +88 -0
  21. package/dist/commands/migration-review.d.ts +248 -0
  22. package/dist/commands/migration-review.js +624 -0
  23. package/dist/commands/migration-secrets.d.ts +24 -0
  24. package/dist/commands/migration-secrets.js +93 -0
  25. package/dist/commands/migration-slice.d.ts +132 -0
  26. package/dist/commands/migration-slice.js +266 -0
  27. package/dist/commands/migration-verification.d.ts +12 -0
  28. package/dist/commands/migration-verification.js +194 -0
  29. package/dist/commands/products.d.ts +1 -0
  30. package/dist/commands/products.js +33 -1
  31. package/dist/commands/secrets.d.ts +8 -0
  32. package/dist/commands/secrets.js +44 -0
  33. package/dist/index.js +354 -2
  34. package/dist/lib/migration-artifact.d.ts +13 -0
  35. package/dist/lib/migration-artifact.js +103 -0
  36. package/package.json +8 -1
  37. package/API_PARITY.md +0 -58
  38. package/DB_MIGRATE_PLAN.md +0 -223
  39. package/ductape.example.ts +0 -18
  40. package/src/commands/apply.ts +0 -153
  41. package/src/commands/apps-import.ts +0 -43
  42. package/src/commands/apps.ts +0 -92
  43. package/src/commands/cloud.ts +0 -68
  44. package/src/commands/completion.ts +0 -119
  45. package/src/commands/db-migrate.ts +0 -209
  46. package/src/commands/db-schema.ts +0 -429
  47. package/src/commands/db.ts +0 -63
  48. package/src/commands/generate.ts +0 -74
  49. package/src/commands/graph.ts +0 -51
  50. package/src/commands/init.ts +0 -39
  51. package/src/commands/install.ts +0 -76
  52. package/src/commands/link.ts +0 -84
  53. package/src/commands/login.ts +0 -145
  54. package/src/commands/logout.ts +0 -7
  55. package/src/commands/platform.ts +0 -123
  56. package/src/commands/products.ts +0 -228
  57. package/src/commands/profiles.ts +0 -23
  58. package/src/commands/resources.ts +0 -213
  59. package/src/commands/secrets.ts +0 -46
  60. package/src/commands/unlink.ts +0 -15
  61. package/src/commands/whoami.ts +0 -27
  62. package/src/commands/workspaces.ts +0 -98
  63. package/src/index.ts +0 -523
  64. package/src/lib/api-client.ts +0 -88
  65. package/src/lib/app-import.ts +0 -82
  66. package/src/lib/apply-loaders.ts +0 -30
  67. package/src/lib/config.ts +0 -230
  68. package/src/lib/context-store.ts +0 -77
  69. package/src/lib/db-methods.ts +0 -56
  70. package/src/lib/db-types.ts +0 -104
  71. package/src/lib/encryption.ts +0 -12
  72. package/src/lib/forms/enums.ts +0 -52
  73. package/src/lib/forms/index.ts +0 -8
  74. package/src/lib/forms/prompt.ts +0 -209
  75. package/src/lib/forms/schemas.ts +0 -288
  76. package/src/lib/forms/types.ts +0 -27
  77. package/src/lib/http.ts +0 -76
  78. package/src/lib/integrations.ts +0 -110
  79. package/src/lib/interactive-opts.ts +0 -13
  80. package/src/lib/migration-files.ts +0 -58
  81. package/src/lib/output.ts +0 -39
  82. package/src/lib/platform-api.ts +0 -209
  83. package/src/lib/proxy/context.ts +0 -94
  84. package/src/lib/proxy/db-proxy.ts +0 -40
  85. package/src/lib/proxy/graph-proxy.ts +0 -64
  86. package/src/lib/proxy/sdk-proxy.ts +0 -58
  87. package/src/lib/read-body.ts +0 -57
  88. package/src/lib/resources.ts +0 -160
  89. package/src/lib/schema-loader.ts +0 -152
  90. package/src/lib/snippets.ts +0 -165
  91. package/src/lib/templates.ts +0 -157
  92. package/src/lib/workspace-context.ts +0 -43
  93. package/src/lib/workspaces.ts +0 -283
  94. package/test/apply-loaders.test.ts +0 -40
  95. package/test/encryption.test.ts +0 -20
  96. package/test/forms.test.ts +0 -25
  97. package/test/http.test.ts +0 -15
  98. package/test/platform-api.test.ts +0 -42
  99. package/test/resources.test.ts +0 -23
  100. package/test/workspace-resolve.test.ts +0 -29
  101. package/tsconfig.json +0 -15
@@ -1,110 +0,0 @@
1
- import type { Credentials } from './config.js';
2
-
3
- export interface TableColumnRecord {
4
- name: string;
5
- type: string;
6
- nullable: boolean;
7
- primaryKey: boolean;
8
- unique: boolean;
9
- autoIncrement: boolean;
10
- defaultValue?: unknown;
11
- }
12
-
13
- export interface TableSchemaRecord {
14
- table: string;
15
- columns: TableColumnRecord[];
16
- updated_at: string;
17
- }
18
-
19
- export interface GeneratePayloadRequest {
20
- workspace_id: string;
21
- user_id: string;
22
- public_key: string;
23
- product_tag: string;
24
- env_slug: string;
25
- operation_family: string;
26
- method: string;
27
- targets?: Record<string, unknown>;
28
- include_session?: boolean;
29
- include_cache?: boolean;
30
- schema_mode?: 'strict' | 'best_effort';
31
- input_hint?: Record<string, unknown>;
32
- }
33
-
34
- export interface GeneratePayloadResponse {
35
- payload: Record<string, unknown>;
36
- meta: Record<string, unknown>;
37
- }
38
-
39
- export async function generateExecutablePayload(
40
- apiUrl: string,
41
- creds: Credentials,
42
- request: GeneratePayloadRequest,
43
- ): Promise<GeneratePayloadResponse> {
44
- const url = `${apiUrl}/integrations/v1/payloads/generate`;
45
- const res = await fetch(url, {
46
- method: 'POST',
47
- headers: {
48
- 'Content-Type': 'application/json',
49
- Authorization: `Bearer ${creds.auth_token}`,
50
- 'x-access-key': creds.public_key,
51
- },
52
- body: JSON.stringify({
53
- ...request,
54
- operation_family: request.operation_family.toLowerCase() === 'features'
55
- ? 'feature'
56
- : request.operation_family,
57
- }),
58
- });
59
-
60
- const body = await res.json();
61
- if (!res.ok) {
62
- throw new Error(body.message ?? `Payload generation failed (${res.status})`);
63
- }
64
- if (body.status === false) {
65
- throw new Error(body.message ?? 'Payload generation failed');
66
- }
67
- return (body.data ?? body) as GeneratePayloadResponse;
68
- }
69
-
70
- export async function pushDatabaseSchema(
71
- apiUrl: string,
72
- creds: Credentials,
73
- opts: {
74
- workspace_id: string;
75
- product_tag: string;
76
- database_tag: string;
77
- env_slug: string;
78
- table_schemas: TableSchemaRecord[];
79
- },
80
- ): Promise<{ synced: number; tables: string[] }> {
81
- const url = `${apiUrl}/integrations/v1/databases/schema-sync`;
82
- const res = await fetch(url, {
83
- method: 'POST',
84
- headers: {
85
- 'Content-Type': 'application/json',
86
- Authorization: `Bearer ${creds.auth_token}`,
87
- 'x-access-key': creds.public_key,
88
- },
89
- body: JSON.stringify({
90
- user_id: creds.user_id,
91
- public_key: creds.public_key,
92
- workspace_id: opts.workspace_id,
93
- product_tag: opts.product_tag,
94
- database_tag: opts.database_tag,
95
- env_slug: opts.env_slug,
96
- table_schemas: opts.table_schemas,
97
- }),
98
- });
99
-
100
- const body = await res.json() as Record<string, unknown>;
101
- if (!res.ok) {
102
- const msg = (body as any).errors ?? (body as any).message;
103
- throw new Error(typeof msg === 'string' ? msg : `Schema sync failed (${res.status})`);
104
- }
105
- if (body.status === false) {
106
- const msg = (body as any).errors ?? (body as any).message;
107
- throw new Error(typeof msg === 'string' ? msg : 'Schema sync failed');
108
- }
109
- return (body.data ?? body) as { synced: number; tables: string[] };
110
- }
@@ -1,13 +0,0 @@
1
- import type { InteractiveOpts } from './forms/index.js';
2
-
3
- export type CommandInteractiveFlags = {
4
- interactive?: boolean;
5
- noInteractive?: boolean;
6
- };
7
-
8
- export function toInteractiveOpts(flags: CommandInteractiveFlags): InteractiveOpts {
9
- return {
10
- interactive: flags.noInteractive ? false : flags.interactive,
11
- noInteractive: flags.noInteractive,
12
- };
13
- }
@@ -1,58 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { PROJECT_CONFIG_DIR } from './config.js';
4
- import type { IMigration } from './db-types.js';
5
-
6
- export function getMigrationsDir(projectDir: string, dbTag: string): string {
7
- return path.join(projectDir, PROJECT_CONFIG_DIR, 'database', 'migrations', dbTag);
8
- }
9
-
10
- export function loadMigrationFiles(projectDir: string, dbTag: string): IMigration[] {
11
- const dir = getMigrationsDir(projectDir, dbTag);
12
- if (!fs.existsSync(dir)) return [];
13
-
14
- const files = fs
15
- .readdirSync(dir)
16
- .filter((f) => f.endsWith('.json'))
17
- .sort();
18
-
19
- return files.map((file) => {
20
- const raw = JSON.parse(
21
- fs.readFileSync(path.join(dir, file), 'utf8'),
22
- ) as IMigration;
23
- return raw;
24
- });
25
- }
26
-
27
- function makeTimestamp(counter: number): string {
28
- const now = new Date();
29
- const pad = (n: number, len = 2) => String(n).padStart(len, '0');
30
- const ts =
31
- String(now.getFullYear()) +
32
- pad(now.getMonth() + 1) +
33
- pad(now.getDate()) +
34
- pad(now.getHours()) +
35
- pad(now.getMinutes()) +
36
- pad(now.getSeconds());
37
- return `${ts}_${pad(counter, 3)}`;
38
- }
39
-
40
- export function writeMigrationFile(
41
- projectDir: string,
42
- dbTag: string,
43
- migration: IMigration,
44
- counter: number,
45
- ): string {
46
- const dir = getMigrationsDir(projectDir, dbTag);
47
- fs.mkdirSync(dir, { recursive: true });
48
-
49
- const safeName = migration.name
50
- .toLowerCase()
51
- .replace(/[^a-z0-9]+/g, '_')
52
- .replace(/^_|_$/g, '');
53
- const ts = makeTimestamp(counter);
54
- const filename = `${ts}_${safeName}.json`;
55
- const filePath = path.join(dir, filename);
56
- fs.writeFileSync(filePath, JSON.stringify(migration, null, 2) + '\n');
57
- return filePath;
58
- }
package/src/lib/output.ts DELETED
@@ -1,39 +0,0 @@
1
- const REDACTED_KEYS = new Set(['private_key']);
2
-
3
- function redactSensitiveFields(data: unknown): unknown {
4
- if (Array.isArray(data)) return data.map(redactSensitiveFields);
5
- if (data !== null && typeof data === 'object') {
6
- const result: Record<string, unknown> = {};
7
- for (const [key, value] of Object.entries(data as Record<string, unknown>)) {
8
- result[key] = REDACTED_KEYS.has(key) ? '[REDACTED]' : redactSensitiveFields(value);
9
- }
10
- return result;
11
- }
12
- return data;
13
- }
14
-
15
- export function printJson(data: unknown, jsonMode: boolean): void {
16
- const safe = redactSensitiveFields(data);
17
- if (jsonMode) {
18
- console.log(JSON.stringify(safe, null, 2));
19
- return;
20
- }
21
- if (safe === undefined || safe === null) {
22
- console.log('(no data)');
23
- return;
24
- }
25
- if (typeof safe === 'object') {
26
- console.log(JSON.stringify(safe, null, 2));
27
- return;
28
- }
29
- console.log(String(safe));
30
- }
31
-
32
- export function success(message: string): void {
33
- console.log(`✓ ${message}`);
34
- }
35
-
36
- export function fail(message: string): never {
37
- console.error(`✗ ${message}`);
38
- process.exit(1);
39
- }
@@ -1,209 +0,0 @@
1
- import { ApiClient } from './api-client.js';
2
- import { createSdkProxyClient } from './proxy/sdk-proxy.js';
3
- import type { WorkspaceContext } from './workspace-context.js';
4
- import { workspaceAuthQuery } from './workspace-context.js';
5
-
6
- function client(ctx: WorkspaceContext): ApiClient {
7
- return ApiClient.forProfile(ctx.profile, ctx.credentials);
8
- }
9
-
10
- function proxy(ctx: WorkspaceContext) {
11
- return createSdkProxyClient({
12
- apiUrl: ctx.apiUrl,
13
- workspaceId: ctx.workspaceId,
14
- userId: ctx.credentials.user_id,
15
- publicKey: ctx.credentials.public_key,
16
- token: ctx.credentials.auth_token,
17
- });
18
- }
19
-
20
- function unwrapList<T>(result: unknown): T[] {
21
- if (Array.isArray(result)) return result;
22
- if (result && typeof result === 'object' && Array.isArray((result as { data?: T[] }).data)) {
23
- return (result as { data: T[] }).data;
24
- }
25
- return [];
26
- }
27
-
28
- function unwrapOne<T>(result: unknown): T {
29
- if (result && typeof result === 'object' && 'data' in result) {
30
- return (result as { data: T }).data;
31
- }
32
- return result as T;
33
- }
34
-
35
- // —— Products (integrations REST + sdk-proxy for update) ——
36
-
37
- const PRODUCT_LIST_ARRAY_FIELDS = [
38
- 'apps', 'caches', 'quota', 'fallback', 'storage', 'brokers',
39
- 'sessions', 'messageBrokers', 'functions', 'variables', 'auths',
40
- 'databases', 'graphs', 'jobs', 'healthchecks', 'notifications',
41
- 'features', 'vectors', 'agents', 'models', 'steps_data',
42
- ];
43
-
44
- function summarizeProduct(p: unknown): unknown {
45
- if (!p || typeof p !== 'object') return p;
46
- const out: Record<string, unknown> = { ...(p as Record<string, unknown>) };
47
- for (const field of PRODUCT_LIST_ARRAY_FIELDS) delete out[field];
48
- return out;
49
- }
50
-
51
- export async function listProducts(
52
- ctx: WorkspaceContext,
53
- status = 'all',
54
- ): Promise<unknown[]> {
55
- const result = await client(ctx).getPath<unknown>(
56
- `/integrations/v1/workspace/${ctx.workspaceId}/${status}`,
57
- workspaceAuthQuery(ctx),
58
- );
59
- return unwrapList<unknown>(result).map(summarizeProduct);
60
- }
61
-
62
- export async function getProduct(
63
- ctx: WorkspaceContext,
64
- opts: { id?: string; tag?: string },
65
- ): Promise<unknown> {
66
- const q = workspaceAuthQuery(ctx);
67
- if (opts.id) {
68
- const result = await client(ctx).getPath<unknown>(`/integrations/v1/${opts.id}`, q);
69
- return unwrapOne(result);
70
- }
71
- if (opts.tag) {
72
- // The integrations REST fetch-by-tag route rejects current CLI login tokens with HTTP 401.
73
- // Product inventory is an administrative read, so route it through the authenticated CLI
74
- // SDK proxy (x-access-token), not the publishable-key runtime MCP proxy.
75
- const result = await proxy(ctx).execute<unknown>('product', 'fetch', [opts.tag]);
76
- return unwrapOne(result);
77
- }
78
- throw new Error('Provide --id <product_id> or --tag <product_tag>');
79
- }
80
-
81
- export async function createProduct(ctx: WorkspaceContext, body: Record<string, unknown>): Promise<unknown> {
82
- const payload = {
83
- workspace_id: ctx.workspaceId,
84
- user_id: ctx.credentials.user_id,
85
- public_key: ctx.credentials.public_key,
86
- ...body,
87
- };
88
- const result = await client(ctx).post<unknown>('/integrations/v1/create', payload);
89
- return unwrapOne(result);
90
- }
91
-
92
- export async function updateProduct(
93
- ctx: WorkspaceContext,
94
- tag: string,
95
- body: Record<string, unknown>,
96
- ): Promise<unknown> {
97
- return proxy(ctx).execute('product', 'update', [tag, body]);
98
- }
99
-
100
- export async function deleteProduct(ctx: WorkspaceContext, productId: string): Promise<unknown> {
101
- return client(ctx).delete<unknown>(
102
- `/integrations/v1/${productId}?${new URLSearchParams(workspaceAuthQuery(ctx)).toString()}`,
103
- );
104
- }
105
-
106
- export async function listProductApps(ctx: WorkspaceContext, productId: string): Promise<unknown[]> {
107
- const result = await client(ctx).getPath<unknown>(
108
- `/integrations/v1/fetch-product-apps/${productId}`,
109
- workspaceAuthQuery(ctx),
110
- );
111
- return unwrapList(result);
112
- }
113
-
114
- // —— Apps (apps REST) ——
115
-
116
- export async function listApps(ctx: WorkspaceContext, status = 'all'): Promise<unknown[]> {
117
- const result = await client(ctx).getPath<unknown>(
118
- `/apps/v1/workspace/${ctx.workspaceId}/${status}`,
119
- {
120
- user_id: ctx.credentials.user_id,
121
- public_key: ctx.credentials.public_key,
122
- },
123
- );
124
- return unwrapList(result);
125
- }
126
-
127
- export async function getApp(
128
- ctx: WorkspaceContext,
129
- opts: { id?: string; tag?: string },
130
- ): Promise<unknown> {
131
- const q = {
132
- user_id: ctx.credentials.user_id,
133
- public_key: ctx.credentials.public_key,
134
- };
135
- if (opts.id) {
136
- const result = await client(ctx).getPath<unknown>(`/apps/v1/${opts.id}`, q);
137
- return unwrapOne(result);
138
- }
139
- if (opts.tag) {
140
- const result = await client(ctx).getPath<unknown>(`/apps/v1/fetch/tag`, { ...q, tag: opts.tag });
141
- return unwrapOne(result);
142
- }
143
- throw new Error('Provide --id <app_id> or --tag <app_tag>');
144
- }
145
-
146
- export async function createApp(ctx: WorkspaceContext, body: Record<string, unknown>): Promise<unknown> {
147
- const payload = {
148
- workspace_id: ctx.workspaceId,
149
- user_id: ctx.credentials.user_id,
150
- public_key: ctx.credentials.public_key,
151
- version: '1.0.0',
152
- logo: '',
153
- envs: [],
154
- ...body,
155
- };
156
- const result = await client(ctx).post<unknown>('/apps/v1/create', payload);
157
- return unwrapOne(result);
158
- }
159
-
160
- export async function updateApp(
161
- ctx: WorkspaceContext,
162
- appId: string,
163
- body: Record<string, unknown>,
164
- ): Promise<unknown> {
165
- const q = {
166
- user_id: ctx.credentials.user_id,
167
- public_key: ctx.credentials.public_key,
168
- };
169
- const result = await client(ctx).put<unknown>(
170
- `/apps/v1/${appId}?${new URLSearchParams(q).toString()}`,
171
- body,
172
- );
173
- return unwrapOne(result);
174
- }
175
-
176
- export async function updateAppViaProxy(
177
- ctx: WorkspaceContext,
178
- tag: string,
179
- body: Record<string, unknown>,
180
- ): Promise<unknown> {
181
- return proxy(ctx).execute('app', 'update', [tag, body]);
182
- }
183
-
184
- export async function deleteApp(ctx: WorkspaceContext, appId: string): Promise<unknown> {
185
- const q = {
186
- user_id: ctx.credentials.user_id,
187
- public_key: ctx.credentials.public_key,
188
- };
189
- return client(ctx).delete<unknown>(
190
- `/apps/v1/${appId}?${new URLSearchParams(q).toString()}`,
191
- );
192
- }
193
-
194
- // —— Cloud tiers ——
195
-
196
- export interface TierQuery {
197
- provider?: string;
198
- resource_type?: string;
199
- db_type?: string;
200
- }
201
-
202
- export async function listCloudTiers(ctx: WorkspaceContext, q: TierQuery): Promise<unknown[]> {
203
- const params: Record<string, string> = workspaceAuthQuery(ctx);
204
- if (q.provider) params.provider = q.provider;
205
- if (q.resource_type) params.resource_type = q.resource_type;
206
- if (q.db_type) params.db_type = q.db_type;
207
- const result = await client(ctx).getPath<unknown>('/integrations/v1/cloud/tiers', params);
208
- return unwrapList<unknown>(result);
209
- }
@@ -1,94 +0,0 @@
1
- import {
2
- findProjectConfig,
3
- getActiveProfileName,
4
- getApiUrl,
5
- loadCredentials,
6
- loadProjectConfig,
7
- type Credentials,
8
- type ResolvedProjectConfig,
9
- } from '../config.js';
10
- import { loadRuntimeContext } from '../context-store.js';
11
- import { createSdkProxyClient, type SdkProxyClient } from './sdk-proxy.js';
12
- import { DbProxyClient } from './db-proxy.js';
13
- import { GraphProxyClient } from './graph-proxy.js';
14
-
15
- export interface SessionContext {
16
- credentials: Credentials;
17
- project: ResolvedProjectConfig;
18
- apiUrl: string;
19
- }
20
-
21
- export function requireCredentials(): Credentials {
22
- const creds = loadCredentials();
23
- if (!creds?.auth_token || !creds.public_key || !creds.user_id) {
24
- throw new Error('Not logged in. Run: ductape login');
25
- }
26
- return creds;
27
- }
28
-
29
- export function requireSession(): SessionContext {
30
- const credentials = requireCredentials();
31
- const project = loadProjectConfig();
32
- const profile = getActiveProfileName(project);
33
- const apiUrl = getApiUrl(profile);
34
- return { credentials, project, apiUrl };
35
- }
36
-
37
- export function getSdkProxy(session?: SessionContext): SdkProxyClient {
38
- const s = session ?? requireSession();
39
- return createSdkProxyClient({
40
- apiUrl: s.apiUrl,
41
- workspaceId: s.project.workspace_id,
42
- userId: s.credentials.user_id,
43
- publicKey: s.credentials.public_key,
44
- token: s.credentials.auth_token,
45
- });
46
- }
47
-
48
- export function getDbProxy(session?: SessionContext): DbProxyClient {
49
- const s = session ?? requireSession();
50
- const runtime = loadRuntimeContext(s.project.workspace_id, s.project.product_tag);
51
- const proxy = new DbProxyClient({
52
- apiUrl: s.apiUrl,
53
- workspaceId: s.project.workspace_id,
54
- userId: s.credentials.user_id,
55
- publicKey: s.credentials.public_key,
56
- token: s.credentials.auth_token,
57
- });
58
- return proxy;
59
- }
60
-
61
- export function getDbContext(session?: SessionContext) {
62
- const s = session ?? requireSession();
63
- const runtime = loadRuntimeContext(s.project.workspace_id, s.project.product_tag);
64
- return (
65
- runtime?.database_context ?? {
66
- database: '',
67
- env: s.project.env_slug,
68
- product: s.project.product_tag,
69
- }
70
- );
71
- }
72
-
73
- export function getGraphProxy(session?: SessionContext): GraphProxyClient {
74
- const s = session ?? requireSession();
75
- const runtime = loadRuntimeContext(s.project.workspace_id, s.project.product_tag);
76
- return new GraphProxyClient({
77
- apiUrl: s.apiUrl,
78
- workspaceId: s.project.workspace_id,
79
- userId: s.credentials.user_id,
80
- publicKey: s.credentials.public_key,
81
- token: s.credentials.auth_token,
82
- graphContext: runtime?.graph_context ?? null,
83
- });
84
- }
85
-
86
- export function getOptionalProject(): ResolvedProjectConfig | null {
87
- const found = findProjectConfig();
88
- if (!found) return null;
89
- try {
90
- return loadProjectConfig();
91
- } catch {
92
- return null;
93
- }
94
- }
@@ -1,40 +0,0 @@
1
- import { encryptProxyPayload } from '../encryption.js';
2
- import { postProxyJson } from '../http.js';
3
- import type { DatabaseContext } from '../context-store.js';
4
-
5
- export interface DbProxyContext {
6
- apiUrl: string;
7
- workspaceId: string;
8
- userId: string;
9
- publicKey: string;
10
- token: string;
11
- }
12
-
13
- export class DbProxyClient {
14
- constructor(private readonly ctx: DbProxyContext) {}
15
-
16
- async execute<T>(
17
- method: string,
18
- params: unknown[],
19
- databaseContext?: DatabaseContext | null,
20
- ): Promise<T> {
21
- const sensitive: Record<string, unknown> = {
22
- method,
23
- params,
24
- user_id: this.ctx.userId,
25
- };
26
- if (databaseContext) sensitive.database_context = databaseContext;
27
-
28
- const encrypted_payload = encryptProxyPayload(sensitive, this.ctx.publicKey);
29
- const body: Record<string, unknown> = {
30
- encrypted_payload,
31
- workspace_id: this.ctx.workspaceId,
32
- user_id: this.ctx.userId,
33
- public_key: this.ctx.publicKey,
34
- };
35
- if (databaseContext) body.database_context = databaseContext;
36
-
37
- const url = `${this.ctx.apiUrl}/proxy/v1/db-proxy/execute`;
38
- return postProxyJson<T>(url, body, { 'x-access-token': this.ctx.token });
39
- }
40
- }
@@ -1,64 +0,0 @@
1
- import { encryptProxyPayload } from '../encryption.js';
2
- import { postProxyJson } from '../http.js';
3
-
4
- export interface GraphContext {
5
- graph: string;
6
- env: string;
7
- product: string;
8
- }
9
-
10
- export interface GraphProxyContext {
11
- apiUrl: string;
12
- workspaceId: string;
13
- userId: string;
14
- publicKey: string;
15
- token: string;
16
- graphContext?: GraphContext | null;
17
- }
18
-
19
- export class GraphProxyClient {
20
- constructor(private readonly ctx: GraphProxyContext) {}
21
-
22
- setGraphContext(context: GraphContext | null): void {
23
- this.ctx.graphContext = context;
24
- }
25
-
26
- async execute<T>(
27
- method: string,
28
- params: unknown[] = [],
29
- graphContext?: GraphContext | null,
30
- ): Promise<T> {
31
- const ctx = graphContext ?? this.ctx.graphContext;
32
- const sensitive: Record<string, unknown> = {
33
- method,
34
- params,
35
- user_id: this.ctx.userId,
36
- };
37
- if (ctx) sensitive.graph_context = ctx;
38
-
39
- const encrypted_payload = encryptProxyPayload(sensitive, this.ctx.publicKey);
40
- const body: Record<string, unknown> = {
41
- encrypted_payload,
42
- workspace_id: this.ctx.workspaceId,
43
- user_id: this.ctx.userId,
44
- public_key: this.ctx.publicKey,
45
- };
46
- if (ctx) body.graph_context = ctx;
47
-
48
- const url = `${this.ctx.apiUrl}/proxy/v1/graph-proxy/execute`;
49
- const result = await postProxyJson<T>(url, body, {
50
- 'x-access-token': this.ctx.token,
51
- });
52
-
53
- if (method === 'connect' && params[0] && typeof params[0] === 'object') {
54
- const cfg = params[0] as GraphContext;
55
- this.setGraphContext({
56
- graph: cfg.graph,
57
- env: cfg.env,
58
- product: cfg.product,
59
- });
60
- }
61
-
62
- return result;
63
- }
64
- }
@@ -1,58 +0,0 @@
1
- import { encryptProxyPayload } from '../encryption.js';
2
- import { postProxyJson } from '../http.js';
3
-
4
- export type SDKModule =
5
- | 'product'
6
- | 'app'
7
- | 'databases'
8
- | 'graph'
9
- | 'webhooks'
10
- | 'notifications'
11
- | 'messageBrokers'
12
- | 'storage'
13
- | 'vector'
14
- | 'caches'
15
- | 'sessions'
16
- | 'quotas'
17
- | 'actions'
18
- | 'features'
19
- | 'jobs'
20
- | 'logs'
21
- | 'resilience'
22
- | 'health'
23
- | 'fallback'
24
- | 'secrets'
25
- | 'cloud';
26
-
27
- export interface SdkProxyContext {
28
- apiUrl: string;
29
- workspaceId: string;
30
- userId: string;
31
- publicKey: string;
32
- token: string;
33
- }
34
-
35
- export class SdkProxyClient {
36
- constructor(private readonly ctx: SdkProxyContext) {}
37
-
38
- async execute<T>(module: SDKModule, method: string, params: unknown[] = []): Promise<T> {
39
- const sensitive = { module, method, params, user_id: this.ctx.userId };
40
- const encrypted_payload = encryptProxyPayload(sensitive, this.ctx.publicKey);
41
-
42
- const url = `${this.ctx.apiUrl}/proxy/v1/sdk-proxy/execute`;
43
- return postProxyJson<T>(
44
- url,
45
- {
46
- encrypted_payload,
47
- workspace_id: this.ctx.workspaceId,
48
- user_id: this.ctx.userId,
49
- public_key: this.ctx.publicKey,
50
- },
51
- { 'x-access-token': this.ctx.token },
52
- );
53
- }
54
- }
55
-
56
- export function createSdkProxyClient(ctx: SdkProxyContext): SdkProxyClient {
57
- return new SdkProxyClient(ctx);
58
- }