@liquidmetal-ai/raindrop 0.4.11 → 0.4.13

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 (50) hide show
  1. package/README.md +209 -53
  2. package/dist/base-command.d.ts +6 -0
  3. package/dist/base-command.d.ts.map +1 -1
  4. package/dist/base-command.js +16 -1
  5. package/dist/codegen.js +3 -3
  6. package/dist/codegen.test.js +6 -6
  7. package/dist/commands/bucket/create-credential.d.ts +25 -0
  8. package/dist/commands/bucket/create-credential.d.ts.map +1 -0
  9. package/dist/commands/bucket/create-credential.js +171 -0
  10. package/dist/commands/bucket/delete-credential.d.ts +24 -0
  11. package/dist/commands/bucket/delete-credential.d.ts.map +1 -0
  12. package/dist/commands/bucket/delete-credential.js +140 -0
  13. package/dist/commands/bucket/get-credential.d.ts +24 -0
  14. package/dist/commands/bucket/get-credential.d.ts.map +1 -0
  15. package/dist/commands/bucket/get-credential.js +149 -0
  16. package/dist/commands/bucket/list-credentials.d.ts +23 -0
  17. package/dist/commands/bucket/list-credentials.d.ts.map +1 -0
  18. package/dist/commands/bucket/list-credentials.js +146 -0
  19. package/dist/commands/build/branch.d.ts +1 -0
  20. package/dist/commands/build/branch.d.ts.map +1 -1
  21. package/dist/commands/build/branch.js +17 -0
  22. package/dist/commands/build/deploy.d.ts +1 -0
  23. package/dist/commands/build/deploy.d.ts.map +1 -1
  24. package/dist/commands/build/deploy.js +17 -0
  25. package/dist/commands/build/find.d.ts +2 -0
  26. package/dist/commands/build/find.d.ts.map +1 -1
  27. package/dist/commands/build/find.js +181 -16
  28. package/dist/commands/build/list.d.ts +6 -0
  29. package/dist/commands/build/list.d.ts.map +1 -1
  30. package/dist/commands/build/list.js +280 -99
  31. package/dist/commands/build/status.d.ts +0 -4
  32. package/dist/commands/build/status.d.ts.map +1 -1
  33. package/dist/commands/build/status.js +32 -82
  34. package/dist/commands/object/delete.d.ts.map +1 -1
  35. package/dist/commands/object/delete.js +10 -8
  36. package/dist/commands/object/get.d.ts.map +1 -1
  37. package/dist/commands/object/get.js +9 -8
  38. package/dist/commands/object/list.d.ts.map +1 -1
  39. package/dist/commands/object/list.js +8 -6
  40. package/dist/commands/object/put.d.ts.map +1 -1
  41. package/dist/commands/object/put.js +12 -10
  42. package/dist/index.d.ts +2 -0
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +4 -0
  45. package/dist/status.d.ts +21 -0
  46. package/dist/status.d.ts.map +1 -0
  47. package/dist/status.js +137 -0
  48. package/dist/tsconfig.tsbuildinfo +1 -1
  49. package/oclif.manifest.json +2214 -1199
  50. package/package.json +4 -3
@@ -130,10 +130,10 @@ test('kebabCaseToCamelCase', () => {
130
130
  test('kebabCaseToUpperCamelCase', () => {
131
131
  expect(kebabCaseToUpperCamelCase('my-variable')).toEqual('MyVariable');
132
132
  });
133
- test('generates AgentMemory type bindings', async () => {
133
+ test('generates SmartMemory type bindings', async () => {
134
134
  const apps = await mustManifestFromString(`
135
135
  application "test-app" {
136
- agent_memory "user-memory" {}
136
+ smartmemory "user-memory" {}
137
137
 
138
138
  service "test-service" {}
139
139
  }
@@ -141,10 +141,10 @@ test('generates AgentMemory type bindings', async () => {
141
141
  const app = apps[0];
142
142
  const service = app.service[0];
143
143
  const generated = gatherEnvForHandler(service, app);
144
- // Should include AgentMemory import
145
- expect(generated).toMatch(/import\s+{[^}]*AgentMemory[^}]*}\s+from\s+'@liquidmetal-ai\/raindrop-framework'/);
146
- // Should include AgentMemory type binding with constant case naming
147
- expect(generated).toMatch(/USER_MEMORY:\s*AgentMemory/);
144
+ // Should include SmartMemory import
145
+ expect(generated).toMatch(/import\s+{[^}]*SmartMemory[^}]*}\s+from\s+'@liquidmetal-ai\/raindrop-framework'/);
146
+ // Should include SmartMemory type binding with constant case naming
147
+ expect(generated).toMatch(/USER_MEMORY:\s*SmartMemory/);
148
148
  });
149
149
  test('generates SmartBucket type bindings', async () => {
150
150
  const apps = await mustManifestFromString(`
@@ -0,0 +1,25 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ export default class CreateCredential extends BaseCommand<typeof CreateCredential> {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ bucket: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ name: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
8
+ 'expires-at': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ 'api-url': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ application: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ version: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
+ impersonate: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
+ manifest: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
15
+ config: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
16
+ rainbowAuthService: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
17
+ raindropCatalogService: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
18
+ rainbowAuthToken: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
+ rainbowOrganizationId: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
20
+ rainbowUserId: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
21
+ sendVersionMetadata: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
22
+ };
23
+ run(): Promise<void>;
24
+ }
25
+ //# sourceMappingURL=create-credential.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-credential.d.ts","sourceRoot":"","sources":["../../../src/commands/bucket/create-credential.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,WAAW,CAAC,OAAO,gBAAgB,CAAC;IAChF,MAAM,CAAC,WAAW,SAAwC;IAE1D,MAAM,CAAC,QAAQ,WAUb;IAEF,MAAM,CAAC,KAAK;;;;;;;;;;;;;;;;;MAqDV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA8G3B"}
@@ -0,0 +1,171 @@
1
+ import { toJsonString } from '@bufbuild/protobuf';
2
+ import { timestampDate, timestampFromDate } from '@bufbuild/protobuf/wkt';
3
+ import { valueOf } from '@liquidmetal-ai/drizzle/appify/build';
4
+ import { CreateCredentialResponseSchema } from '@liquidmetal-ai/drizzle/liquidmetal/v1alpha1/bucket_api_pb';
5
+ import { Flags } from '@oclif/core';
6
+ import { BaseCommand } from '../../base-command.js';
7
+ export default class CreateCredential extends BaseCommand {
8
+ static description = 'Create S3 credentials for a bucket';
9
+ static examples = [
10
+ `<%= config.bin %> bucket create-credential --bucket my-bucket --name "My API Key"
11
+ Create a new S3 credential for my-bucket
12
+ `,
13
+ `<%= config.bin %> bucket create-credential --bucket my-bucket --name "Temp Key" --expires-at "2024-12-31"
14
+ Create a credential that expires on Dec 31, 2024
15
+ `,
16
+ `<%= config.bin %> bucket create-credential --api-url https://bucket.example.com --name "Direct API Key"
17
+ Create a credential using a direct API URL
18
+ `,
19
+ ];
20
+ static flags = {
21
+ ...BaseCommand.HIDDEN_FLAGS,
22
+ bucket: Flags.string({
23
+ char: 'b',
24
+ description: 'bucket name',
25
+ required: false,
26
+ exclusive: ['api-url'],
27
+ }),
28
+ name: Flags.string({
29
+ char: 'n',
30
+ description: 'credential name',
31
+ required: true,
32
+ }),
33
+ 'expires-at': Flags.string({
34
+ description: 'expiration date (ISO 8601 format)',
35
+ required: false,
36
+ }),
37
+ 'api-url': Flags.string({
38
+ description: 'direct API URL (bypasses bucket discovery)',
39
+ required: false,
40
+ exclusive: ['bucket', 'application', 'version'],
41
+ }),
42
+ application: Flags.string({
43
+ char: 'a',
44
+ description: 'application name',
45
+ required: false,
46
+ exclusive: ['api-url'],
47
+ }),
48
+ version: Flags.string({
49
+ char: 'v',
50
+ description: 'application version',
51
+ required: false,
52
+ exclusive: ['api-url'],
53
+ }),
54
+ output: Flags.string({
55
+ char: 'o',
56
+ description: 'output format',
57
+ default: 'text',
58
+ options: ['text', 'json'],
59
+ }),
60
+ impersonate: Flags.string({
61
+ char: 'i',
62
+ description: 'impersonate organization',
63
+ required: false,
64
+ hidden: true,
65
+ }),
66
+ manifest: Flags.string({
67
+ char: 'M',
68
+ description: 'project manifest',
69
+ required: false,
70
+ default: 'raindrop.manifest',
71
+ hidden: true,
72
+ }),
73
+ };
74
+ async run() {
75
+ const { flags } = await this.parse(CreateCredential);
76
+ // Validate that we have either api-url or bucket
77
+ if (!flags['api-url'] && !flags.bucket) {
78
+ this.error('Either --api-url or --bucket must be specified');
79
+ }
80
+ let apiUrl;
81
+ let bucketName;
82
+ if (flags['api-url']) {
83
+ // Direct API URL provided, skip discovery
84
+ apiUrl = flags['api-url'];
85
+ }
86
+ else {
87
+ // Need to discover the bucket
88
+ bucketName = flags.bucket;
89
+ // Get application info from flags or config/manifest
90
+ let applicationName = flags.application;
91
+ let applicationVersionId = flags.version;
92
+ if (!applicationVersionId) {
93
+ const config = await this.loadConfig();
94
+ applicationVersionId = config.versionId;
95
+ }
96
+ if (!applicationName) {
97
+ const apps = await this.loadManifest();
98
+ const app = apps[0];
99
+ if (app === undefined) {
100
+ this.error('No application provided or found in manifest', { exit: 1 });
101
+ }
102
+ applicationName = valueOf(app.name);
103
+ }
104
+ // Query for the bucket module
105
+ const { client: catalogService, userId, organizationId: defaultOrganizationId } = await this.catalogService();
106
+ const organizationId = flags.impersonate ?? defaultOrganizationId;
107
+ const modulesResp = await catalogService.queryModules({
108
+ userId,
109
+ applicationName,
110
+ applicationVersionId,
111
+ organizationId,
112
+ moduleType: 'bucket',
113
+ });
114
+ // Find the specific bucket
115
+ const bucketModule = modulesResp.modules.find(m => m.name === bucketName && m.type === 'bucket');
116
+ if (!bucketModule) {
117
+ this.error(`Bucket '${bucketName}' not found in application ${applicationName}@${applicationVersionId}`);
118
+ }
119
+ // Extract the API URL from the bucket module
120
+ apiUrl = bucketModule.bucket?.s3?.apiUrl;
121
+ if (!apiUrl) {
122
+ this.error(`Bucket '${bucketName}' does not have an API URL configured`);
123
+ }
124
+ }
125
+ // Parse expires_at if provided
126
+ let expiresAt;
127
+ if (flags['expires-at']) {
128
+ const expiresDate = new Date(flags['expires-at']);
129
+ if (isNaN(expiresDate.getTime())) {
130
+ this.error('Invalid expiration date format. Use ISO 8601 format (e.g., 2024-12-31 or 2024-12-31T23:59:59Z)');
131
+ }
132
+ if (expiresDate <= new Date()) {
133
+ this.error('Expiration date must be in the future');
134
+ }
135
+ expiresAt = timestampFromDate(expiresDate);
136
+ }
137
+ // Create the S3 credential service client
138
+ const { client: credentialService } = await this.bucketApiService(apiUrl);
139
+ try {
140
+ const response = await credentialService.createCredential({
141
+ name: flags.name,
142
+ expiresAt,
143
+ });
144
+ // Output the result
145
+ if (flags.output === 'json') {
146
+ console.log(toJsonString(CreateCredentialResponseSchema, response, { prettySpaces: 2 }));
147
+ }
148
+ else {
149
+ const cred = response.credential;
150
+ if (!cred) {
151
+ this.error('No credential returned from service');
152
+ }
153
+ console.log(`Successfully created S3 credential${bucketName ? ` for bucket '${bucketName}'` : ''}`);
154
+ console.log(`\nAccess Key: ${cred.accessKey}`);
155
+ console.log(`Secret Key: ${cred.secretKey}`);
156
+ console.log(`Name: ${cred.name}`);
157
+ if (cred.createdAt) {
158
+ console.log(`Created: ${timestampDate(cred.createdAt).toISOString()}`);
159
+ }
160
+ if (cred.expiresAt) {
161
+ console.log(`Expires: ${timestampDate(cred.expiresAt).toISOString()}`);
162
+ }
163
+ console.log('\n⚠️ Save these credentials securely - the secret key cannot be retrieved again!');
164
+ }
165
+ }
166
+ catch (error) {
167
+ const err = error;
168
+ this.error(`Failed to create credential: ${err.message}`);
169
+ }
170
+ }
171
+ }
@@ -0,0 +1,24 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ export default class DeleteCredential extends BaseCommand<typeof DeleteCredential> {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ bucket: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ 'access-key': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
8
+ 'api-url': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ application: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ version: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
12
+ impersonate: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ manifest: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
14
+ config: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
15
+ rainbowAuthService: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
16
+ raindropCatalogService: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
+ rainbowAuthToken: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
18
+ rainbowOrganizationId: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
+ rainbowUserId: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
20
+ sendVersionMetadata: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
21
+ };
22
+ run(): Promise<void>;
23
+ }
24
+ //# sourceMappingURL=delete-credential.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete-credential.d.ts","sourceRoot":"","sources":["../../../src/commands/bucket/delete-credential.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,WAAW,CAAC,OAAO,gBAAgB,CAAC;IAChF,MAAM,CAAC,WAAW,SAA6B;IAE/C,MAAM,CAAC,QAAQ,WAOb;IAEF,MAAM,CAAC,KAAK;;;;;;;;;;;;;;;;MAgDV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAqF3B"}
@@ -0,0 +1,140 @@
1
+ import { toJsonString } from '@bufbuild/protobuf';
2
+ import { valueOf } from '@liquidmetal-ai/drizzle/appify/build';
3
+ import { DeleteCredentialResponseSchema } from '@liquidmetal-ai/drizzle/liquidmetal/v1alpha1/bucket_api_pb';
4
+ import { Flags } from '@oclif/core';
5
+ import { BaseCommand } from '../../base-command.js';
6
+ export default class DeleteCredential extends BaseCommand {
7
+ static description = 'Delete an S3 credential';
8
+ static examples = [
9
+ `<%= config.bin %> bucket delete-credential --bucket my-bucket --access-key AKIAIOSFODNN7EXAMPLE
10
+ Delete a specific credential
11
+ `,
12
+ `<%= config.bin %> bucket delete-credential --api-url https://bucket.example.com --access-key AKIAIOSFODNN7EXAMPLE
13
+ Delete credential using a direct API URL
14
+ `,
15
+ ];
16
+ static flags = {
17
+ ...BaseCommand.HIDDEN_FLAGS,
18
+ bucket: Flags.string({
19
+ char: 'b',
20
+ description: 'bucket name',
21
+ required: false,
22
+ exclusive: ['api-url'],
23
+ }),
24
+ 'access-key': Flags.string({
25
+ description: 'access key of the credential to delete',
26
+ required: true,
27
+ }),
28
+ 'api-url': Flags.string({
29
+ description: 'direct API URL (bypasses bucket discovery)',
30
+ required: false,
31
+ exclusive: ['bucket', 'application', 'version'],
32
+ }),
33
+ application: Flags.string({
34
+ char: 'a',
35
+ description: 'application name',
36
+ required: false,
37
+ exclusive: ['api-url'],
38
+ }),
39
+ version: Flags.string({
40
+ char: 'v',
41
+ description: 'application version',
42
+ required: false,
43
+ exclusive: ['api-url'],
44
+ }),
45
+ output: Flags.string({
46
+ char: 'o',
47
+ description: 'output format',
48
+ default: 'text',
49
+ options: ['text', 'json'],
50
+ }),
51
+ impersonate: Flags.string({
52
+ char: 'i',
53
+ description: 'impersonate organization',
54
+ required: false,
55
+ hidden: true,
56
+ }),
57
+ manifest: Flags.string({
58
+ char: 'M',
59
+ description: 'project manifest',
60
+ required: false,
61
+ default: 'raindrop.manifest',
62
+ hidden: true,
63
+ }),
64
+ };
65
+ async run() {
66
+ const { flags } = await this.parse(DeleteCredential);
67
+ // Validate that we have either api-url or bucket
68
+ if (!flags['api-url'] && !flags.bucket) {
69
+ this.error('Either --api-url or --bucket must be specified');
70
+ }
71
+ let apiUrl;
72
+ let bucketName;
73
+ if (flags['api-url']) {
74
+ // Direct API URL provided, skip discovery
75
+ apiUrl = flags['api-url'];
76
+ }
77
+ else {
78
+ // Need to discover the bucket
79
+ bucketName = flags.bucket;
80
+ // Get application info from flags or config/manifest
81
+ let applicationName = flags.application;
82
+ let applicationVersionId = flags.version;
83
+ if (!applicationVersionId) {
84
+ const config = await this.loadConfig();
85
+ applicationVersionId = config.versionId;
86
+ }
87
+ if (!applicationName) {
88
+ const apps = await this.loadManifest();
89
+ const app = apps[0];
90
+ if (app === undefined) {
91
+ this.error('No application provided or found in manifest', { exit: 1 });
92
+ }
93
+ applicationName = valueOf(app.name);
94
+ }
95
+ // Query for the bucket module
96
+ const { client: catalogService, userId, organizationId: defaultOrganizationId } = await this.catalogService();
97
+ const organizationId = flags.impersonate ?? defaultOrganizationId;
98
+ const modulesResp = await catalogService.queryModules({
99
+ userId,
100
+ applicationName,
101
+ applicationVersionId,
102
+ organizationId,
103
+ moduleType: 'bucket',
104
+ });
105
+ // Find the specific bucket
106
+ const bucketModule = modulesResp.modules.find(m => m.name === bucketName && m.type === 'bucket');
107
+ if (!bucketModule) {
108
+ this.error(`Bucket '${bucketName}' not found in application ${applicationName}@${applicationVersionId}`);
109
+ }
110
+ // Extract the API URL from the bucket module
111
+ apiUrl = bucketModule.bucket?.s3?.apiUrl;
112
+ if (!apiUrl) {
113
+ this.error(`Bucket '${bucketName}' does not have an API URL configured`);
114
+ }
115
+ }
116
+ // Create the S3 credential service client
117
+ const { client: credentialService } = await this.bucketApiService(apiUrl);
118
+ try {
119
+ const response = await credentialService.deleteCredential({
120
+ accessKey: flags['access-key'],
121
+ });
122
+ // Output the result
123
+ if (flags.output === 'json') {
124
+ console.log(toJsonString(DeleteCredentialResponseSchema, response, { prettySpaces: 2 }));
125
+ }
126
+ else {
127
+ if (response.deleted) {
128
+ console.log(`Successfully deleted credential '${flags['access-key']}'${bucketName ? ` from bucket '${bucketName}'` : ''}`);
129
+ }
130
+ else {
131
+ console.log(`Credential '${flags['access-key']}' not found${bucketName ? ` in bucket '${bucketName}'` : ''}`);
132
+ }
133
+ }
134
+ }
135
+ catch (error) {
136
+ const err = error;
137
+ this.error(`Failed to delete credential: ${err.message}`);
138
+ }
139
+ }
140
+ }
@@ -0,0 +1,24 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ export default class GetCredential extends BaseCommand<typeof GetCredential> {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ bucket: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ 'access-key': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
8
+ 'api-url': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ application: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ version: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
12
+ impersonate: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ manifest: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
14
+ config: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
15
+ rainbowAuthService: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
16
+ raindropCatalogService: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
+ rainbowAuthToken: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
18
+ rainbowOrganizationId: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
+ rainbowUserId: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
20
+ sendVersionMetadata: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
21
+ };
22
+ run(): Promise<void>;
23
+ }
24
+ //# sourceMappingURL=get-credential.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-credential.d.ts","sourceRoot":"","sources":["../../../src/commands/bucket/get-credential.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAW,CAAC,OAAO,aAAa,CAAC;IAC1E,MAAM,CAAC,WAAW,SAA6C;IAE/D,MAAM,CAAC,QAAQ,WAOb;IAEF,MAAM,CAAC,KAAK;;;;;;;;;;;;;;;;MAgDV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA+F3B"}
@@ -0,0 +1,149 @@
1
+ import { toJsonString } from '@bufbuild/protobuf';
2
+ import { timestampDate } from '@bufbuild/protobuf/wkt';
3
+ import { valueOf } from '@liquidmetal-ai/drizzle/appify/build';
4
+ import { GetCredentialResponseSchema } from '@liquidmetal-ai/drizzle/liquidmetal/v1alpha1/bucket_api_pb';
5
+ import { Flags } from '@oclif/core';
6
+ import { BaseCommand } from '../../base-command.js';
7
+ export default class GetCredential extends BaseCommand {
8
+ static description = 'Get details of a specific S3 credential';
9
+ static examples = [
10
+ `<%= config.bin %> bucket get-credential --bucket my-bucket --access-key AKIAIOSFODNN7EXAMPLE
11
+ Get details of a specific credential
12
+ `,
13
+ `<%= config.bin %> bucket get-credential --api-url https://bucket.example.com --access-key AKIAIOSFODNN7EXAMPLE
14
+ Get credential details using a direct API URL
15
+ `,
16
+ ];
17
+ static flags = {
18
+ ...BaseCommand.HIDDEN_FLAGS,
19
+ bucket: Flags.string({
20
+ char: 'b',
21
+ description: 'bucket name',
22
+ required: false,
23
+ exclusive: ['api-url'],
24
+ }),
25
+ 'access-key': Flags.string({
26
+ description: 'access key of the credential to retrieve',
27
+ required: true,
28
+ }),
29
+ 'api-url': Flags.string({
30
+ description: 'direct API URL (bypasses bucket discovery)',
31
+ required: false,
32
+ exclusive: ['bucket', 'application', 'version'],
33
+ }),
34
+ application: Flags.string({
35
+ char: 'a',
36
+ description: 'application name',
37
+ required: false,
38
+ exclusive: ['api-url'],
39
+ }),
40
+ version: Flags.string({
41
+ char: 'v',
42
+ description: 'application version',
43
+ required: false,
44
+ exclusive: ['api-url'],
45
+ }),
46
+ output: Flags.string({
47
+ char: 'o',
48
+ description: 'output format',
49
+ default: 'text',
50
+ options: ['text', 'json'],
51
+ }),
52
+ impersonate: Flags.string({
53
+ char: 'i',
54
+ description: 'impersonate organization',
55
+ required: false,
56
+ hidden: true,
57
+ }),
58
+ manifest: Flags.string({
59
+ char: 'M',
60
+ description: 'project manifest',
61
+ required: false,
62
+ default: 'raindrop.manifest',
63
+ hidden: true,
64
+ }),
65
+ };
66
+ async run() {
67
+ const { flags } = await this.parse(GetCredential);
68
+ // Validate that we have either api-url or bucket
69
+ if (!flags['api-url'] && !flags.bucket) {
70
+ this.error('Either --api-url or --bucket must be specified');
71
+ }
72
+ let apiUrl;
73
+ let bucketName;
74
+ if (flags['api-url']) {
75
+ // Direct API URL provided, skip discovery
76
+ apiUrl = flags['api-url'];
77
+ }
78
+ else {
79
+ // Need to discover the bucket
80
+ bucketName = flags.bucket;
81
+ // Get application info from flags or config/manifest
82
+ let applicationName = flags.application;
83
+ let applicationVersionId = flags.version;
84
+ if (!applicationVersionId) {
85
+ const config = await this.loadConfig();
86
+ applicationVersionId = config.versionId;
87
+ }
88
+ if (!applicationName) {
89
+ const apps = await this.loadManifest();
90
+ const app = apps[0];
91
+ if (app === undefined) {
92
+ this.error('No application provided or found in manifest', { exit: 1 });
93
+ }
94
+ applicationName = valueOf(app.name);
95
+ }
96
+ // Query for the bucket module
97
+ const { client: catalogService, userId, organizationId: defaultOrganizationId } = await this.catalogService();
98
+ const organizationId = flags.impersonate ?? defaultOrganizationId;
99
+ const modulesResp = await catalogService.queryModules({
100
+ userId,
101
+ applicationName,
102
+ applicationVersionId,
103
+ organizationId,
104
+ moduleType: 'bucket',
105
+ });
106
+ // Find the specific bucket
107
+ const bucketModule = modulesResp.modules.find(m => m.name === bucketName && m.type === 'bucket');
108
+ if (!bucketModule) {
109
+ this.error(`Bucket '${bucketName}' not found in application ${applicationName}@${applicationVersionId}`);
110
+ }
111
+ // Extract the API URL from the bucket module
112
+ apiUrl = bucketModule.bucket?.s3?.apiUrl;
113
+ if (!apiUrl) {
114
+ this.error(`Bucket '${bucketName}' does not have an API URL configured`);
115
+ }
116
+ }
117
+ // Create the S3 credential service client
118
+ const { client: credentialService } = await this.bucketApiService(apiUrl);
119
+ try {
120
+ const response = await credentialService.getCredential({
121
+ accessKey: flags['access-key'],
122
+ });
123
+ // Output the result
124
+ if (flags.output === 'json') {
125
+ console.log(toJsonString(GetCredentialResponseSchema, response, { prettySpaces: 2 }));
126
+ }
127
+ else {
128
+ const cred = response.credential;
129
+ if (!cred) {
130
+ this.error('No credential returned from service');
131
+ }
132
+ console.log(`Credential details${bucketName ? ` for bucket '${bucketName}'` : ''}:\n`);
133
+ console.log(`Access Key: ${cred.accessKey}`);
134
+ console.log(`Name: ${cred.name}`);
135
+ if (cred.createdAt) {
136
+ console.log(`Created: ${timestampDate(cred.createdAt).toISOString()}`);
137
+ }
138
+ if (cred.expiresAt) {
139
+ console.log(`Expires: ${timestampDate(cred.expiresAt).toISOString()}`);
140
+ }
141
+ console.log('\nNote: Secret key is not displayed for security reasons');
142
+ }
143
+ }
144
+ catch (error) {
145
+ const err = error;
146
+ this.error(`Failed to get credential: ${err.message}`);
147
+ }
148
+ }
149
+ }
@@ -0,0 +1,23 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ export default class ListCredentials extends BaseCommand<typeof ListCredentials> {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ bucket: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ 'api-url': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ application: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ version: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ impersonate: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ manifest: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
+ config: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
14
+ rainbowAuthService: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
15
+ raindropCatalogService: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
16
+ rainbowAuthToken: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
+ rainbowOrganizationId: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
18
+ rainbowUserId: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
+ sendVersionMetadata: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
20
+ };
21
+ run(): Promise<void>;
22
+ }
23
+ //# sourceMappingURL=list-credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-credentials.d.ts","sourceRoot":"","sources":["../../../src/commands/bucket/list-credentials.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,WAAW,CAAC,OAAO,eAAe,CAAC;IAC9E,MAAM,CAAC,WAAW,SAAsC;IAExD,MAAM,CAAC,QAAQ,WAOb;IAEF,MAAM,CAAC,KAAK;;;;;;;;;;;;;;;MA4CV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAkG3B"}