Skip to content

Commit

Permalink
Merge branch 'main' into cli
Browse files Browse the repository at this point in the history
  • Loading branch information
gimenete committed May 17, 2022
2 parents b540332 + a5f3490 commit 583d230
Show file tree
Hide file tree
Showing 105 changed files with 130 additions and 216 deletions.
6 changes: 6 additions & 0 deletions .changeset/quick-fans-reflect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@xata.io/client': patch
'@xata.io/codegen': patch
---

Add new plugin system for the SDK
3 changes: 3 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# .git-blame-ignore-revs
# Refactor folders into packages/*
0242bddba7ece712c1c16ab023be0d9e6e21b4a1
8 changes: 0 additions & 8 deletions client/src/api/index.ts

This file was deleted.

9 changes: 0 additions & 9 deletions client/src/namespace.ts

This file was deleted.

2 changes: 0 additions & 2 deletions codegen/example/xata/.gitignore

This file was deleted.

5 changes: 0 additions & 5 deletions codegen/example/xata/config.json

This file was deleted.

61 changes: 0 additions & 61 deletions codegen/example/xata/schema.json

This file was deleted.

2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"packages": ["client", "codegen", "importer", "shell"],
"packages": ["packages/*"],
"version": "0.2.2"
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
},
"size-limit": [
{
"path": "client/dist/*"
"path": "packages/client/dist/*"
}
],
"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion client/.eslintrc.cjs → packages/client/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module.exports = {
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
project: 'client/tsconfig.json'
project: 'packages/client/tsconfig.json'
},
rules: {
'@typescript-eslint/no-explicit-any': 'off',
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
17 changes: 17 additions & 0 deletions packages/client/src/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { XataPlugin, XataPluginOptions } from '../plugins';
import { XataApiClient } from './client';
import { operationsByTag } from './components';
import type * as Responses from './responses';
import type * as Schemas from './schemas';

export * from './client';
export * from './components';
export { operationsByTag as Operations };
export type { Responses, Schemas };

export class XataApiPlugin implements XataPlugin {
async build(options: XataPluginOptions) {
const { fetchImpl, apiKey } = await options.getFetchProps();
return new XataApiClient({ fetch: fetchImpl, apiKey });
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
64 changes: 31 additions & 33 deletions client/src/client.ts → packages/client/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { FetcherExtraProps, FetchImpl } from './api/fetcher';
import { Namespace } from './namespace';
import { SchemaNamespace } from './schema';
import { XataPlugin } from './plugins';
import { SchemaPlugin } from './schema';
import { BaseData } from './schema/record';
import { LinkDictionary } from './schema/repository';
import { SearchNamespace } from './search';
import { SearchPlugin } from './search';
import { BranchStrategy, BranchStrategyOption, BranchStrategyValue, isBranchStrategyBuilder } from './util/branches';
import { getAPIKey, getCurrentBranchName, getDatabaseURL } from './util/config';
import { getFetchImplementation } from './util/fetch';
Expand All @@ -16,34 +16,32 @@ export type BaseClientOptions = {
branch?: BranchStrategyOption;
};

export const buildClientWithNamespaces =
<ExternalNamespaces extends Record<string, Namespace>>(namespaces: ExternalNamespaces) =>
<Schemas extends Record<string, BaseData>>() =>
buildClient<Schemas, ExternalNamespaces>(namespaces);

export const buildClient = <
Schemas extends Record<string, BaseData>,
ExternalNamespaces extends Record<string, Namespace> = {},
Namespaces extends Record<string, Namespace> = { db: SchemaNamespace<Schemas>; search: SearchNamespace<Schemas> }
>(
external?: ExternalNamespaces
) =>
export const buildClient = <Plugins extends Record<string, XataPlugin> = {}>(plugins?: Plugins) =>
class {
#branch: BranchStrategyValue;

constructor(options: BaseClientOptions = {}, links?: LinkDictionary) {
const safeOptions = this.#parseOptions(options);

const namespaces = {
db: new SchemaNamespace(links),
search: new SearchNamespace(),
...external
const namespaces: Record<string, XataPlugin> = {
db: new SchemaPlugin(links),
search: new SearchPlugin(),
...plugins
};

for (const [key, namespace] of Object.entries(namespaces)) {
if (!namespace) continue;
// @ts-ignore
this[key] = namespace.build({ getFetchProps: () => this.#getFetchProps(safeOptions) });
const result = namespace.build({ getFetchProps: () => this.#getFetchProps(safeOptions) });

if (result instanceof Promise) {
void result.then((namespace: unknown) => {
// @ts-ignore
this[key] = namespace;
});
} else {
// @ts-ignore
this[key] = result;
}
}
}

Expand Down Expand Up @@ -103,18 +101,18 @@ export const buildClient = <
}
}
}
} as unknown as WrapperConstructor<Schemas, Namespaces, ExternalNamespaces>;

export interface WrapperConstructor<
Schemas extends Record<string, BaseData> = Record<string, any>,
Namespaces extends Record<string, Namespace> = { db: SchemaNamespace<Schemas>; search: SearchNamespace<Schemas> },
ExternalNamespaces extends Record<string, Namespace> = Record<string, Namespace>
> {
new (options?: Partial<BaseClientOptions>, links?: LinkDictionary): {
[Key in StringKeys<Namespaces>]: ReturnType<Namespaces[Key]['build']>;
} & {
[Key in StringKeys<NonNullable<ExternalNamespaces>>]: ReturnType<NonNullable<ExternalNamespaces>[Key]['build']>;
} as unknown as ClientConstructor<Plugins>;

export interface ClientConstructor<Plugins extends Record<string, XataPlugin>> {
new <Schemas extends Record<string, BaseData>>(options?: Partial<BaseClientOptions>, links?: LinkDictionary): Omit<
{
db: Awaited<ReturnType<SchemaPlugin<Schemas>['build']>>;
search: Awaited<ReturnType<SearchPlugin<Schemas>['build']>>;
},
keyof Plugins
> & {
[Key in StringKeys<NonNullable<Plugins>>]: Awaited<ReturnType<NonNullable<Plugins>[Key]['build']>>;
};
}

export class BaseClient extends buildClient<Record<string, any>>() {}
export class BaseClient extends buildClient()<Record<string, any>> {}
1 change: 1 addition & 0 deletions client/src/index.ts → packages/client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export class XataError extends Error {
}

export * from './api';
export * from './plugins';
export * from './client';
export * from './schema';
export * from './search';
Expand Down
9 changes: 9 additions & 0 deletions packages/client/src/plugins.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { FetcherExtraProps } from './api/fetcher';

export abstract class XataPlugin {
abstract build(options: XataPluginOptions): unknown | Promise<unknown>;
}

export type XataPluginOptions = {
getFetchProps: () => Promise<FetcherExtraProps>;
};
File renamed without changes.
File renamed without changes.
File renamed without changes.
18 changes: 10 additions & 8 deletions client/src/schema/index.ts → packages/client/src/schema/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Namespace, NamespaceBuildOptions } from '../namespace';
import { XataPlugin, XataPluginOptions } from '../plugins';
import { isString } from '../util/lang';
import { BaseData } from './record';
import { LinkDictionary, Repository, RestRepository } from './repository';
Expand All @@ -7,38 +7,40 @@ export * from './operators';
export * from './pagination';
export { Query } from './query';
export { isIdentifiable, isXataRecord } from './record';
export type { Identifiable, XataRecord } from './record';
export type { BaseData, EditableData, Identifiable, XataRecord } from './record';
export { Repository, RestRepository } from './repository';
export type { LinkDictionary } from './repository';
export * from './selection';

export type SchemaDefinition = {
table: string;
links?: LinkDictionary;
};

export type SchemaNamespaceResult<Schemas extends Record<string, BaseData>> = {
export type SchemaPluginResult<Schemas extends Record<string, BaseData>> = {
[Key in keyof Schemas]: Repository<Schemas[Key]>;
};

export class SchemaNamespace<Schemas extends Record<string, BaseData>> extends Namespace {
export class SchemaPlugin<Schemas extends Record<string, BaseData>> extends XataPlugin {
constructor(private links?: LinkDictionary) {
super();
}

build(options: NamespaceBuildOptions): SchemaNamespaceResult<Schemas> {
build(options: XataPluginOptions): SchemaPluginResult<Schemas> {
const { getFetchProps } = options;

const links = this.links;

const schemaNamespace: any = new Proxy(
const db: any = new Proxy(
{},
{
get: (_target, table) => {
if (!isString(table)) throw new Error('Invalid table name');
return new RestRepository({ schemaNamespace, getFetchProps, table, links });
return new RestRepository({ db, getFetchProps, table, links });
}
}
);

return schemaNamespace;
return db;
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SchemaNamespaceResult } from '.';
import { SchemaPluginResult } from '.';
import {
bulkInsertTableRecords,
deleteRecord,
Expand Down Expand Up @@ -150,27 +150,27 @@ export abstract class Repository<Data extends BaseData, Record extends XataRecor
abstract query<Result extends XataRecord>(query: Query<Record, Result>): Promise<Page<Record, Result>>;
}

export class RestRepository<Data extends BaseData, Record extends XataRecord = Data & XataRecord> extends Query<
Record,
SelectedPick<Record, ['*']>
> {
export class RestRepository<Data extends BaseData, Record extends XataRecord = Data & XataRecord>
extends Query<Record, SelectedPick<Record, ['*']>>
implements Repository<Data, Record>
{
#table: string;
#links: LinkDictionary;
#getFetchProps: () => Promise<FetcherExtraProps>;
#schemaNamespace: SchemaNamespaceResult<any>;
db: SchemaPluginResult<any>;

constructor(options: {
table: string;
links?: LinkDictionary;
getFetchProps: () => Promise<FetcherExtraProps>;
schemaNamespace: SchemaNamespaceResult<any>;
db: SchemaPluginResult<any>;
}) {
super(null, options.table, {});

this.#table = options.table;
this.#links = options.links ?? {};
this.#getFetchProps = options.getFetchProps;
this.#schemaNamespace = options.schemaNamespace;
this.db = options.db;
}

async create(object: EditableData<Data>): Promise<SelectedPick<Record, ['*']>>;
Expand Down Expand Up @@ -470,7 +470,7 @@ export class RestRepository<Data extends BaseData, Record extends XataRecord = D
}
}

const db = this.#schemaNamespace;
const db = this.db;
result.read = function () {
return db[table].read(result['id'] as string);
};
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { searchBranch } from '../api';
import { Namespace, NamespaceBuildOptions } from '../namespace';
import { XataPlugin, XataPluginOptions } from '../plugins';
import { BaseData, XataRecord } from '../schema/record';
import { SelectedPick } from '../schema/selection';
import { GetArrayInnerType, StringKeys, Values } from '../util/types';

export class SearchNamespace<Schemas extends Record<string, BaseData>> extends Namespace {
build({ getFetchProps }: NamespaceBuildOptions) {
export class SearchPlugin<Schemas extends Record<string, BaseData>> extends XataPlugin {
build({ getFetchProps }: XataPluginOptions) {
return {
all: async <Tables extends StringKeys<Schemas>>(
query: string,
Expand Down Expand Up @@ -48,7 +48,7 @@ export class SearchNamespace<Schemas extends Record<string, BaseData>> extends N
async #search<Tables extends StringKeys<Schemas>>(
query: string,
options: { fuzziness?: number; tables?: Tables[] },
getFetchProps: NamespaceBuildOptions['getFetchProps']
getFetchProps: XataPluginOptions['getFetchProps']
) {
const fetchProps = await getFetchProps();
const { tables, fuzziness } = options ?? {};
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion codegen/.eslintrc.cjs → packages/codegen/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module.exports = {
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
project: 'codegen/tsconfig.json'
project: 'packages/codegen/tsconfig.json'
},
rules: {
'@typescript-eslint/no-explicit-any': 'off',
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 583d230

Please sign in to comment.