Skip to content

Commit

Permalink
add query replication state
Browse files Browse the repository at this point in the history
  • Loading branch information
kilbot committed Dec 19, 2023
1 parent 6907a59 commit aff4a01
Show file tree
Hide file tree
Showing 18 changed files with 902 additions and 118 deletions.
16 changes: 3 additions & 13 deletions src/collection-replication-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ interface CollectionReplicationConfig<T extends RxCollection> {
collection: T;
httpClient: any;
hooks?: any;
endpoint: string;
}

export class CollectionReplicationState<T extends RxCollection> {
Expand Down Expand Up @@ -60,11 +61,11 @@ export class CollectionReplicationState<T extends RxCollection> {
/**
*
*/
constructor({ collection, httpClient, hooks }: CollectionReplicationConfig<T>) {
constructor({ collection, httpClient, hooks, endpoint }: CollectionReplicationConfig<T>) {
this.collection = collection;
this.httpClient = httpClient;
this.hooks = hooks || {};
this.endpoint = this.getEndpoint();
this.endpoint = endpoint;

/**
* Subscribe to the remoteIDs local document
Expand Down Expand Up @@ -129,17 +130,6 @@ export class CollectionReplicationState<T extends RxCollection> {
// await this.syncRemoteIDs();
}

/**
* Allow the user to override the endpoint, eg: variations collection will have
* /products/<parent_id>/variations endpoint
*/
getEndpoint(): string {
if (this.hooks.preEndpoint) {
return this.hooks.preEndpoint(this.collection);
}
return this.collection.name;
}

/**
*
*/
Expand Down
31 changes: 31 additions & 0 deletions src/hooks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
This should be abstracted, perhaps as part of the QueryProvider config?

We have two formats for querying data:

- one for the local rxdb database (mongo like syntax)
- one for the WC REST API which has it's own quirks

For example:

Query products by category 19 in rxdb, ordered by name.

```
{
selector: {
categories: {
$elemMatch: 19
}
},
sortBy: 'name'
}
```

Query products by category 19 in WC REST API, ordered by name.

```
queryParams = {
category: 19,
orderby: 'title'
}
```
36 changes: 36 additions & 0 deletions src/hooks/categories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import isEmpty from 'lodash/isEmpty';

type ProductCategoryDocument = import('@wcpos/database/src').ProductCategoryDocument;

interface APIQueryParams {
context?: 'view' | 'edit';
page?: number;
per_page?: number;
search?: string;
exclude?: number[];
include?: number[];
order?: 'asc' | 'desc';
orderby?: 'id' | 'include' | 'name' | 'slug' | 'term_group' | 'description' | 'count';
hide_empty?: boolean;
parent?: number;
product?: number;
slug?: string;
}

/**
*
*/
const filterApiQueryParams = (params, checkpoint, batchSize) => {
const { include } = checkpoint;

/**
* Categories don't have a date field, so if localIDs = remoteIDs, then we can skip the API call
*/
if (isEmpty(include)) {
return false;
}

return params;
};

export { filterApiQueryParams };
48 changes: 48 additions & 0 deletions src/hooks/customers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
type CustomerDocument = import('@wcpos/database/src').CustomerDocument;

interface APIQueryParams {
context?: 'view' | 'edit';
page?: number;
per_page?: number;
search?: string;
exclude?: number[];
include?: number[];
offset?: number;
order?: 'asc' | 'desc';
orderby?: 'id' | 'include' | 'name' | 'registered_date';
email?: string;
role?:
| 'all'
| 'administrator'
| 'editor'
| 'author'
| 'contributor'
| 'subscriber'
| 'customer'
| 'shop_manager';
}

/**
*
*/
const filterApiQueryParams = (params, checkpoint, batchSize) => {
let orderby = params.orderby;

if (orderby === 'date_created') {
orderby = 'registered_date';
}

// HACK: get the deafult_customer, probably a better way to do this
// if (params.id) {
// params.include = params.id;
// params.id = undefined;
// }

return {
...params,
role: 'all',
orderby,
};
};

export { filterApiQueryParams };
55 changes: 55 additions & 0 deletions src/hooks/orders.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
type OrderDocument = import('@wcpos/database/src').OrderDocument;

interface APIQueryParams {
context?: 'view' | 'edit';
page?: number;
per_page?: number;
search?: string;
after?: string;
before?: string;
modified_after?: string;
modified_before?: string;
dates_are_gmt?: boolean;
exclude?: number[];
include?: number[];
offset?: number;
order?: 'asc' | 'desc';
orderby?: 'date' | 'id' | 'include' | 'title' | 'slug';
parent?: number[];
parent_exclude?: number[];
status?:
| 'any'
| 'pending'
| 'processing'
| 'on-hold'
| 'completed'
| 'cancelled'
| 'refunded'
| 'failed'
| 'trash';
customer?: number;
product?: number;
dp?: number;
}

/**
*
*/
const filterApiQueryParams = (params, checkpoint, batchSize) => {
let orderby = params.orderby;

if (orderby === 'date_created' || orderby === 'date_created_gmt') {
orderby = 'date';
}

if (orderby === 'number') {
orderby = 'id';
}

return {
...params,
orderby,
};
};

export { filterApiQueryParams };
71 changes: 71 additions & 0 deletions src/hooks/products.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import get from 'lodash/get';

type ProductDocument = import('@wcpos/database/src').ProductDocument;

interface APIQueryParams {
context?: 'view' | 'edit';
page?: number;
per_page?: number;
search?: string;
after?: string;
before?: string;
modified_after?: string;
modified_before?: string;
dates_are_gmt?: boolean;
exclude?: number[];
include?: number[];
offset?: number;
order?: 'asc' | 'desc';
orderby?: 'date' | 'id' | 'include' | 'title' | 'slug' | 'price' | 'popularity' | 'rating';
parent?: number[];
parent_exclude?: number[];
slug?: string;
status?: 'any' | 'draft' | 'pending' | 'private' | 'publish';
type?: 'simple' | 'grouped' | 'external' | 'variable';
sku?: string;
featured?: boolean;
category?: string;
tag?: string;
shipping_class?: string;
attribute?: string;
attribute_term?: string;
tax_class?: 'standard' | 'reduced-rate' | 'zero-rate';
on_sale?: boolean;
min_price?: string;
max_price?: string;
stock_status?: 'instock' | 'outofstock' | 'onbackorder';
}

/**
*
*/
const filterApiQueryParams = (params, checkpoint, batchSize) => {
let orderby = params.orderby;

if (orderby === 'name') {
orderby = 'title';
}

if (orderby === 'date_created') {
orderby = 'date';
}

if (params.categories) {
params.category = get(params, ['categories', '$elemMatch', 'id']);
delete params.categories;
}

if (params.tags) {
params.tag = get(params, ['tags', '$elemMatch', 'id']);
delete params.categories;
}

return {
...params,
id: undefined, // remove id: { $in: [] } from query, eg: grouped products
orderby,
status: 'publish',
};
};

export { filterApiQueryParams };
36 changes: 36 additions & 0 deletions src/hooks/tags.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import isEmpty from 'lodash/isEmpty';

type ProductTagDocument = import('@wcpos/database/src').ProductTagDocument;

interface APIQueryParams {
context?: 'view' | 'edit';
page?: number;
per_page?: number;
search?: string;
exclude?: number[];
include?: number[];
offset?: number;
order?: 'asc' | 'desc';
orderby?: 'id' | 'include' | 'name' | 'slug' | 'term_group' | 'description' | 'count';
hide_empty?: boolean;
product?: number;
slug?: string;
}

/**
*
*/
const filterApiQueryParams = (params, checkpoint, batchSize) => {
const { include } = checkpoint;

/**
* Tags don't have a date field, so if localIDs = remoteIDs, then we can skip the API call
*/
if (isEmpty(include)) {
return false;
}

return params;
};

export { filterApiQueryParams };
Loading

0 comments on commit aff4a01

Please sign in to comment.