Skip to content

Commit

Permalink
Aggregate resolvers added to GraphQL options (#7373)
Browse files Browse the repository at this point in the history
* Don't use tags interface for CSV filter (#7258)

Fixes #6778

* Rely on `RETURNING` when possible (#7259)

* WIP use returning clause instead of max from id

* Use returning where applicable, fallback to fetch

Fixes #6279

* update dependency p-queue to v7 (#7255)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* update dependency @vitejs/plugin-vue to v1.4.0 (#7263)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* Move p-queue to app dev dependencies (#7273)

* Log error message when registering app extension fails (#7274)

* update dependency rollup to v2.56.1 (#7269)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* update dependency vue-router to v4.0.11 (#7272)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* update dependency ts-node to v10.2.0 (#7271)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* Only loads app extensions if SERVE_APP is true (#7275)

This also ensures API/App only load their respective extensions in dev.

* Fix gitignore file in extension templates being deleted when publishing (#7279)

* New Crowdin updates (#7260)

* New translations en-US.yaml (Spanish)

* New translations en-US.yaml (Spanish)

* New translations en-US.yaml (Russian)

* New translations en-US.yaml (Russian)

* New translations en-US.yaml (Russian)

* New translations en-US.yaml (Russian)

* update typescript-eslint monorepo to v4.29.1 (#7283)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* Only treat `tinyint(1)` and `tinyint(0)` as booleans (#7287)

* added an if catch for tinyint(1) and tinyint(0)

* made suggested changes toLowerCase()

* update dependency @vue/compiler-sfc to v3.2.0 (#7288)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* update dependency vue to v3.2.0 (#7289)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* Handle JSON in labels display (#7292)

Fixes #7278

* update dependency pinia to v2.0.0-rc.3 (#7055)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* update vue monorepo to v3.2.1 (#7293)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* Flush caches on server (re)start (#7294)

* v9.0.0-rc.89

* Update package-lock

* Update release script

To workaround breaking change in npm patch 🎉

* Update changelog

* update dependency pinia to v2.0.0-rc.4 (#7297)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* update dependency rollup to v2.56.2 (#7303)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* Fix HTTP method for collections.createMany in SDK (#7304)

* Fix HTTP method for collections.createMany in SDK

* Post collections in data body

Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>

* Add perm check for sqlite, upload, extensions dirs (#7310)

Co-authored-by: Rijk van Zanten <rijkvanzanten@me.com>

* update dependency eslint-plugin-vue to v7.16.0 (#7300)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* Fix uuid resolving in SQLite (#7312)

Fixes #7306

* Clear the file payload after file upload (#7315)

Fixes #7305

* Improve type checking

* Mention TELEMETRY environment variable in docs (#7317)

* Mention TELEMETRY environment variable in docs

* Add clarification

Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>

* Import access from fs-extra instead of fs/promises

* Resolve sorting in list-o2m-tree-view on dnd

* Fix graphql GET request cache query extraction (#7319)

Fixes #7298

* Check for related collection before creation relation (#7323)

Fixes #7302

* Fix colors on different types (#7322)

Co-authored-by: Rijk van Zanten <rijkvanzanten@me.com>

* group is working on aggregate resolver

* Check for non-existing parent pk records (#7331)

Fixes #7330

* Schema field types are not translated in the app (#7327)

* Fix field type label translations

* Use translate-object-values util

Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>

* Update release script

* Add import ref for TS

* Tweak, hopefully fix release flow

* getAggregateQuery

* clean up payload
Co-authored-by: Rijk van Zanten <rijkvanzanten@me.com>

* Treat alias-only fields properly

* Add missing translations (#7358)

* v9.0.0-rc.90

* Update changelog.md

* update dependency nanoid to v3.1.24 (#7365)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* update dependency supertest to v6.1.5 (#7360)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* update vue monorepo to v3.2.2 (#7355)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* filters working avg{id} format with number fields

* Fix english string after #7358 (#7371)

Fixed wrong string in en-US after #7358 PR

* group field working

* update dependency nanoid to v3.1.25 (#7375)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* update dependency directory-tree to v2.3.0 (#7376)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* Export Collection button now shows collection name not table name (#7379)

* export collection button to uses name not db name

* removed unused var

* fixed for review

* computed collectionName

* Add support for Geometry type, add Map Layout & Interface (#5684)

* Added map layout

* Cleanup and bug fixes

* Removed package-lock

* Cleanup and fixes

* Small fix

* Added back package-lock

* Saved camera, autofitting option, bug fixes

* Refactor and ui improvements

* Improvements

* Added seled mode

* Removed unused dependency

* Changed selection behaviour, cleanup.

* update import and dependencies

* make custom style into drawer

* remove unused imports

* use lodash functions

* add popups

* allow header to become small

* reorganize settings

* add styling to popup

* change default template

* add projection option

* add basic map interface

* finish simple map

* add mapbox style

* support more mapbox layouts

* add api key option

* add mapbox backgrounds to layout

* warn when no api key is set

* fix for latest version

* Improved map layout and interface, bug fixes, refactoring.

.

.

* Added postgis geometry format, added marker icon shadow

* Made map buttons bigger and their icons thinner. Added transition to header bar.

* Bug fixes and error handling in map interface.

* Moved box-select control out of the map component. Removed material icons sprite and use addImage for marker support.

* Handle MultiGeometry -> Geometry interface error.

* Removed hardcoded styles. Added migrations for basemap column. Lots of refactoring.

Removed hardcoded styles. Added migrations for basemap column. Lots of refactoring.

* Fixed style reloading error. Added translations.

* Moved worker code to lib.

* Removed worker code. Prevent Mapbox from removing access_token from the URL.

* Refactoring.

* Change basemap selection to in-map dropdown for layout and interface.

* Touchscreen selection support and small fixes.

* Small change.

* Fixed unused imports.

* Added support for PostgreSQL identity column

* Renamed migration. Added crs translation.

* Only show fields using the map interface in the map layout.

* Removed logging.

* Reverted Dockerfile change.

* Improved crs support.

* Fixed translations.

* Check for schema identity before updating it.

* Fixed popup not updating on feature hover.

* Added feature hover styling. Fixed layer customization input. Added out of bounds error handling.

* Added geometry type and support for database native geometries.

* Fixed linting.

* Fixed layout.

* Fixed layout.

* Actually fixed linting

* Full support for native geometries
Fixed basemap input
Improved feature popup on hover
Locked interfaced support

* Fixed geometryType option not updating

* Bug fixes in interface

* Fixed crash when empty basemap settings. Fixed fitBounds option not updating.

* Added back storage type option. Improved interface behaviour.

* Dropped wkb because of vendor inconsistency with binary data

* Updated layout to match new geometry type. Fixed geojson payload transform.

* Added missing geometry_format attributes to local types.

* Fixed typos & refactoring

* Removed dependency on proj4

* Fix error when empty map interface options

* Set geometry SRID to 4326 when inserting into the database

* Add support for selectMode

* Fix error on initial source load

* Added geocoder, use GeoJSON for api i/o, removed geometry_format option, refactoring

* Added geometry intersects filter. Created geometry helper class.

* Fix error when null geometryOptions, added mapbox_key setting.

* Moved all geometry parsing/serializing into processGeometries in `payload.ts`. Fixed type errors.

* Migrate to Vue 3

* Use wellknown instead of wkx

* Fixed basemap selection.

* Added available operator for geometry type

* Added nintersects filter, fixed map interface for filter input

* Added intersects_bbox filter & bug fixes.

* Fixed icons rendering

* Fixed cursor icon in select mode

* Added geometry aggregate function

* Fixed geometry processing bug when imported from relational field.

* Fixed error with geocoder instanciation

* Removed @types/maplibre-gl dependency

* Removed fitViewToData options

* Merge remote-tracking branch 'upstream/main' into map-layout

* Fixed style and geometryType in map interface options

* Fixed style change on map interface.

* Improved fitViewToData behaviour

* Fixed type imports and previous merge conflict

* Fixed linting

* Added available operators

* Fix and merge migrations

* Remove outdated p-queue dep

* Fix get-schema column extract

* Replace pg with postgis for local debugging

* Re-add missing import

* Add mapbox as a basemap when key exists

* Remove unused tz flag

* Process delta in payloadservice

* Set default map, add limit number styling

* Default display template to just PK

* Tweak styling of error dialog

* Fix method usage in helpers

* Move sdo_geo to oracle section

* Remove extensions from ts config exclude

* Move geo types to shared, remove _Geometry

* Remove unused type

* Tiny Tweaks

* Remove fit to bounds option in favor of on

* Validate incoming intersects query

* Deepmap filter values

* Add GraphQL support

* No defaultValue for geometryType

* Resolve c

* Fix translations

Co-authored-by: Nitwel <nitwel@arcor.de>
Co-authored-by: Rijk van Zanten <rijkvanzanten@me.com>

* New Crowdin updates (#7359)

* New translations en-US.yaml (Estonian)

* New translations en-US.yaml (Ukrainian)

* New translations en-US.yaml (Norwegian)

* New translations en-US.yaml (Polish)

* New translations en-US.yaml (Portuguese)

* New translations en-US.yaml (Russian)

* New translations en-US.yaml (Serbian (Cyrillic))

* New translations en-US.yaml (Swedish)

* New translations en-US.yaml (Turkish)

* New translations en-US.yaml (Chinese Traditional)

* New translations en-US.yaml (Portuguese, Brazilian)

* New translations en-US.yaml (Indonesian)

* New translations en-US.yaml (Spanish, Chile)

* New translations en-US.yaml (Thai)

* New translations en-US.yaml (Hindi)

* New translations en-US.yaml (Malay)

* New translations en-US.yaml (Serbian (Latin))

* New translations en-US.yaml (Dutch)

* New translations en-US.yaml (Italian)

* New translations en-US.yaml (Afrikaans)

* New translations en-US.yaml (Lithuanian)

* New translations en-US.yaml (Spanish, Latin America)

* New translations en-US.yaml (Slovenian)

* New translations en-US.yaml (Vietnamese)

* New translations en-US.yaml (Chinese Simplified)

* New translations en-US.yaml (Bulgarian)

* New translations en-US.yaml (Romanian)

* New translations en-US.yaml (French)

* New translations en-US.yaml (Spanish)

* New translations en-US.yaml (Arabic)

* New translations en-US.yaml (Georgian)

* New translations en-US.yaml (Catalan)

* New translations en-US.yaml (Czech)

* New translations en-US.yaml (Danish)

* New translations en-US.yaml (German)

* New translations en-US.yaml (Greek)

* New translations en-US.yaml (Finnish)

* New translations en-US.yaml (Hebrew)

* New translations en-US.yaml (Hungarian)

* New translations en-US.yaml (Japanese)

* Update source file en-US.yaml

* New translations en-US.yaml (Italian)

* New translations en-US.yaml (Slovenian)

* New translations en-US.yaml (Estonian)

* New translations en-US.yaml (Estonian)

* New translations en-US.yaml (Sinhala)

* New translations en-US.yaml (Russian)

* New translations en-US.yaml (Russian)

* New translations en-US.yaml (Bulgarian)

* Update source file en-US.yaml

* New translations en-US.yaml (Estonian)

* New translations en-US.yaml (Norwegian)

* New translations en-US.yaml (Polish)

* New translations en-US.yaml (Portuguese)

* New translations en-US.yaml (Russian)

* New translations en-US.yaml (Swedish)

* New translations en-US.yaml (Turkish)

* New translations en-US.yaml (Portuguese, Brazilian)

* New translations en-US.yaml (Spanish, Chile)

* New translations en-US.yaml (Thai)

* New translations en-US.yaml (Serbian (Latin))

* New translations en-US.yaml (Dutch)

* New translations en-US.yaml (Lithuanian)

* New translations en-US.yaml (Spanish, Latin America)

* New translations en-US.yaml (Vietnamese)

* New translations en-US.yaml (Chinese Simplified)

* New translations en-US.yaml (Bulgarian)

* New translations en-US.yaml (French)

* New translations en-US.yaml (Spanish)

* New translations en-US.yaml (Arabic)

* New translations en-US.yaml (German)

* New translations en-US.yaml (Finnish)

* New translations en-US.yaml (Hungarian)

* update dependency directory-tree to v2.3.1 (#7380)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* pin dependencies (#7384)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* update dependency macos-release to v3 (#7381)

* update dependency macos-release to v3

* Update package-lock

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>

* New Crowdin updates (#7386)

* Update source file en-US.yaml

* New translations en-US.yaml (Estonian)

* New translations en-US.yaml (Polish)

* New translations en-US.yaml (Portuguese)

* New translations en-US.yaml (Russian)

* New translations en-US.yaml (Swedish)

* New translations en-US.yaml (Turkish)

* New translations en-US.yaml (Chinese Traditional)

* New translations en-US.yaml (Portuguese, Brazilian)

* New translations en-US.yaml (Indonesian)

* New translations en-US.yaml (Spanish, Chile)

* New translations en-US.yaml (Thai)

* New translations en-US.yaml (Serbian (Latin))

* New translations en-US.yaml (Dutch)

* New translations en-US.yaml (Italian)

* New translations en-US.yaml (Lithuanian)

* New translations en-US.yaml (Spanish, Latin America)

* New translations en-US.yaml (Slovenian)

* New translations en-US.yaml (Vietnamese)

* New translations en-US.yaml (Chinese Simplified)

* New translations en-US.yaml (Bulgarian)

* New translations en-US.yaml (French)

* New translations en-US.yaml (Spanish)

* New translations en-US.yaml (Arabic)

* New translations en-US.yaml (German)

* New translations en-US.yaml (Finnish)

* New translations en-US.yaml (Hungarian)

* Revert "update dependency macos-release to v3 (#7381)" (#7389)

This reverts commit ca111a8.

* update dependency npm to v7.20.6 (#7387)

Co-authored-by: Renovate Bot <bot@renovateapp.com>

* Fix flat lock number

* Small tweaks, fix type bug

Co-authored-by: Rijk van Zanten <rijkvanzanten@me.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Nicola Krumschmidt <nicola.krumschmidt@freenet.de>
Co-authored-by: Pascal Jufer <paescuj@users.noreply.github.com>
Co-authored-by: Adrian Dimitrov <dimitrov.adrian@gmail.com>
Co-authored-by: Oreille <33065839+Oreilles@users.noreply.github.com>
Co-authored-by: Nitwel <nitwel@arcor.de>
  • Loading branch information
9 people committed Aug 12, 2021
1 parent 21e221f commit be34474
Show file tree
Hide file tree
Showing 158 changed files with 6,696 additions and 827 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/release.yml
Expand Up @@ -38,6 +38,9 @@ jobs:
with:
node-version: '16.x'

# See https://github.com/npm/cli/issues/3637
- run: npm i -g npm@7.20.2

- uses: c-hive/gha-npm-cache@v1
- run: npm ci
- run: npm run build
Expand Down Expand Up @@ -65,6 +68,9 @@ jobs:
node-version: '16.x'
registry-url: 'https://registry.npmjs.org'

# See https://github.com/npm/cli/issues/3637
- run: npm i -g npm@7.20.2

- run: npm ci

- run: npx lerna publish from-git --no-verify-access --yes
Expand Down
28 changes: 16 additions & 12 deletions api/package.json
@@ -1,6 +1,6 @@
{
"name": "directus",
"version": "9.0.0-rc.88",
"version": "9.0.0-rc.90",
"license": "GPL-3.0-only",
"homepage": "https://github.com/directus/directus#readme",
"description": "Directus is a real-time API and App dashboard for managing SQL database content.",
Expand Down Expand Up @@ -68,15 +68,15 @@
"example.env"
],
"dependencies": {
"@directus/app": "9.0.0-rc.88",
"@directus/drive": "9.0.0-rc.88",
"@directus/drive-azure": "9.0.0-rc.88",
"@directus/drive-gcs": "9.0.0-rc.88",
"@directus/drive-s3": "9.0.0-rc.88",
"@directus/format-title": "9.0.0-rc.88",
"@directus/schema": "9.0.0-rc.88",
"@directus/shared": "9.0.0-rc.88",
"@directus/specs": "9.0.0-rc.88",
"@directus/app": "9.0.0-rc.90",
"@directus/drive": "9.0.0-rc.90",
"@directus/drive-azure": "9.0.0-rc.90",
"@directus/drive-gcs": "9.0.0-rc.90",
"@directus/drive-s3": "9.0.0-rc.90",
"@directus/format-title": "9.0.0-rc.90",
"@directus/schema": "9.0.0-rc.90",
"@directus/shared": "9.0.0-rc.90",
"@directus/specs": "9.0.0-rc.90",
"@godaddy/terminus": "^4.9.0",
"@rollup/plugin-alias": "^3.1.2",
"@rollup/plugin-virtual": "^2.0.3",
Expand All @@ -92,7 +92,7 @@
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"csv-parser": "^3.0.0",
"date-fns": "^2.21.1",
"date-fns": "^2.22.1",
"deep-map": "^2.0.0",
"destroy": "^1.0.4",
"dotenv": "^10.0.0",
Expand All @@ -101,6 +101,7 @@
"exifr": "^7.1.2",
"express": "^4.17.1",
"express-session": "^1.17.2",
"flat": "^5.0.2",
"fs-extra": "^10.0.0",
"grant": "^5.4.14",
"graphql": "^15.5.0",
Expand Down Expand Up @@ -139,7 +140,8 @@
"stream-json": "^1.7.1",
"update-check": "^1.5.4",
"uuid": "^8.3.2",
"uuid-validate": "0.0.3"
"uuid-validate": "0.0.3",
"wellknown": "^0.5.0"
},
"optionalDependencies": {
"@keyv/redis": "^2.1.2",
Expand Down Expand Up @@ -167,6 +169,7 @@
"@types/express": "4.17.13",
"@types/express-pino-logger": "4.0.2",
"@types/express-session": "1.17.4",
"@types/flat": "^5.0.2",
"@types/fs-extra": "9.0.12",
"@types/inquirer": "7.3.3",
"@types/js-yaml": "4.0.2",
Expand All @@ -185,6 +188,7 @@
"@types/stream-json": "1.7.1",
"@types/uuid": "8.3.1",
"@types/uuid-validate": "0.0.1",
"@types/wellknown": "0.5.1",
"copyfiles": "2.4.1",
"cross-env": "7.0.3",
"ts-node-dev": "1.1.8",
Expand Down
9 changes: 8 additions & 1 deletion api/src/app.ts
Expand Up @@ -41,8 +41,11 @@ import sanitizeQuery from './middleware/sanitize-query';
import schema from './middleware/schema';
import { track } from './utils/track';
import { validateEnv } from './utils/validate-env';
import { validateStorage } from './utils/validate-storage';
import { register as registerWebhooks } from './webhooks';
import { session } from './middleware/session';
import { flushCaches } from './cache';
import { URL } from 'url';

export default async function createApp(): Promise<express.Application> {
validateEnv(['KEY', 'SECRET']);
Expand All @@ -53,6 +56,8 @@ export default async function createApp(): Promise<express.Application> {
logger.warn('PUBLIC_URL is not a valid URL');
}

await validateStorage();

await validateDBConnection();

if ((await isInstalled()) === false) {
Expand All @@ -64,6 +69,8 @@ export default async function createApp(): Promise<express.Application> {
logger.warn(`Database migrations have not all been run`);
}

await flushCaches();

await initializeExtensions();

registerExtensionHooks();
Expand Down Expand Up @@ -171,7 +178,7 @@ export default async function createApp(): Promise<express.Application> {
app.use('/relations', relationsRouter);
app.use('/revisions', revisionsRouter);
app.use('/roles', rolesRouter);
app.use('/server/', serverRouter);
app.use('/server', serverRouter);
app.use('/settings', settingsRouter);
app.use('/users', usersRouter);
app.use('/utils', utilsRouter);
Expand Down
6 changes: 6 additions & 0 deletions api/src/cache.ts
Expand Up @@ -23,6 +23,12 @@ export function getCache(): { cache: Keyv | null; schemaCache: Keyv | null } {
return { cache, schemaCache };
}

export async function flushCaches(): Promise<void> {
const { schemaCache, cache } = getCache();
await schemaCache?.clear();
await cache?.clear();
}

function getKeyvInstance(ttl: number | undefined): Keyv {
switch (env.CACHE_STORE) {
case 'redis':
Expand Down
5 changes: 4 additions & 1 deletion api/src/controllers/files.ts
Expand Up @@ -33,7 +33,7 @@ const multipartHandler = asyncHandler(async (req, res, next) => {
*/

let disk: string = toArray(env.STORAGE_LOCATIONS)[0];
const payload: Partial<File> = {};
let payload: Partial<File> = {};
let fileCount = 0;

busboy.on('field', (fieldname: keyof File, val) => {
Expand Down Expand Up @@ -70,6 +70,9 @@ const multipartHandler = asyncHandler(async (req, res, next) => {
storage: payload.storage || disk,
};

// Clear the payload for the next to-be-uploaded file
payload = {};

try {
const primaryKey = await service.uploadOne(fileStream, payloadWithRequiredFields, existingPrimaryKey);
savedFiles.push(primaryKey);
Expand Down
7 changes: 2 additions & 5 deletions api/src/controllers/utils.ts
Expand Up @@ -8,7 +8,7 @@ import { respond } from '../middleware/respond';
import { RevisionsService, UtilsService, ImportService } from '../services';
import asyncHandler from '../utils/async-handler';
import Busboy from 'busboy';
import { getCache } from '../cache';
import { flushCaches } from '../cache';

const router = Router();

Expand Down Expand Up @@ -123,10 +123,7 @@ router.post(
throw new ForbiddenException();
}

const { cache, schemaCache } = getCache();

await cache?.clear();
await schemaCache?.clear();
await flushCaches();

res.status(200).end();
})
Expand Down
163 changes: 163 additions & 0 deletions api/src/database/helpers/geometry.ts
@@ -0,0 +1,163 @@
import { Field, RawField } from '@directus/shared/types';
import { Knex } from 'knex';
import { stringify as geojsonToWKT, GeoJSONGeometry } from 'wellknown';
import getDatabase from '..';

let geometryHelper: KnexSpatial | undefined;

export function getGeometryHelper(): KnexSpatial {
if (!geometryHelper) {
const db = getDatabase();
const client = db.client.config.client as string;
const constructor = {
mysql: KnexSpatial_MySQL,
mariadb: KnexSpatial_MySQL,
sqlite3: KnexSpatial,
pg: KnexSpatial_PG,
redshift: KnexSpatial_Redshift,
mssql: KnexSpatial_MSSQL,
oracledb: KnexSpatial_Oracle,
}[client];
if (!constructor) {
throw new Error(`Geometry helper not implemented on ${client}.`);
}
geometryHelper = new constructor(db);
}
return geometryHelper;
}

class KnexSpatial {
constructor(protected knex: Knex) {}
isTrue(expression: Knex.Raw) {
return expression;
}
isFalse(expression: Knex.Raw) {
return expression.wrap('NOT ', '');
}
createColumn(table: Knex.CreateTableBuilder, field: RawField | Field) {
const type = field.schema?.geometry_type ?? 'geometry';
return table.specificType(field.field, type);
}
asText(table: string, column: string): Knex.Raw {
return this.knex.raw('st_astext(??.??) as ??', [table, column, column]);
}
fromText(text: string): Knex.Raw {
return this.knex.raw('st_geomfromtext(?, 4326)', text);
}
fromGeoJSON(geojson: GeoJSONGeometry): Knex.Raw {
return this.fromText(geojsonToWKT(geojson));
}
_intersects(key: string, geojson: GeoJSONGeometry): Knex.Raw {
const geometry = this.fromGeoJSON(geojson);
return this.knex.raw('st_intersects(??, ?)', [key, geometry]);
}
intersects(key: string, geojson: GeoJSONGeometry): Knex.Raw {
return this.isTrue(this._intersects(key, geojson));
}
nintersects(key: string, geojson: GeoJSONGeometry): Knex.Raw {
return this.isFalse(this._intersects(key, geojson));
}
_intersects_bbox(key: string, geojson: GeoJSONGeometry): Knex.Raw {
const geometry = this.fromGeoJSON(geojson);
return this.knex.raw('intersects(??, ?)', [key, geometry]);
}
intersects_bbox(key: string, geojson: GeoJSONGeometry): Knex.Raw {
return this.isTrue(this._intersects_bbox(key, geojson));
}
nintersects_bbox(key: string, geojson: GeoJSONGeometry): Knex.Raw {
return this.isFalse(this._intersects_bbox(key, geojson));
}
collect(table: string, column: string): Knex.Raw {
return this.knex.raw('st_astext(st_collect(??.??))', [table, column]);
}
}

class KnexSpatial_PG extends KnexSpatial {
createColumn(table: Knex.CreateTableBuilder, field: RawField | Field) {
const type = field.schema?.geometry_type ?? 'geometry';
return table.specificType(field.field, `geometry(${type})`);
}
_intersects_bbox(key: string, geojson: GeoJSONGeometry): Knex.Raw {
const geometry = this.fromGeoJSON(geojson);
return this.knex.raw('?? && ?', [key, geometry]);
}
}

class KnexSpatial_MySQL extends KnexSpatial {
collect(table: string, column: string): Knex.Raw {
return this.knex.raw(
`concat('geometrycollection(', group_concat(? separator ', '), ')'`,
this.asText(table, column)
);
}
}

class KnexSpatial_Redshift extends KnexSpatial {
createColumn(table: Knex.CreateTableBuilder, field: RawField | Field) {
const type = field.schema?.geometry_type ?? 'geometry';
if (type !== 'geometry') field.meta!.special![1] = type;
return table.specificType(field.field, 'geometry');
}
}

class KnexSpatial_MSSQL extends KnexSpatial {
isTrue(expression: Knex.Raw) {
return expression.wrap(``, ` = 1`);
}
isFalse(expression: Knex.Raw) {
return expression.wrap(``, ` = 0`);
}
createColumn(table: Knex.CreateTableBuilder, field: RawField | Field) {
const type = field.schema?.geometry_type ?? 'geometry';
if (type !== 'geometry') field.meta!.special![1] = type;
return table.specificType(field.field, 'geometry');
}
asText(table: string, column: string): Knex.Raw {
return this.knex.raw('??.??.STAsText() as ??', [table, column, column]);
}
fromText(text: string): Knex.Raw {
return this.knex.raw('geometry::STGeomFromText(?, 4326)', text);
}
_intersects(key: string, geojson: GeoJSONGeometry): Knex.Raw {
const geometry = this.fromGeoJSON(geojson);
return this.knex.raw('??.STIntersects(?)', [key, geometry]);
}
_intersects_bbox(key: string, geojson: GeoJSONGeometry): Knex.Raw {
const geometry = this.fromGeoJSON(geojson);
return this.knex.raw('??.STEnvelope().STIntersects(?.STEnvelope())', [key, geometry]);
}
collect(table: string, column: string): Knex.Raw {
return this.knex.raw('geometry::CollectionAggregate(??.??).STAsText()', [table, column]);
}
}

class KnexSpatial_Oracle extends KnexSpatial {
isTrue(expression: Knex.Raw) {
return expression.wrap(``, ` = 'TRUE'`);
}
isFalse(expression: Knex.Raw) {
return expression.wrap(``, ` = 'FALSE'`);
}
createColumn(table: Knex.CreateTableBuilder, field: RawField | Field) {
const type = field.schema?.geometry_type ?? 'geometry';
if (type !== 'geometry') field.meta!.special![1] = type;
return table.specificType(field.field, 'sdo_geometry');
}
asText(table: string, column: string): Knex.Raw {
return this.knex.raw('sdo_util.from_wktgeometry(??.??) as ??', [table, column, column]);
}
fromText(text: string): Knex.Raw {
return this.knex.raw('sdo_geometry(?, 4326)', text);
}
_intersects(key: string, geojson: GeoJSONGeometry): Knex.Raw {
const geometry = this.fromGeoJSON(geojson);
return this.knex.raw(`sdo_overlapbdyintersect(??, ?)`, [key, geometry]);
}
_intersects_bbox(key: string, geojson: GeoJSONGeometry): Knex.Raw {
const geometry = this.fromGeoJSON(geojson);
return this.knex.raw(`sdo_overlapbdyintersect(sdo_geom.sdo_mbr(??), sdo_geom.sdo_mbr(?))`, [key, geometry]);
}
collect(table: string, column: string): Knex.Raw {
return this.knex.raw(`concat('geometrycollection(', listagg(?, ', '), ')'`, this.asText(table, column));
}
}
5 changes: 4 additions & 1 deletion api/src/database/index.ts
Expand Up @@ -53,7 +53,10 @@ export default function getDatabase(): Knex {
searchPath: env.DB_SEARCH_PATH,
connection: env.DB_CONNECTION_STRING || connectionConfig,
log: {
warn: (msg) => logger.warn(msg),
warn: (msg) => {
if (msg.startsWith('.returning()')) return;
return logger.warn(msg);
},
error: (msg) => logger.error(msg),
deprecate: (msg) => logger.info(msg),
debug: (msg) => logger.debug(msg),
Expand Down
15 changes: 15 additions & 0 deletions api/src/database/migrations/20210811A-add-geometry-config.ts
@@ -0,0 +1,15 @@
import { Knex } from 'knex';

export async function up(knex: Knex): Promise<void> {
await knex.schema.alterTable('directus_settings', (table) => {
table.json('basemaps');
table.string('mapbox_key');
});
}

export async function down(knex: Knex): Promise<void> {
await knex.schema.alterTable('directus_settings', (table) => {
table.dropColumn('basemaps');
table.dropColumn('mapbox_key');
});
}

0 comments on commit be34474

Please sign in to comment.