Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Google sheets to v3 #423

Open
wants to merge 45 commits into
base: managed-adapter
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
a7b0ba6
wip
michaelir Oct 23, 2022
3c74c25
wip
michaelir Oct 25, 2022
b11e8d4
disconnected all database implementations from the adapter (Only mysq…
michaelir Oct 26, 2022
f6f05be
removed databases from main.yaml
michaelir Oct 26, 2022
42b0a2a
transferring find tests to query endpoint
michaelir Oct 30, 2022
6c2faa0
Data spi V3 (#353)
michaelir Nov 15, 2022
6e360a9
Capabilities endpoint + test (#359)
michaelir Nov 20, 2022
56ef057
Managed adapter auth scheme (#360)
rosenvered Nov 30, 2022
0d8dd8c
adapter-auth: change according to Wix-Data returned response (#364)
rosenvered Dec 5, 2022
ff754b9
refactor: disable import of unsupported libraries (#361)
MXPOL Dec 6, 2022
1383741
Managed adapter lint fixes (#366)
Idokah Dec 7, 2022
be6312e
refactor app data e2e (#372)
Idokah Dec 15, 2022
9ede3d0
rebase
Idokah Dec 15, 2022
0dfd55b
filter by date v3 (#374)
Idokah Dec 15, 2022
7af57b1
implementing errors spi (#365)
michaelir Dec 18, 2022
c8e7f8e
fixes for provision flow (#377)
justinass-wix Dec 20, 2022
7551fa3
New Collection SPI implementation (#354)
MXPOL Dec 26, 2022
b111339
Capabilities property in collection object (#381)
MXPOL Jan 9, 2023
82865d0
temp - comment new tests
Idokah Jan 11, 2023
1c0b9a2
insert/update null tests to v3 format (#388)
Idokah Jan 11, 2023
726d785
Support queries on nested fields (MySQL) (#393)
Idokah Jan 23, 2023
3e5b866
fix flaky test
Idokah Jan 24, 2023
271e8d5
change upsert test to be bulk
Idokah Jan 24, 2023
3198cfb
Collection and field capabilities tests refactor (#396)
MXPOL Jan 24, 2023
f66e396
fix: disable sorting on object columns
MXPOL Jan 24, 2023
7da6fa5
Errors v3 add e2e tests (#399)
Idokah Jan 29, 2023
5eee646
fix e2e error tests
Idokah Jan 29, 2023
11982d6
without include (#401)
Idokah Jan 29, 2023
2313637
New properties in CollectionCapabilities and FieldCapabilities (#398)
MXPOL Jan 30, 2023
71d59c0
Postgres to v3 (#400)
michaelir Feb 5, 2023
ca0eb90
fix postgres collectionCapabilities
Idokah Feb 5, 2023
cd1991e
fix flaky test postgres
Idokah Feb 5, 2023
4d3f7ad
MSSQL to v3 (#395)
Idokah Feb 5, 2023
e4fc22e
fix typo
Idokah Feb 5, 2023
f5d60a0
Spanner to v3 (#404)
Idokah Feb 5, 2023
5b85442
Mongo to V3 (#397)
MXPOL Feb 6, 2023
6f0ce45
rebasing
Idokah Feb 6, 2023
7f02071
Data hooks to v3 (#413)
Idokah Feb 22, 2023
39dee13
Dynamo to v3 (#411)
Idokah Feb 22, 2023
141cf61
Firestore v3 (#414)
michaelir Feb 22, 2023
879cf77
init: google-sheets-to-v3
MXPOL Mar 6, 2023
2da944b
refactor: remove the comment from google sheet
MXPOL Mar 6, 2023
19c6cd0
feat: changes to support V3
MXPOL Mar 6, 2023
1fd36c9
test: run tests on github action
MXPOL Mar 6, 2023
81d3a7a
refactor: added googles test to run tests
MXPOL Mar 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@
"@typescript-eslint/no-unused-vars": [ "error", { "ignoreRestSiblings": true, "argsIgnorePattern": "^_" } ],
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/ban-ts-comment": "warn",
"eol-last": [ "error", "always" ]
"eol-last": [ "error", "always" ],
"@typescript-eslint/no-empty-interface": "off"
}
}
]
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ jobs:
matrix:
database: [
"postgres", "postgres13", "postgres12", "postgres11", "postgres10", "postgres9",
"spanner",
"mysql", "mysql5",
"mssql", "mssql17",
spanner,
"mongo", "mongo4",
"firestore",
"dynamodb",
"firestore",
"google-sheets"
]

Expand Down
20 changes: 10 additions & 10 deletions apps/velo-external-db/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ import { create, readCommonConfig } from '@wix-velo/external-db-config'
import { ExternalDbRouter, Hooks } from '@wix-velo/velo-external-db-core'
import { engineConnectorFor } from './storage/factory'


const initConnector = async(hooks?: Hooks) => {
const { vendor, type: adapterType, hideAppInfo } = readCommonConfig()

const initConnector = async(wixDataBaseUrl?: string, hooks?: Hooks) => {
const { vendor, type: adapterType, externalDatabaseId, allowedMetasites, hideAppInfo } = readCommonConfig()
const configReader = create()
const { authorization, secretKey, ...dbConfig } = await configReader.readConfig()
const { authorization, ...dbConfig } = await configReader.readConfig()

const { connector: engineConnector, providers, cleanup } = await engineConnectorFor(adapterType, dbConfig)

Expand All @@ -18,23 +16,25 @@ const initConnector = async(hooks?: Hooks) => {
authorization: {
roleConfig: authorization
},
secretKey,
externalDatabaseId,
allowedMetasites,
vendor,
adapterType,
commonExtended: true,
hideAppInfo
hideAppInfo,
wixDataBaseUrl: wixDataBaseUrl || 'https://www.wixapis.com/wix-data'
},
hooks,
})

return { externalDbRouter, cleanup: async() => await cleanup(), schemaProvider: providers.schemaProvider }
}

export const createApp = async() => {
export const createApp = async(wixDataBaseUrl?: string) => {
const app = express()
const initConnectorResponse = await initConnector()
const initConnectorResponse = await initConnector(wixDataBaseUrl)
app.use(initConnectorResponse.externalDbRouter.router)
const server = app.listen(8080, () => console.log('Connector listening on port 8080'))

return { server, ...initConnectorResponse, reload: () => initConnector() }
return { server, ...initConnectorResponse, reload: () => initConnector(wixDataBaseUrl) }
}
16 changes: 8 additions & 8 deletions apps/velo-external-db/src/storage/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,18 @@ export const engineConnectorFor = async(_type: string, config: any): Promise<Dat
const { googleSheetFactory } = require('@wix-velo/external-db-google-sheets')
return await googleSheetFactory(config)
}
case 'airtable': {
const { airtableFactory } = require('@wix-velo/external-db-airtable')
return await airtableFactory(config)
}
// case 'airtable': {
// const { airtableFactory } = require('@wix-velo/external-db-airtable')
// return await airtableFactory(config)
// }
case 'dynamodb': {
const { dynamoDbFactory } = require('@wix-velo/external-db-dynamodb')
return await dynamoDbFactory(config)
}
case 'bigquery': {
const { bigqueryFactory } = require('@wix-velo/external-db-bigquery')
return await bigqueryFactory(config)
}
// case 'bigquery': {
// const { bigqueryFactory } = require('@wix-velo/external-db-bigquery')
// return await bigqueryFactory(config)
// }
default: {
const { stubFactory } = require('./stub-db/stub-connector')
return await stubFactory(type, config)
Expand Down
67 changes: 64 additions & 3 deletions apps/velo-external-db/test/drivers/data_api_rest_test_support.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,70 @@
import axios from 'axios'
import { Item } from '@wix-velo/velo-external-db-types'
import { dataSpi } from '@wix-velo/velo-external-db-core'
import { streamToArray } from '@wix-velo/test-commons'

const axios = require('axios').create({
const axiosInstance = axios.create({
baseURL: 'http://localhost:8080'
})

export const givenItems = async(items: Item[], collectionName: string, auth: any) => await axios.post('/data/insert/bulk', { collectionName: collectionName, items: items }, auth)
export const insertRequest = (collectionName: string, items: Item[], overwriteExisting: boolean): dataSpi.InsertRequest => ({
collectionId: collectionName,
items: items,
overwriteExisting,
options: {
consistentRead: false,
appOptions: {},
}
})

export const updateRequest = (collectionName: string, items: Item[]): dataSpi.UpdateRequest => ({
collectionId: collectionName,
items: items,
options: {
consistentRead: false,
appOptions: {},
}
})

export const countRequest = (collectionName: string, filter?: dataSpi.Filter): dataSpi.CountRequest => ({
collectionId: collectionName,
filter: filter ?? '',
options: {
consistentRead: false,
appOptions: {},
},
})

export const queryRequest = (collectionName: string, sort: dataSpi.Sorting[], fields: string[], filter?: dataSpi.Filter): dataSpi.QueryRequest => ({
collectionId: collectionName,
query: {
filter: filter ?? '',
sort: sort,
fields: fields,
fieldsets: undefined,
paging: {
limit: 25,
offset: 0,
},
cursorPaging: null
},
includeReferencedItems: [],
options: {
consistentRead: false,
appOptions: {},
},
omitTotalCount: false
})


export const queryCollectionAsArray = (collectionName: string, sort: dataSpi.Sorting[], fields: string[], auth: any, filter?: dataSpi.Filter) =>
axiosInstance.post('/data/query',
queryRequest(collectionName, sort, fields, filter), { responseType: 'stream', transformRequest: auth.transformRequest })
.then(response => streamToArray(response.data))


export const pagingMetadata = (count: number, total?: number): dataSpi.QueryResponsePart => ({ pagingMetadata: { count: count, offset: 0, total: total, tooManyToCount: false } })


export const expectAllDataIn = async(collectionName: string, auth: any) => (await axios.post('/data/find', { collectionName: collectionName, filter: '', sort: '', skip: 0, limit: 25 }, auth)).data
export const givenItems = async(items: Item[], collectionName: string, auth: any) =>
await axiosInstance.post('/data/insert', insertRequest(collectionName, items, false), { responseType: 'stream', transformRequest: auth.transformRequest })
34 changes: 34 additions & 0 deletions apps/velo-external-db/test/drivers/hooks_test_support_v3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { ExternalDbRouter } from '@wix-velo/velo-external-db-core'
import { Item } from '@wix-velo/velo-external-db-types'


export const requestBodyWith = (collectionId: string, items: Item[]) => ({
...writeRequestBodyWith(collectionId, items), ...readRequestBodyWith(collectionId)
})

export const writeRequestBodyWith = (collectionId: string, items: Item[]) => ({
collectionId, items, item: items[0], itemId: items[0]?._id, itemIds: items.map((item: { _id: any }) => item._id), overWriteExisting: true
})

export const readRequestBodyWith = (collectionId: string) => ({
collectionId, filter: {}, query: { filter: {} }, omitTotalCount: false, group: { by: [], aggregation: [] }, initialFilter: {}, finalFilter: {}, sort: [], paging: { offset: 0, limit: 10 }
})

export const splitIdToThreeParts = (id: string) => {
return [id.slice(0, id.length / 3), id.slice(id.length / 3, id.length / 3 * 2), id.slice(id.length / 3 * 2)]
}

export const concatToProperty = <T>(obj: T, path: string, value: any): T => {
const pathArray = path.split('.')
const newObject = { ...obj }
let current = newObject

for (let i = 0; i < pathArray.length - 1; i++) {
current = current[pathArray[i]]
}

current[pathArray[pathArray.length - 1]] += value
return newObject
}

export const resetHooks = (externalDbRouter: ExternalDbRouter) => externalDbRouter.reloadHooks()
43 changes: 42 additions & 1 deletion apps/velo-external-db/test/drivers/schema_api_rest_matchers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { SystemFields, asWixSchemaHeaders } from '@wix-velo/velo-external-db-commons'
import { InputField } from '@wix-velo/velo-external-db-types'
import { InputField, DataOperation, FieldType, CollectionOperation } from '@wix-velo/velo-external-db-types'
import { schemaUtils } from '@wix-velo/velo-external-db-core'
import { Capabilities, ColumnsCapabilities } from '../types'

export const responseWith = (matcher: any) => expect.objectContaining( { data: matcher } )

Expand Down Expand Up @@ -40,3 +42,42 @@ const toHaveCollections = (collections: string[]) => expect.objectContaining( {
const listToHaveCollection = (collectionName: string) => expect.objectContaining( {
schemas: expect.arrayContaining( [ expect.objectContaining( { id: collectionName } ) ] )
} )

const collectionCapabilities = (collectionOperations: CollectionOperation[], dataOperations: DataOperation[], fieldTypes: FieldType[]) => ({
collectionOperations: expect.arrayContaining(collectionOperations.map(schemaUtils.collectionOperationsToWixDataCollectionOperations)),
dataOperations: expect.arrayContaining(dataOperations.map(schemaUtils.dataOperationsToWixDataQueryOperators)),
fieldTypes: expect.arrayContaining(fieldTypes.map(schemaUtils.fieldTypeToWixDataEnum)),
referenceCapabilities: expect.objectContaining({ supportedNamespaces: [] }),
indexing: [],
encryption: 0
})

const filedMatcher = (field: InputField, columnsCapabilities: ColumnsCapabilities) => ({
key: field.name,
type: schemaUtils.fieldTypeToWixDataEnum(field.type),
capabilities: {
sortable: columnsCapabilities[field.type].sortable,
queryOperators: columnsCapabilities[field.type].columnQueryOperators.map(schemaUtils.queryOperatorsToWixDataQueryOperators)
},
encrypted: expect.any(Boolean)
})

const fieldsWith = (fields: InputField[], columnsCapabilities: ColumnsCapabilities) => expect.toIncludeSameMembers(fields.map(f => filedMatcher(f, columnsCapabilities)))

export const collectionResponsesWith = (collectionName: string, fields: InputField[], capabilities: Capabilities) => {
const dataOperations = fields.map(f => f.name).includes('_id') ? capabilities.ReadWriteOperations : capabilities.ReadOnlyOperations
return {
id: collectionName,
capabilities: collectionCapabilities(capabilities.CollectionOperations, dataOperations, capabilities.FieldTypes),
fields: fieldsWith(fields, capabilities.ColumnsCapabilities),
}
}

export const createCollectionResponseWith = (collectionName: string, fields: InputField[], capabilities: Capabilities) => {
const dataOperations = fields.map(f => f.name).includes('_id') ? capabilities.ReadWriteOperations : capabilities.ReadOnlyOperations
return {
id: collectionName,
capabilities: collectionCapabilities(capabilities.CollectionOperations, dataOperations, capabilities.FieldTypes),
fields: fieldsWith(fields, capabilities.ColumnsCapabilities),
}
}
30 changes: 25 additions & 5 deletions apps/velo-external-db/test/drivers/schema_api_rest_test_support.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
import axios from 'axios'
import { InputField } from '@wix-velo/velo-external-db-types'
import { streamToArray } from '@wix-velo/test-commons'
import { schemaUtils } from '@wix-velo/velo-external-db-core'

const axios = require('axios').create({

const axiosClient = axios.create({
baseURL: 'http://localhost:8080'
})

export const givenCollection = async(name: string, columns: InputField[], auth: any) => {
await axios.post('/schemas/create', { collectionName: name }, auth)
for (const column of columns) {
await axios.post('/schemas/column/add', { collectionName: name, column: column }, auth)
const collection = {
id: name,
fields: columns.map(schemaUtils.InputFieldToWixFormatField)
}
await axiosClient.post('/collections/create', { collection }, { ...auth, responseType: 'stream' })
}

export const retrieveSchemaFor = async(collectionName: string, auth: any) => axios.post('/schemas/find', { schemaIds: [collectionName] }, auth)
export const deleteAllCollections = async(auth: any) => {
const res = await axiosClient.post('/collections/get', { collectionIds: [] }, { ...auth, responseType: 'stream' })
const dataRes = await streamToArray(res.data) as any []
const collectionIds = dataRes.map(d => d.id)

for (const collectionId of collectionIds) {
await axiosClient.post('/collections/delete', { collectionId }, { ...auth, responseType: 'stream' })
}

}

export const retrieveSchemaFor = async(collectionName: string, auth: any) => {
const collectionGetStream = await axiosClient.post('/collections/get', { collectionIds: [collectionName] }, { ...auth, responseType: 'stream' })
const [collectionGetRes] = await streamToArray(collectionGetStream.data) as any[]
return collectionGetRes
}
31 changes: 26 additions & 5 deletions apps/velo-external-db/test/drivers/schema_provider_matchers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
export const hasSameSchemaFieldsLike = (fields: {field: string, [x: string]: any}[]) => expect.arrayContaining( fields.map((f: any) => expect.objectContaining( f ) ))
import { SystemFields } from '@wix-velo/velo-external-db-commons'
import { ResponseField } from '@wix-velo/velo-external-db-types'
import { Capabilities, ColumnsCapabilities } from '../types'

export const collectionWithDefaultFields = () => hasSameSchemaFieldsLike([ { field: '_id', type: 'text' },
{ field: '_createdDate', type: 'datetime' },
{ field: '_updatedDate', type: 'datetime' },
{ field: '_owner', type: 'text' } ])
export const hasSameSchemaFieldsLike = (fields: ResponseField[]) => expect.arrayContaining(fields.map((f) => expect.objectContaining( f )))

export const toContainDefaultFields = (columnsCapabilities: ColumnsCapabilities) => hasSameSchemaFieldsLike(SystemFields.map(f => ({
field: f.name,
type: f.type,
capabilities: columnsCapabilities[f.type]
})))


export const collectionToContainFields = (collectionName: string, fields: any[], capabilities: Capabilities) => ({
id: collectionName,
fields: hasSameSchemaFieldsLike(fields),
capabilities: {
collectionOperations: capabilities.CollectionOperations,
dataOperations: capabilities.ReadWriteOperations,
fieldTypes: capabilities.FieldTypes,
referenceCapabilities: { supportedNamespaces: [] },
indexing: [],
encryption: 'notSupported'
}
})

export const toBeDefaultCollectionWith = (collectionName: string, capabilities: any) => collectionToContainFields(collectionName, SystemFields.map(f => ({ field: f.name, type: f.type })), capabilities)
17 changes: 17 additions & 0 deletions apps/velo-external-db/test/drivers/wix_data_resources.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Server } from 'http'
import { app as mockServer } from './wix_data_testkit'

let _server: Server
const PORT = 9001

export const initWixDataEnv = async() => {
_server = mockServer.listen(PORT)
}

export const shutdownWixDataEnv = async() => {
_server.close()
}

export const wixDataBaseUrl = () => {
return `http://localhost:${PORT}`
}
33 changes: 33 additions & 0 deletions apps/velo-external-db/test/drivers/wix_data_testkit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { authConfig } from '@wix-velo/test-commons'
import * as express from 'express'

export const app = express()

app.set('case sensitive routing', true)

app.use(express.json())

app.get('/v1/external-databases/:externalDatabaseId/public-keys', (_req, res) => {
res.json({
publicKeys: [
{ id: authConfig.kid, publicKeyPem: authConfig.authPublicKey },
]
})
})

app.use((_req, res) => {
res.status(404)
res.json({ error: 'NOT_FOUND' })
})

app.use((err, _req, res, next) => {
res.status(err.status)
res.json({
error: {
message: err.message,
status: err.status,
error: err.error
}
})
next()
})
Loading