@clonecommand/cloud 0.0.3 → 0.0.7

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/README.md CHANGED
@@ -4,6 +4,13 @@ The official SDK for CloneCommand managed services.
4
4
 
5
5
  This library simplifies integration with ephemeral preview environments and provides access to CloneCommand Cloud services like Login Proxy, Storage, and Email.
6
6
 
7
+ ### 🤖 Agent Ready
8
+ This package is designed to be easily consumed by AI agents and LLMs. It features:
9
+ - **Full TypeScript Definitions**: All methods, arguments, and return types are strictly typed.
10
+ - **Rich JSDoc**: Comprehensive comments and examples to help agents understand the intent behind every function.
11
+ - **Clean API Surface**: A logical, singleton-based structure that is easy to navigate.
12
+
13
+
7
14
  ## Documentation
8
15
 
9
16
  Full documentation is available in the [`docs/`](./docs/README.md) directory.
@@ -1,69 +1,61 @@
1
- import { CloneCommandCloud } from '../index.js';
2
- export interface EmailConfig {
3
- id: string;
4
- projectId: string;
5
- domainId: string;
6
- isEnabled: boolean;
7
- sesIdentityArn?: string;
8
- sesVerificationStatus?: string;
9
- dkimTokens?: string;
10
- }
11
- export interface InboundEmail {
12
- id: string;
13
- projectId: string;
14
- sender: string;
15
- recipient: string;
16
- subject: string;
17
- snippet: string;
18
- bucketPath: string;
19
- receivedAt: string;
20
- isRead: boolean;
21
- hasAttachments: boolean;
22
- rawSize: number;
23
- threadId?: string;
24
- messageId?: string;
25
- inReplyTo?: string;
26
- references?: string;
27
- }
28
- export interface SendEmailOptions {
29
- from?: string;
30
- to: string | string[];
31
- subject: string;
32
- html?: string;
33
- text?: string;
34
- }
1
+ import { CloneCommandCloud } from "..";
2
+ import { InboundEmail, SendEmailOptions } from "./types";
3
+ /**
4
+ * Client for interacting with CloneCommand Email services.
5
+ */
35
6
  export declare class EmailClient {
36
7
  private ccc;
37
8
  constructor(ccc: CloneCommandCloud);
38
9
  /**
39
- * Get email configuration for the project.
40
- */
41
- getConfig(projectId?: string): Promise<EmailConfig | null>;
42
- /**
43
- * Enable email service for a domain.
10
+ * Checks if the email service is enabled for the current project.
11
+ *
12
+ * @returns A promise resolving to true if enabled, false otherwise.
44
13
  */
45
- enable(domainId: string, projectId?: string): Promise<EmailConfig>;
14
+ isEnabled(): Promise<boolean>;
46
15
  /**
47
- * Send an email.
16
+ * Sends an email message.
17
+ *
18
+ * @param options - The email content and recipient details.
19
+ * @returns A promise resolving to the Message-ID of the sent email.
20
+ * @throws Error if sending fails.
21
+ *
22
+ * @example
23
+ * await ccc.email.send({
24
+ * to: 'user@example.com',
25
+ * subject: 'Hello',
26
+ * text: 'This is a test'
27
+ * });
48
28
  */
49
- send(options: SendEmailOptions, projectId?: string): Promise<string>;
29
+ send(options: SendEmailOptions): Promise<string>;
50
30
  /**
51
- * Get inbound emails.
31
+ * Retrieves a list of inbound emails received by the project.
32
+ *
33
+ * @param options - Filtering and pagination options (limit, before).
34
+ * @returns A promise resolving to an array of InboundEmail previews.
52
35
  */
53
36
  getInbound(options?: {
54
37
  limit?: number;
55
38
  before?: Date;
56
- }, projectId?: string): Promise<InboundEmail[]>;
39
+ }): Promise<InboundEmail[]>;
57
40
  /**
58
- * Get a specific email by ID.
41
+ * Retrieves the full details of a specific inbound email, including the body.
42
+ *
43
+ * @param emailId - The unique ID of the email.
44
+ * @returns A promise resolving to the full InboundEmail object, or null if not found.
59
45
  */
60
46
  get(emailId: string): Promise<InboundEmail | null>;
61
47
  /**
62
- * Mark an email as read.
48
+ * Marks an inbound email as read.
49
+ *
50
+ * @param emailId - The unique ID of the email.
51
+ * @returns A promise resolving to true if successful.
63
52
  */
64
53
  markAsRead(emailId: string): Promise<boolean>;
65
54
  /**
66
- * Delete an email.
55
+ * Deletes an inbound email permanently.
56
+ *
57
+ * @param emailId - The unique ID of the email.
58
+ * @returns A promise resolving to true if successful.
67
59
  */
68
60
  delete(emailId: string): Promise<boolean>;
69
61
  }
@@ -1,24 +1,24 @@
1
+ /**
2
+ * Client for interacting with CloneCommand Email services.
3
+ */
1
4
  export class EmailClient {
2
5
  ccc;
3
6
  constructor(ccc) {
4
7
  this.ccc = ccc;
5
8
  }
6
9
  /**
7
- * Get email configuration for the project.
10
+ * Checks if the email service is enabled for the current project.
11
+ *
12
+ * @returns A promise resolving to true if enabled, false otherwise.
8
13
  */
9
- async getConfig(projectId) {
10
- const pid = projectId || this.ccc.projectId;
14
+ async isEnabled() {
15
+ const pid = this.ccc.projectId;
11
16
  if (!pid)
12
- throw new Error("projectId is required");
17
+ throw new Error("projectId could not be resolved. Ensure CC_PROJECT_TOKEN is set.");
13
18
  const query = `
14
- query EmailConfig($projectId: ID!) {
19
+ query EmailStatus($projectId: ID!) {
15
20
  emailConfig(projectId: $projectId) {
16
- id
17
- projectId
18
- domainId
19
21
  isEnabled
20
- sesVerificationStatus
21
- dkimTokens
22
22
  }
23
23
  }
24
24
  `;
@@ -32,46 +32,26 @@ export class EmailClient {
32
32
  });
33
33
  if (result.errors)
34
34
  throw new Error(result.errors[0].message);
35
- return result.data.emailConfig;
36
- }
37
- /**
38
- * Enable email service for a domain.
39
- */
40
- async enable(domainId, projectId) {
41
- const pid = projectId || this.ccc.projectId;
42
- if (!pid)
43
- throw new Error("projectId is required");
44
- const query = `
45
- mutation EnableEmail($projectId: ID!, $domainId: ID!) {
46
- enableEmail(projectId: $projectId, domainId: $domainId) {
47
- id
48
- projectId
49
- domainId
50
- isEnabled
51
- sesVerificationStatus
52
- dkimTokens
53
- }
54
- }
55
- `;
56
- const result = await this.ccc.request('/graphql', {
57
- method: 'POST',
58
- headers: { 'Content-Type': 'application/json' },
59
- body: JSON.stringify({
60
- query,
61
- variables: { projectId: pid, domainId }
62
- })
63
- });
64
- if (result.errors)
65
- throw new Error(result.errors[0].message);
66
- return result.data.enableEmail;
35
+ return !!result.data.emailConfig?.isEnabled;
67
36
  }
68
37
  /**
69
- * Send an email.
38
+ * Sends an email message.
39
+ *
40
+ * @param options - The email content and recipient details.
41
+ * @returns A promise resolving to the Message-ID of the sent email.
42
+ * @throws Error if sending fails.
43
+ *
44
+ * @example
45
+ * await ccc.email.send({
46
+ * to: 'user@example.com',
47
+ * subject: 'Hello',
48
+ * text: 'This is a test'
49
+ * });
70
50
  */
71
- async send(options, projectId) {
72
- const pid = projectId || this.ccc.projectId;
51
+ async send(options) {
52
+ const pid = this.ccc.projectId;
73
53
  if (!pid)
74
- throw new Error("projectId is required");
54
+ throw new Error("projectId could not be resolved. Ensure CC_PROJECT_TOKEN is set.");
75
55
  const query = `
76
56
  mutation SendEmail($projectId: ID!, $email: SendEmailInput!) {
77
57
  sendEmail(projectId: $projectId, email: $email)
@@ -99,12 +79,15 @@ export class EmailClient {
99
79
  return result.data.sendEmail;
100
80
  }
101
81
  /**
102
- * Get inbound emails.
82
+ * Retrieves a list of inbound emails received by the project.
83
+ *
84
+ * @param options - Filtering and pagination options (limit, before).
85
+ * @returns A promise resolving to an array of InboundEmail previews.
103
86
  */
104
- async getInbound(options = {}, projectId) {
105
- const pid = projectId || this.ccc.projectId;
87
+ async getInbound(options = {}) {
88
+ const pid = this.ccc.projectId;
106
89
  if (!pid)
107
- throw new Error("projectId is required");
90
+ throw new Error("projectId could not be resolved. Ensure CC_PROJECT_TOKEN is set.");
108
91
  const query = `
109
92
  query InboundEmails($projectId: ID!, $limit: Int, $before: DateTime) {
110
93
  inboundEmails(projectId: $projectId, limit: $limit, before: $before) {
@@ -137,7 +120,10 @@ export class EmailClient {
137
120
  return result.data.inboundEmails;
138
121
  }
139
122
  /**
140
- * Get a specific email by ID.
123
+ * Retrieves the full details of a specific inbound email, including the body.
124
+ *
125
+ * @param emailId - The unique ID of the email.
126
+ * @returns A promise resolving to the full InboundEmail object, or null if not found.
141
127
  */
142
128
  async get(emailId) {
143
129
  const query = `
@@ -169,7 +155,10 @@ export class EmailClient {
169
155
  return result.data.email;
170
156
  }
171
157
  /**
172
- * Mark an email as read.
158
+ * Marks an inbound email as read.
159
+ *
160
+ * @param emailId - The unique ID of the email.
161
+ * @returns A promise resolving to true if successful.
173
162
  */
174
163
  async markAsRead(emailId) {
175
164
  const query = `
@@ -190,7 +179,10 @@ export class EmailClient {
190
179
  return result.data.markEmailAsRead;
191
180
  }
192
181
  /**
193
- * Delete an email.
182
+ * Deletes an inbound email permanently.
183
+ *
184
+ * @param emailId - The unique ID of the email.
185
+ * @returns A promise resolving to true if successful.
194
186
  */
195
187
  async delete(emailId) {
196
188
  const query = `
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Represents an inbound email received by the system.
3
+ */
4
+ export interface InboundEmail {
5
+ /** Unique ID of the email. */
6
+ id: string;
7
+ /** Project ID this email belongs to. */
8
+ projectId: string;
9
+ /** The email address of the sender. */
10
+ sender: string;
11
+ /** The email address of the recipient. */
12
+ recipient: string;
13
+ /** The subject line of the email. */
14
+ subject: string;
15
+ /** A short snippet/preview of the email content. */
16
+ snippet: string;
17
+ /** The full HTML or text body of the email (only available in detailed view). */
18
+ body?: string;
19
+ /** The path to the raw email file in storage. */
20
+ bucketPath: string;
21
+ /** ISO timestamp when the email was received. */
22
+ receivedAt: string;
23
+ /** Whether the email has been marked as read. */
24
+ isRead: boolean;
25
+ /** Whether the email contains attachments. */
26
+ hasAttachments: boolean;
27
+ /** Total size of the raw email in bytes. */
28
+ rawSize: number;
29
+ /** Thread ID for grouping related emails. */
30
+ threadId?: string;
31
+ /** Standard Message-ID header. */
32
+ messageId?: string;
33
+ /** In-Reply-To header. */
34
+ inReplyTo?: string;
35
+ /** References header. */
36
+ references?: string;
37
+ }
38
+ /**
39
+ * Options for sending an email.
40
+ */
41
+ export interface SendEmailOptions {
42
+ /**
43
+ * The sender address. Must be a verified domain.
44
+ * Use "Name <email@domain.com>" or just "email@domain.com".
45
+ */
46
+ from?: string;
47
+ /** The recipient(s). Can be a string or an array of strings. */
48
+ to: string | string[];
49
+ /** The subject line. */
50
+ subject: string;
51
+ /** The HTML body of the email. */
52
+ html?: string;
53
+ /** The plain text body of the email. */
54
+ text?: string;
55
+ }
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.d.ts CHANGED
@@ -1,79 +1,100 @@
1
- export interface CCCConfig {
2
- projectId?: string;
3
- baseUrl?: string;
4
- }
5
- export interface StorageFile {
6
- id: string;
7
- projectId: string;
8
- fileId: string;
9
- originalFilename?: string;
10
- contentType: string;
11
- sizeBytes?: number;
12
- extension?: string;
13
- publicUrl: string;
14
- createdAt: string;
15
- }
16
1
  import { EmailClient } from './email/index.js';
2
+ import { CCCConfig, StorageFile } from './types.js';
3
+ /**
4
+ * The main client for interacting with CloneCommand managed services.
5
+ * This class provides access to storage, email, and authentication features.
6
+ */
17
7
  export declare class CloneCommandCloud {
18
8
  private config;
9
+ private _email;
10
+ /**
11
+ * Initializes the SDK with configuration options.
12
+ *
13
+ * @param config - The configuration object.
14
+ */
19
15
  init(config: CCCConfig): void;
16
+ /**
17
+ * Returns the current project ID.
18
+ * Resolution order:
19
+ * 1. Manual config via `init()`
20
+ * 2. `CC_PROJECT_ID` environment variable
21
+ * 3. Extracted from the `CC_PROJECT_TOKEN` JWT.
22
+ */
20
23
  get projectId(): string | undefined;
24
+ /**
25
+ * The base URL for API requests.
26
+ */
21
27
  get baseUrl(): string;
28
+ /**
29
+ * The service token used for authentication.
30
+ * Resolution order:
31
+ * 1. Manual config via `init()`
32
+ * 2. `CC_PROJECT_TOKEN` environment variable.
33
+ */
22
34
  get serviceToken(): string | undefined;
23
35
  /**
24
36
  * Internal helper to make authenticated requests to the CloneCommand API.
25
- * This is used by server-side methods (e.g., image uploads).
37
+ *
38
+ * @param path - The API path (e.g., '/graphql').
39
+ * @param options - Standard RequestInit options.
40
+ * @returns A promise resolving to the JSON response.
41
+ * @throws Error if the request fails or returns a non-OK status.
42
+ */
43
+ request<T = any>(path: string, options?: RequestInit): Promise<T>;
44
+ /**
45
+ * Login and authentication utilities.
26
46
  */
27
- request(path: string, options?: RequestInit): Promise<any>;
28
47
  get login(): {
29
48
  /**
30
49
  * Wraps a standard OAuth authorization URL with the CloneCommand Proxy.
31
50
  * This allows ephemeral preview environments (*.clonecommand.app) to handle
32
51
  * OAuth redirects without constant provider configuration changes.
33
52
  *
34
- * @param originalUrl The standard OAuth authorization URL
35
- * @returns The proxied URL to redirect the user to
53
+ * @param originalUrl - The standard OAuth authorization URL.
54
+ * @returns The proxied URL to redirect the user to.
55
+ * @throws Error if projectId is not configured.
36
56
  */
37
57
  proxy: (originalUrl: string) => string;
38
58
  };
59
+ /**
60
+ * Storage and file management utilities.
61
+ */
39
62
  get storage(): {
40
63
  /**
41
- * Import a file from a URL and upload it to CloneCommand Storage.
64
+ * Imports a file from a URL and uploads it to CloneCommand Storage.
42
65
  *
43
- * @param url The URL of the file to import
44
- * @param contentType Optional content type (auto-detected if not provided)
45
- * @returns StorageFile object with publicUrl
66
+ * @param url - The URL of the file to import.
67
+ * @param contentType - Optional content type (auto-detected if not provided).
68
+ * @returns A promise resolving to the StorageFile record.
46
69
  *
47
70
  * @example
48
71
  * const file = await ccc.storage.importFileFromUrl('https://example.com/image.png');
49
- * console.log(file.publicUrl); // https://media.clonecommand.com/:projectId/:fileId/original.png
50
72
  */
51
73
  importFileFromUrl: (url: string, contentType?: string) => Promise<StorageFile>;
52
74
  /**
53
- * Import a file from a Buffer and upload it to CloneCommand Storage.
54
- *
55
- * @param buffer The file buffer
56
- * @param contentType The content type of the file
57
- * @returns StorageFile object with publicUrl
75
+ * Uploads a file from a memory buffer.
58
76
  *
59
- * @example
60
- * const buffer = fs.readFileSync('image.png');
61
- * const file = await ccc.storage.importFileFromBuffer(buffer, 'image/png');
77
+ * @param buffer - The file contents as a Buffer.
78
+ * @param contentType - The MIME type of the file.
79
+ * @param filename - Optional filename.
80
+ * @returns A promise resolving to the StorageFile record.
62
81
  */
63
82
  importFileFromBuffer: (buffer: Buffer, contentType: string, filename?: string) => Promise<StorageFile>;
64
83
  /**
65
- * Get the public URL for a file.
66
- *
67
- * @param fileId The file ID
68
- * @param projectSlug Optional project slug (uses projectId from config if not provided)
69
- * @returns The public URL
84
+ * Generates a public URL for a given file ID.
70
85
  *
71
- * @example
72
- * const url = ccc.storage.getFileUrl('abc-123-def', 'my-project');
73
- * // => https://my-project.clonecommand.media/abc-123-def/original
86
+ * @param fileId - The unique file ID.
87
+ * @param projectSlug - Optional project slug (automatically resolved from projectId if not provided).
88
+ * @returns The public URL string.
74
89
  */
75
90
  getFileUrl: (fileId: string, projectSlug?: string) => string;
76
91
  };
92
+ /**
93
+ * Access to email services.
94
+ */
77
95
  get email(): EmailClient;
78
96
  }
97
+ /**
98
+ * Singleton instance of the CloneCommandCloud client.
99
+ */
79
100
  export declare const ccc: CloneCommandCloud;
package/dist/index.js CHANGED
@@ -1,12 +1,29 @@
1
1
  import { EmailClient } from './email/index.js';
2
+ /**
3
+ * The main client for interacting with CloneCommand managed services.
4
+ * This class provides access to storage, email, and authentication features.
5
+ */
2
6
  export class CloneCommandCloud {
3
7
  config = {};
8
+ _email = null;
9
+ /**
10
+ * Initializes the SDK with configuration options.
11
+ *
12
+ * @param config - The configuration object.
13
+ */
4
14
  init(config) {
5
15
  this.config = {
6
16
  ...this.config,
7
17
  ...config,
8
18
  };
9
19
  }
20
+ /**
21
+ * Returns the current project ID.
22
+ * Resolution order:
23
+ * 1. Manual config via `init()`
24
+ * 2. `CC_PROJECT_ID` environment variable
25
+ * 3. Extracted from the `CC_PROJECT_TOKEN` JWT.
26
+ */
10
27
  get projectId() {
11
28
  if (this.config.projectId)
12
29
  return this.config.projectId;
@@ -30,15 +47,28 @@ export class CloneCommandCloud {
30
47
  }
31
48
  return undefined;
32
49
  }
50
+ /**
51
+ * The base URL for API requests.
52
+ */
33
53
  get baseUrl() {
34
54
  return this.config.baseUrl || 'https://graph.clonecommand.com';
35
55
  }
56
+ /**
57
+ * The service token used for authentication.
58
+ * Resolution order:
59
+ * 1. Manual config via `init()`
60
+ * 2. `CC_PROJECT_TOKEN` environment variable.
61
+ */
36
62
  get serviceToken() {
37
- return typeof process !== 'undefined' ? process.env.CC_PROJECT_TOKEN : undefined;
63
+ return this.config.serviceToken || (typeof process !== 'undefined' ? process.env.CC_PROJECT_TOKEN : undefined);
38
64
  }
39
65
  /**
40
66
  * Internal helper to make authenticated requests to the CloneCommand API.
41
- * This is used by server-side methods (e.g., image uploads).
67
+ *
68
+ * @param path - The API path (e.g., '/graphql').
69
+ * @param options - Standard RequestInit options.
70
+ * @returns A promise resolving to the JSON response.
71
+ * @throws Error if the request fails or returns a non-OK status.
42
72
  */
43
73
  async request(path, options = {}) {
44
74
  const token = this.serviceToken;
@@ -56,6 +86,9 @@ export class CloneCommandCloud {
56
86
  }
57
87
  return response.json();
58
88
  }
89
+ /**
90
+ * Login and authentication utilities.
91
+ */
59
92
  get login() {
60
93
  return {
61
94
  /**
@@ -63,43 +96,40 @@ export class CloneCommandCloud {
63
96
  * This allows ephemeral preview environments (*.clonecommand.app) to handle
64
97
  * OAuth redirects without constant provider configuration changes.
65
98
  *
66
- * @param originalUrl The standard OAuth authorization URL
67
- * @returns The proxied URL to redirect the user to
99
+ * @param originalUrl - The standard OAuth authorization URL.
100
+ * @returns The proxied URL to redirect the user to.
101
+ * @throws Error if projectId is not configured.
68
102
  */
69
103
  proxy: (originalUrl) => {
70
104
  const pid = this.projectId;
71
105
  if (!pid) {
72
- throw new Error("CloneCommand: projectId is required. Provide it in ccc.init({ projectId }) " +
73
- "or set the CC_PROJECT_ID environment variable.");
106
+ throw new Error("CloneCommand: projectId is required but could not be resolved from CC_PROJECT_TOKEN or environment. " +
107
+ "Provide it in ccc.init({ projectId }) or set the CC_PROJECT_ID environment variable.");
74
108
  }
75
109
  const encodedUrl = encodeURIComponent(originalUrl);
76
110
  return `${this.baseUrl}/login/proxy/start?projectId=${pid}&url=${encodedUrl}`;
77
111
  }
78
112
  };
79
113
  }
114
+ /**
115
+ * Storage and file management utilities.
116
+ */
80
117
  get storage() {
81
118
  return {
82
119
  /**
83
- * Import a file from a URL and upload it to CloneCommand Storage.
120
+ * Imports a file from a URL and uploads it to CloneCommand Storage.
84
121
  *
85
- * @param url The URL of the file to import
86
- * @param contentType Optional content type (auto-detected if not provided)
87
- * @returns StorageFile object with publicUrl
122
+ * @param url - The URL of the file to import.
123
+ * @param contentType - Optional content type (auto-detected if not provided).
124
+ * @returns A promise resolving to the StorageFile record.
88
125
  *
89
126
  * @example
90
127
  * const file = await ccc.storage.importFileFromUrl('https://example.com/image.png');
91
- * console.log(file.publicUrl); // https://media.clonecommand.com/:projectId/:fileId/original.png
92
128
  */
93
129
  importFileFromUrl: async (url, contentType) => {
94
- const token = this.serviceToken;
95
130
  const pid = this.projectId;
96
- if (!token) {
97
- throw new Error("CloneCommand Storage: CC_PROJECT_TOKEN is required. " +
98
- "Ensure your service is deployed via CloneCommand or use 'clones run' for local development.");
99
- }
100
131
  if (!pid) {
101
- throw new Error("CloneCommand Storage: projectId is required. " +
102
- "Set CC_PROJECT_ID environment variable or call ccc.init({ projectId }).");
132
+ throw new Error("CloneCommand Storage: projectId could not be resolved. Ensure CC_PROJECT_TOKEN is set.");
103
133
  }
104
134
  const query = `
105
135
  mutation UploadFileFromUrl($projectId: String!, $url: String!, $contentType: String) {
@@ -118,9 +148,7 @@ export class CloneCommandCloud {
118
148
  `;
119
149
  const result = await this.request('/graphql', {
120
150
  method: 'POST',
121
- headers: {
122
- 'Content-Type': 'application/json',
123
- },
151
+ headers: { 'Content-Type': 'application/json' },
124
152
  body: JSON.stringify({
125
153
  query,
126
154
  variables: { projectId: pid, url, contentType },
@@ -132,24 +160,17 @@ export class CloneCommandCloud {
132
160
  return result.data.uploadFileFromUrl;
133
161
  },
134
162
  /**
135
- * Import a file from a Buffer and upload it to CloneCommand Storage.
163
+ * Uploads a file from a memory buffer.
136
164
  *
137
- * @param buffer The file buffer
138
- * @param contentType The content type of the file
139
- * @returns StorageFile object with publicUrl
140
- *
141
- * @example
142
- * const buffer = fs.readFileSync('image.png');
143
- * const file = await ccc.storage.importFileFromBuffer(buffer, 'image/png');
165
+ * @param buffer - The file contents as a Buffer.
166
+ * @param contentType - The MIME type of the file.
167
+ * @param filename - Optional filename.
168
+ * @returns A promise resolving to the StorageFile record.
144
169
  */
145
170
  importFileFromBuffer: async (buffer, contentType, filename = 'file') => {
146
- const token = this.serviceToken;
147
171
  const pid = this.projectId;
148
- if (!token) {
149
- throw new Error("CloneCommand Storage: CC_PROJECT_TOKEN is required.");
150
- }
151
172
  if (!pid) {
152
- throw new Error("CloneCommand Storage: projectId is required.");
173
+ throw new Error("CloneCommand Storage: projectId could not be resolved. Ensure CC_PROJECT_TOKEN is set.");
153
174
  }
154
175
  const query = `
155
176
  mutation UploadFileFromBuffer($projectId: String!, $buffer: String!, $contentType: String!, $filename: String!) {
@@ -185,31 +206,33 @@ export class CloneCommandCloud {
185
206
  return result.data.uploadFileFromBuffer;
186
207
  },
187
208
  /**
188
- * Get the public URL for a file.
209
+ * Generates a public URL for a given file ID.
189
210
  *
190
- * @param fileId The file ID
191
- * @param projectSlug Optional project slug (uses projectId from config if not provided)
192
- * @returns The public URL
193
- *
194
- * @example
195
- * const url = ccc.storage.getFileUrl('abc-123-def', 'my-project');
196
- * // => https://my-project.clonecommand.media/abc-123-def/original
211
+ * @param fileId - The unique file ID.
212
+ * @param projectSlug - Optional project slug (automatically resolved from projectId if not provided).
213
+ * @returns The public URL string.
197
214
  */
198
215
  getFileUrl: (fileId, projectSlug) => {
199
216
  const pid = this.projectId;
200
217
  const slug = projectSlug || pid;
201
218
  if (!slug) {
202
- throw new Error("CloneCommand Storage: projectId or projectSlug is required. " +
203
- "Set CC_PROJECT_ID environment variable or call ccc.init({ projectId }).");
219
+ throw new Error("CloneCommand Storage: projectId or projectSlug could not be resolved.");
204
220
  }
205
- // Note: This returns the default projectslug.clonecommand.media URL
206
- // Custom domains are handled server-side
207
221
  return `https://${slug}.clonecommand.media/${fileId}/original`;
208
222
  },
209
223
  };
210
224
  }
225
+ /**
226
+ * Access to email services.
227
+ */
211
228
  get email() {
212
- return new EmailClient(this);
229
+ if (!this._email) {
230
+ this._email = new EmailClient(this);
231
+ }
232
+ return this._email;
213
233
  }
214
234
  }
235
+ /**
236
+ * Singleton instance of the CloneCommandCloud client.
237
+ */
215
238
  export const ccc = new CloneCommandCloud();
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Configuration for the CloneCommand Cloud SDK.
3
+ */
4
+ export interface CCCConfig {
5
+ /**
6
+ * The unique identifier for your project.
7
+ * Can also be set via the `CC_PROJECT_ID` environment variable.
8
+ */
9
+ projectId?: string;
10
+ /**
11
+ * The base URL for the CloneCommand API.
12
+ * Defaults to `https://graph.clonecommand.com`.
13
+ */
14
+ baseUrl?: string;
15
+ /**
16
+ * The service token for authentication.
17
+ * Can also be set via the `CC_PROJECT_TOKEN` environment variable.
18
+ */
19
+ serviceToken?: string;
20
+ }
21
+ /**
22
+ * Represents a file stored in CloneCommand Storage.
23
+ */
24
+ export interface StorageFile {
25
+ /** Unique ID of the storage record. */
26
+ id: string;
27
+ /** Project ID this file belongs to. */
28
+ projectId: string;
29
+ /** The underlying storage provider's file ID. */
30
+ fileId: string;
31
+ /** Original filename if available. */
32
+ originalFilename?: string;
33
+ /** MIME type of the file. */
34
+ contentType: string;
35
+ /** Size of the file in bytes. */
36
+ sizeBytes?: number;
37
+ /** File extension. */
38
+ extension?: string;
39
+ /** Publicly accessible URL for the file. */
40
+ publicUrl: string;
41
+ /** ISO timestamp when the file was uploaded. */
42
+ createdAt: string;
43
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/docs/email.md CHANGED
@@ -10,17 +10,17 @@ Managed email sending and receiving with inbound processing and domain verificat
10
10
 
11
11
  ## Usage
12
12
 
13
- ### Getting Configuration
13
+ ### Checking Status
14
14
 
15
- Check if email is enabled for the current project.
15
+ Check if the email service is enabled and ready to use for the current project.
16
16
 
17
17
  ```typescript
18
18
  import { ccc } from '@clonecommand/cloud';
19
19
 
20
- const config = await ccc.email.getConfig();
20
+ const enabled = await ccc.email.isEnabled();
21
21
 
22
- if (config?.isEnabled) {
23
- console.log('Email is active!');
22
+ if (enabled) {
23
+ console.log('Email is active and ready to send!');
24
24
  }
25
25
  ```
26
26
 
package/package.json CHANGED
@@ -1,10 +1,20 @@
1
1
  {
2
2
  "name": "@clonecommand/cloud",
3
- "version": "0.0.3",
3
+ "version": "0.0.7",
4
4
  "type": "module",
5
5
  "description": "The official SDK for CloneCommand managed services",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./email": {
14
+ "types": "./dist/email/index.d.ts",
15
+ "import": "./dist/email/index.js"
16
+ }
17
+ },
8
18
  "files": [
9
19
  "dist",
10
20
  "README.md",