@tightknitai/tightknit 0.1.0-alpha.4 → 0.1.0-alpha.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.
@@ -1,26 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import { spawn } from 'node:child_process';
3
- import { fileURLToPath } from 'node:url';
4
- import { dirname, join } from 'node:path';
5
- import { realpathSync, existsSync } from 'node:fs';
6
-
7
- const __filename = realpathSync(fileURLToPath(import.meta.url));
8
- const __dirname = dirname(__filename);
9
-
10
- function findTsx() {
11
- let dir = __dirname;
12
- while (dir !== dirname(dir)) {
13
- const candidate = join(dir, 'node_modules', '.bin', 'tsx');
14
- if (existsSync(candidate)) {
15
- return candidate;
16
- }
17
- dir = dirname(dir);
18
- }
19
- return 'tsx';
20
- }
21
-
22
- const tsx = findTsx();
23
- const script = join(__dirname, '..', 'src', 'mcp', 'server.ts');
24
-
25
- const child = spawn(tsx, [script], { stdio: 'inherit' });
26
- child.on('exit', (code) => process.exit(code ?? 0));
2
+ await import('../dist/mcp/server.js');
package/bin/tightknit.js CHANGED
@@ -1,40 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { spawn, execFileSync } from 'node:child_process';
3
- import { fileURLToPath } from 'node:url';
4
- import { dirname, join } from 'node:path';
5
- import { realpathSync, existsSync } from 'node:fs';
2
+ import { createProgram, checkForUpdates } from '../dist/cli/index.js';
6
3
 
7
- // Resolve symlinks to get the actual package directory
8
- const __filename = realpathSync(fileURLToPath(import.meta.url));
9
- const __dirname = dirname(__filename);
4
+ checkForUpdates();
10
5
 
11
- /** Find tsx binary by walking up node_modules */
12
- function findTsx() {
13
- let dir = __dirname;
14
- while (dir !== dirname(dir)) {
15
- const candidate = join(dir, 'node_modules', '.bin', 'tsx');
16
- if (existsSync(candidate)) {
17
- return candidate;
18
- }
19
- dir = dirname(dir);
20
- }
21
- // Fallback: assume tsx is on PATH
22
- return 'tsx';
23
- }
6
+ const program = createProgram();
24
7
 
25
- const tsx = findTsx();
26
-
27
- // If first arg is "mcp", run the MCP server (needs spawn for bidirectional stdio)
28
- if (process.argv[2] === 'mcp') {
29
- const script = join(__dirname, '..', 'src', 'mcp', 'server.ts');
30
- const child = spawn(tsx, [script], { stdio: 'inherit' });
31
- child.on('exit', (code) => process.exit(code ?? 0));
32
- } else {
33
- // Run the CLI
34
- const script = join(__dirname, 'tightknit.ts');
35
- try {
36
- execFileSync(tsx, [script, ...process.argv.slice(2)], { stdio: 'inherit' });
37
- } catch (err) {
38
- process.exit(err.status ?? 1);
39
- }
40
- }
8
+ program.parseAsync(process.argv).catch(() => {
9
+ process.exit(1);
10
+ });
@@ -0,0 +1,280 @@
1
+ // src/core/config.ts
2
+ import Conf from "conf";
3
+ var config = new Conf({
4
+ projectName: "tightknit",
5
+ defaults: {
6
+ apiKey: "",
7
+ defaultOutput: "table",
8
+ environment: "production"
9
+ }
10
+ });
11
+ var runtimeApiKey;
12
+ function setRuntimeApiKey(key) {
13
+ runtimeApiKey = key;
14
+ }
15
+ function getApiKey() {
16
+ return runtimeApiKey || process.env.TIGHTKNIT_API_KEY || config.get("apiKey");
17
+ }
18
+ function setApiKey(key) {
19
+ config.set("apiKey", key);
20
+ }
21
+ function getDefaultOutput() {
22
+ return config.get("defaultOutput");
23
+ }
24
+ function setDefaultOutput(format) {
25
+ config.set("defaultOutput", format);
26
+ }
27
+ function getEnvironment() {
28
+ return process.env.TIGHTKNIT_ENVIRONMENT || config.get("environment");
29
+ }
30
+ function setEnvironment(env) {
31
+ config.set("environment", env);
32
+ }
33
+ var VALID_CONFIG_KEYS = "api-key, default-output, environment";
34
+ function getConfigValue(key) {
35
+ switch (key) {
36
+ case "api-key":
37
+ return getApiKey();
38
+ case "default-output":
39
+ return getDefaultOutput();
40
+ case "environment":
41
+ return getEnvironment();
42
+ default:
43
+ throw new Error(`Unknown config key: ${key}. Valid keys: ${VALID_CONFIG_KEYS}`);
44
+ }
45
+ }
46
+ function setConfigValue(key, value) {
47
+ switch (key) {
48
+ case "api-key":
49
+ setApiKey(value);
50
+ break;
51
+ case "default-output":
52
+ if (value !== "json" && value !== "table") {
53
+ throw new Error(`Invalid output format: ${value}. Must be "json" or "table"`);
54
+ }
55
+ setDefaultOutput(value);
56
+ break;
57
+ case "environment":
58
+ if (value !== "production" && value !== "staging") {
59
+ throw new Error(`Invalid environment: ${value}. Must be "production" or "staging"`);
60
+ }
61
+ setEnvironment(value);
62
+ break;
63
+ default:
64
+ throw new Error(`Unknown config key: ${key}. Valid keys: ${VALID_CONFIG_KEYS}`);
65
+ }
66
+ }
67
+ function getConfigPath() {
68
+ return config.path;
69
+ }
70
+
71
+ // src/core/version.ts
72
+ import { readFileSync } from "fs";
73
+ import { fileURLToPath } from "url";
74
+ import { dirname, join } from "path";
75
+ function readVersion() {
76
+ let dir = dirname(fileURLToPath(import.meta.url));
77
+ for (let i = 0; i < 5; i++) {
78
+ try {
79
+ const pkgPath = join(dir, "package.json");
80
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
81
+ if (pkg.name === "@tightknitai/tightknit") {
82
+ return pkg.version ?? "0.0.0";
83
+ }
84
+ } catch {
85
+ }
86
+ dir = dirname(dir);
87
+ }
88
+ return "0.0.0";
89
+ }
90
+ var VERSION = readVersion();
91
+
92
+ // src/core/client.ts
93
+ var BASE_URLS = {
94
+ production: "https://api.tightknit.ai",
95
+ staging: "https://staging-api.tightknit.ai"
96
+ };
97
+ var API_PREFIX = "/admin/v0";
98
+ function getBaseUrl() {
99
+ return BASE_URLS[getEnvironment()];
100
+ }
101
+ function buildUrl(path, params) {
102
+ const url = new URL(`${API_PREFIX}${path}`, getBaseUrl());
103
+ if (params) {
104
+ for (const [key, value] of Object.entries(params)) {
105
+ if (value !== void 0) {
106
+ url.searchParams.set(key, String(value));
107
+ }
108
+ }
109
+ }
110
+ return url.toString();
111
+ }
112
+ async function parseErrorResponse(response) {
113
+ let message;
114
+ try {
115
+ const body = await response.json();
116
+ message = body.message || body.error || response.statusText;
117
+ } catch {
118
+ message = response.statusText;
119
+ }
120
+ return {
121
+ error: true,
122
+ code: response.status,
123
+ message: `${message} (${response.status})`
124
+ };
125
+ }
126
+ async function apiRequest(path, options = {}) {
127
+ const { method = "GET", body, params, idempotencyKey } = options;
128
+ const apiKey = getApiKey();
129
+ if (!apiKey) {
130
+ throw new TightknitApiError(
131
+ "No API key configured. Run: tightknit config set api-key <YOUR_KEY>",
132
+ 401
133
+ );
134
+ }
135
+ const headers = {
136
+ Authorization: `Bearer ${apiKey}`,
137
+ "Content-Type": "application/json"
138
+ };
139
+ if (idempotencyKey && (method === "POST" || method === "PATCH")) {
140
+ headers["Idempotency-Key"] = idempotencyKey;
141
+ }
142
+ const url = buildUrl(path, params);
143
+ const response = await fetch(url, {
144
+ method,
145
+ headers,
146
+ body: body ? JSON.stringify(body) : void 0
147
+ });
148
+ if (!response.ok) {
149
+ const apiError = await parseErrorResponse(response);
150
+ throw new TightknitApiError(apiError.message, apiError.code);
151
+ }
152
+ if (response.status === 204) {
153
+ return void 0;
154
+ }
155
+ return await response.json();
156
+ }
157
+ var TightknitApiError = class extends Error {
158
+ code;
159
+ constructor(message, code) {
160
+ super(message);
161
+ this.name = "TightknitApiError";
162
+ this.code = code;
163
+ }
164
+ toJSON() {
165
+ return {
166
+ error: true,
167
+ code: this.code,
168
+ message: this.message
169
+ };
170
+ }
171
+ };
172
+ async function listEvents(params) {
173
+ return apiRequest(
174
+ "/calendar_events",
175
+ { params }
176
+ );
177
+ }
178
+ async function createEvent(input) {
179
+ return apiRequest("/calendar_events", {
180
+ method: "POST",
181
+ body: input,
182
+ idempotencyKey: crypto.randomUUID()
183
+ });
184
+ }
185
+ async function getEvent(id) {
186
+ return apiRequest(`/calendar_events/${id}`);
187
+ }
188
+ async function deleteEvent(id) {
189
+ return apiRequest(`/calendar_events/${id}`, { method: "DELETE" });
190
+ }
191
+ async function updateAttendee(eventId, input) {
192
+ return apiRequest(`/calendar_events/${eventId}/attendees`, {
193
+ method: "PATCH",
194
+ body: input,
195
+ idempotencyKey: crypto.randomUUID()
196
+ });
197
+ }
198
+ async function assignAward(awardId, input) {
199
+ return apiRequest(`/awards/${awardId}/assign`, {
200
+ method: "POST",
201
+ body: input,
202
+ idempotencyKey: crypto.randomUUID()
203
+ });
204
+ }
205
+ async function listFeeds(params) {
206
+ return apiRequest(
207
+ "/feeds",
208
+ { params }
209
+ );
210
+ }
211
+ async function getFeed(feedId) {
212
+ return apiRequest(`/feeds/${feedId}`);
213
+ }
214
+ async function listPostsInFeed(feedId, params) {
215
+ return apiRequest(
216
+ `/feeds/${feedId}/posts`,
217
+ { params }
218
+ );
219
+ }
220
+ async function getPost(postId) {
221
+ return apiRequest(`/posts/${postId}`);
222
+ }
223
+ async function addMember(input) {
224
+ return apiRequest("/members", {
225
+ method: "POST",
226
+ body: input,
227
+ idempotencyKey: crypto.randomUUID()
228
+ });
229
+ }
230
+ async function checkMembership(email) {
231
+ return apiRequest("/members/check", {
232
+ method: "POST",
233
+ body: { email }
234
+ });
235
+ }
236
+ async function addUserToGroup(groupId, input) {
237
+ return apiRequest(`/groups/${groupId}/members`, {
238
+ method: "POST",
239
+ body: input,
240
+ idempotencyKey: crypto.randomUUID()
241
+ });
242
+ }
243
+ async function sendMessage(input) {
244
+ return apiRequest("/messages", {
245
+ method: "POST",
246
+ body: input,
247
+ idempotencyKey: crypto.randomUUID()
248
+ });
249
+ }
250
+ async function search(params) {
251
+ return apiRequest(
252
+ "/search",
253
+ { params }
254
+ );
255
+ }
256
+
257
+ export {
258
+ setRuntimeApiKey,
259
+ getConfigValue,
260
+ setConfigValue,
261
+ getConfigPath,
262
+ VERSION,
263
+ TightknitApiError,
264
+ listEvents,
265
+ createEvent,
266
+ getEvent,
267
+ deleteEvent,
268
+ updateAttendee,
269
+ assignAward,
270
+ listFeeds,
271
+ getFeed,
272
+ listPostsInFeed,
273
+ getPost,
274
+ addMember,
275
+ checkMembership,
276
+ addUserToGroup,
277
+ sendMessage,
278
+ search
279
+ };
280
+ //# sourceMappingURL=chunk-PRA5JZ27.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/config.ts","../src/core/version.ts","../src/core/client.ts"],"sourcesContent":["import Conf from \"conf\";\n\nexport type Environment = \"production\" | \"staging\";\n\ninterface TightknitConfig {\n apiKey: string;\n defaultOutput: \"json\" | \"table\";\n environment: Environment;\n}\n\nconst config = new Conf<TightknitConfig>({\n projectName: \"tightknit\",\n defaults: {\n apiKey: \"\",\n defaultOutput: \"table\",\n environment: \"production\",\n },\n});\n\n/** Runtime API key set via --api-key flag (highest precedence) */\nlet runtimeApiKey: string | undefined;\n\n/** Set a runtime API key (from --api-key flag). Takes highest precedence. */\nexport function setRuntimeApiKey(key: string | undefined): void {\n runtimeApiKey = key;\n}\n\n/** Get the API key — --api-key flag > env var > stored config */\nexport function getApiKey(): string {\n return runtimeApiKey || process.env.TIGHTKNIT_API_KEY || config.get(\"apiKey\");\n}\n\n/** Set the API key */\nexport function setApiKey(key: string): void {\n config.set(\"apiKey\", key);\n}\n\n/** Get the default output format */\nexport function getDefaultOutput(): \"json\" | \"table\" {\n return config.get(\"defaultOutput\");\n}\n\n/** Set the default output format */\nexport function setDefaultOutput(format: \"json\" | \"table\"): void {\n config.set(\"defaultOutput\", format);\n}\n\n/** Get the configured environment */\nexport function getEnvironment(): Environment {\n return (process.env.TIGHTKNIT_ENVIRONMENT as Environment) || config.get(\"environment\");\n}\n\n/** Set the environment */\nexport function setEnvironment(env: Environment): void {\n config.set(\"environment\", env);\n}\n\nconst VALID_CONFIG_KEYS = \"api-key, default-output, environment\";\n\n/** Get a config value by key name */\nexport function getConfigValue(key: string): string {\n switch (key) {\n case \"api-key\":\n return getApiKey();\n case \"default-output\":\n return getDefaultOutput();\n case \"environment\":\n return getEnvironment();\n default:\n throw new Error(`Unknown config key: ${key}. Valid keys: ${VALID_CONFIG_KEYS}`);\n }\n}\n\n/** Set a config value by key name */\nexport function setConfigValue(key: string, value: string): void {\n switch (key) {\n case \"api-key\":\n setApiKey(value);\n break;\n case \"default-output\":\n if (value !== \"json\" && value !== \"table\") {\n throw new Error(`Invalid output format: ${value}. Must be \"json\" or \"table\"`);\n }\n setDefaultOutput(value);\n break;\n case \"environment\":\n if (value !== \"production\" && value !== \"staging\") {\n throw new Error(`Invalid environment: ${value}. Must be \"production\" or \"staging\"`);\n }\n setEnvironment(value);\n break;\n default:\n throw new Error(`Unknown config key: ${key}. Valid keys: ${VALID_CONFIG_KEYS}`);\n }\n}\n\n/** Get the config file path (useful for debugging) */\nexport function getConfigPath(): string {\n return config.path;\n}\n","import { readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join } from 'node:path';\n\n/** Walks up from the current module to find the CLI's package.json version */\nfunction readVersion(): string {\n let dir = dirname(fileURLToPath(import.meta.url));\n for (let i = 0; i < 5; i++) {\n try {\n const pkgPath = join(dir, 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as {\n name?: string;\n version?: string;\n };\n if (pkg.name === '@tightknitai/tightknit') {\n return pkg.version ?? '0.0.0';\n }\n } catch {\n // continue walking up\n }\n dir = dirname(dir);\n }\n return '0.0.0';\n}\n\nexport const VERSION = readVersion();\n","import { getApiKey, getEnvironment } from \"./config\";\nimport type { ApiError } from \"./types\";\n\nconst BASE_URLS = {\n production: \"https://api.tightknit.ai\",\n staging: \"https://staging-api.tightknit.ai\",\n} as const;\n\nconst API_PREFIX = \"/admin/v0\";\n\n/** Get the base URL for the current environment */\nfunction getBaseUrl(): string {\n return BASE_URLS[getEnvironment()];\n}\n\ninterface RequestOptions {\n method?: \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\";\n body?: Record<string, unknown>;\n params?: Record<string, string | number | boolean | undefined>;\n idempotencyKey?: string;\n}\n\n/** Build a URL with query parameters */\nfunction buildUrl(path: string, params?: Record<string, string | number | boolean | undefined>): string {\n const url = new URL(`${API_PREFIX}${path}`, getBaseUrl());\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n return url.toString();\n}\n\n/** Parse an API error response into a structured error */\nasync function parseErrorResponse(response: Response): Promise<ApiError> {\n let message: string;\n try {\n const body = await response.json() as Record<string, unknown>;\n message = (body.message as string) || (body.error as string) || response.statusText;\n } catch {\n message = response.statusText;\n }\n\n return {\n error: true,\n code: response.status,\n message: `${message} (${response.status})`,\n };\n}\n\n/** Make an authenticated request to the Tightknit API */\nexport async function apiRequest<T>(path: string, options: RequestOptions = {}): Promise<T> {\n const { method = \"GET\", body, params, idempotencyKey } = options;\n\n const apiKey = getApiKey();\n if (!apiKey) {\n throw new TightknitApiError(\n 'No API key configured. Run: tightknit config set api-key <YOUR_KEY>',\n 401\n );\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n };\n\n if (idempotencyKey && (method === \"POST\" || method === \"PATCH\")) {\n headers[\"Idempotency-Key\"] = idempotencyKey;\n }\n\n const url = buildUrl(path, params);\n\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const apiError = await parseErrorResponse(response);\n throw new TightknitApiError(apiError.message, apiError.code);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n return (await response.json()) as T;\n}\n\n/** Custom error class for Tightknit API errors */\nexport class TightknitApiError extends Error {\n code: number;\n\n constructor(message: string, code: number) {\n super(message);\n this.name = \"TightknitApiError\";\n this.code = code;\n }\n\n toJSON(): ApiError {\n return {\n error: true,\n code: this.code,\n message: this.message,\n };\n }\n}\n\n// --- Calendar Events ---\n// Paths use underscores: /calendar_events\n\nexport interface ListEventsParams {\n page?: number;\n per_page?: number;\n time_filter?: \"upcoming\" | \"past\";\n date_filter?: string;\n status?: \"draft\" | \"needs_approval\" | \"published\";\n published_to_site?: boolean;\n is_unlisted?: boolean;\n feed_id?: string;\n tag_ids?: string;\n}\n\n/**\n * List calendar events with optional filtering and pagination.\n * @param params - Optional filters for time, status, feed, pagination, etc.\n * @returns Paginated list of calendar events.\n */\nexport async function listEvents(params?: ListEventsParams) {\n return apiRequest<{ data: unknown[]; page: number; per_page: number }>(\n \"/calendar_events\",\n { params: params as Record<string, string | number | boolean | undefined> }\n );\n}\n\nexport interface CreateEventInput {\n title: string;\n description: string;\n start_date: string;\n end_date: string;\n location?: string;\n link?: string;\n status?: \"needs_approval\" | \"published\";\n slug?: string;\n publish_to_site?: boolean;\n is_unlisted?: boolean;\n allow_public_guest_list?: boolean;\n enable_registration_button?: boolean;\n triggers_webhooks?: boolean;\n external_speakers?: string;\n cover_image_file_id?: string;\n reminders_config?: number[];\n publish_to_slack_channels?: string[];\n}\n\n/**\n * Create a new calendar event.\n * @param input - Event details including title, dates, and optional settings.\n * @returns The created event's ID and success status.\n */\nexport async function createEvent(input: CreateEventInput) {\n return apiRequest<{ success: boolean; data: { calendar_event_id: string } }>(\"/calendar_events\", {\n method: \"POST\",\n body: input as unknown as Record<string, unknown>,\n idempotencyKey: crypto.randomUUID(),\n });\n}\n\n/**\n * Get a single calendar event by ID.\n * @param id - The calendar event ID.\n * @returns The calendar event details.\n */\nexport async function getEvent(id: string) {\n return apiRequest<unknown>(`/calendar_events/${id}`);\n}\n\n/**\n * Delete a calendar event by ID.\n * @param id - The calendar event ID.\n * @returns void on success (204 response).\n */\nexport async function deleteEvent(id: string) {\n return apiRequest<void>(`/calendar_events/${id}`, { method: \"DELETE\" });\n}\n\nexport interface UpdateAttendeeInput {\n user: { slack_user_id: string } | { email: string } | { profile_id: string };\n personal_join_link?: string;\n}\n\n/**\n * Update or add an attendee for a calendar event.\n * @param eventId - The calendar event ID.\n * @param input - Attendee user identifier and optional join link.\n * @returns The updated attendee details.\n */\nexport async function updateAttendee(eventId: string, input: UpdateAttendeeInput) {\n return apiRequest<unknown>(`/calendar_events/${eventId}/attendees`, {\n method: \"PATCH\",\n body: input as unknown as Record<string, unknown>,\n idempotencyKey: crypto.randomUUID(),\n });\n}\n\n// --- Awards ---\n\nexport interface AssignAwardInput {\n recipient: { slack_user_id: string } | { email: string } | { profile_id: string };\n sender?: { slack_user_id: string } | { email: string } | { profile_id: string } | null;\n send_anonymously?: boolean;\n}\n\n/**\n * Assign an award to a recipient.\n * @param awardId - The award ID to assign.\n * @param input - Recipient identifier and optional sender/anonymity settings.\n * @returns Success status.\n */\nexport async function assignAward(awardId: string, input: AssignAwardInput) {\n return apiRequest<{ success: boolean }>(`/awards/${awardId}/assign`, {\n method: \"POST\",\n body: input as unknown as Record<string, unknown>,\n idempotencyKey: crypto.randomUUID(),\n });\n}\n\n// --- Feeds ---\n\nexport interface ListFeedsParams {\n page?: number;\n per_page?: number;\n is_unlisted?: boolean;\n is_archived?: boolean;\n}\n\n/**\n * List feeds with optional filtering and pagination.\n * @param params - Optional filters for unlisted/archived status and pagination.\n * @returns Paginated list of feeds.\n */\nexport async function listFeeds(params?: ListFeedsParams) {\n return apiRequest<{ data: unknown[]; page: number; per_page: number }>(\n \"/feeds\",\n { params: params as Record<string, string | number | boolean | undefined> }\n );\n}\n\n/**\n * Get a single feed by ID.\n * @param feedId - The feed ID.\n * @returns The feed details.\n */\nexport async function getFeed(feedId: string) {\n return apiRequest<unknown>(`/feeds/${feedId}`);\n}\n\nexport interface ListPostsInFeedParams {\n page?: number;\n per_page?: number;\n sort?: \"oldest\" | \"newest\" | \"most-recent-activity\";\n}\n\n/**\n * List posts within a feed with optional sorting and pagination.\n * @param feedId - The feed ID to list posts from.\n * @param params - Optional sort order and pagination.\n * @returns Paginated list of posts.\n */\nexport async function listPostsInFeed(feedId: string, params?: ListPostsInFeedParams) {\n return apiRequest<{ data: unknown[]; page: number; per_page: number }>(\n `/feeds/${feedId}/posts`,\n { params: params as Record<string, string | number | boolean | undefined> }\n );\n}\n\n// --- Posts ---\n\n/**\n * Get a single post by ID.\n * @param postId - The post ID.\n * @returns The post details.\n */\nexport async function getPost(postId: string) {\n return apiRequest<unknown>(`/posts/${postId}`);\n}\n\n// --- Members ---\n\nexport interface AddMemberInput {\n email: string;\n full_name: string;\n avatar_url_original?: string;\n}\n\n/**\n * Add a new member to the community (Enterprise feature).\n * @param input - Member details including email, name, and optional avatar.\n * @returns The created member details.\n */\nexport async function addMember(input: AddMemberInput) {\n return apiRequest<unknown>(\"/members\", {\n method: \"POST\",\n body: input as unknown as Record<string, unknown>,\n idempotencyKey: crypto.randomUUID(),\n });\n}\n\n/**\n * Check if a user is a member of the community by email.\n * @param email - The email address to check.\n * @returns Membership status and details.\n */\nexport async function checkMembership(email: string) {\n return apiRequest<unknown>(\"/members/check\", {\n method: \"POST\",\n body: { email },\n });\n}\n\n// --- Groups ---\n\nexport interface AddUserToGroupInput {\n user: { slack_user_id: string } | { email: string } | { profile_id: string };\n}\n\n/**\n * Add a user to a group.\n * @param groupId - The group ID.\n * @param input - User identifier to add to the group.\n * @returns The updated group membership details.\n */\nexport async function addUserToGroup(groupId: string, input: AddUserToGroupInput) {\n return apiRequest<unknown>(`/groups/${groupId}/members`, {\n method: \"POST\",\n body: input as unknown as Record<string, unknown>,\n idempotencyKey: crypto.randomUUID(),\n });\n}\n\n// --- Messages ---\n\nexport interface SendMessageInput {\n channel: string;\n text: string;\n thread_ts?: string;\n}\n\n/**\n * Send a message to a Slack channel.\n * @param input - Channel, message text, and optional thread timestamp.\n * @returns The sent message details.\n */\nexport async function sendMessage(input: SendMessageInput) {\n return apiRequest<unknown>(\"/messages\", {\n method: \"POST\",\n body: input as unknown as Record<string, unknown>,\n idempotencyKey: crypto.randomUUID(),\n });\n}\n\n// --- Search ---\n\nexport interface SearchParams {\n q: string;\n type: \"post\" | \"comment\" | \"content_resource\";\n page?: number;\n per_page?: number;\n}\n\n/**\n * Search across community content (Beta).\n * @param params - Search query, content type, and optional pagination.\n * @returns Paginated search results.\n */\nexport async function search(params: SearchParams) {\n return apiRequest<{ data: unknown[]; page: number; per_page: number }>(\n \"/search\",\n { params: params as unknown as Record<string, string | number | boolean | undefined> }\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,12 @@
1
+ import { Command } from 'commander';
2
+
3
+ /**
4
+ * Check for updates in the background and print a notice if a newer version is available.
5
+ * This is non-blocking — the check runs asynchronously and the CLI doesn't wait for it.
6
+ */
7
+ declare function checkForUpdates(): void;
8
+
9
+ /** Create and configure the root CLI program */
10
+ declare function createProgram(): Command;
11
+
12
+ export { checkForUpdates, createProgram };