Dirty fix twenty cli ci build order issue (#16024)
# Introduction
- fix twenty-apps hello world deps lockfile
- improve error response format in application resolver
- fixed tests by adding applicationId back to serverless function
service v2
## New log format
We should have a tmp logs folder where we write the errors so the user
can see the whole of them such as what's done in yarn logs
```ts
console.log
✓ Client generated successfully!
at GenerateService.generateClient (src/services/generate.service.ts:58:13)
console.log
Generated files at: /Users/paulrastoin/ws/twenty/packages/twenty-apps/hello-world/generated
at GenerateService.generateClient (src/services/generate.service.ts:59:13)
console.error
❌ Serverless functions Sync failed: {
message: 'Multiple validation errors occurred while creating serverless function',
extensions: {
code: 'METADATA_VALIDATION_FAILED',
errors: {
fieldMetadata: [],
objectMetadata: [],
view: [],
viewField: [],
viewGroup: [],
index: [],
serverlessFunction: [Array],
cronTrigger: [],
databaseEventTrigger: [],
routeTrigger: [],
viewFilter: []
},
summary: {
invalidViewFilter: 0,
invalidObjectMetadata: 0,
invalidView: 0,
invalidViewField: 0,
invalidIndex: 0,
invalidServerlessFunction: 0,
invalidDatabaseEventTrigger: 0,
invalidCronTrigger: 0,
invalidRouteTrigger: 0,
invalidFieldMetadata: 0,
invalidViewGroup: 0,
totalErrors: 0
},
message: 'Validation failed for 0 object(s) and 0 field(s)',
userFriendlyMessage: 'Validation failed for 0 object(s) and 0 field(s)'
}
}
63 | JSON.stringify(serverlessSyncResult.error, null, 2),
64 | );
> 65 | console.error(
| ^
66 | chalk.red('❌ Serverless functions Sync failed:'),
67 | serverlessSyncResult.error,
68 | );
at AppSyncCommand.synchronize (src/commands/app-sync.command.ts:65:15)
at async AppSyncCommand.execute (src/commands/app-sync.command.ts:21:14)
at async Object.<anonymous> (src/__tests__/e2e/applications-install-delete-reinstall.e2e-spec.ts:28:22)
```
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
"cwd": "packages/twenty-cli",
|
||||
"commands": ["rimraf dist", "tsc --project tsconfig.lib.json"]
|
||||
},
|
||||
"dependsOn": ["^build"]
|
||||
"dependsOn": ["^build", "typecheck"]
|
||||
},
|
||||
"build": {
|
||||
"executor": "nx:run-commands",
|
||||
@@ -40,14 +40,7 @@
|
||||
"command": "node dist/cli.js"
|
||||
}
|
||||
},
|
||||
"typecheck": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"cwd": "packages/twenty-cli",
|
||||
"command": "tsc --noEmit --project tsconfig.lib.json"
|
||||
},
|
||||
"dependsOn": ["build"]
|
||||
},
|
||||
"typecheck": {},
|
||||
"lint": {
|
||||
"options": {
|
||||
"lintFilePatterns": ["{projectRoot}/src/**/*.{ts,json}"],
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { existsSync } from 'fs';
|
||||
import { AppUninstallCommand } from 'src/commands/app-uninstall.command';
|
||||
import { AppSyncCommand } from '../../commands/app-sync.command';
|
||||
import { AppUninstallCommand } from '../../commands/app-uninstall.command';
|
||||
import { COVERED_APPLICATION_FOLDERS } from './constants/covered-applications-folder.constant';
|
||||
import { getTestedApplicationPath } from './utils/get-tested-application-path.util';
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import chalk from 'chalk';
|
||||
import { Command, CommanderError } from 'commander';
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import chalk from 'chalk';
|
||||
import { CURRENT_EXECUTION_DIRECTORY } from '../constants/current-execution-directory';
|
||||
import { ApiService } from '../services/api.service';
|
||||
import { GenerateService } from '../services/generate.service';
|
||||
import { ApiResponse } from '../types/config.types';
|
||||
import { loadManifest } from '../utils/load-manifest';
|
||||
import { GenerateService } from '../services/generate.service';
|
||||
|
||||
export class AppSyncCommand {
|
||||
private apiService = new ApiService();
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import axios, { type AxiosInstance, type AxiosResponse } from 'axios';
|
||||
import chalk from 'chalk';
|
||||
import {
|
||||
buildClientSchema,
|
||||
getIntrospectionQuery,
|
||||
printSchema,
|
||||
} from 'graphql/index';
|
||||
import {
|
||||
type ApiResponse,
|
||||
type AppManifest,
|
||||
type PackageJson,
|
||||
} from '../types/config.types';
|
||||
import { ConfigService } from './config.service';
|
||||
import {
|
||||
buildClientSchema,
|
||||
getIntrospectionQuery,
|
||||
printSchema,
|
||||
} from 'graphql/index';
|
||||
|
||||
export class ApiService {
|
||||
private client: AxiosInstance;
|
||||
@@ -125,8 +125,7 @@ export class ApiService {
|
||||
if (response.data.errors) {
|
||||
return {
|
||||
success: false,
|
||||
error:
|
||||
response.data.errors[0]?.message || 'Failed to sync application',
|
||||
error: response.data.errors[0],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -136,13 +135,10 @@ export class ApiService {
|
||||
message: `Successfully synced application: ${packageJson.name}`,
|
||||
};
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error) && error.response) {
|
||||
return {
|
||||
success: false,
|
||||
error: error.response.data?.errors?.[0]?.message || error.message,
|
||||
};
|
||||
}
|
||||
throw error;
|
||||
return {
|
||||
success: false,
|
||||
error,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import chalk from 'chalk';
|
||||
import { generate } from '@genql/cli';
|
||||
import chalk from 'chalk';
|
||||
import { join, resolve } from 'path';
|
||||
import { ConfigService } from './config.service';
|
||||
import { ApiService } from './api.service';
|
||||
import { ConfigService } from './config.service';
|
||||
|
||||
export const GENERATED_FOLDER_NAME = 'generated';
|
||||
|
||||
@@ -38,7 +38,11 @@ export class GenerateService {
|
||||
console.log(chalk.gray(`API URL: ${url}`));
|
||||
console.log(chalk.gray(`Output: ${outputPath}`));
|
||||
|
||||
const { data: schema } = await this.apiService.getSchema();
|
||||
const getSchemaResponse = await this.apiService.getSchema();
|
||||
if (!getSchemaResponse.success) {
|
||||
return;
|
||||
}
|
||||
const { data: schema } = getSchemaResponse;
|
||||
|
||||
await generate({
|
||||
schema,
|
||||
|
||||
@@ -96,9 +96,16 @@ export type ObjectManifest = {
|
||||
fields: FieldMetadata[];
|
||||
};
|
||||
|
||||
export interface ApiResponse<T = any> {
|
||||
success: boolean;
|
||||
data?: T;
|
||||
error?: string;
|
||||
export type SuccessfulApiResponse<T = unknown> = {
|
||||
success: true;
|
||||
data: T;
|
||||
message?: string;
|
||||
}
|
||||
};
|
||||
export type FailingApiResponse = {
|
||||
success: false;
|
||||
error?: unknown;
|
||||
message?: string;
|
||||
};
|
||||
export type ApiResponse<T = unknown> =
|
||||
| SuccessfulApiResponse<T>
|
||||
| FailingApiResponse;
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
isExportAssignment,
|
||||
isFunctionExpression,
|
||||
isIdentifier,
|
||||
isImportDeclaration,
|
||||
isNoSubstitutionTemplateLiteral,
|
||||
isNumericLiteral,
|
||||
isObjectLiteralExpression,
|
||||
@@ -30,8 +31,8 @@ import {
|
||||
isStringLiteralLike,
|
||||
isTemplateExpression,
|
||||
isVariableStatement,
|
||||
isImportDeclaration,
|
||||
} from 'typescript';
|
||||
import { GENERATED_FOLDER_NAME } from '../services/generate.service';
|
||||
import {
|
||||
AppManifest,
|
||||
Application,
|
||||
@@ -42,10 +43,9 @@ import {
|
||||
Sources,
|
||||
} from '../types/config.types';
|
||||
import { findPathFile } from '../utils/find-path-file';
|
||||
import { getTsProgramAndDiagnostics } from '../utils/get-ts-program-and-diagnostics';
|
||||
import { parseJsoncFile, parseTextFile } from '../utils/jsonc-parser';
|
||||
import { formatAndWarnTsDiagnostics } from './format-and-warn-ts-diagnostics';
|
||||
import { getTsProgramAndDiagnostics } from '../utils/get-ts-program-and-diagnostics';
|
||||
import { GENERATED_FOLDER_NAME } from '../services/generate.service';
|
||||
|
||||
type JSONValue =
|
||||
| string
|
||||
|
||||
Reference in New Issue
Block a user