twenty-sdk 0.0.6 → 0.1.1

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/README.md +82 -8
  2. package/dist/_commonjsHelpers-DKOUU3wS.js +1 -0
  3. package/dist/_commonjsHelpers-DaMA6jEr.mjs +8 -0
  4. package/dist/application/application-config.d.ts +1 -2
  5. package/dist/application/field-metadata/field.decorator.d.ts +1 -2
  6. package/dist/application/field-metadata/relation.decorator.d.ts +1 -2
  7. package/dist/application/{serverless-function-config.d.ts → function-config.d.ts} +4 -5
  8. package/dist/application/index.d.ts +1 -1
  9. package/dist/application/object-metadata/object.decorator.d.ts +1 -2
  10. package/dist/cli/cli.d.ts +2 -0
  11. package/dist/cli/commands/app-add.command.d.ts +12 -0
  12. package/dist/cli/commands/app-dev.command.d.ts +10 -0
  13. package/dist/cli/commands/app-generate.command.d.ts +4 -0
  14. package/dist/cli/commands/app-sync.command.d.ts +7 -0
  15. package/dist/cli/commands/app-uninstall.command.d.ts +9 -0
  16. package/dist/cli/commands/app.command.d.ts +9 -0
  17. package/dist/cli/commands/auth.command.d.ts +9 -0
  18. package/dist/cli/constants/current-execution-directory.d.ts +1 -0
  19. package/dist/cli/services/api.service.d.ts +14 -0
  20. package/dist/cli/services/config.service.d.ts +14 -0
  21. package/dist/cli/services/generate.service.d.ts +7 -0
  22. package/dist/cli/types/config.types.d.ts +99 -0
  23. package/dist/cli/utils/convert-to-label.d.ts +1 -0
  24. package/dist/cli/utils/find-path-file.d.ts +1 -0
  25. package/dist/cli/utils/format-and-warn-ts-diagnostics.d.ts +4 -0
  26. package/dist/cli/utils/format-path.d.ts +1 -0
  27. package/dist/cli/utils/get-function-base-file.d.ts +4 -0
  28. package/dist/cli/utils/get-object-decorated-class.d.ts +4 -0
  29. package/dist/cli/utils/get-ts-program-and-diagnostics.d.ts +7 -0
  30. package/dist/cli/utils/jsonc-parser.d.ts +17 -0
  31. package/dist/cli/utils/load-env-variables.d.ts +2 -0
  32. package/dist/cli/utils/load-manifest.d.ts +9 -0
  33. package/dist/cli.cjs +242 -0
  34. package/dist/cli.mjs +9507 -0
  35. package/dist/index.cjs +51 -1
  36. package/dist/index.d.ts +1 -2
  37. package/dist/index.mjs +17588 -2
  38. package/package.json +54 -22
  39. package/dist/application.cjs +0 -20
  40. package/dist/application.mjs +0 -3202
package/README.md CHANGED
@@ -1,6 +1,26 @@
1
- # twenty-sdk
1
+ <div align="center">
2
+ <a href="https://twenty.com">
3
+ <picture>
4
+ <img alt="Twenty logo" src="https://raw.githubusercontent.com/twentyhq/twenty/2f25922f4cd5bd61e1427c57c4f8ea224e1d552c/packages/twenty-website/public/images/core/logo.svg" height="128">
5
+ </picture>
6
+ </a>
7
+ <h1>Twenty SDK</h1>
2
8
 
3
- A lightweight TypeScript SDK for Twenty CRM.
9
+ <a href="https://www.npmjs.com/package/twenty-sdk"><img alt="NPM version" src="https://img.shields.io/npm/v/twenty-sdk.svg?style=for-the-badge&labelColor=000000"></a>
10
+ <a href="https://github.com/twentyhq/twenty/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/npm/l/next.svg?style=for-the-badge&labelColor=000000"></a>
11
+ <a href="https://discord.gg/cx5n4Jzs57"><img alt="Join the community on Discord" src="https://img.shields.io/badge/Join%20the%20community-blueviolet.svg?style=for-the-badge&logo=Twenty&labelColor=000000&logoWidth=20"></a>
12
+
13
+ </div>
14
+
15
+ A CLI and SDK to develop, build, and publish applications that extend [Twenty CRM](https://twenty.com).
16
+
17
+ - Type‑safe client and workspace entity typings
18
+ - Built‑in CLI for auth, generate, dev sync, one‑off sync, and uninstall
19
+ - Works great with the scaffolder: [create-twenty-app](https://www.npmjs.com/package/create-twenty-app)
20
+
21
+ ## Prerequisites
22
+ - Node.js 24+ (recommended) and Yarn 4
23
+ - A Twenty workspace and an API key. Generate one at https://app.twenty.com/settings/api-webhooks
4
24
 
5
25
  ## Installation
6
26
 
@@ -10,18 +30,72 @@ npm install twenty-sdk
10
30
  yarn add twenty-sdk
11
31
  ```
12
32
 
13
- ## Usage
33
+ ## Getting started
34
+ You can either scaffold a new app or add the SDK to an existing one.
35
+
36
+ - Start new (recommended):
37
+ ```bash
38
+ npx create-twenty-app@latest my-twenty-app
39
+ cd my-twenty-app
40
+ ```
41
+ - Existing project: install the SDK as shown above, then use the CLI below.
42
+
43
+ ## CLI quickstart
44
+ ```bash
45
+ # Authenticate using your API key (CLI will prompt for it)
46
+ twenty auth login
47
+
48
+ # Add a new entity to your application (guided prompts)
49
+ twenty app add
50
+
51
+ # Generate a typed Twenty client and TypeScript definitions for your workspace entities
52
+ twenty app generate
53
+
54
+ # Start dev mode: automatically syncs changes to your workspace for instant testing
55
+ twenty app dev
56
+
57
+ # One‑time sync of local changes
58
+ twenty app sync
14
59
 
60
+ # Uninstall the application from the current workspace
61
+ twenty app uninstall
62
+ ```
63
+
64
+ ## Usage (SDK)
15
65
  ```typescript
66
+ // Example: import what you need from the SDK
16
67
  import { /* your exports */ } from 'twenty-sdk';
17
68
  ```
18
69
 
19
- ## Development
70
+ ## Publish your application
71
+ Applications are currently stored in [`twenty/packages/twenty-apps`](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps).
72
+
73
+ You can share your application with all Twenty users:
20
74
 
21
75
  ```bash
22
- # Build
23
- npx nx build twenty-sdk
76
+ # pull the Twenty project
77
+ git clone https://github.com/twentyhq/twenty.git
78
+ cd twenty
79
+
80
+ # create a new branch
81
+ git checkout -b feature/my-awesome-app
82
+ ```
24
83
 
25
- # Lint
26
- npx nx lint twenty-sdk
84
+ - Copy your app folder into `twenty/packages/twenty-apps`.
85
+ - Commit your changes and open a pull request on https://github.com/twentyhq/twenty
86
+
87
+ ```bash
88
+ git commit -m "Add new application"
89
+ git push
27
90
  ```
91
+
92
+ Our team reviews contributions for quality, security, and reusability.
93
+
94
+ ## Troubleshooting
95
+ - Auth errors: run `twenty auth login` again and ensure the API key has the required permissions.
96
+ - Typings out of date: run `twenty app generate` to refresh the client and types.
97
+ - Not seeing changes in dev: make sure dev mode is running (`twenty app dev`).
98
+
99
+ ## Contributing
100
+ - See our [GitHub](https://github.com/twentyhq/twenty)
101
+ - Join our [Discord](https://discord.gg/cx5n4Jzs57)
@@ -0,0 +1 @@
1
+ "use strict";var o=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function l(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}exports.commonjsGlobal=o;exports.getDefaultExportFromCjs=l;
@@ -0,0 +1,8 @@
1
+ var o = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {};
2
+ function l(e) {
3
+ return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e;
4
+ }
5
+ export {
6
+ o as c,
7
+ l as g
8
+ };
@@ -1,5 +1,4 @@
1
- import { SyncableEntityOptions } from '@/application/syncable-entity-options.type';
2
-
1
+ import { SyncableEntityOptions } from './syncable-entity-options.type';
3
2
  type ApplicationVariable = SyncableEntityOptions & {
4
3
  value?: string;
5
4
  description?: string;
@@ -1,6 +1,5 @@
1
+ import { SyncableEntityOptions } from '../syncable-entity-options.type';
1
2
  import { FieldMetadataType, FieldMetadataSettings, FieldMetadataOptions, FieldMetadataDefaultValue } from 'twenty-shared/types';
2
- import { SyncableEntityOptions } from '@/application/syncable-entity-options.type';
3
-
4
3
  type FieldOptions<T extends FieldMetadataType = Exclude<FieldMetadataType, FieldMetadataType.RELATION>> = SyncableEntityOptions & {
5
4
  type: T;
6
5
  label: string;
@@ -1,6 +1,5 @@
1
+ import { SyncableEntityOptions } from '../syncable-entity-options.type';
1
2
  import { RelationOnDeleteAction, RelationType } from 'twenty-shared/types';
2
- import { SyncableEntityOptions } from '@/application/syncable-entity-options.type';
3
-
4
3
  interface WorkspaceRelationMinimumBaseOptions<TClass> {
5
4
  label: string;
6
5
  description?: string;
@@ -1,5 +1,4 @@
1
- import { SyncableEntityOptions } from '@/application/syncable-entity-options.type';
2
-
1
+ import { SyncableEntityOptions } from './syncable-entity-options.type';
3
2
  type RouteTrigger = {
4
3
  type: 'route';
5
4
  path: string;
@@ -14,11 +13,11 @@ type DatabaseEventTrigger = {
14
13
  type: 'databaseEvent';
15
14
  eventName: string;
16
15
  };
17
- type ServerlessFunctionTrigger = SyncableEntityOptions & (RouteTrigger | CronTrigger | DatabaseEventTrigger);
18
- export type ServerlessFunctionConfig = SyncableEntityOptions & {
16
+ type FunctionTrigger = SyncableEntityOptions & (RouteTrigger | CronTrigger | DatabaseEventTrigger);
17
+ export type FunctionConfig = SyncableEntityOptions & {
19
18
  name?: string;
20
19
  description?: string;
21
20
  timeoutSeconds?: number;
22
- triggers?: ServerlessFunctionTrigger[];
21
+ triggers?: FunctionTrigger[];
23
22
  };
24
23
  export {};
@@ -5,7 +5,7 @@ export { Field } from './field-metadata/field.decorator';
5
5
  export { OnDeleteAction } from './field-metadata/on-delete-action';
6
6
  export { RelationType } from './field-metadata/relation-type';
7
7
  export { Relation } from './field-metadata/relation.decorator';
8
+ export type { FunctionConfig } from './function-config';
8
9
  export { Object } from './object-metadata/object.decorator';
9
10
  export { STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS } from './object-metadata/standard-object-ids';
10
- export type { ServerlessFunctionConfig } from './serverless-function-config';
11
11
  export type { SyncableEntityOptions } from './syncable-entity-options.type';
@@ -1,5 +1,4 @@
1
- import { SyncableEntityOptions } from '@/application/syncable-entity-options.type';
2
-
1
+ import { SyncableEntityOptions } from '../syncable-entity-options.type';
3
2
  type ObjectMetadataOptions = SyncableEntityOptions & {
4
3
  nameSingular: string;
5
4
  namePlural: string;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,12 @@
1
+ export declare enum SyncableEntity {
2
+ AGENT = "agent",
3
+ OBJECT = "object",
4
+ FUNCTION = "function"
5
+ }
6
+ export declare const isSyncableEntity: (value: string) => value is SyncableEntity;
7
+ export declare class AppAddCommand {
8
+ execute(entityType?: SyncableEntity, path?: string): Promise<void>;
9
+ private getEntity;
10
+ private getEntityName;
11
+ private getObjectData;
12
+ }
@@ -0,0 +1,10 @@
1
+ export declare class AppDevCommand {
2
+ private syncCommand;
3
+ execute(options: {
4
+ appPath?: string;
5
+ debounce: string;
6
+ }): Promise<void>;
7
+ private logStartupInfo;
8
+ private setupFileWatcher;
9
+ private setupGracefulShutdown;
10
+ }
@@ -0,0 +1,4 @@
1
+ export declare class AppGenerateCommand {
2
+ private generateService;
3
+ execute(appPath?: string): Promise<void>;
4
+ }
@@ -0,0 +1,7 @@
1
+ import { ApiResponse } from '../types/config.types';
2
+ export declare class AppSyncCommand {
3
+ private apiService;
4
+ private generateService;
5
+ execute(appPath?: string): Promise<ApiResponse<any>>;
6
+ private synchronize;
7
+ }
@@ -0,0 +1,9 @@
1
+ import { ApiResponse } from '../types/config.types';
2
+ export declare class AppUninstallCommand {
3
+ private apiService;
4
+ execute({ appPath, askForConfirmation, }: {
5
+ appPath?: string;
6
+ askForConfirmation: boolean;
7
+ }): Promise<ApiResponse<any>>;
8
+ private confirmationPrompt;
9
+ }
@@ -0,0 +1,9 @@
1
+ import { Command } from 'commander';
2
+ export declare class AppCommand {
3
+ private devCommand;
4
+ private syncCommand;
5
+ private uninstallCommand;
6
+ private addCommand;
7
+ private generateCommand;
8
+ getCommand(): Command;
9
+ }
@@ -0,0 +1,9 @@
1
+ import { Command } from 'commander';
2
+ export declare class AuthCommand {
3
+ private configService;
4
+ private apiService;
5
+ getCommand(): Command;
6
+ private login;
7
+ private logout;
8
+ private status;
9
+ }
@@ -0,0 +1 @@
1
+ export declare const CURRENT_EXECUTION_DIRECTORY: string;
@@ -0,0 +1,14 @@
1
+ import { ApiResponse, AppManifest, PackageJson } from '../types/config.types';
2
+ export declare class ApiService {
3
+ private client;
4
+ private configService;
5
+ constructor();
6
+ validateAuth(): Promise<boolean>;
7
+ syncApplication({ packageJson, yarnLock, manifest, }: {
8
+ packageJson: PackageJson;
9
+ yarnLock: string;
10
+ manifest: AppManifest;
11
+ }): Promise<ApiResponse>;
12
+ uninstallApplication(universalIdentifier: string): Promise<ApiResponse>;
13
+ getSchema(): Promise<ApiResponse<string>>;
14
+ }
@@ -0,0 +1,14 @@
1
+ import { TwentyConfig } from '../types/config.types';
2
+ export declare class ConfigService {
3
+ private readonly configPath;
4
+ private static activeWorkspace;
5
+ constructor();
6
+ static setActiveWorkspace(name?: string): void;
7
+ static getActiveWorkspace(): string;
8
+ private getActiveWorkspaceName;
9
+ private readRawConfig;
10
+ getConfig(): Promise<TwentyConfig>;
11
+ setConfig(config: Partial<TwentyConfig>): Promise<void>;
12
+ clearConfig(): Promise<void>;
13
+ private getDefaultConfig;
14
+ }
@@ -0,0 +1,7 @@
1
+ export declare const GENERATED_FOLDER_NAME = "generated";
2
+ export declare class GenerateService {
3
+ private configService;
4
+ private apiService;
5
+ constructor();
6
+ generateClient(appPath: string): Promise<void>;
7
+ }
@@ -0,0 +1,99 @@
1
+ export interface TwentyConfig {
2
+ apiUrl: string;
3
+ apiKey?: string;
4
+ }
5
+ export type PackageJson = {
6
+ name: string;
7
+ license: string;
8
+ engines: {
9
+ node: string;
10
+ npm: string;
11
+ yarn: string;
12
+ };
13
+ packageManager: string;
14
+ version: string;
15
+ dependencies?: object;
16
+ devDependencies?: object;
17
+ };
18
+ type ApplicationVariable = {
19
+ universalIdentifier: string;
20
+ value?: string;
21
+ description?: string;
22
+ isSecret?: boolean;
23
+ };
24
+ export type Application = {
25
+ universalIdentifier: string;
26
+ displayName?: string;
27
+ description?: string;
28
+ icon?: string;
29
+ applicationVariables?: Record<string, ApplicationVariable>;
30
+ };
31
+ export type AppManifest = {
32
+ application: Application;
33
+ objects: ObjectManifest[];
34
+ serverlessFunctions: ServerlessFunctionManifest[];
35
+ sources: Sources;
36
+ };
37
+ export type ServerlessFunctionManifest = {
38
+ universalIdentifier: string;
39
+ name?: string;
40
+ description?: string;
41
+ timeoutSeconds?: number;
42
+ triggers: ServerlessFunctionTriggerManifest[];
43
+ handlerPath: string;
44
+ handlerName: string;
45
+ };
46
+ export type DatabaseEventTrigger = {
47
+ type: 'databaseEvent';
48
+ eventName: string;
49
+ };
50
+ export type CronTrigger = {
51
+ type: 'cron';
52
+ pattern: string;
53
+ };
54
+ export type RouteTrigger = {
55
+ type: 'route';
56
+ path: string;
57
+ httpMethod: string;
58
+ isAuthRequired: boolean;
59
+ };
60
+ export type ServerlessFunctionTriggerManifest = {
61
+ universalIdentifier: string;
62
+ } & (CronTrigger | DatabaseEventTrigger | RouteTrigger);
63
+ export type Sources = {
64
+ [key: string]: string | Sources;
65
+ };
66
+ export type FieldMetadata = {
67
+ universalIdentifier: string;
68
+ type: string;
69
+ label: string;
70
+ description?: string;
71
+ icon?: string;
72
+ defaultValue?: any;
73
+ options?: any;
74
+ settings?: any;
75
+ isNullable?: boolean;
76
+ isFieldUiReadOnly?: boolean;
77
+ };
78
+ export type ObjectManifest = {
79
+ universalIdentifier: string;
80
+ nameSingular: string;
81
+ namePlural: string;
82
+ labelSingular: string;
83
+ labelPlural: string;
84
+ description?: string;
85
+ icon?: string;
86
+ fields: FieldMetadata[];
87
+ };
88
+ export type SuccessfulApiResponse<T = unknown> = {
89
+ success: true;
90
+ data: T;
91
+ message?: string;
92
+ };
93
+ export type FailingApiResponse = {
94
+ success: false;
95
+ error?: unknown;
96
+ message?: string;
97
+ };
98
+ export type ApiResponse<T = unknown> = SuccessfulApiResponse<T> | FailingApiResponse;
99
+ export {};
@@ -0,0 +1 @@
1
+ export declare const convertToLabel: (str: string) => string;
@@ -0,0 +1 @@
1
+ export declare const findPathFile: (appPath: string, fileName: string) => Promise<string>;
@@ -0,0 +1,4 @@
1
+ import { Diagnostic } from 'typescript';
2
+ export declare const formatAndWarnTsDiagnostics: ({ diagnostics, }: {
3
+ diagnostics: Diagnostic[];
4
+ }) => void;
@@ -0,0 +1 @@
1
+ export declare const formatPath: (appPath?: string) => string | undefined;
@@ -0,0 +1,4 @@
1
+ export declare const getFunctionBaseFile: ({ name, universalIdentifier, }: {
2
+ name: string;
3
+ universalIdentifier?: string;
4
+ }) => string;
@@ -0,0 +1,4 @@
1
+ export declare const getObjectDecoratedClass: ({ data, name, }: {
2
+ data: object;
3
+ name: string;
4
+ }) => string;
@@ -0,0 +1,7 @@
1
+ import { Program, Diagnostic } from 'typescript';
2
+ export declare const getTsProgramAndDiagnostics: ({ appPath, }: {
3
+ appPath: string;
4
+ }) => Promise<{
5
+ program: Program;
6
+ diagnostics: Diagnostic[];
7
+ }>;
@@ -0,0 +1,17 @@
1
+ import { ParseError } from 'jsonc-parser';
2
+ export interface JsoncParseOptions {
3
+ allowTrailingComma?: boolean;
4
+ disallowComments?: boolean;
5
+ allowEmptyContent?: boolean;
6
+ }
7
+ export declare class JsoncParseError extends Error {
8
+ readonly parseErrors: ParseError[];
9
+ readonly filePath?: string | undefined;
10
+ constructor(message: string, parseErrors: ParseError[], filePath?: string | undefined);
11
+ }
12
+ export declare const parseJsoncString: (content: string, options?: JsoncParseOptions) => any;
13
+ export declare const parseTextFile: (filePath: string) => Promise<string>;
14
+ export declare const parseJsoncFile: (filePath: string, options?: JsoncParseOptions) => Promise<any>;
15
+ export declare const writeJsoncFile: (filePath: string, data: any, options?: {
16
+ spaces?: number;
17
+ }) => Promise<void>;
@@ -0,0 +1,2 @@
1
+ import { default as dotenv } from 'dotenv';
2
+ export declare const loadEnvVariables: (appPath: string) => Promise<dotenv.DotenvParseOutput>;
@@ -0,0 +1,9 @@
1
+ import { Program } from 'typescript';
2
+ import { AppManifest, Application, PackageJson } from '../types/config.types';
3
+ export declare const extractTwentyAppConfig: (program: Program) => Application;
4
+ export declare const loadManifest: (appPath: string) => Promise<{
5
+ packageJson: PackageJson;
6
+ yarnLock: string;
7
+ manifest: AppManifest;
8
+ shouldGenerate: boolean;
9
+ }>;