@comapeo/core 4.4.0 → 5.0.0
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/dist/blob-store/downloader.d.ts +5 -2
- package/dist/blob-store/downloader.d.ts.map +1 -1
- package/dist/constants.d.ts +0 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/datatype/index.d.ts +1 -1
- package/dist/datatype/index.d.ts.map +1 -1
- package/dist/discovery/local-discovery.d.ts.map +1 -1
- package/dist/import-categories.d.ts +19 -0
- package/dist/import-categories.d.ts.map +1 -0
- package/dist/intl/iso639.d.ts +4 -0
- package/dist/intl/iso639.d.ts.map +1 -0
- package/dist/intl/parse-bcp-47.d.ts +22 -0
- package/dist/intl/parse-bcp-47.d.ts.map +1 -0
- package/dist/invite/invite-api.d.ts.map +1 -1
- package/dist/lib/drizzle-helpers.d.ts +19 -1
- package/dist/lib/drizzle-helpers.d.ts.map +1 -1
- package/dist/mapeo-manager.d.ts +15 -9
- package/dist/mapeo-manager.d.ts.map +1 -1
- package/dist/mapeo-project.d.ts +4968 -3017
- package/dist/mapeo-project.d.ts.map +1 -1
- package/dist/schema/client.d.ts +246 -232
- package/dist/schema/client.d.ts.map +1 -1
- package/dist/schema/comapeo-to-drizzle.d.ts +65 -0
- package/dist/schema/comapeo-to-drizzle.d.ts.map +1 -0
- package/dist/schema/json-schema-to-drizzle.d.ts +18 -0
- package/dist/schema/json-schema-to-drizzle.d.ts.map +1 -0
- package/dist/schema/project.d.ts +2711 -1835
- package/dist/schema/project.d.ts.map +1 -1
- package/dist/schema/types.d.ts +73 -66
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/translation-api.d.ts +111 -189
- package/dist/translation-api.d.ts.map +1 -1
- package/dist/utils.d.ts +10 -0
- package/dist/utils.d.ts.map +1 -1
- package/drizzle/client/0004_glorious_shape.sql +1 -0
- package/drizzle/client/meta/0000_snapshot.json +13 -9
- package/drizzle/client/meta/0001_snapshot.json +13 -9
- package/drizzle/client/meta/0002_snapshot.json +13 -9
- package/drizzle/client/meta/0003_snapshot.json +13 -9
- package/drizzle/client/meta/0004_snapshot.json +239 -0
- package/drizzle/client/meta/_journal.json +7 -0
- package/drizzle/project/meta/0000_snapshot.json +43 -24
- package/drizzle/project/meta/0001_snapshot.json +47 -26
- package/drizzle/project/meta/0002_snapshot.json +47 -26
- package/package.json +16 -8
- package/src/constants.js +0 -3
- package/src/datatype/index.js +8 -5
- package/src/discovery/local-discovery.js +3 -2
- package/src/import-categories.js +364 -0
- package/src/index-writer/index.js +1 -1
- package/src/intl/iso639.js +8118 -0
- package/src/intl/parse-bcp-47.js +91 -0
- package/src/invite/invite-api.js +2 -0
- package/src/lib/drizzle-helpers.js +70 -18
- package/src/mapeo-manager.js +138 -88
- package/src/mapeo-project.js +56 -218
- package/src/roles.js +1 -1
- package/src/schema/client.js +22 -28
- package/src/schema/comapeo-to-drizzle.js +57 -0
- package/src/schema/{schema-to-drizzle.js → json-schema-to-drizzle.js} +25 -25
- package/src/schema/project.js +24 -37
- package/src/schema/types.ts +138 -99
- package/src/translation-api.js +64 -12
- package/src/utils.js +13 -0
- package/dist/config-import.d.ts +0 -74
- package/dist/config-import.d.ts.map +0 -1
- package/dist/schema/schema-to-drizzle.d.ts +0 -20
- package/dist/schema/schema-to-drizzle.d.ts.map +0 -1
- package/dist/schema/utils.d.ts +0 -55
- package/dist/schema/utils.d.ts.map +0 -1
- package/src/config-import.js +0 -603
- package/src/schema/utils.js +0 -51
package/src/schema/project.js
CHANGED
|
@@ -3,47 +3,34 @@
|
|
|
3
3
|
import { blob, sqliteTable, text } from 'drizzle-orm/sqlite-core'
|
|
4
4
|
import { dereferencedDocSchemas as schemas } from '@comapeo/schema'
|
|
5
5
|
import { NAMESPACES } from '../constants.js'
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import {
|
|
7
|
+
comapeoSchemaToDrizzleTable as toDrizzle,
|
|
8
|
+
backlinkTable,
|
|
9
|
+
} from './comapeo-to-drizzle.js'
|
|
8
10
|
|
|
9
|
-
export const translationTable =
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
)
|
|
13
|
-
export const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
)
|
|
17
|
-
export const
|
|
18
|
-
export const
|
|
19
|
-
'remoteDetectionAlert',
|
|
20
|
-
toColumns(schemas.remoteDetectionAlert)
|
|
21
|
-
)
|
|
22
|
-
export const presetTable = sqliteTable('preset', toColumns(schemas.preset))
|
|
23
|
-
export const fieldTable = sqliteTable('field', toColumns(schemas.field))
|
|
24
|
-
export const coreOwnershipTable = sqliteTable(
|
|
25
|
-
'coreOwnership',
|
|
26
|
-
toColumns(schemas.coreOwnership)
|
|
27
|
-
)
|
|
28
|
-
export const roleTable = sqliteTable('role', toColumns(schemas.role))
|
|
29
|
-
export const deviceInfoTable = sqliteTable(
|
|
30
|
-
'deviceInfo',
|
|
31
|
-
toColumns(schemas.deviceInfo)
|
|
32
|
-
)
|
|
33
|
-
export const iconTable = sqliteTable('icon', toColumns(schemas.icon))
|
|
11
|
+
export const translationTable = toDrizzle(schemas.translation)
|
|
12
|
+
export const observationTable = toDrizzle(schemas.observation)
|
|
13
|
+
export const trackTable = toDrizzle(schemas.track)
|
|
14
|
+
export const remoteDetectionAlertTable = toDrizzle(schemas.remoteDetectionAlert)
|
|
15
|
+
export const presetTable = toDrizzle(schemas.preset)
|
|
16
|
+
export const fieldTable = toDrizzle(schemas.field)
|
|
17
|
+
export const coreOwnershipTable = toDrizzle(schemas.coreOwnership)
|
|
18
|
+
export const roleTable = toDrizzle(schemas.role)
|
|
19
|
+
export const deviceInfoTable = toDrizzle(schemas.deviceInfo)
|
|
20
|
+
export const iconTable = toDrizzle(schemas.icon)
|
|
34
21
|
|
|
35
|
-
export const translationBacklinkTable = backlinkTable(
|
|
36
|
-
export const observationBacklinkTable = backlinkTable(
|
|
37
|
-
export const trackBacklinkTable = backlinkTable(
|
|
22
|
+
export const translationBacklinkTable = backlinkTable('translation')
|
|
23
|
+
export const observationBacklinkTable = backlinkTable('observation')
|
|
24
|
+
export const trackBacklinkTable = backlinkTable('track')
|
|
38
25
|
export const remoteDetectionAlertBacklinkTable = backlinkTable(
|
|
39
|
-
|
|
26
|
+
'remoteDetectionAlert'
|
|
40
27
|
)
|
|
41
|
-
export const presetBacklinkTable = backlinkTable(
|
|
42
|
-
export const fieldBacklinkTable = backlinkTable(
|
|
43
|
-
export const coreOwnershipBacklinkTable = backlinkTable(
|
|
44
|
-
export const roleBacklinkTable = backlinkTable(
|
|
45
|
-
export const deviceInfoBacklinkTable = backlinkTable(
|
|
46
|
-
export const iconBacklinkTable = backlinkTable(
|
|
28
|
+
export const presetBacklinkTable = backlinkTable('preset')
|
|
29
|
+
export const fieldBacklinkTable = backlinkTable('field')
|
|
30
|
+
export const coreOwnershipBacklinkTable = backlinkTable('coreOwnership')
|
|
31
|
+
export const roleBacklinkTable = backlinkTable('role')
|
|
32
|
+
export const deviceInfoBacklinkTable = backlinkTable('deviceInfo')
|
|
33
|
+
export const iconBacklinkTable = backlinkTable('icon')
|
|
47
34
|
|
|
48
35
|
export const coresTable = sqliteTable('cores', {
|
|
49
36
|
publicKey: blob('publicKey', { mode: 'buffer' }).notNull(),
|
package/src/schema/types.ts
CHANGED
|
@@ -3,101 +3,86 @@ import {
|
|
|
3
3
|
JSONSchema7 as JSONSchema7Writable,
|
|
4
4
|
JSONSchema7Type,
|
|
5
5
|
} from 'json-schema'
|
|
6
|
+
import type {
|
|
7
|
+
SQLiteBooleanBuilder,
|
|
8
|
+
SQLiteIntegerBuilder,
|
|
9
|
+
SQLiteRealBuilder,
|
|
10
|
+
SQLiteTableWithColumns,
|
|
11
|
+
SQLiteTextBuilder,
|
|
12
|
+
SQLiteTextJsonBuilder,
|
|
13
|
+
} from 'drizzle-orm/sqlite-core'
|
|
14
|
+
import type {
|
|
15
|
+
$Type,
|
|
16
|
+
BuildColumns,
|
|
17
|
+
ColumnBuilderBase,
|
|
18
|
+
HasDefault,
|
|
19
|
+
IsPrimaryKey,
|
|
20
|
+
NotNull,
|
|
21
|
+
} from 'drizzle-orm'
|
|
6
22
|
|
|
7
|
-
/** Convert optional properties to nullable */
|
|
8
|
-
export type OptionalToNull<T extends {}> = {
|
|
9
|
-
[K in keyof T]-?: undefined extends T[K] ? T[K] | null : T[K]
|
|
10
|
-
}
|
|
11
23
|
/** Convert a readonly array/object to writeable */
|
|
12
24
|
type Writable<T> = { -readonly [P in keyof T]: T[P] }
|
|
13
|
-
/** Type returned by text(columnName, { enum: [] }) */
|
|
14
|
-
type TextBuilder<
|
|
15
|
-
TName extends string,
|
|
16
|
-
TEnum extends readonly [string, ...string[]],
|
|
17
|
-
TNotNull extends boolean,
|
|
18
|
-
THasDefault extends boolean
|
|
19
|
-
> = import('drizzle-orm/sqlite-core').SQLiteTextBuilder<{
|
|
20
|
-
name: TName
|
|
21
|
-
data: Writable<TEnum>[number]
|
|
22
|
-
driverParam: string
|
|
23
|
-
columnType: 'SQLiteText'
|
|
24
|
-
dataType: 'string'
|
|
25
|
-
enumValues: Writable<TEnum>
|
|
26
|
-
notNull: TNotNull
|
|
27
|
-
hasDefault: THasDefault
|
|
28
|
-
}>
|
|
29
|
-
|
|
30
|
-
/** Type returned by integer(columnName, { mode: 'boolean' }) */
|
|
31
|
-
type BooleanBuilder<
|
|
32
|
-
TName extends string,
|
|
33
|
-
TNotNull extends boolean,
|
|
34
|
-
THasDefault extends boolean
|
|
35
|
-
> = import('drizzle-orm/sqlite-core').SQLiteBooleanBuilder<{
|
|
36
|
-
name: TName
|
|
37
|
-
data: boolean
|
|
38
|
-
driverParam: number
|
|
39
|
-
columnType: 'SQLiteBoolean'
|
|
40
|
-
dataType: 'boolean'
|
|
41
|
-
notNull: TNotNull
|
|
42
|
-
hasDefault: THasDefault
|
|
43
|
-
enumValues: undefined
|
|
44
|
-
}>
|
|
45
|
-
|
|
46
|
-
/** Type returned by real(columnName) */
|
|
47
|
-
type RealBuilder<
|
|
48
|
-
TName extends string,
|
|
49
|
-
TNotNull extends boolean,
|
|
50
|
-
THasDefault extends boolean
|
|
51
|
-
> = import('drizzle-orm/sqlite-core').SQLiteRealBuilder<{
|
|
52
|
-
name: TName
|
|
53
|
-
data: number
|
|
54
|
-
driverParam: number
|
|
55
|
-
columnType: 'SQLiteReal'
|
|
56
|
-
dataType: 'number'
|
|
57
|
-
notNull: TNotNull
|
|
58
|
-
hasDefault: THasDefault
|
|
59
|
-
enumValues: undefined
|
|
60
|
-
}>
|
|
61
|
-
|
|
62
|
-
/** Type returned by integer(columnName) */
|
|
63
|
-
type IntegerBuilder<
|
|
64
|
-
TName extends string,
|
|
65
|
-
TNotNull extends boolean,
|
|
66
|
-
THasDefault extends boolean
|
|
67
|
-
> = import('drizzle-orm/sqlite-core').SQLiteIntegerBuilder<{
|
|
68
|
-
name: TName
|
|
69
|
-
data: number
|
|
70
|
-
driverParam: number
|
|
71
|
-
columnType: 'SQLiteInteger'
|
|
72
|
-
dataType: 'number'
|
|
73
|
-
notNull: TNotNull
|
|
74
|
-
hasDefault: THasDefault
|
|
75
|
-
enumValues: undefined
|
|
76
|
-
}>
|
|
77
|
-
|
|
78
|
-
/** Type returned by the `customJson` custom type */
|
|
79
|
-
type JsonBuilder<
|
|
80
|
-
TName extends string,
|
|
81
|
-
TData extends unknown,
|
|
82
|
-
TNotNull extends boolean,
|
|
83
|
-
THasDefault extends boolean
|
|
84
|
-
> = import('drizzle-orm/sqlite-core').SQLiteCustomColumnBuilder<{
|
|
85
|
-
name: TName
|
|
86
|
-
data: TData
|
|
87
|
-
dataType: 'custom'
|
|
88
|
-
driverParam: string
|
|
89
|
-
columnType: 'SQLiteCustomColumn'
|
|
90
|
-
notNull: TNotNull
|
|
91
|
-
hasDefault: THasDefault
|
|
92
|
-
enumValues: undefined
|
|
93
|
-
}>
|
|
94
25
|
|
|
95
26
|
export type JSONSchema7 = ReadonlyDeep<JSONSchema7Writable>
|
|
96
27
|
type JsonSchema7Properties = { readonly [K: string]: JSONSchema7 }
|
|
97
|
-
export type
|
|
28
|
+
export type JSONSchema7Object = Omit<JSONSchema7, 'properties' | 'type'> & {
|
|
29
|
+
readonly type: 'object'
|
|
98
30
|
readonly properties: JsonSchema7Properties
|
|
99
31
|
}
|
|
100
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Create a Drizzle SQLite table definition from a JSONSchema object. All
|
|
35
|
+
* top-level properties map to SQLite columns, with `required` properties marked
|
|
36
|
+
* as `NOT NULL`, and JSONSchema `default` will map to SQLite defaults.
|
|
37
|
+
*
|
|
38
|
+
* Any properties that are of type `object` or `array` in the JSONSchema will be
|
|
39
|
+
* mapped to a text field, which drizzle will parse and stringify. Types for
|
|
40
|
+
* `object` and `array` properties will be derived from `TObjectType`.
|
|
41
|
+
*/
|
|
42
|
+
export type JsonSchemaToDrizzleSqliteTable<
|
|
43
|
+
/** Typescript type for the object defined in the JSONSchema */
|
|
44
|
+
TObjectType extends { [K in keyof TSchema['properties']]?: any },
|
|
45
|
+
/** The JSONSchema object schema */
|
|
46
|
+
TSchema extends JSONSchema7Object,
|
|
47
|
+
/** Name of the table to create */
|
|
48
|
+
TTableName extends string,
|
|
49
|
+
/** Additional columns to add to the table definition (e.g. not defined in JSONSchema ) */
|
|
50
|
+
TColumnsMap extends Record<string, ColumnBuilderBase> = {},
|
|
51
|
+
/** Name of the property to use as primary key */
|
|
52
|
+
TPrimaryKey extends keyof TSchema['properties'] | undefined = undefined
|
|
53
|
+
> = SQLiteTableWithColumns<{
|
|
54
|
+
name: TTableName
|
|
55
|
+
schema: undefined
|
|
56
|
+
columns: BuildColumns<
|
|
57
|
+
TTableName,
|
|
58
|
+
JsonSchemaToDrizzleColumns<TObjectType, TSchema, TPrimaryKey> & TColumnsMap,
|
|
59
|
+
'sqlite'
|
|
60
|
+
>
|
|
61
|
+
dialect: 'sqlite'
|
|
62
|
+
}>
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Convert a JSONSchema Object Schema to a Drizzle Columns map (e.g. parameter
|
|
66
|
+
* for `sqliteTable()`). All top-level properties map to SQLite columns, with
|
|
67
|
+
* `required` properties marked as `NOT NULL`, and JSONSchema `default` will map
|
|
68
|
+
* to SQLite defaults.
|
|
69
|
+
*
|
|
70
|
+
* Any properties that are of type `object` or `array` in the JSONSchema will be
|
|
71
|
+
* mapped to a text field, which drizzle will parse and stringify. Types for
|
|
72
|
+
* `object` and `array` properties will be derived from `TObjectType`.
|
|
73
|
+
*/
|
|
74
|
+
type JsonSchemaToDrizzleColumns<
|
|
75
|
+
TObjectType extends { [K in keyof TSchema['properties']]?: any },
|
|
76
|
+
TSchema extends JSONSchema7Object,
|
|
77
|
+
TPrimaryKey extends keyof TSchema['properties'] | undefined = undefined
|
|
78
|
+
> = AddJSONSchemaDefaults<
|
|
79
|
+
TSchema,
|
|
80
|
+
AddJSONSchemaRequired<
|
|
81
|
+
TSchema,
|
|
82
|
+
SchemaToDrizzleColumnsBase<TSchema, TObjectType>
|
|
83
|
+
>
|
|
84
|
+
>
|
|
85
|
+
|
|
101
86
|
/** Get the type of a JSONSchema string: array of constants for an enum,
|
|
102
87
|
otherwise string[]. Strangeness is to convert it into the format expected by
|
|
103
88
|
drizzle, which results in the correct type for the field from SQLite */
|
|
@@ -111,13 +96,12 @@ type Enum<
|
|
|
111
96
|
: [string, ...string[]]
|
|
112
97
|
|
|
113
98
|
/** True if JSONSchema object has a default */
|
|
114
|
-
type
|
|
115
|
-
? true
|
|
116
|
-
: false
|
|
99
|
+
type HasJSONSchemaDefault<T extends JSONSchema7> =
|
|
100
|
+
T['default'] extends JSONSchema7Type ? true : false
|
|
117
101
|
|
|
118
102
|
/** True if JSONSchema value is required */
|
|
119
|
-
type
|
|
120
|
-
T extends
|
|
103
|
+
type IsJSONSchemaRequired<
|
|
104
|
+
T extends JSONSchema7Object,
|
|
121
105
|
U extends string,
|
|
122
106
|
V extends JSONSchema7['required'] = T['required']
|
|
123
107
|
> = V extends readonly any[] ? Includes<V, U> : false
|
|
@@ -131,23 +115,78 @@ type IsRequired<
|
|
|
131
115
|
* stringify. Types for parsed JSON will be derived from MapeoDoc types.
|
|
132
116
|
*/
|
|
133
117
|
export type SchemaToDrizzleColumns<
|
|
134
|
-
|
|
118
|
+
TSchema extends JSONSchema7Object,
|
|
119
|
+
/** This is the type matching the JSONSchema */
|
|
120
|
+
TObjectType extends { [K in keyof TSchema['properties']]?: any },
|
|
121
|
+
TPrimaryKey extends keyof TSchema['properties'] | undefined = undefined
|
|
122
|
+
> = AddPrimaryKey<
|
|
123
|
+
AddJSONSchemaDefaults<
|
|
124
|
+
TSchema,
|
|
125
|
+
AddJSONSchemaRequired<
|
|
126
|
+
TSchema,
|
|
127
|
+
SchemaToDrizzleColumnsBase<TSchema, TObjectType>
|
|
128
|
+
>
|
|
129
|
+
>,
|
|
130
|
+
TPrimaryKey
|
|
131
|
+
>
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Add `HasDefault` to columns if the JSONSchema has a default for that property
|
|
135
|
+
*/
|
|
136
|
+
type AddJSONSchemaDefaults<
|
|
137
|
+
TJSONSchema extends JSONSchema7Object,
|
|
138
|
+
TColumns extends Record<string, ColumnBuilderBase>,
|
|
139
|
+
U extends JsonSchema7Properties = TJSONSchema['properties']
|
|
140
|
+
> = {
|
|
141
|
+
[K in keyof TColumns]: K extends keyof U
|
|
142
|
+
? HasJSONSchemaDefault<U[K]> extends true
|
|
143
|
+
? HasDefault<TColumns[K]>
|
|
144
|
+
: TColumns[K]
|
|
145
|
+
: TColumns[K]
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Mark columns as NotNull if they are required in the JSONSchema
|
|
150
|
+
*/
|
|
151
|
+
type AddJSONSchemaRequired<
|
|
152
|
+
TJSONSchema extends JSONSchema7Object,
|
|
153
|
+
TColumns extends Record<string, ColumnBuilderBase>
|
|
154
|
+
> = {
|
|
155
|
+
[K in keyof TColumns]: K extends string
|
|
156
|
+
? IsJSONSchemaRequired<TJSONSchema, K> extends true
|
|
157
|
+
? NotNull<TColumns[K]>
|
|
158
|
+
: TColumns[K]
|
|
159
|
+
: TColumns[K]
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
type AddPrimaryKey<
|
|
163
|
+
TColumns extends Record<string, ColumnBuilderBase>,
|
|
164
|
+
TKey extends keyof TColumns | undefined
|
|
165
|
+
> = TKey extends string
|
|
166
|
+
? Omit<TColumns, TKey> & { [K in TKey]: IsPrimaryKey<TColumns[TKey]> }
|
|
167
|
+
: TColumns
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Map JSONSchema object properties to Drizzle column types.
|
|
171
|
+
*/
|
|
172
|
+
type SchemaToDrizzleColumnsBase<
|
|
173
|
+
TSchema extends JSONSchema7Object,
|
|
135
174
|
TObjectType extends { [K in keyof U]?: any },
|
|
136
|
-
U extends JsonSchema7Properties =
|
|
175
|
+
U extends JsonSchema7Properties = TSchema['properties']
|
|
137
176
|
> = {
|
|
138
177
|
[K in keyof U]: K extends string
|
|
139
178
|
? U[K]['type'] extends 'string'
|
|
140
|
-
?
|
|
179
|
+
? SQLiteTextBuilder<Enum<U[K]>>
|
|
141
180
|
: U[K]['type'] extends 'boolean'
|
|
142
|
-
?
|
|
181
|
+
? SQLiteBooleanBuilder
|
|
143
182
|
: U[K]['type'] extends 'number'
|
|
144
|
-
?
|
|
183
|
+
? SQLiteRealBuilder
|
|
145
184
|
: U[K]['type'] extends 'integer'
|
|
146
|
-
?
|
|
185
|
+
? SQLiteIntegerBuilder
|
|
147
186
|
: U[K]['type'] extends 'array' | 'object'
|
|
148
|
-
?
|
|
187
|
+
? $Type<SQLiteTextJsonBuilder, TObjectType[K]>
|
|
149
188
|
: never
|
|
150
189
|
: never
|
|
151
|
-
} & { forks:
|
|
190
|
+
} & { forks: $Type<SQLiteTextJsonBuilder, string[]> }
|
|
152
191
|
|
|
153
192
|
export type NonEmptyArray<T> = [T, ...T[]]
|
package/src/translation-api.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { and, sql } from 'drizzle-orm'
|
|
1
|
+
import { and, eq, inArray, sql } from 'drizzle-orm'
|
|
2
2
|
import { kCreateWithDocId, kSelect } from './datatype/index.js'
|
|
3
3
|
import { deNullify, hashObject } from './utils.js'
|
|
4
4
|
import { nullIfNotFound } from './errors.js'
|
|
5
5
|
import { omit } from './lib/omit.js'
|
|
6
|
-
|
|
6
|
+
import { iso6391To6393, iso6393To6391 } from './intl/iso639.js'
|
|
7
|
+
import { translationTable } from './schema/project.js'
|
|
8
|
+
/** @import { MapeoDoc, Translation, TranslationValue } from '@comapeo/schema' */
|
|
7
9
|
/** @import { SetOptional } from 'type-fest' */
|
|
8
10
|
|
|
9
11
|
export const ktranslatedLanguageCodeToSchemaNames = Symbol(
|
|
@@ -14,6 +16,9 @@ export default class TranslationApi {
|
|
|
14
16
|
* TranslationValue['languageCode'],
|
|
15
17
|
* Set<import('@comapeo/schema/dist/types.js').SchemaName>>} */
|
|
16
18
|
#translatedLanguageCodeToSchemaNames = new Map()
|
|
19
|
+
// A bug in previous versions meant that translations were stored with ISO
|
|
20
|
+
// 639-1 codes, so we need to handle backwards compatibility for that case.
|
|
21
|
+
#hasLegacyIso6391Translations = false
|
|
17
22
|
#dataType
|
|
18
23
|
#indexPromise
|
|
19
24
|
|
|
@@ -69,19 +74,48 @@ export default class TranslationApi {
|
|
|
69
74
|
async get(value) {
|
|
70
75
|
await this.ready()
|
|
71
76
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
// Allow this API to accept both ISO 639-1 and ISO 639-3 codes for languageCode
|
|
78
|
+
const normalizedLanguageCode =
|
|
79
|
+
value.languageCode.length === 2
|
|
80
|
+
? iso6391To6393.get(value.languageCode)
|
|
81
|
+
: value.languageCode
|
|
82
|
+
if (!normalizedLanguageCode) return [] // invalid language code
|
|
83
|
+
|
|
84
|
+
const languageCodesToQuery = [normalizedLanguageCode]
|
|
85
|
+
|
|
86
|
+
// A bug in previous versions meant that translations could be stored with
|
|
87
|
+
// ISO 639-1 codes, so we need to query for both in this case by looking up
|
|
88
|
+
// the ISO 639-1 code for the langauge, and then checking whether there are
|
|
89
|
+
// translations for that language (looking up in our in-memory index saves
|
|
90
|
+
// an extra sqlite query when unnecessary)
|
|
91
|
+
if (this.#hasLegacyIso6391Translations) {
|
|
92
|
+
const iso6391LanguageCode =
|
|
93
|
+
value.languageCode.length === 2
|
|
94
|
+
? value.languageCode
|
|
95
|
+
: iso6393To6391.get(value.languageCode)
|
|
96
|
+
const isTranslationStoredWithIso6391Code =
|
|
97
|
+
iso6391LanguageCode &&
|
|
98
|
+
this.#isTranslated(
|
|
99
|
+
/** @type {MapeoDoc['schemaName']} */
|
|
100
|
+
(value.docRefType),
|
|
101
|
+
iso6391LanguageCode
|
|
79
102
|
)
|
|
103
|
+
if (isTranslationStoredWithIso6391Code) {
|
|
104
|
+
languageCodesToQuery.push(iso6391LanguageCode)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const docTypeIsTranslatedToLanguage =
|
|
109
|
+
this.#isTranslated(
|
|
110
|
+
/** @type {MapeoDoc['schemaName']} */
|
|
111
|
+
(value.docRefType),
|
|
112
|
+
normalizedLanguageCode
|
|
113
|
+
) || languageCodesToQuery.length > 1
|
|
80
114
|
if (!docTypeIsTranslatedToLanguage) return []
|
|
81
115
|
|
|
82
116
|
const filters = [
|
|
83
|
-
|
|
84
|
-
|
|
117
|
+
eq(translationTable.docRefType, value.docRefType),
|
|
118
|
+
inArray(translationTable.languageCode, languageCodesToQuery),
|
|
85
119
|
sql`json_extract(docRef, '$.docId') = ${value.docRef.docId}`,
|
|
86
120
|
]
|
|
87
121
|
|
|
@@ -94,7 +128,9 @@ export default class TranslationApi {
|
|
|
94
128
|
filters.push(sql`propertyRef = ${value.propertyRef}`)
|
|
95
129
|
}
|
|
96
130
|
if (value.regionCode) {
|
|
97
|
-
|
|
131
|
+
// Use COLLATE NOCASE for case-insensitive matching because in previous
|
|
132
|
+
// versions we did not normalize regionCode to uppercase.
|
|
133
|
+
filters.push(sql`regionCode = ${value.regionCode} COLLATE NOCASE`)
|
|
98
134
|
}
|
|
99
135
|
|
|
100
136
|
return (await this.#dataType[kSelect]())
|
|
@@ -118,6 +154,9 @@ export default class TranslationApi {
|
|
|
118
154
|
translatedSchemas
|
|
119
155
|
)
|
|
120
156
|
}
|
|
157
|
+
if (doc.languageCode.length === 2) {
|
|
158
|
+
this.#hasLegacyIso6391Translations = true
|
|
159
|
+
}
|
|
121
160
|
translatedSchemas.add(
|
|
122
161
|
/** @type {import('@comapeo/schema/dist/types.js').SchemaName} */ (
|
|
123
162
|
doc.docRefType
|
|
@@ -125,6 +164,19 @@ export default class TranslationApi {
|
|
|
125
164
|
)
|
|
126
165
|
}
|
|
127
166
|
|
|
167
|
+
/**
|
|
168
|
+
* @param {MapeoDoc['schemaName']} docType
|
|
169
|
+
* @param {string} languageCode
|
|
170
|
+
* @returns {boolean}
|
|
171
|
+
*/
|
|
172
|
+
#isTranslated(docType, languageCode) {
|
|
173
|
+
return (
|
|
174
|
+
this.#translatedLanguageCodeToSchemaNames
|
|
175
|
+
.get(languageCode)
|
|
176
|
+
?.has(docType) || false
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
|
|
128
180
|
// This should only be used by tests.
|
|
129
181
|
get [ktranslatedLanguageCodeToSchemaNames]() {
|
|
130
182
|
return this.#translatedLanguageCodeToSchemaNames
|
package/src/utils.js
CHANGED
|
@@ -240,3 +240,16 @@ export function buildBlobId(attachment, requestedVariant) {
|
|
|
240
240
|
driveId: attachment.driveDiscoveryId,
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Get typed entries from an object. Use this only on objects that you are
|
|
246
|
+
* certain have no extra properties - TS does not check for extra properties on
|
|
247
|
+
* an object, which is why Object.entries is untyped by default.
|
|
248
|
+
*
|
|
249
|
+
* @template {Record<string, unknown>} T
|
|
250
|
+
* @param {T} obj - The object to get entries from (must _not_ have extra properties)
|
|
251
|
+
* @returns {import('type-fest').Entries<T>}
|
|
252
|
+
*/
|
|
253
|
+
export function typedEntries(obj) {
|
|
254
|
+
return /** @type {import('type-fest').Entries<T>} */ (Object.entries(obj))
|
|
255
|
+
}
|
package/dist/config-import.d.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {yauzl.Entry} Entry
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* @typedef {{
|
|
6
|
-
* presets: { [id: string]: unknown }
|
|
7
|
-
* fields: { [id: string]: unknown }
|
|
8
|
-
* }} PresetsFile
|
|
9
|
-
*/
|
|
10
|
-
/** @typedef {('presets' | 'fields')} ValidDocTypes */
|
|
11
|
-
/**
|
|
12
|
-
* @typedef {{
|
|
13
|
-
* [lang: string]: unknown
|
|
14
|
-
* }} TranslationsFile
|
|
15
|
-
*/
|
|
16
|
-
/** @typedef {NonNullable<import('@comapeo/schema').ProjectSettingsValue['configMetadata']>} MetadataFile */
|
|
17
|
-
/**
|
|
18
|
-
* @typedef {Parameters<import('./icon-api.js').IconApi['create']>[0]} IconData
|
|
19
|
-
*/
|
|
20
|
-
/**
|
|
21
|
-
* @param {string} configPath
|
|
22
|
-
*/
|
|
23
|
-
export function readConfig(configPath: string): Promise<{
|
|
24
|
-
readonly warnings: Error[];
|
|
25
|
-
readonly metadata: {
|
|
26
|
-
importDate: string;
|
|
27
|
-
name: string;
|
|
28
|
-
buildDate: string;
|
|
29
|
-
fileVersion: string;
|
|
30
|
-
};
|
|
31
|
-
close(): Promise<void>;
|
|
32
|
-
/**
|
|
33
|
-
* @returns {AsyncIterable<IconData>}
|
|
34
|
-
*/
|
|
35
|
-
icons(): AsyncIterable<IconData>;
|
|
36
|
-
/**
|
|
37
|
-
* @returns {Iterable<{ name: string, value: import('@comapeo/schema').FieldValue }>}
|
|
38
|
-
*/
|
|
39
|
-
fields(): Iterable<{
|
|
40
|
-
name: string;
|
|
41
|
-
value: import("@comapeo/schema").FieldValue;
|
|
42
|
-
}>;
|
|
43
|
-
/**
|
|
44
|
-
* @returns {Iterable<{ fieldNames: string[], iconName: string | undefined, value: import('@comapeo/schema').PresetValue, name: string}>}
|
|
45
|
-
*/
|
|
46
|
-
presets(): Iterable<{
|
|
47
|
-
fieldNames: string[];
|
|
48
|
-
iconName: string | undefined;
|
|
49
|
-
value: import("@comapeo/schema").PresetValue;
|
|
50
|
-
name: string;
|
|
51
|
-
}>;
|
|
52
|
-
/** @returns {Iterable<{ name: string, value:Omit<import('@comapeo/schema').TranslationValue, 'docRef'>}>} */
|
|
53
|
-
translations(): Iterable<{
|
|
54
|
-
name: string;
|
|
55
|
-
value: Omit<import("@comapeo/schema").TranslationValue, "docRef">;
|
|
56
|
-
}>;
|
|
57
|
-
}>;
|
|
58
|
-
export type Entry = yauzl.Entry;
|
|
59
|
-
export type PresetsFile = {
|
|
60
|
-
presets: {
|
|
61
|
-
[id: string]: unknown;
|
|
62
|
-
};
|
|
63
|
-
fields: {
|
|
64
|
-
[id: string]: unknown;
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
export type ValidDocTypes = ("presets" | "fields");
|
|
68
|
-
export type TranslationsFile = {
|
|
69
|
-
[lang: string]: unknown;
|
|
70
|
-
};
|
|
71
|
-
export type MetadataFile = NonNullable<import("@comapeo/schema").ProjectSettingsValue["configMetadata"]>;
|
|
72
|
-
export type IconData = Parameters<import("./icon-api.js").IconApi["create"]>[0];
|
|
73
|
-
import yauzl from 'yauzl-promise';
|
|
74
|
-
//# sourceMappingURL=config-import.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config-import.d.ts","sourceRoot":"","sources":["../src/config-import.js"],"names":[],"mappings":"AAaA;;GAEG;AACH;;;;;GAKG;AAEH,sDAAsD;AACtD;;;;GAIG;AAEH,4GAA4G;AAE5G;;GAEG;AAEH;;GAEG;AACH,uCAFW,MAAM;;;;;;;;;IAmCb;;OAEG;aADU,aAAa,CAAC,QAAQ,CAAC;IAiDpC;;OAEG;cADU,QAAQ,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,iBAAiB,EAAE,UAAU,CAAA;KAAE,CAAC;IA6BpF;;OAEG;eADU,QAAQ,CAAC;QAAE,UAAU,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,KAAK,EAAE,OAAO,iBAAiB,EAAE,WAAW,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC;IAiFxI,6GAA6G;oBAA/F,QAAQ,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAC,IAAI,CAAC,OAAO,iBAAiB,EAAE,gBAAgB,EAAE,QAAQ,CAAC,CAAA;KAAC,CAAC;GAkB5G;oBA9OY,KAAK,CAAC,KAAK;0BAGX;IACR,OAAO,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;IAClC,MAAM,EAAG;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;CACnC;4BAGU,CAAC,SAAS,GAAG,QAAQ,CAAC;+BAEvB;IACZ,CAAI,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;2BAGU,WAAW,CAAC,OAAO,iBAAiB,EAAE,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;uBAG9E,UAAU,CAAC,OAAO,eAAe,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;kBAjCnD,eAAe"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/** @import { MapeoDoc } from '@comapeo/schema' */
|
|
2
|
-
/** @import { MapeoDocMap } from '../types.js' */
|
|
3
|
-
/**
|
|
4
|
-
Convert a JSONSchema definition to a Drizzle Columns Map (the parameter for
|
|
5
|
-
`sqliteTable()`).
|
|
6
|
-
|
|
7
|
-
**NOTE**: The return of this function is _not_ type-checked (it is coerced with
|
|
8
|
-
`as`, because it's not possible to type-check what this function is doing), but
|
|
9
|
-
the return type _should_ be correct when using this function.
|
|
10
|
-
@template {import('./types.js').JSONSchema7WithProps} TSchema
|
|
11
|
-
NB: The inline typescript checker often marks this next line as an error, but this seems to be a bug with JSDoc parsing - running `tsc` does not show this as an error.
|
|
12
|
-
@template {import('type-fest').Get<TSchema, 'properties.schemaName.const'>} TSchemaName
|
|
13
|
-
@template {TSchemaName extends MapeoDoc['schemaName'] ? MapeoDocMap[TSchemaName] : any} TObjectType
|
|
14
|
-
@param {TSchema} schema
|
|
15
|
-
@returns {import('./types.js').SchemaToDrizzleColumns<TSchema, TObjectType>}
|
|
16
|
-
*/
|
|
17
|
-
export function jsonSchemaToDrizzleColumns<TSchema extends import("./types.js").JSONSchema7WithProps, TSchemaName extends import("type-fest").Get<TSchema, "properties.schemaName.const">, TObjectType extends TSchemaName extends MapeoDoc["schemaName"] ? MapeoDocMap[TSchemaName] : any>(schema: TSchema): import("./types.js").SchemaToDrizzleColumns<TSchema, TObjectType>;
|
|
18
|
-
import type { MapeoDoc } from '@comapeo/schema';
|
|
19
|
-
import type { MapeoDocMap } from '../types.js';
|
|
20
|
-
//# sourceMappingURL=schema-to-drizzle.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schema-to-drizzle.d.ts","sourceRoot":"","sources":["../../src/schema/schema-to-drizzle.js"],"names":[],"mappings":"AAGA,kDAAkD;AAClD,iDAAiD;AAEjD;;;;;;;;;;;;;GAaG;AACH,2CAPsD,OAAO,SAAnD,OAAQ,YAAY,EAAE,oBAAqB,EAEuB,WAAW,SAA7E,OAAQ,WAAW,EAAE,GAAG,CAAC,OAAO,EAAE,6BAA6B,CAAE,EACa,WAAW,SAAxF,WAAW,SAAS,QAAQ,CAAC,YAAY,CAAC,GAAG,WAAW,CAAC,WAAW,CAAC,GAAG,GAAI,UAC/E,OAAO,GACL,OAAO,YAAY,EAAE,sBAAsB,CAAC,OAAO,EAAE,WAAW,CAAC,CAyD1E;8BAxE6B,iBAAiB;iCACd,aAAa"}
|
package/dist/schema/utils.d.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Table for storing backlinks, used for indexing. There needs to be one for
|
|
3
|
-
* each indexed document type
|
|
4
|
-
* @param {SqliteTable} tableSchema
|
|
5
|
-
*/
|
|
6
|
-
export function backlinkTable(tableSchema: SqliteTable): SQLiteTableWithColumns<{
|
|
7
|
-
name: string;
|
|
8
|
-
schema: undefined;
|
|
9
|
-
columns: {
|
|
10
|
-
versionId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
11
|
-
name: "versionId";
|
|
12
|
-
tableName: string;
|
|
13
|
-
dataType: "string";
|
|
14
|
-
columnType: "SQLiteText";
|
|
15
|
-
data: string;
|
|
16
|
-
driverParam: string;
|
|
17
|
-
notNull: true;
|
|
18
|
-
hasDefault: false;
|
|
19
|
-
enumValues: [string, ...string[]];
|
|
20
|
-
baseColumn: never;
|
|
21
|
-
}, object>;
|
|
22
|
-
};
|
|
23
|
-
dialect: "sqlite";
|
|
24
|
-
}>;
|
|
25
|
-
/**
|
|
26
|
-
* @param {string} tableName
|
|
27
|
-
*/
|
|
28
|
-
export function getBacklinkTableName(tableName: string): string;
|
|
29
|
-
/** @import { SQLiteTableWithColumns } from 'drizzle-orm/sqlite-core' */
|
|
30
|
-
/**
|
|
31
|
-
* @template {string} [TName=string]
|
|
32
|
-
* @typedef {SQLiteTableWithColumns<{
|
|
33
|
-
* name: TName;
|
|
34
|
-
* dialect: 'sqlite';
|
|
35
|
-
* schema: string | undefined;
|
|
36
|
-
* columns: any
|
|
37
|
-
* }>} SqliteTable
|
|
38
|
-
*/
|
|
39
|
-
export const BACKLINK_TABLE_POSTFIX: "_backlink";
|
|
40
|
-
export const customJson: <TName extends string>(dbName: TName, fieldConfig?: unknown) => import("drizzle-orm/sqlite-core").SQLiteCustomColumnBuilder<{
|
|
41
|
-
name: TName;
|
|
42
|
-
dataType: "custom";
|
|
43
|
-
columnType: "SQLiteCustomColumn";
|
|
44
|
-
data: unknown;
|
|
45
|
-
driverParam: unknown;
|
|
46
|
-
enumValues: undefined;
|
|
47
|
-
}>;
|
|
48
|
-
export type SqliteTable<TName extends string = string> = SQLiteTableWithColumns<{
|
|
49
|
-
name: TName;
|
|
50
|
-
dialect: "sqlite";
|
|
51
|
-
schema: string | undefined;
|
|
52
|
-
columns: any;
|
|
53
|
-
}>;
|
|
54
|
-
import type { SQLiteTableWithColumns } from 'drizzle-orm/sqlite-core';
|
|
55
|
-
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/schema/utils.js"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH,2CAFW,WAAW;;;;;;;;;;;;;;;;;;GAOrB;AAED;;GAEG;AACH,gDAFW,MAAM,UAIhB;AA/BD,wEAAwE;AAExE;;;;;;;;GAQG;AAEH,iDAAiD;AAqBjD;;;;;;;GAWE;wBAzCqB,KAAK,SAAf,MAAQ,aACR,uBAAuB;IAC/B,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,EAAE,QAAQ,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,GAAG,CAAA;CACb,CAAC;4CATuC,yBAAyB"}
|