@agendapanda/cli 0.1.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 (40) hide show
  1. package/dist/bin/ap.d.ts +2 -0
  2. package/dist/bin/ap.js +21 -0
  3. package/dist/bin/ap.js.map +1 -0
  4. package/dist/src/commands/auth.d.ts +2 -0
  5. package/dist/src/commands/auth.js +219 -0
  6. package/dist/src/commands/auth.js.map +1 -0
  7. package/dist/src/commands/calendar.d.ts +2 -0
  8. package/dist/src/commands/calendar.js +207 -0
  9. package/dist/src/commands/calendar.js.map +1 -0
  10. package/dist/src/commands/connections.d.ts +2 -0
  11. package/dist/src/commands/connections.js +198 -0
  12. package/dist/src/commands/connections.js.map +1 -0
  13. package/dist/src/commands/media.d.ts +2 -0
  14. package/dist/src/commands/media.js +44 -0
  15. package/dist/src/commands/media.js.map +1 -0
  16. package/dist/src/commands/post.d.ts +2 -0
  17. package/dist/src/commands/post.js +271 -0
  18. package/dist/src/commands/post.js.map +1 -0
  19. package/dist/src/commands/projects.d.ts +2 -0
  20. package/dist/src/commands/projects.js +66 -0
  21. package/dist/src/commands/projects.js.map +1 -0
  22. package/dist/src/index.d.ts +3 -0
  23. package/dist/src/index.js +38 -0
  24. package/dist/src/index.js.map +1 -0
  25. package/dist/src/lib/api.d.ts +13 -0
  26. package/dist/src/lib/api.js +106 -0
  27. package/dist/src/lib/api.js.map +1 -0
  28. package/dist/src/lib/config.d.ts +8 -0
  29. package/dist/src/lib/config.js +34 -0
  30. package/dist/src/lib/config.js.map +1 -0
  31. package/dist/src/lib/input.d.ts +1 -0
  32. package/dist/src/lib/input.js +10 -0
  33. package/dist/src/lib/input.js.map +1 -0
  34. package/dist/src/lib/output.d.ts +26 -0
  35. package/dist/src/lib/output.js +74 -0
  36. package/dist/src/lib/output.js.map +1 -0
  37. package/dist/src/types.d.ts +86 -0
  38. package/dist/src/types.js +3 -0
  39. package/dist/src/types.js.map +1 -0
  40. package/package.json +30 -0
@@ -0,0 +1,38 @@
1
+ import { Command } from 'commander';
2
+ import { registerAuthCommands } from './commands/auth.js';
3
+ import { registerProjectsCommands } from './commands/projects.js';
4
+ import { registerConnectionsCommands } from './commands/connections.js';
5
+ import { registerPostCommands } from './commands/post.js';
6
+ import { registerMediaCommands } from './commands/media.js';
7
+ import { registerCalendarCommands } from './commands/calendar.js';
8
+ import { initJsonMode } from './lib/output.js';
9
+ // Detect JSON mode early from argv/TTY, before Commander parses.
10
+ // This ensures parser-level errors (missing args, unknown commands)
11
+ // also emit structured JSON.
12
+ export const earlyJsonMode = process.argv.includes('--json') || !process.stdout.isTTY;
13
+ if (earlyJsonMode) {
14
+ initJsonMode({ json: true });
15
+ }
16
+ export const program = new Command();
17
+ program
18
+ .name('ap')
19
+ .description('Agenda Panda CLI - schedule social media posts from the terminal')
20
+ .version('0.1.0');
21
+ // Throw CommanderError instead of calling process.exit(), so bin/ap.ts
22
+ // can catch it and emit structured JSON when appropriate.
23
+ program.exitOverride();
24
+ // Suppress Commander's default stderr output when in JSON mode;
25
+ // the catch block in bin/ap.ts emits the structured envelope instead.
26
+ // Keep stdout untouched so --help / --version still work normally.
27
+ if (earlyJsonMode) {
28
+ program.configureOutput({
29
+ writeErr: () => { },
30
+ });
31
+ }
32
+ registerAuthCommands(program);
33
+ registerProjectsCommands(program);
34
+ registerConnectionsCommands(program);
35
+ registerPostCommands(program);
36
+ registerMediaCommands(program);
37
+ registerCalendarCommands(program);
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,iEAAiE;AACjE,oEAAoE;AACpE,6BAA6B;AAC7B,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;AACtF,IAAI,aAAa,EAAE,CAAC;IACnB,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAErC,OAAO;KACL,IAAI,CAAC,IAAI,CAAC;KACV,WAAW,CAAC,kEAAkE,CAAC;KAC/E,OAAO,CAAC,OAAO,CAAC,CAAC;AAEnB,uEAAuE;AACvE,0DAA0D;AAC1D,OAAO,CAAC,YAAY,EAAE,CAAC;AAEvB,gEAAgE;AAChE,sEAAsE;AACtE,mEAAmE;AACnE,IAAI,aAAa,EAAE,CAAC;IACnB,OAAO,CAAC,eAAe,CAAC;QACvB,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC;KAClB,CAAC,CAAC;AACJ,CAAC;AAED,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAClC,2BAA2B,CAAC,OAAO,CAAC,CAAC;AACrC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,wBAAwB,CAAC,OAAO,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ export declare class ApiError extends Error {
2
+ statusCode: number;
3
+ code?: string | undefined;
4
+ constructor(message: string, statusCode: number, code?: string | undefined);
5
+ }
6
+ export declare const api: {
7
+ get<T = any>(path: string): Promise<T>;
8
+ post<T = any>(path: string, body?: unknown): Promise<T>;
9
+ put<T = any>(path: string, body?: unknown): Promise<T>;
10
+ delete<T = any>(path: string): Promise<T>;
11
+ upload<T = any>(path: string, formData: FormData): Promise<T>;
12
+ getRedirect(path: string): Promise<string>;
13
+ };
@@ -0,0 +1,106 @@
1
+ import { getApiKey, getApiUrl } from './config.js';
2
+ export class ApiError extends Error {
3
+ statusCode;
4
+ code;
5
+ constructor(message, statusCode, code) {
6
+ super(message);
7
+ this.statusCode = statusCode;
8
+ this.code = code;
9
+ this.name = 'ApiError';
10
+ }
11
+ }
12
+ function getHeaders() {
13
+ const key = getApiKey();
14
+ if (!key) {
15
+ throw new ApiError('Not authenticated. Run `ap auth login` or set AP_API_KEY.', 0, 'NOT_AUTHENTICATED');
16
+ }
17
+ return {
18
+ Authorization: `Bearer ${key}`,
19
+ 'Content-Type': 'application/json',
20
+ };
21
+ }
22
+ async function handleResponse(res) {
23
+ const body = await res.text();
24
+ let data;
25
+ try {
26
+ data = JSON.parse(body);
27
+ }
28
+ catch {
29
+ throw new ApiError(`Invalid response from server: ${body.slice(0, 200)}`, res.status);
30
+ }
31
+ if (!res.ok) {
32
+ const message = data.error?.message || data.error || `Request failed with status ${res.status}`;
33
+ const code = data.code || undefined;
34
+ throw new ApiError(message, res.status, code);
35
+ }
36
+ return data;
37
+ }
38
+ function buildUrl(path) {
39
+ const base = getApiUrl().replace(/\/$/, '');
40
+ return `${base}${path}`;
41
+ }
42
+ export const api = {
43
+ async get(path) {
44
+ const res = await fetch(buildUrl(path), {
45
+ method: 'GET',
46
+ headers: getHeaders(),
47
+ });
48
+ return handleResponse(res);
49
+ },
50
+ async post(path, body) {
51
+ const res = await fetch(buildUrl(path), {
52
+ method: 'POST',
53
+ headers: getHeaders(),
54
+ body: body !== undefined ? JSON.stringify(body) : undefined,
55
+ });
56
+ return handleResponse(res);
57
+ },
58
+ async put(path, body) {
59
+ const res = await fetch(buildUrl(path), {
60
+ method: 'PUT',
61
+ headers: getHeaders(),
62
+ body: body !== undefined ? JSON.stringify(body) : undefined,
63
+ });
64
+ return handleResponse(res);
65
+ },
66
+ async delete(path) {
67
+ const res = await fetch(buildUrl(path), {
68
+ method: 'DELETE',
69
+ headers: getHeaders(),
70
+ });
71
+ return handleResponse(res);
72
+ },
73
+ async upload(path, formData) {
74
+ const key = getApiKey();
75
+ if (!key) {
76
+ throw new ApiError('Not authenticated. Run `ap auth login` or set AP_API_KEY.', 0, 'NOT_AUTHENTICATED');
77
+ }
78
+ const res = await fetch(buildUrl(path), {
79
+ method: 'POST',
80
+ headers: {
81
+ Authorization: `Bearer ${key}`,
82
+ // Don't set Content-Type - fetch sets it with boundary for FormData
83
+ },
84
+ body: formData,
85
+ });
86
+ return handleResponse(res);
87
+ },
88
+ async getRedirect(path) {
89
+ const res = await fetch(buildUrl(path), {
90
+ method: 'GET',
91
+ headers: getHeaders(),
92
+ redirect: 'manual',
93
+ });
94
+ if (res.status >= 300 && res.status < 400) {
95
+ const location = res.headers.get('location');
96
+ if (!location) {
97
+ throw new ApiError('Missing redirect location from server', res.status, 'MISSING_REDIRECT');
98
+ }
99
+ return location;
100
+ }
101
+ // For non-redirect responses, parse the body to surface a proper API error.
102
+ await handleResponse(res);
103
+ throw new ApiError(`Expected redirect from server, got status ${res.status}`, res.status, 'UNEXPECTED_RESPONSE');
104
+ },
105
+ };
106
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/lib/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare function getApiKey(): string;
2
+ export declare function getApiUrl(): string;
3
+ export declare function getActiveProject(): string;
4
+ export declare function setApiKey(key: string): void;
5
+ export declare function setApiUrl(url: string): void;
6
+ export declare function setActiveProject(projectId: string): void;
7
+ export declare function clearConfig(): void;
8
+ export declare function getConfigPath(): string;
@@ -0,0 +1,34 @@
1
+ import Conf from 'conf';
2
+ const config = new Conf({
3
+ projectName: 'agendapanda',
4
+ schema: {
5
+ api_key: { type: 'string', default: '' },
6
+ api_url: { type: 'string', default: 'https://agendapanda.com' },
7
+ active_project: { type: 'string', default: '' },
8
+ },
9
+ });
10
+ export function getApiKey() {
11
+ return process.env.AP_API_KEY || config.get('api_key');
12
+ }
13
+ export function getApiUrl() {
14
+ return process.env.AP_API_URL || config.get('api_url');
15
+ }
16
+ export function getActiveProject() {
17
+ return process.env.AP_PROJECT || config.get('active_project');
18
+ }
19
+ export function setApiKey(key) {
20
+ config.set('api_key', key);
21
+ }
22
+ export function setApiUrl(url) {
23
+ config.set('api_url', url);
24
+ }
25
+ export function setActiveProject(projectId) {
26
+ config.set('active_project', projectId);
27
+ }
28
+ export function clearConfig() {
29
+ config.clear();
30
+ }
31
+ export function getConfigPath() {
32
+ return config.path;
33
+ }
34
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAQxB,MAAM,MAAM,GAAG,IAAI,IAAI,CAAe;IACrC,WAAW,EAAE,aAAa;IAC1B,MAAM,EAAE;QACP,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE;QACxC,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,yBAAyB,EAAE;QAC/D,cAAc,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE;KAC/C;CACD,CAAC,CAAC;AAEH,MAAM,UAAU,SAAS;IACxB,OAAO,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,SAAS;IACxB,OAAO,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC/B,OAAO,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW;IACpC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW;IACpC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IACjD,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,WAAW;IAC1B,MAAM,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,aAAa;IAC5B,OAAO,MAAM,CAAC,IAAI,CAAC;AACpB,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function readStdin(): Promise<string | null>;
@@ -0,0 +1,10 @@
1
+ export async function readStdin() {
2
+ if (process.stdin.isTTY)
3
+ return null;
4
+ const chunks = [];
5
+ for await (const chunk of process.stdin) {
6
+ chunks.push(chunk);
7
+ }
8
+ return Buffer.concat(chunks).toString('utf8').trim() || null;
9
+ }
10
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../../../src/lib/input.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,SAAS;IAC9B,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Call at the top of every command action to lock in the output mode
3
+ * for the entire command lifetime, including error paths.
4
+ */
5
+ export declare function initJsonMode(options: {
6
+ json?: boolean;
7
+ }): void;
8
+ export declare function isJsonMode(options: {
9
+ json?: boolean;
10
+ }): boolean;
11
+ export declare function outputJson(data: unknown): void;
12
+ export declare function outputTable(headers: string[], rows: string[][]): void;
13
+ export declare function outputSuccess(msg: string): void;
14
+ /**
15
+ * Output an error as JSON to stderr when the process is in JSON mode
16
+ * (set by initJsonMode), or as human-readable text otherwise.
17
+ */
18
+ export declare function outputError(msg: string, code?: string): void;
19
+ /** Wrap list data in stable JSON envelope */
20
+ export declare function outputItems(items: unknown[], options: {
21
+ json?: boolean;
22
+ }): void;
23
+ /** Wrap mutation result in stable JSON envelope */
24
+ export declare function outputMutation(item: unknown, options: {
25
+ json?: boolean;
26
+ }): void;
@@ -0,0 +1,74 @@
1
+ import chalk from 'chalk';
2
+ // Process-level flag: once a command sets this, all subsequent outputError
3
+ // calls in that process (including catch blocks without access to options)
4
+ // will emit structured JSON.
5
+ let _jsonMode = false;
6
+ /**
7
+ * Call at the top of every command action to lock in the output mode
8
+ * for the entire command lifetime, including error paths.
9
+ */
10
+ export function initJsonMode(options) {
11
+ _jsonMode = options.json === true || !process.stdout.isTTY;
12
+ }
13
+ export function isJsonMode(options) {
14
+ return options.json === true || !process.stdout.isTTY;
15
+ }
16
+ export function outputJson(data) {
17
+ process.stdout.write(JSON.stringify(data, null, 2) + '\n');
18
+ }
19
+ export function outputTable(headers, rows) {
20
+ if (rows.length === 0) {
21
+ console.log(chalk.dim('No results.'));
22
+ return;
23
+ }
24
+ // Calculate column widths
25
+ const widths = headers.map((h, i) => {
26
+ const maxData = rows.reduce((max, row) => Math.max(max, (row[i] || '').length), 0);
27
+ return Math.max(h.length, maxData);
28
+ });
29
+ // Print header
30
+ const headerLine = headers.map((h, i) => h.padEnd(widths[i])).join(' ');
31
+ console.log(chalk.bold(headerLine));
32
+ console.log(chalk.dim(widths.map((w) => '-'.repeat(w)).join(' ')));
33
+ // Print rows
34
+ for (const row of rows) {
35
+ const line = row.map((cell, i) => (cell || '').padEnd(widths[i])).join(' ');
36
+ console.log(line);
37
+ }
38
+ }
39
+ export function outputSuccess(msg) {
40
+ if (_jsonMode) {
41
+ outputJson({ success: true, message: msg });
42
+ }
43
+ else {
44
+ console.log(chalk.green('✓') + ' ' + msg);
45
+ }
46
+ }
47
+ /**
48
+ * Output an error as JSON to stderr when the process is in JSON mode
49
+ * (set by initJsonMode), or as human-readable text otherwise.
50
+ */
51
+ export function outputError(msg, code) {
52
+ if (_jsonMode) {
53
+ const data = { error: msg };
54
+ if (code)
55
+ data.code = code;
56
+ process.stderr.write(JSON.stringify(data) + '\n');
57
+ }
58
+ else {
59
+ console.error(chalk.red('Error:') + ' ' + msg);
60
+ }
61
+ }
62
+ /** Wrap list data in stable JSON envelope */
63
+ export function outputItems(items, options) {
64
+ if (isJsonMode(options)) {
65
+ outputJson({ items });
66
+ }
67
+ }
68
+ /** Wrap mutation result in stable JSON envelope */
69
+ export function outputMutation(item, options) {
70
+ if (isJsonMode(options)) {
71
+ outputJson({ success: true, item });
72
+ }
73
+ }
74
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/lib/output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ export interface ApiUser {
2
+ id: string;
3
+ name: string;
4
+ email: string;
5
+ plan: string;
6
+ }
7
+ export interface MeResponse {
8
+ user: ApiUser;
9
+ active_projects_count: number;
10
+ }
11
+ export interface ApiKey {
12
+ id: string;
13
+ name: string;
14
+ key?: string;
15
+ key_prefix: string;
16
+ last_used_at: string | null;
17
+ created_at: string;
18
+ }
19
+ export interface Project {
20
+ id: string;
21
+ name: string;
22
+ has_twitter: boolean;
23
+ website: string | null;
24
+ industry: string | null;
25
+ target_audience: string | null;
26
+ brand_voice: string | null;
27
+ onboarding_completed: boolean;
28
+ created_at: string;
29
+ user_role: string;
30
+ }
31
+ export interface Post {
32
+ id: string;
33
+ project_id: string;
34
+ project_name?: string;
35
+ content: string;
36
+ platform: string;
37
+ scheduled_at: string;
38
+ posted: boolean;
39
+ posted_at: string | null;
40
+ error: string | null;
41
+ created_at: string;
42
+ social_connection_id: string | null;
43
+ media_url: string | null;
44
+ account_name?: string | null;
45
+ }
46
+ export interface Connection {
47
+ id: string;
48
+ platform: string;
49
+ platform_username: string | null;
50
+ platform_display_name: string | null;
51
+ platform_user_id: string;
52
+ created_at: string;
53
+ }
54
+ export interface ConnectionHealth {
55
+ connection_id: string;
56
+ platform: string;
57
+ account_name: string;
58
+ status: 'healthy' | 'warning' | 'error';
59
+ summary: string;
60
+ details: string[];
61
+ checked_at: string;
62
+ token_expires_at: number | null;
63
+ expires_in_seconds: number | null;
64
+ }
65
+ export interface MediaUploadResult {
66
+ id: string;
67
+ url: string;
68
+ filename: string;
69
+ contentType: string;
70
+ size: number;
71
+ }
72
+ export interface CalendarItem {
73
+ content: string;
74
+ connection: string;
75
+ schedule: string;
76
+ image?: string;
77
+ idempotency_key?: string;
78
+ }
79
+ export interface CalendarImportResult {
80
+ status: 'created' | 'skipped' | 'failed';
81
+ content: string;
82
+ connection: string;
83
+ schedule: string;
84
+ error?: string;
85
+ post?: Post;
86
+ }
@@ -0,0 +1,3 @@
1
+ // Type definitions matching backend response shapes
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,oDAAoD"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@agendapanda/cli",
3
+ "version": "0.1.0",
4
+ "description": "Agenda Panda CLI - schedule social media posts from the terminal",
5
+ "bin": {
6
+ "ap": "dist/bin/ap.js"
7
+ },
8
+ "type": "module",
9
+ "engines": {
10
+ "node": ">=20.0.0"
11
+ },
12
+ "files": [
13
+ "dist/"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "dev": "tsc --watch",
18
+ "prepublishOnly": "npm run build"
19
+ },
20
+ "dependencies": {
21
+ "chalk": "^5.3.0",
22
+ "commander": "^12.0.0",
23
+ "conf": "^12.0.0",
24
+ "ora": "^8.0.0"
25
+ },
26
+ "devDependencies": {
27
+ "@types/node": "^20.0.0",
28
+ "typescript": "^5.5.0"
29
+ }
30
+ }