@syncular/core 0.15.32 → 0.15.34
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/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/relational-identifier.d.ts +20 -0
- package/dist/relational-identifier.js +44 -0
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/relational-identifier.ts +69 -0
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export * from './frames.js';
|
|
|
16
16
|
export * from './message.js';
|
|
17
17
|
export * from './realtime.js';
|
|
18
18
|
export * from './rejection-details.js';
|
|
19
|
+
export * from './relational-identifier.js';
|
|
19
20
|
export * from './render.js';
|
|
20
21
|
export * from './row-codec.js';
|
|
21
22
|
export * from './segment.js';
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ export * from './frames.js';
|
|
|
16
16
|
export * from './message.js';
|
|
17
17
|
export * from './realtime.js';
|
|
18
18
|
export * from './rejection-details.js';
|
|
19
|
+
export * from './relational-identifier.js';
|
|
19
20
|
export * from './render.js';
|
|
20
21
|
export * from './row-codec.js';
|
|
21
22
|
export * from './segment.js';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portable relational identifier rules shared by typegen and every server
|
|
3
|
+
* runtime. PostgreSQL truncates identifiers after 63 UTF-8 bytes, while the
|
|
4
|
+
* relational Syncular projection reserves its own table/column namespace.
|
|
5
|
+
*
|
|
6
|
+
* Keeping this validation in core prevents a generated schema from passing
|
|
7
|
+
* typegen and then failing later when a server or testkit compiles it.
|
|
8
|
+
*/
|
|
9
|
+
export declare const PORTABLE_RELATIONAL_IDENTIFIER_MAX_BYTES = 63;
|
|
10
|
+
export type PortableRelationalIdentifierFailure = 'empty' | 'reserved-prefix' | 'too-long';
|
|
11
|
+
export declare class PortableRelationalIdentifierError extends Error {
|
|
12
|
+
readonly kind: string;
|
|
13
|
+
readonly identifier: string;
|
|
14
|
+
readonly failure: PortableRelationalIdentifierFailure;
|
|
15
|
+
readonly byteLength: number;
|
|
16
|
+
readonly code = "schema.invalid_identifier";
|
|
17
|
+
constructor(kind: string, identifier: string, failure: PortableRelationalIdentifierFailure, byteLength: number);
|
|
18
|
+
}
|
|
19
|
+
/** Validate one identifier against the strictest supported relational host. */
|
|
20
|
+
export declare function validatePortableRelationalIdentifier(kind: string, identifier: string): void;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portable relational identifier rules shared by typegen and every server
|
|
3
|
+
* runtime. PostgreSQL truncates identifiers after 63 UTF-8 bytes, while the
|
|
4
|
+
* relational Syncular projection reserves its own table/column namespace.
|
|
5
|
+
*
|
|
6
|
+
* Keeping this validation in core prevents a generated schema from passing
|
|
7
|
+
* typegen and then failing later when a server or testkit compiles it.
|
|
8
|
+
*/
|
|
9
|
+
export const PORTABLE_RELATIONAL_IDENTIFIER_MAX_BYTES = 63;
|
|
10
|
+
export class PortableRelationalIdentifierError extends Error {
|
|
11
|
+
kind;
|
|
12
|
+
identifier;
|
|
13
|
+
failure;
|
|
14
|
+
byteLength;
|
|
15
|
+
code = 'schema.invalid_identifier';
|
|
16
|
+
constructor(kind, identifier, failure, byteLength) {
|
|
17
|
+
const quoted = JSON.stringify(identifier);
|
|
18
|
+
const message = failure === 'empty'
|
|
19
|
+
? `${kind} name must not be empty`
|
|
20
|
+
: failure === 'reserved-prefix'
|
|
21
|
+
? `${kind} name ${quoted} uses a reserved prefix (sync_/_sync are the server storage namespace)`
|
|
22
|
+
: `${kind} name ${quoted} exceeds ${PORTABLE_RELATIONAL_IDENTIFIER_MAX_BYTES} bytes (Postgres identifier limit; actual UTF-8 length: ${byteLength} bytes)`;
|
|
23
|
+
super(message);
|
|
24
|
+
this.kind = kind;
|
|
25
|
+
this.identifier = identifier;
|
|
26
|
+
this.failure = failure;
|
|
27
|
+
this.byteLength = byteLength;
|
|
28
|
+
this.name = 'PortableRelationalIdentifierError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Validate one identifier against the strictest supported relational host. */
|
|
32
|
+
export function validatePortableRelationalIdentifier(kind, identifier) {
|
|
33
|
+
const byteLength = new TextEncoder().encode(identifier).length;
|
|
34
|
+
if (identifier.length === 0) {
|
|
35
|
+
throw new PortableRelationalIdentifierError(kind, identifier, 'empty', byteLength);
|
|
36
|
+
}
|
|
37
|
+
const lower = identifier.toLowerCase();
|
|
38
|
+
if (lower.startsWith('sync_') || lower.startsWith('_sync')) {
|
|
39
|
+
throw new PortableRelationalIdentifierError(kind, identifier, 'reserved-prefix', byteLength);
|
|
40
|
+
}
|
|
41
|
+
if (byteLength > PORTABLE_RELATIONAL_IDENTIFIER_MAX_BYTES) {
|
|
42
|
+
throw new PortableRelationalIdentifierError(kind, identifier, 'too-long', byteLength);
|
|
43
|
+
}
|
|
44
|
+
}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portable relational identifier rules shared by typegen and every server
|
|
3
|
+
* runtime. PostgreSQL truncates identifiers after 63 UTF-8 bytes, while the
|
|
4
|
+
* relational Syncular projection reserves its own table/column namespace.
|
|
5
|
+
*
|
|
6
|
+
* Keeping this validation in core prevents a generated schema from passing
|
|
7
|
+
* typegen and then failing later when a server or testkit compiles it.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export const PORTABLE_RELATIONAL_IDENTIFIER_MAX_BYTES = 63;
|
|
11
|
+
|
|
12
|
+
export type PortableRelationalIdentifierFailure =
|
|
13
|
+
| 'empty'
|
|
14
|
+
| 'reserved-prefix'
|
|
15
|
+
| 'too-long';
|
|
16
|
+
|
|
17
|
+
export class PortableRelationalIdentifierError extends Error {
|
|
18
|
+
readonly code = 'schema.invalid_identifier';
|
|
19
|
+
|
|
20
|
+
constructor(
|
|
21
|
+
readonly kind: string,
|
|
22
|
+
readonly identifier: string,
|
|
23
|
+
readonly failure: PortableRelationalIdentifierFailure,
|
|
24
|
+
readonly byteLength: number,
|
|
25
|
+
) {
|
|
26
|
+
const quoted = JSON.stringify(identifier);
|
|
27
|
+
const message =
|
|
28
|
+
failure === 'empty'
|
|
29
|
+
? `${kind} name must not be empty`
|
|
30
|
+
: failure === 'reserved-prefix'
|
|
31
|
+
? `${kind} name ${quoted} uses a reserved prefix (sync_/_sync are the server storage namespace)`
|
|
32
|
+
: `${kind} name ${quoted} exceeds ${PORTABLE_RELATIONAL_IDENTIFIER_MAX_BYTES} bytes (Postgres identifier limit; actual UTF-8 length: ${byteLength} bytes)`;
|
|
33
|
+
super(message);
|
|
34
|
+
this.name = 'PortableRelationalIdentifierError';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Validate one identifier against the strictest supported relational host. */
|
|
39
|
+
export function validatePortableRelationalIdentifier(
|
|
40
|
+
kind: string,
|
|
41
|
+
identifier: string,
|
|
42
|
+
): void {
|
|
43
|
+
const byteLength = new TextEncoder().encode(identifier).length;
|
|
44
|
+
if (identifier.length === 0) {
|
|
45
|
+
throw new PortableRelationalIdentifierError(
|
|
46
|
+
kind,
|
|
47
|
+
identifier,
|
|
48
|
+
'empty',
|
|
49
|
+
byteLength,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
const lower = identifier.toLowerCase();
|
|
53
|
+
if (lower.startsWith('sync_') || lower.startsWith('_sync')) {
|
|
54
|
+
throw new PortableRelationalIdentifierError(
|
|
55
|
+
kind,
|
|
56
|
+
identifier,
|
|
57
|
+
'reserved-prefix',
|
|
58
|
+
byteLength,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
if (byteLength > PORTABLE_RELATIONAL_IDENTIFIER_MAX_BYTES) {
|
|
62
|
+
throw new PortableRelationalIdentifierError(
|
|
63
|
+
kind,
|
|
64
|
+
identifier,
|
|
65
|
+
'too-long',
|
|
66
|
+
byteLength,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
}
|