@storecraft/database-sql-base 1.0.12 → 1.0.14
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/index.js +20 -19
- package/migrations.mysql/00003_alter_auth_users.js +1 -0
- package/migrations.postgres/00003_alter_auth_users.js +1 -0
- package/migrations.shared/00003_alter_auth_users.js +37 -0
- package/migrations.sqlite/00003_alter_auth_users.js +1 -0
- package/package.json +1 -1
- package/src/con.auth_users.js +21 -20
- package/src/con.collections.js +123 -22
- package/src/con.customers.js +51 -16
- package/src/con.discounts.js +193 -58
- package/src/con.discounts.utils.js +13 -12
- package/src/con.helpers.json.js +34 -30
- package/src/con.helpers.json.mysql.js +39 -19
- package/src/con.helpers.json.postgres.js +14 -8
- package/src/con.helpers.json.sqlite.js +35 -15
- package/src/con.notifications.js +10 -6
- package/src/con.orders.js +4 -3
- package/src/con.posts.js +6 -6
- package/src/con.products.js +82 -33
- package/src/con.search.js +1 -7
- package/src/con.shared.experiment.js +1 -0
- package/src/con.shared.js +110 -63
- package/src/con.shipping.js +6 -6
- package/src/con.storefronts.js +170 -90
- package/src/con.tags.js +9 -5
- package/src/con.templates.js +3 -1
- package/src/utils.funcs.js +6 -2
- package/src/utils.query.js +24 -20
- package/src/utils.types.d.ts +25 -0
- package/tests/Untitled-1.sqlite3-query +19 -0
- package/tests/sandbox.js +210 -0
- package/types.sql.tables.d.ts +76 -22
- package/src/con.helpers.json.mssql.js +0 -233
- package/tests/sandbox.test.js +0 -73
package/src/con.templates.js
CHANGED
@@ -42,6 +42,7 @@ export const upsert = (client) => {
|
|
42
42
|
created_at: item.created_at,
|
43
43
|
updated_at: item.updated_at,
|
44
44
|
id: item.id,
|
45
|
+
active: item.active ? 1 : 0,
|
45
46
|
title: item.title,
|
46
47
|
handle: item.handle,
|
47
48
|
template_html: decode_if_base64(item.template_html),
|
@@ -95,7 +96,8 @@ const remove = (driver) => {
|
|
95
96
|
async (trx) => {
|
96
97
|
|
97
98
|
// entities
|
98
|
-
await delete_search_of(trx, id_or_handle);
|
99
|
+
await delete_search_of(trx, id_or_handle, id_or_handle, table_name);
|
100
|
+
|
99
101
|
// delete me
|
100
102
|
await delete_me(trx, table_name, id_or_handle);
|
101
103
|
}
|
package/src/utils.funcs.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @import { ReplaceValuesOfKeys } from './utils.types.js'
|
2
|
+
* @import { ReplaceValuesOfKeys, ReplaceValuesOfKeys2 } from './utils.types.js'
|
3
3
|
*/
|
4
4
|
|
5
5
|
export const isDef = v => v!==undefined && v!==null;
|
@@ -29,7 +29,7 @@ export const delete_keys = (...keys) => {
|
|
29
29
|
* Sanitize null/undefined valued keys
|
30
30
|
* @template T
|
31
31
|
* @param {T} o
|
32
|
-
* @return {
|
32
|
+
* @return {ReplaceValuesOfKeys2<T, 'active' | 'confirmed_mail', boolean>}
|
33
33
|
*/
|
34
34
|
export const sanitize = o => {
|
35
35
|
for (const key in o) {
|
@@ -39,6 +39,10 @@ export const sanitize = o => {
|
|
39
39
|
delete o[key];
|
40
40
|
continue;
|
41
41
|
}
|
42
|
+
if(key.startsWith('_')) {
|
43
|
+
delete o[key];
|
44
|
+
continue;
|
45
|
+
}
|
42
46
|
if(key==='active') {
|
43
47
|
// @ts-ignore
|
44
48
|
o[key] = Boolean(value);
|
package/src/utils.query.js
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
* @import { ApiQuery, Cursor } from '@storecraft/core/api'
|
3
3
|
* @import { VQL } from '@storecraft/core/vql'
|
4
4
|
* @import { Database } from '../types.sql.tables.js'
|
5
|
-
* @import { ExpressionBuilder } from 'kysely'
|
5
|
+
* @import { BinaryOperator, ExpressionBuilder } from 'kysely'
|
6
6
|
*/
|
7
7
|
|
8
8
|
import { parse } from "@storecraft/core/vql";
|
@@ -22,7 +22,9 @@ import { parse } from "@storecraft/core/vql";
|
|
22
22
|
*/
|
23
23
|
export const query_cursor_to_eb = (eb, c, relation, transformer=(x)=>x) => {
|
24
24
|
|
25
|
+
/** @type {BinaryOperator} */
|
25
26
|
let rel_key_1; // relation in last conjunction term in [0, n-1] disjunctions
|
27
|
+
/** @type {BinaryOperator} */
|
26
28
|
let rel_key_2; // relation in last conjunction term in last disjunction
|
27
29
|
|
28
30
|
if (relation==='>' || relation==='>=') {
|
@@ -73,9 +75,8 @@ export const query_cursor_to_eb = (eb, c, relation, transformer=(x)=>x) => {
|
|
73
75
|
// return result;
|
74
76
|
}
|
75
77
|
|
76
|
-
|
77
78
|
/**
|
78
|
-
* @template {
|
79
|
+
* @template {QueryableTables} T
|
79
80
|
* @param {ExpressionBuilder<Database>} eb
|
80
81
|
* @param {VQL.Node} node
|
81
82
|
* @param {T} table_name
|
@@ -125,7 +126,7 @@ export const query_vql_node_to_eb = (eb, node, table_name) => {
|
|
125
126
|
/**
|
126
127
|
* @param {ExpressionBuilder<Database>} eb
|
127
128
|
* @param {VQL.Node} root
|
128
|
-
* @param {
|
129
|
+
* @param {QueryableTables} table_name
|
129
130
|
*/
|
130
131
|
export const query_vql_to_eb = (eb, root, table_name) => {
|
131
132
|
return root ? query_vql_node_to_eb(eb, root, table_name) : undefined;
|
@@ -135,26 +136,28 @@ export const query_vql_to_eb = (eb, root, table_name) => {
|
|
135
136
|
/**
|
136
137
|
*
|
137
138
|
* @param {[k: string, v: any]} kv
|
139
|
+
* @param {keyof Database} table_name
|
138
140
|
* @returns {[k: string, v: any]}
|
139
141
|
*/
|
140
|
-
const transform_boolean_to_0_or_1 = (kv) => {
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
]
|
146
|
-
|
142
|
+
const transform_boolean_to_0_or_1 = (kv, table_name) => {
|
143
|
+
|
144
|
+
// console.log('transform_boolean_to_0_or_1', kv)
|
145
|
+
kv = [
|
146
|
+
table_name ? `${table_name}.${kv[0]}` : kv[0],
|
147
|
+
typeof kv[1] === 'boolean' ? (kv[1] ? 1 : 0) : kv[1]
|
148
|
+
];
|
149
|
+
|
147
150
|
return kv;
|
148
151
|
}
|
149
152
|
|
150
153
|
/**
|
151
|
-
* Convert an API Query into
|
154
|
+
* Convert an API Query into dialect, also sanitize.
|
152
155
|
*
|
153
156
|
* @template {any} [T=any]
|
154
157
|
*
|
155
158
|
* @param {ExpressionBuilder<Database>} eb
|
156
159
|
* @param {ApiQuery<T>} q
|
157
|
-
* @param {
|
160
|
+
* @param {QueryableTables} table_name
|
158
161
|
*
|
159
162
|
*/
|
160
163
|
export const query_to_eb = (eb, q={}, table_name) => {
|
@@ -162,18 +165,19 @@ export const query_to_eb = (eb, q={}, table_name) => {
|
|
162
165
|
|
163
166
|
const sort_sign = q.order === 'asc' ? 1 : -1;
|
164
167
|
const asc = sort_sign==1;
|
168
|
+
const transformer = (x) => transform_boolean_to_0_or_1(x, table_name);
|
165
169
|
|
166
170
|
// compute index clauses
|
167
171
|
if(q.startAt) {
|
168
|
-
clauses.push(query_cursor_to_eb(eb, q.startAt, asc ? '>=' : '<=',
|
172
|
+
clauses.push(query_cursor_to_eb(eb, q.startAt, asc ? '>=' : '<=', transformer));
|
169
173
|
} else if(q.startAfter) {
|
170
|
-
clauses.push(query_cursor_to_eb(eb, q.startAfter, asc ? '>' : '<',
|
174
|
+
clauses.push(query_cursor_to_eb(eb, q.startAfter, asc ? '>' : '<', transformer));
|
171
175
|
}
|
172
176
|
|
173
177
|
if(q.endAt) {
|
174
|
-
clauses.push(query_cursor_to_eb(eb, q.endAt, asc ? '<=' : '>=',
|
178
|
+
clauses.push(query_cursor_to_eb(eb, q.endAt, asc ? '<=' : '>=', transformer));
|
175
179
|
} else if(q.endBefore) {
|
176
|
-
clauses.push(query_cursor_to_eb(eb, q.endBefore, asc ? '<' : '>',
|
180
|
+
clauses.push(query_cursor_to_eb(eb, q.endBefore, asc ? '<' : '>', transformer));
|
177
181
|
}
|
178
182
|
|
179
183
|
// compute VQL clauses
|
@@ -197,7 +201,7 @@ const SIGN = {
|
|
197
201
|
// export type DirectedOrderByStringReference<DB, TB extends keyof DB, O> = `${StringReference<DB, TB> | (keyof O & string)} ${OrderByDirection}`;
|
198
202
|
|
199
203
|
/**
|
200
|
-
* @import {DirectedOrderByStringReference} from './utils.types.js'
|
204
|
+
* @import {DirectedOrderByStringReference, QueryableTables} from './utils.types.js'
|
201
205
|
*/
|
202
206
|
// OE extends OrderByExpression<DB, TB, O>
|
203
207
|
/**
|
@@ -219,9 +223,9 @@ export const query_to_sort = (q={}, table) => {
|
|
219
223
|
// compute sort fields and order
|
220
224
|
const keys = q.sortBy?.length ? q.sortBy : ['updated_at', 'id'];
|
221
225
|
const sort = keys.map(
|
222
|
-
s => `${s} ${SIGN[sort_sign]}`
|
226
|
+
s => table ? `${table}.${s} ${SIGN[sort_sign]}` : `${s} ${SIGN[sort_sign]}`
|
223
227
|
)
|
224
228
|
// it's too complicated to map each ket to table column.
|
225
229
|
// kysely was designed to do this in place
|
226
|
-
return sort;
|
230
|
+
return (/** @type {DirectedOrderByStringReference<Database, Table, Database[Table]>[]} */ (sort));
|
227
231
|
}
|
package/src/utils.types.d.ts
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
import { App } from "@storecraft/core";
|
1
2
|
import { StringReference } from "kysely";
|
3
|
+
import { Database } from "../types.sql.tables.js";
|
4
|
+
import { type ApiQuery } from "@storecraft/core/api";
|
2
5
|
|
3
6
|
export type NoActive<T> = T extends {active:number} ? Omit<T, 'active'> & {active: boolean} : T;
|
4
7
|
export type ReplaceValues<T, Find extends any=any, ReplaceWith extends any=any> = {
|
@@ -9,9 +12,31 @@ export type ReplaceValuesOfKeys<T, Find extends keyof T=keyof T, ReplaceWith ext
|
|
9
12
|
[K in keyof T]: K extends Find ? ReplaceWith : T[K]
|
10
13
|
};
|
11
14
|
|
15
|
+
export type ReplaceValuesOfKeys2<T, Find extends keyof T=keyof T, ReplaceWith extends any=any> = {
|
16
|
+
[K in keyof T]: K extends Find ? ReplaceWith : ReplaceValuesOfKeys2<T[K], Find, ReplaceWith>
|
17
|
+
};
|
18
|
+
|
19
|
+
// export type ENV<T> = Partial<
|
20
|
+
// {
|
21
|
+
// readonly [K in keyof T]: T[K] extends (number | string | boolean | Function | any[]) ? string : ENV<T[K]>
|
22
|
+
// // readonly [K in keyof T]: T[K] extends (any[] | Function) ? string : T[K] extends Record<string, any> ? ENV<T[K]> : (string)
|
23
|
+
// }
|
24
|
+
// >;
|
25
|
+
|
26
|
+
|
12
27
|
export type NO<T> = {
|
13
28
|
[P in keyof T]: T[P]
|
14
29
|
}
|
15
30
|
|
16
31
|
export type OrderByDirection = 'asc' | 'desc';
|
17
32
|
export type DirectedOrderByStringReference<DB, TB extends keyof DB, O> = `${StringReference<DB, TB> | (keyof O & string)} ${OrderByDirection}`;
|
33
|
+
|
34
|
+
/**
|
35
|
+
* Those that are queryable with {@link ApiQuery} object
|
36
|
+
*/
|
37
|
+
export type QueryableTables = Exclude<
|
38
|
+
keyof Database,
|
39
|
+
'storefronts_to_other' | 'entity_to_media' | 'entity_to_tags_projections' |
|
40
|
+
'entity_to_search_terms' | 'products_to_collections' | 'products_to_discounts' |
|
41
|
+
'products_to_variants' | 'products_to_related_products'
|
42
|
+
>;
|
@@ -0,0 +1,19 @@
|
|
1
|
+
-- database: ../../../playground/node-libsql/data.db
|
2
|
+
|
3
|
+
-- Use the ▷ button in the top right corner to run the entire file.
|
4
|
+
|
5
|
+
SELECT
|
6
|
+
-- products.id,
|
7
|
+
-- products.handle,
|
8
|
+
-- products_to_collections.reporter as collection,
|
9
|
+
-- products.*,
|
10
|
+
-- products_to_collections.*,
|
11
|
+
entity_to_tags_projections.value as tag
|
12
|
+
FROM products
|
13
|
+
INNER JOIN
|
14
|
+
products_to_collections ON products.id = products_to_collections.entity_id
|
15
|
+
INNER JOIN
|
16
|
+
entity_to_tags_projections ON products.id = entity_to_tags_projections.entity_id
|
17
|
+
WHERE products_to_collections.reporter = 'playstation-4-games'
|
18
|
+
GROUP BY tag
|
19
|
+
|
package/tests/sandbox.js
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
/**
|
2
|
+
* @import {Database} from '../types.sql.tables.js';
|
3
|
+
*/
|
4
|
+
import 'dotenv/config';
|
5
|
+
import { App } from '@storecraft/core';
|
6
|
+
import { SQL } from '@storecraft/database-sql-base';
|
7
|
+
import { migrateToLatest } from '@storecraft/database-sql-base/migrate.js';
|
8
|
+
import { NodePlatform } from '@storecraft/core/platform/node';
|
9
|
+
import { api } from '@storecraft/core/test-runner'
|
10
|
+
import SQLite from 'better-sqlite3'
|
11
|
+
import { SqliteDialect } from 'kysely';
|
12
|
+
import { homedir } from 'node:os';
|
13
|
+
import { join } from 'node:path';
|
14
|
+
import { jsonArrayFrom, stringArrayFrom } from '../src/con.helpers.json.js';
|
15
|
+
import { query_to_sort } from '../src/utils.query.js';
|
16
|
+
import { products_with_collections, products_with_discounts, products_with_related_products, products_with_variants, with_media, with_tags } from '../src/con.shared.js';
|
17
|
+
|
18
|
+
export const sqlite_dialect = new SqliteDialect({
|
19
|
+
database: async () => new SQLite(join(homedir(), 'db.sqlite')),
|
20
|
+
});
|
21
|
+
|
22
|
+
export const create_app = async () => {
|
23
|
+
const app = new App(
|
24
|
+
{
|
25
|
+
auth_admins_emails: ['admin@sc.com'],
|
26
|
+
auth_secret_access_token: 'auth_secret_access_token',
|
27
|
+
auth_secret_refresh_token: 'auth_secret_refresh_token'
|
28
|
+
}
|
29
|
+
)
|
30
|
+
.withPlatform(new NodePlatform())
|
31
|
+
.withDatabase(
|
32
|
+
new SQL({
|
33
|
+
dialect: sqlite_dialect,
|
34
|
+
dialect_type: 'SQLITE'
|
35
|
+
})
|
36
|
+
);
|
37
|
+
|
38
|
+
await app.init();
|
39
|
+
await migrateToLatest(app.db, false);
|
40
|
+
|
41
|
+
return app;
|
42
|
+
}
|
43
|
+
|
44
|
+
/**
|
45
|
+
* @template {keyof Database} [T=keyof Database]
|
46
|
+
* @typedef {{}}
|
47
|
+
*/
|
48
|
+
|
49
|
+
/**
|
50
|
+
* @type {Record<keyof Database, (keyof Database['collections'])[]>}
|
51
|
+
*/
|
52
|
+
|
53
|
+
/**
|
54
|
+
* @type {{[K in keyof Database]?: (keyof Database[K])[]}}
|
55
|
+
*/
|
56
|
+
const resource_to_props = (
|
57
|
+
{
|
58
|
+
'collections': ['active', 'attributes', 'created_at', 'description', 'handle', 'id', 'published', 'title', 'updated_at'],
|
59
|
+
'discounts': ['active', 'application', 'attributes', 'created_at', 'description', 'handle', 'id', 'info', 'priority', 'published', 'title', 'updated_at'],
|
60
|
+
'products': ['active', 'attributes', 'compare_at_price', 'created_at', 'description', 'handle', 'id', 'isbn', 'parent_handle', 'parent_id', 'price', 'qty', 'title', 'updated_at', 'variant_hint', 'variants_options', 'video'],
|
61
|
+
'shipping_methods': ['active', 'attributes', 'created_at', 'description', 'handle', 'id', 'price', 'title', 'updated_at'],
|
62
|
+
'posts': ['active', 'attributes', 'created_at', 'description', 'handle', 'id', 'text', 'title', 'updated_at'],
|
63
|
+
}
|
64
|
+
);
|
65
|
+
|
66
|
+
|
67
|
+
async function test() {
|
68
|
+
const app = await create_app();
|
69
|
+
const client = app.db.client;
|
70
|
+
const limit = 0;
|
71
|
+
const items = await client.selectNoFrom(
|
72
|
+
eb => [
|
73
|
+
jsonArrayFrom(
|
74
|
+
eb
|
75
|
+
.selectFrom('collections')
|
76
|
+
.select(resource_to_props.collections)
|
77
|
+
.select(
|
78
|
+
eb => [
|
79
|
+
with_tags(eb, eb.ref('collections.id'), app.db.dialectType),
|
80
|
+
with_media(eb, eb.ref('collections.id'), app.db.dialectType),
|
81
|
+
]
|
82
|
+
)
|
83
|
+
.where('active', '=', 1)
|
84
|
+
.orderBy(['updated_at asc'])
|
85
|
+
.limit(limit),
|
86
|
+
app.db.dialectType
|
87
|
+
).as('collections'),
|
88
|
+
|
89
|
+
jsonArrayFrom(
|
90
|
+
eb
|
91
|
+
.selectFrom('products')
|
92
|
+
.select(resource_to_props.products)
|
93
|
+
.select(
|
94
|
+
eb => [
|
95
|
+
with_tags(eb, eb.ref('products.id'), app.db.dialectType),
|
96
|
+
with_media(eb, eb.ref('products.id'), app.db.dialectType),
|
97
|
+
products_with_collections(eb, eb.ref('products.id'), app.db.dialectType),
|
98
|
+
products_with_discounts(eb, eb.ref('products.id'), app.db.dialectType),
|
99
|
+
products_with_variants(eb, eb.ref('products.id'), app.db.dialectType),
|
100
|
+
products_with_related_products(eb, eb.ref('products.id'), app.db.dialectType),
|
101
|
+
]
|
102
|
+
)
|
103
|
+
.where('active', '=', 1)
|
104
|
+
.orderBy(['updated_at asc'])
|
105
|
+
.limit(limit),
|
106
|
+
app.db.dialectType
|
107
|
+
).as('products'),
|
108
|
+
|
109
|
+
jsonArrayFrom(
|
110
|
+
eb
|
111
|
+
.selectFrom('discounts')
|
112
|
+
.select(resource_to_props.discounts)
|
113
|
+
.select(
|
114
|
+
eb => [
|
115
|
+
with_tags(eb, eb.ref('discounts.id'), app.db.dialectType),
|
116
|
+
with_media(eb, eb.ref('discounts.id'), app.db.dialectType),
|
117
|
+
]
|
118
|
+
)
|
119
|
+
.where('active', '=', 1)
|
120
|
+
.orderBy(['updated_at asc'])
|
121
|
+
.limit(limit),
|
122
|
+
app.db.dialectType
|
123
|
+
).as('discounts'),
|
124
|
+
|
125
|
+
jsonArrayFrom(
|
126
|
+
eb
|
127
|
+
.selectFrom('shipping_methods')
|
128
|
+
.select(resource_to_props.shipping_methods)
|
129
|
+
.select(
|
130
|
+
eb => [
|
131
|
+
with_tags(eb, eb.ref('shipping_methods.id'), app.db.dialectType),
|
132
|
+
with_media(eb, eb.ref('shipping_methods.id'), app.db.dialectType),
|
133
|
+
]
|
134
|
+
)
|
135
|
+
.where('active', '=', 1)
|
136
|
+
.orderBy(['updated_at asc'])
|
137
|
+
.limit(limit),
|
138
|
+
app.db.dialectType
|
139
|
+
).as('shipping_methods'),
|
140
|
+
|
141
|
+
jsonArrayFrom(
|
142
|
+
eb
|
143
|
+
.selectFrom('posts')
|
144
|
+
.select(resource_to_props.posts)
|
145
|
+
.select(
|
146
|
+
eb => [
|
147
|
+
with_tags(eb, eb.ref('posts.id'), app.db.dialectType),
|
148
|
+
with_media(eb, eb.ref('posts.id'), app.db.dialectType),
|
149
|
+
]
|
150
|
+
)
|
151
|
+
.where('active', '=', 1)
|
152
|
+
.orderBy(['updated_at asc'])
|
153
|
+
.limit(limit),
|
154
|
+
app.db.dialectType
|
155
|
+
).as('posts'),
|
156
|
+
|
157
|
+
stringArrayFrom(
|
158
|
+
eb.selectFrom('products')
|
159
|
+
.innerJoin(
|
160
|
+
'products_to_collections',
|
161
|
+
'products_to_collections.entity_id',
|
162
|
+
'products.id'
|
163
|
+
)
|
164
|
+
.innerJoin(
|
165
|
+
'entity_to_tags_projections',
|
166
|
+
'entity_to_tags_projections.entity_id',
|
167
|
+
'products.id'
|
168
|
+
)
|
169
|
+
.select('entity_to_tags_projections.value as tag')
|
170
|
+
.groupBy('tag'),
|
171
|
+
app.db.dialectType
|
172
|
+
).as('all_products_tags')
|
173
|
+
]
|
174
|
+
)
|
175
|
+
.executeTakeFirst();
|
176
|
+
|
177
|
+
console.log(JSON.stringify(items, null, 2))
|
178
|
+
}
|
179
|
+
|
180
|
+
async function test2() {
|
181
|
+
const app = await create_app();
|
182
|
+
const client = app.db.client;
|
183
|
+
const items = await client.selectNoFrom(
|
184
|
+
eb => Object
|
185
|
+
.entries(resource_to_props)
|
186
|
+
.map(
|
187
|
+
/**
|
188
|
+
* @param {[keyof Database, (keyof Database[keyof Database])[]]} params
|
189
|
+
*/
|
190
|
+
([table_name, props]) => {
|
191
|
+
// console.log(table_name, props)
|
192
|
+
// props
|
193
|
+
return jsonArrayFrom(
|
194
|
+
eb
|
195
|
+
.selectFrom(table_name)
|
196
|
+
.select(props)
|
197
|
+
.orderBy(['updated_at asc'])
|
198
|
+
.limit(0),
|
199
|
+
app.db.dialectType
|
200
|
+
).as(table_name)
|
201
|
+
}
|
202
|
+
)
|
203
|
+
)
|
204
|
+
.executeTakeFirst();
|
205
|
+
|
206
|
+
console.log(JSON.stringify(items, null, 2))
|
207
|
+
}
|
208
|
+
|
209
|
+
test();
|
210
|
+
|
package/types.sql.tables.d.ts
CHANGED
@@ -1,17 +1,15 @@
|
|
1
|
-
import {
|
1
|
+
import {
|
2
|
+
AttributeType, AuthUserType, Role, TagType,
|
2
3
|
CollectionType, ProductType, ShippingMethodType,
|
3
4
|
VariantOption, PostType, CustomerType,
|
4
5
|
VariantOptionSelection, OrderData, StorefrontType,
|
5
|
-
AddressType, ImageType,
|
6
|
-
|
7
|
-
|
8
|
-
OrderStatus, DiscountType,
|
9
|
-
PricingData,
|
10
|
-
ValidationEntry,
|
6
|
+
AddressType, ImageType, OrderContact,
|
7
|
+
LineItem, OrderStatus, DiscountType,
|
8
|
+
PricingData, ValidationEntry,
|
11
9
|
OrderPaymentGatewayData, NotificationType,
|
12
|
-
NotificationAction,
|
13
|
-
|
14
|
-
|
10
|
+
NotificationAction, DiscountInfo,
|
11
|
+
DiscountApplicationEnum
|
12
|
+
} from '@storecraft/core/api'
|
15
13
|
import {
|
16
14
|
ColumnType,
|
17
15
|
Generated,
|
@@ -61,48 +59,104 @@ export interface entity_to_value {
|
|
61
59
|
}
|
62
60
|
|
63
61
|
export interface entity_to_media extends entity_to_value {}
|
64
|
-
|
62
|
+
|
63
|
+
/**
|
64
|
+
* **Here**:
|
65
|
+
* - (`entity_id`, `entity_handle`) = (entity id, entity handle) of the resource for example (product id, product handle)
|
66
|
+
* - (`value`) = search term , for example 'game', 'shoes'
|
67
|
+
* - (`context`) = the resource name `tags` / `collections` / `products` / `posts` / `discounts` / `shipping` / `storefronts` / `notifications` / 'auth_users' etc...)
|
68
|
+
*
|
69
|
+
* **Note**:
|
70
|
+
* - `entity_id` ALWAYS IDENTIFIES THE ENTITY
|
71
|
+
* - `entity_handle` DOES NOT IDENTIFY (imagine a product and collection with same handle)
|
72
|
+
* - `entity_handle` + `context` ALWAYS IDENTIFIES AN ENTITY
|
73
|
+
*/
|
65
74
|
export interface entity_to_search_terms extends entity_to_value {}
|
66
75
|
|
76
|
+
/**
|
77
|
+
* Here:
|
78
|
+
* - (`entity_id`, `entity_handle`) = (entity id, entity handle) of the resource for example (product id, product handle)
|
79
|
+
* - (`value`) = search term , for example 'game', 'shoes'
|
80
|
+
* - (`context`) = the resource name `tags` / `collections` / `products` / `posts` / `discounts` / `shipping` / `storefronts` / `notifications` / 'auth_users' etc...)
|
81
|
+
*
|
82
|
+
* Note:
|
83
|
+
* - `entity_id` ALWAYS IDENTIFIES AN ENTITY
|
84
|
+
* - `entity_handle` DOES NOT IDENTIFY AN ENTITY (imagine a product and collection with same handle)
|
85
|
+
* - `entity_handle` + `context` ALWAYS IDENTIFIES AN ENTITY
|
86
|
+
*/
|
87
|
+
export interface entity_to_tags_projections extends entity_to_value {}
|
88
|
+
|
67
89
|
/**
|
68
90
|
* here:
|
69
|
-
* - entity_id
|
70
|
-
* - value
|
91
|
+
* - (`entity_id`, `entity_handle`) = (product id, product handle)
|
92
|
+
* - (`value`, `reporter`) = (collection id, collection handle)
|
93
|
+
* - (`context`) = NULL
|
94
|
+
*
|
95
|
+
* NOTE:
|
96
|
+
* - `entity_id` ALWAYS IDENTIFIES AN ENTITY
|
97
|
+
* - `entity_handle` ALWAYS IDENTIFIES AN ENTITY
|
98
|
+
* - `value` ALWAYS IDENTIFIES AN ENTITY
|
99
|
+
* - `reporter` ALWAYS IDENTIFIES AN ENTITY
|
71
100
|
*/
|
72
101
|
export interface products_to_collections extends entity_to_value {}
|
73
102
|
|
74
103
|
/**
|
75
104
|
* here:
|
76
|
-
* - entity_id
|
77
|
-
* - value
|
105
|
+
* - (`entity_id`, `entity_handle`) = (product id, product handle)
|
106
|
+
* - (`value`, `reporter`) = (discount id, discount handle)
|
107
|
+
*
|
108
|
+
* NOTE:
|
109
|
+
* - `entity_id` ALWAYS IDENTIFIES AN ENTITY
|
110
|
+
* - `entity_handle` ALWAYS IDENTIFIES AN ENTITY
|
111
|
+
* - `value` ALWAYS IDENTIFIES AN ENTITY
|
112
|
+
* - `reporter` ALWAYS IDENTIFIES AN ENTITY
|
78
113
|
*/
|
79
114
|
export interface products_to_discounts extends entity_to_value {}
|
80
115
|
|
81
116
|
/**
|
82
117
|
* here:
|
83
|
-
* - (entity_id
|
84
|
-
* - (value
|
118
|
+
* - (`entity_id`, `entity_handle`) = (parent product id, parent product handle)
|
119
|
+
* - (`value`, `reporter`) = (variant product id, variant product handle)
|
120
|
+
*
|
121
|
+
* NOTE:
|
122
|
+
* - `entity_id` ALWAYS IDENTIFIES AN ENTITY
|
123
|
+
* - `entity_handle` ALWAYS IDENTIFIES AN ENTITY
|
124
|
+
* - `value` ALWAYS IDENTIFIES AN ENTITY
|
125
|
+
* - `reporter` ALWAYS IDENTIFIES AN ENTITY
|
85
126
|
*/
|
86
127
|
export interface products_to_variants extends entity_to_value {}
|
87
128
|
|
88
129
|
/**
|
89
130
|
* here:
|
90
|
-
* - (entity_id
|
91
|
-
* - (value
|
131
|
+
* - (`entity_id`, `entity_handle`) = (parent product id, parent product handle)
|
132
|
+
* - (`value`, `reporter`) = (related product id, related product handle)
|
133
|
+
*
|
134
|
+
* NOTE:
|
135
|
+
* - `entity_id` ALWAYS IDENTIFIES AN ENTITY
|
136
|
+
* - `entity_handle` ALWAYS IDENTIFIES AN ENTITY
|
137
|
+
* - `value` ALWAYS IDENTIFIES AN ENTITY
|
138
|
+
* - `reporter` ALWAYS IDENTIFIES AN ENTITY
|
92
139
|
*/
|
93
140
|
export interface products_to_related_products extends entity_to_value {}
|
94
141
|
|
95
142
|
/**
|
96
143
|
* storefronts to products/collections/posts/discounts/shipping
|
97
144
|
* here:
|
98
|
-
* - entity_id, entity_handle = storefront id, storefront handle
|
99
|
-
* - value, reporter = other entity id, other entity handle, i.e(product_id, product_handle)
|
100
|
-
* - context = `products` / `collections` / `posts` / `discounts` / `shipping`
|
145
|
+
* - (entity_id, entity_handle) = (storefront id, storefront handle)
|
146
|
+
* - (value, reporter) = (other entity id, other entity handle), i.e(product_id, product_handle)
|
147
|
+
* - (context) = `products` / `collections` / `posts` / `discounts` / `shipping`
|
101
148
|
*
|
102
149
|
* This will probably be a small table hence everything is recorded in the same table.
|
103
150
|
* Usually, a user will have:
|
104
151
|
* - small number of storefronts
|
105
152
|
* - small number of attached products/collections/posts/discounts/shipping per storefront
|
153
|
+
*
|
154
|
+
* NOTE:
|
155
|
+
* - `entity_id` ALWAYS IDENTIFIES AN ENTITY
|
156
|
+
* - `entity_handle` ALWAYS IDENTIFIES AN ENTITY
|
157
|
+
* - `value` ALWAYS IDENTIFIES AN ENTITY
|
158
|
+
* - `reporter` DOES NOT IDENTIFY AN ENTITY (because you can have a product and a collection with the same handle for example)
|
159
|
+
* - `reporter` + `context` ALWAYS IDENTIFIES AN ENTITY (in case you need to delete)
|
106
160
|
*/
|
107
161
|
export interface storefronts_to_other extends entity_to_value {}
|
108
162
|
|