@directus/api 22.0.0 → 22.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.
- package/dist/cli/commands/init/questions.d.ts +7 -6
- package/dist/cli/commands/init/questions.js +2 -2
- package/dist/cli/utils/create-env/index.d.ts +2 -2
- package/dist/cli/utils/create-env/index.js +3 -1
- package/dist/cli/utils/drivers.js +1 -1
- package/dist/database/helpers/index.d.ts +3 -3
- package/dist/database/migrations/20210519A-add-system-fk-triggers.js +3 -2
- package/dist/database/migrations/20230721A-require-shares-fields.js +3 -5
- package/dist/database/migrations/20240716A-update-files-date-fields.js +3 -7
- package/dist/database/migrations/20240806A-permissions-policies.js +16 -2
- package/dist/server.js +17 -4
- package/dist/types/database.d.ts +1 -1
- package/dist/utils/get-address.d.ts +5 -0
- package/dist/utils/get-address.js +13 -0
- package/dist/utils/transaction.js +28 -11
- package/dist/websocket/controllers/graphql.js +2 -3
- package/dist/websocket/controllers/rest.js +2 -3
- package/package.json +12 -12
|
@@ -1,20 +1,21 @@
|
|
|
1
|
+
import type { Driver } from '../../../types/index.js';
|
|
1
2
|
export declare const databaseQuestions: {
|
|
2
3
|
sqlite3: (({ filepath }: {
|
|
3
4
|
filepath: string;
|
|
4
5
|
}) => Record<string, string>)[];
|
|
5
|
-
|
|
6
|
-
client:
|
|
6
|
+
mysql2: (({ client }: {
|
|
7
|
+
client: Exclude<Driver, 'sqlite3'>;
|
|
7
8
|
}) => Record<string, any>)[];
|
|
8
9
|
pg: (({ client }: {
|
|
9
|
-
client:
|
|
10
|
+
client: Exclude<Driver, 'sqlite3'>;
|
|
10
11
|
}) => Record<string, any>)[];
|
|
11
12
|
cockroachdb: (({ client }: {
|
|
12
|
-
client:
|
|
13
|
+
client: Exclude<Driver, 'sqlite3'>;
|
|
13
14
|
}) => Record<string, any>)[];
|
|
14
15
|
oracledb: (({ client }: {
|
|
15
|
-
client:
|
|
16
|
+
client: Exclude<Driver, 'sqlite3'>;
|
|
16
17
|
}) => Record<string, any>)[];
|
|
17
18
|
mssql: (({ client }: {
|
|
18
|
-
client:
|
|
19
|
+
client: Exclude<Driver, 'sqlite3'>;
|
|
19
20
|
}) => Record<string, any>)[];
|
|
20
21
|
};
|
|
@@ -19,7 +19,7 @@ const port = ({ client }) => ({
|
|
|
19
19
|
const ports = {
|
|
20
20
|
pg: 5432,
|
|
21
21
|
cockroachdb: 26257,
|
|
22
|
-
|
|
22
|
+
mysql2: 3306,
|
|
23
23
|
oracledb: 1521,
|
|
24
24
|
mssql: 1433,
|
|
25
25
|
};
|
|
@@ -57,7 +57,7 @@ const ssl = () => ({
|
|
|
57
57
|
});
|
|
58
58
|
export const databaseQuestions = {
|
|
59
59
|
sqlite3: [filename],
|
|
60
|
-
|
|
60
|
+
mysql2: [host, port, database, user, password],
|
|
61
61
|
pg: [host, port, database, user, password, ssl],
|
|
62
62
|
cockroachdb: [host, port, database, user, password, ssl],
|
|
63
63
|
oracledb: [host, port, database, user, password],
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
+
import type { Driver } from '../../../types/index.js';
|
|
1
2
|
import type { Credentials } from '../create-db-connection.js';
|
|
2
|
-
|
|
3
|
-
export default function createEnv(client: keyof typeof drivers, credentials: Credentials, directory: string): Promise<void>;
|
|
3
|
+
export default function createEnv(client: Driver, credentials: Credentials, directory: string): Promise<void>;
|
|
@@ -14,12 +14,14 @@ const liquidEngine = new Liquid({
|
|
|
14
14
|
});
|
|
15
15
|
export default async function createEnv(client, credentials, directory) {
|
|
16
16
|
const { nanoid } = await import('nanoid');
|
|
17
|
+
// For backwards-compatibility, DB_CLIENT is still 'mysql'
|
|
18
|
+
const dbClient = client === 'mysql2' ? 'mysql' : client;
|
|
17
19
|
const config = {
|
|
18
20
|
security: {
|
|
19
21
|
SECRET: nanoid(32),
|
|
20
22
|
},
|
|
21
23
|
database: {
|
|
22
|
-
DB_CLIENT:
|
|
24
|
+
DB_CLIENT: dbClient,
|
|
23
25
|
},
|
|
24
26
|
};
|
|
25
27
|
for (const [key, value] of Object.entries(credentials)) {
|
|
@@ -8,10 +8,10 @@ import * as sequenceHelpers from './sequence/index.js';
|
|
|
8
8
|
import * as numberHelpers from './number/index.js';
|
|
9
9
|
export declare function getHelpers(database: Knex): {
|
|
10
10
|
date: dateHelpers.postgres | dateHelpers.oracle | dateHelpers.mysql | dateHelpers.mssql | dateHelpers.sqlite;
|
|
11
|
-
st: geometryHelpers.
|
|
12
|
-
schema: schemaHelpers.
|
|
11
|
+
st: geometryHelpers.postgres | geometryHelpers.mssql | geometryHelpers.mysql | geometryHelpers.sqlite | geometryHelpers.oracle | geometryHelpers.redshift;
|
|
12
|
+
schema: schemaHelpers.cockroachdb | schemaHelpers.mssql | schemaHelpers.mysql | schemaHelpers.postgres | schemaHelpers.sqlite | schemaHelpers.oracle | schemaHelpers.redshift;
|
|
13
13
|
sequence: sequenceHelpers.mysql | sequenceHelpers.postgres;
|
|
14
14
|
number: numberHelpers.cockroachdb | numberHelpers.mssql | numberHelpers.postgres | numberHelpers.sqlite | numberHelpers.oracle;
|
|
15
15
|
};
|
|
16
|
-
export declare function getFunctions(database: Knex, schema: SchemaOverview): fnHelpers.
|
|
16
|
+
export declare function getFunctions(database: Knex, schema: SchemaOverview): fnHelpers.postgres | fnHelpers.mssql | fnHelpers.mysql | fnHelpers.sqlite | fnHelpers.oracle;
|
|
17
17
|
export type Helpers = ReturnType<typeof getHelpers>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createInspector } from '@directus/schema';
|
|
2
2
|
import { useLogger } from '../../logger/index.js';
|
|
3
|
+
import { getDatabaseClient } from '../index.js';
|
|
3
4
|
/**
|
|
4
5
|
* Things to keep in mind:
|
|
5
6
|
*
|
|
@@ -99,7 +100,7 @@ export async function up(knex) {
|
|
|
99
100
|
* MySQL won't delete the index when you drop the foreign key constraint. Gotta make
|
|
100
101
|
* sure to clean those up as well
|
|
101
102
|
*/
|
|
102
|
-
if (knex
|
|
103
|
+
if (getDatabaseClient(knex) === 'mysql') {
|
|
103
104
|
try {
|
|
104
105
|
await knex.schema.alterTable(update.table, (table) => {
|
|
105
106
|
// Knex uses a default convention for index names: `table_column_type`
|
|
@@ -140,7 +141,7 @@ export async function down(knex) {
|
|
|
140
141
|
* MySQL won't delete the index when you drop the foreign key constraint. Gotta make
|
|
141
142
|
* sure to clean those up as well
|
|
142
143
|
*/
|
|
143
|
-
if (knex
|
|
144
|
+
if (getDatabaseClient(knex) === 'mysql') {
|
|
144
145
|
try {
|
|
145
146
|
await knex.schema.alterTable(update.table, (table) => {
|
|
146
147
|
// Knex uses a default convention for index names: `table_column_type`
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { createInspector } from '@directus/schema';
|
|
2
2
|
import { useLogger } from '../../logger/index.js';
|
|
3
|
-
import {
|
|
3
|
+
import { getDatabaseClient } from '../index.js';
|
|
4
4
|
export async function up(knex) {
|
|
5
|
-
const
|
|
6
|
-
const isMysql = helper.isOneOfClients(['mysql']);
|
|
5
|
+
const isMysql = getDatabaseClient(knex) === 'mysql';
|
|
7
6
|
if (isMysql) {
|
|
8
7
|
await dropConstraint(knex);
|
|
9
8
|
}
|
|
@@ -16,8 +15,7 @@ export async function up(knex) {
|
|
|
16
15
|
}
|
|
17
16
|
}
|
|
18
17
|
export async function down(knex) {
|
|
19
|
-
const
|
|
20
|
-
const isMysql = helper.isOneOfClients(['mysql']);
|
|
18
|
+
const isMysql = getDatabaseClient(knex) === 'mysql';
|
|
21
19
|
if (isMysql) {
|
|
22
20
|
await dropConstraint(knex);
|
|
23
21
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getDatabaseClient } from '../index.js';
|
|
2
2
|
export async function up(knex) {
|
|
3
|
-
|
|
4
|
-
const isMysql = helper.isOneOfClients(['mysql']);
|
|
5
|
-
if (isMysql) {
|
|
3
|
+
if (getDatabaseClient(knex) === 'mysql') {
|
|
6
4
|
// Knex creates invalid statement on MySQL, see https://github.com/knex/knex/issues/1888
|
|
7
5
|
await knex.schema.raw('ALTER TABLE `directus_files` CHANGE `uploaded_on` `created_on` TIMESTAMP NOT NULL DEFAULT current_timestamp();');
|
|
8
6
|
}
|
|
@@ -20,9 +18,7 @@ export async function down(knex) {
|
|
|
20
18
|
await knex.schema.alterTable('directus_files', (table) => {
|
|
21
19
|
table.dropColumn('uploaded_on');
|
|
22
20
|
});
|
|
23
|
-
|
|
24
|
-
const isMysql = helper.isOneOfClients(['mysql']);
|
|
25
|
-
if (isMysql) {
|
|
21
|
+
if (getDatabaseClient(knex) === 'mysql') {
|
|
26
22
|
await knex.schema.raw('ALTER TABLE `directus_files` CHANGE `created_on` `uploaded_on` TIMESTAMP NOT NULL DEFAULT current_timestamp();');
|
|
27
23
|
}
|
|
28
24
|
else {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { processChunk, toBoolean } from '@directus/utils';
|
|
2
2
|
import { flatten, intersection, isEqual, merge, omit, uniq } from 'lodash-es';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { useLogger } from '../../logger/index.js';
|
|
4
5
|
import { fetchPermissions } from '../../permissions/lib/fetch-permissions.js';
|
|
5
6
|
import { fetchPolicies } from '../../permissions/lib/fetch-policies.js';
|
|
6
7
|
import { fetchRolesTree } from '../../permissions/lib/fetch-roles-tree.js';
|
|
7
8
|
import { getSchema } from '../../utils/get-schema.js';
|
|
9
|
+
import { getSchemaInspector } from '../index.js';
|
|
8
10
|
// Adapted from https://github.com/directus/directus/blob/141b8adbf4dd8e06530a7929f34e3fc68a522053/api/src/utils/merge-permissions.ts#L4
|
|
9
11
|
export function mergePermissions(strategy, ...permissions) {
|
|
10
12
|
const allPermissions = flatten(permissions);
|
|
@@ -129,6 +131,7 @@ async function fetchRoleAccess(roles, context) {
|
|
|
129
131
|
*/
|
|
130
132
|
const PUBLIC_POLICY_ID = 'abf8a154-5b1c-4a46-ac9c-7300570f4f17';
|
|
131
133
|
export async function up(knex) {
|
|
134
|
+
const logger = useLogger();
|
|
132
135
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
133
136
|
// If the policies table already exists the migration has already run
|
|
134
137
|
if (await knex.schema.hasTable('directus_policies')) {
|
|
@@ -184,9 +187,20 @@ export async function up(knex) {
|
|
|
184
187
|
// Link permissions to policies instead of roles
|
|
185
188
|
await knex.schema.alterTable('directus_permissions', (table) => {
|
|
186
189
|
table.uuid('policy').references('directus_policies.id').onDelete('CASCADE');
|
|
187
|
-
// Drop the foreign key constraint here in order to update `null` role to public policy ID
|
|
188
|
-
table.dropForeign('role');
|
|
189
190
|
});
|
|
191
|
+
try {
|
|
192
|
+
const inspector = await getSchemaInspector();
|
|
193
|
+
const foreignKeys = await inspector.foreignKeys('directus_permissions');
|
|
194
|
+
const foreignConstraint = foreignKeys.find((foreign) => foreign.foreign_key_table === 'directus_roles' && foreign.column === 'role')
|
|
195
|
+
?.constraint_name || undefined;
|
|
196
|
+
await knex.schema.alterTable('directus_permissions', (table) => {
|
|
197
|
+
// Drop the foreign key constraint here in order to update `null` role to public policy ID
|
|
198
|
+
table.dropForeign('role', foreignConstraint);
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
logger.warn('Failed to drop foreign key constraint on `role` column in `directus_permissions` table');
|
|
203
|
+
}
|
|
190
204
|
await knex('directus_permissions')
|
|
191
205
|
.update({
|
|
192
206
|
role: PUBLIC_POLICY_ID,
|
package/dist/server.js
CHANGED
|
@@ -13,6 +13,7 @@ import emitter from './emitter.js';
|
|
|
13
13
|
import { useLogger } from './logger/index.js';
|
|
14
14
|
import { getConfigFromEnv } from './utils/get-config-from-env.js';
|
|
15
15
|
import { getIPFromReq } from './utils/get-ip-from-req.js';
|
|
16
|
+
import { getAddress } from './utils/get-address.js';
|
|
16
17
|
import { createSubscriptionController, createWebSocketController, getSubscriptionController, getWebSocketController, } from './websocket/controllers/index.js';
|
|
17
18
|
import { startWebSocketHandlers } from './websocket/handlers/index.js';
|
|
18
19
|
export let SERVER_ONLINE = true;
|
|
@@ -116,10 +117,22 @@ export async function createServer() {
|
|
|
116
117
|
export async function startServer() {
|
|
117
118
|
const server = await createServer();
|
|
118
119
|
const host = env['HOST'];
|
|
119
|
-
const
|
|
120
|
+
const path = env['UNIX_SOCKET_PATH'];
|
|
121
|
+
const port = env['PORT'];
|
|
122
|
+
let listenOptions;
|
|
123
|
+
if (path) {
|
|
124
|
+
listenOptions = { path };
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
listenOptions = {
|
|
128
|
+
host,
|
|
129
|
+
port: parseInt(port || '8055'),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
120
132
|
server
|
|
121
|
-
.listen(
|
|
122
|
-
|
|
133
|
+
.listen(listenOptions, () => {
|
|
134
|
+
const protocol = server instanceof https.Server ? 'https' : 'http';
|
|
135
|
+
logger.info(`Server started at ${listenOptions.port ? `${protocol}://${getAddress(server)}` : getAddress(server)}`);
|
|
123
136
|
process.send?.('ready');
|
|
124
137
|
emitter.emitAction('server.start', { server }, {
|
|
125
138
|
database: getDatabase(),
|
|
@@ -129,7 +142,7 @@ export async function startServer() {
|
|
|
129
142
|
})
|
|
130
143
|
.once('error', (err) => {
|
|
131
144
|
if (err?.code === 'EADDRINUSE') {
|
|
132
|
-
logger.error(`Port ${port} is already in use`);
|
|
145
|
+
logger.error(`${listenOptions.port ? `Port ${listenOptions.port}` : getAddress(server)} is already in use`);
|
|
133
146
|
process.exit(1);
|
|
134
147
|
}
|
|
135
148
|
else {
|
package/dist/types/database.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export type Driver = '
|
|
1
|
+
export type Driver = 'mysql2' | 'pg' | 'cockroachdb' | 'sqlite3' | 'oracledb' | 'mssql';
|
|
2
2
|
export declare const DatabaseClients: readonly ["mysql", "postgres", "cockroachdb", "sqlite", "oracle", "mssql", "redshift"];
|
|
3
3
|
export type DatabaseClient = (typeof DatabaseClients)[number];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as http from 'http';
|
|
2
|
+
export function getAddress(server) {
|
|
3
|
+
const address = server.address();
|
|
4
|
+
if (address === null) {
|
|
5
|
+
// Before the 'listening' event has been emitted or after calling server.close()
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
if (typeof address === 'string') {
|
|
9
|
+
// unix path
|
|
10
|
+
return address;
|
|
11
|
+
}
|
|
12
|
+
return `${address.address}:${address.port}`;
|
|
13
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isObject } from '@directus/utils';
|
|
1
2
|
import {} from 'knex';
|
|
2
3
|
import { getDatabaseClient } from '../database/index.js';
|
|
3
4
|
import { useLogger } from '../logger/index.js';
|
|
@@ -18,16 +19,7 @@ export const transaction = async (knex, handler) => {
|
|
|
18
19
|
}
|
|
19
20
|
catch (error) {
|
|
20
21
|
const client = getDatabaseClient(knex);
|
|
21
|
-
|
|
22
|
-
* This error code indicates that the transaction failed due to another
|
|
23
|
-
* concurrent or recent transaction attempting to write to the same data.
|
|
24
|
-
* This can usually be solved by restarting the transaction on client-side
|
|
25
|
-
* after a short delay, so that it is executed against the latest state.
|
|
26
|
-
*
|
|
27
|
-
* @link https://www.cockroachlabs.com/docs/stable/transaction-retry-error-reference
|
|
28
|
-
*/
|
|
29
|
-
const COCKROACH_RETRY_ERROR_CODE = '40001';
|
|
30
|
-
if (client !== 'cockroachdb' || error?.code !== COCKROACH_RETRY_ERROR_CODE)
|
|
22
|
+
if (!shouldRetryTransaction(client, error))
|
|
31
23
|
throw error;
|
|
32
24
|
const MAX_ATTEMPTS = 3;
|
|
33
25
|
const BASE_DELAY = 100;
|
|
@@ -40,7 +32,7 @@ export const transaction = async (knex, handler) => {
|
|
|
40
32
|
return await knex.transaction((trx) => handler(trx));
|
|
41
33
|
}
|
|
42
34
|
catch (error) {
|
|
43
|
-
if (error
|
|
35
|
+
if (!shouldRetryTransaction(client, error))
|
|
44
36
|
throw error;
|
|
45
37
|
}
|
|
46
38
|
}
|
|
@@ -50,3 +42,28 @@ export const transaction = async (knex, handler) => {
|
|
|
50
42
|
}
|
|
51
43
|
}
|
|
52
44
|
};
|
|
45
|
+
function shouldRetryTransaction(client, error) {
|
|
46
|
+
/**
|
|
47
|
+
* This error code indicates that the transaction failed due to another
|
|
48
|
+
* concurrent or recent transaction attempting to write to the same data.
|
|
49
|
+
* This can usually be solved by restarting the transaction on client-side
|
|
50
|
+
* after a short delay, so that it is executed against the latest state.
|
|
51
|
+
*
|
|
52
|
+
* @link https://www.cockroachlabs.com/docs/stable/transaction-retry-error-reference
|
|
53
|
+
*/
|
|
54
|
+
const COCKROACH_RETRY_ERROR_CODE = '40001';
|
|
55
|
+
/**
|
|
56
|
+
* SQLITE_BUSY is an error code returned by SQLite when an operation can't be
|
|
57
|
+
* performed due to a locked database file. This often arises due to multiple
|
|
58
|
+
* processes trying to simultaneously access the database, causing potential
|
|
59
|
+
* data inconsistencies. There are a few mechanisms to handle this case,
|
|
60
|
+
* one of which is to retry the complete transaction again
|
|
61
|
+
* on client-side after a short delay.
|
|
62
|
+
*
|
|
63
|
+
* @link https://www.sqlite.org/rescode.html#busy
|
|
64
|
+
*/
|
|
65
|
+
const SQLITE_BUSY_ERROR_CODE = 'SQLITE_BUSY';
|
|
66
|
+
return (isObject(error) &&
|
|
67
|
+
((client === 'cockroachdb' && error['code'] === COCKROACH_RETRY_ERROR_CODE) ||
|
|
68
|
+
(client === 'sqlite' && error['code'] === SQLITE_BUSY_ERROR_CODE)));
|
|
69
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { useEnv } from '@directus/env';
|
|
2
1
|
import { CloseCode, MessageType, makeServer } from 'graphql-ws';
|
|
3
2
|
import { useLogger } from '../../logger/index.js';
|
|
4
3
|
import { bindPubSub } from '../../services/graphql/subscription.js';
|
|
5
4
|
import { GraphQLService } from '../../services/index.js';
|
|
6
5
|
import { getSchema } from '../../utils/get-schema.js';
|
|
6
|
+
import { getAddress } from '../../utils/get-address.js';
|
|
7
7
|
import { authenticateConnection } from '../authenticate.js';
|
|
8
8
|
import { handleWebSocketError } from '../errors.js';
|
|
9
9
|
import { ConnectionParams, WebSocketMessage } from '../messages.js';
|
|
@@ -14,7 +14,6 @@ export class GraphQLSubscriptionController extends SocketController {
|
|
|
14
14
|
gql;
|
|
15
15
|
constructor(httpServer) {
|
|
16
16
|
super(httpServer, 'WEBSOCKETS_GRAPHQL');
|
|
17
|
-
const env = useEnv();
|
|
18
17
|
this.server.on('connection', (ws, auth) => {
|
|
19
18
|
this.bindEvents(this.createClient(ws, auth));
|
|
20
19
|
});
|
|
@@ -31,7 +30,7 @@ export class GraphQLSubscriptionController extends SocketController {
|
|
|
31
30
|
},
|
|
32
31
|
});
|
|
33
32
|
bindPubSub();
|
|
34
|
-
logger.info(`GraphQL Subscriptions started at ws://${
|
|
33
|
+
logger.info(`GraphQL Subscriptions started at ws://${getAddress(httpServer)}${this.endpoint}`);
|
|
35
34
|
}
|
|
36
35
|
bindEvents(client) {
|
|
37
36
|
const closedHandler = this.gql.opened({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { useEnv } from '@directus/env';
|
|
2
1
|
import { parseJSON } from '@directus/utils';
|
|
3
2
|
import emitter from '../../emitter.js';
|
|
4
3
|
import { useLogger } from '../../logger/index.js';
|
|
4
|
+
import { getAddress } from '../../utils/get-address.js';
|
|
5
5
|
import { WebSocketError, handleWebSocketError } from '../errors.js';
|
|
6
6
|
import { WebSocketMessage } from '../messages.js';
|
|
7
7
|
import SocketController from './base.js';
|
|
@@ -9,11 +9,10 @@ const logger = useLogger();
|
|
|
9
9
|
export class WebSocketController extends SocketController {
|
|
10
10
|
constructor(httpServer) {
|
|
11
11
|
super(httpServer, 'WEBSOCKETS_REST');
|
|
12
|
-
const env = useEnv();
|
|
13
12
|
this.server.on('connection', (ws, auth) => {
|
|
14
13
|
this.bindEvents(this.createClient(ws, auth));
|
|
15
14
|
});
|
|
16
|
-
logger.info(`WebSocket Server started at ws://${
|
|
15
|
+
logger.info(`WebSocket Server started at ws://${getAddress(httpServer)}${this.endpoint}`);
|
|
17
16
|
}
|
|
18
17
|
bindEvents(client) {
|
|
19
18
|
client.on('parsed-message', async (message) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@directus/api",
|
|
3
|
-
"version": "22.
|
|
3
|
+
"version": "22.1.0",
|
|
4
4
|
"description": "Directus is a real-time API and App dashboard for managing SQL database content",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"directus",
|
|
@@ -148,30 +148,30 @@
|
|
|
148
148
|
"wellknown": "0.5.0",
|
|
149
149
|
"ws": "8.18.0",
|
|
150
150
|
"zod": "3.23.8",
|
|
151
|
-
"zod-validation-error": "3.3.
|
|
151
|
+
"zod-validation-error": "3.3.1",
|
|
152
|
+
"@directus/app": "13.0.1",
|
|
152
153
|
"@directus/constants": "12.0.0",
|
|
153
|
-
"@directus/
|
|
154
|
-
"@directus/env": "2.0.0",
|
|
154
|
+
"@directus/env": "3.0.0",
|
|
155
155
|
"@directus/errors": "1.0.0",
|
|
156
|
-
"@directus/format-title": "11.0.0",
|
|
157
156
|
"@directus/extensions": "2.0.0",
|
|
158
|
-
"@directus/extensions-sdk": "12.0.0",
|
|
159
157
|
"@directus/extensions-registry": "2.0.0",
|
|
160
|
-
"@directus/
|
|
158
|
+
"@directus/format-title": "11.0.0",
|
|
161
159
|
"@directus/memory": "2.0.0",
|
|
160
|
+
"@directus/pressure": "2.0.0",
|
|
162
161
|
"@directus/schema": "12.0.0",
|
|
162
|
+
"@directus/extensions-sdk": "12.0.0",
|
|
163
163
|
"@directus/specs": "11.0.0",
|
|
164
|
-
"@directus/storage": "11.0.0",
|
|
165
164
|
"@directus/storage-driver-azure": "11.0.0",
|
|
165
|
+
"@directus/storage": "11.0.0",
|
|
166
|
+
"@directus/storage-driver-cloudinary": "11.0.0",
|
|
166
167
|
"@directus/storage-driver-gcs": "11.0.0",
|
|
167
168
|
"@directus/storage-driver-local": "11.0.0",
|
|
168
|
-
"@directus/storage-driver-cloudinary": "11.0.0",
|
|
169
|
-
"@directus/storage-driver-s3": "11.0.0",
|
|
170
169
|
"@directus/storage-driver-supabase": "2.0.0",
|
|
171
170
|
"@directus/system-data": "2.0.0",
|
|
171
|
+
"@directus/storage-driver-s3": "11.0.0",
|
|
172
172
|
"@directus/validation": "1.0.0",
|
|
173
|
-
"
|
|
174
|
-
"directus": "
|
|
173
|
+
"directus": "11.0.1",
|
|
174
|
+
"@directus/utils": "12.0.0"
|
|
175
175
|
},
|
|
176
176
|
"devDependencies": {
|
|
177
177
|
"@ngneat/falso": "7.2.0",
|