rlz-engine 1.0.33 → 1.0.35
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/back/auth/controllers.d.ts +1 -1
- package/dist/back/auth/controllers.js +3 -3
- package/dist/back/auth/storage.d.ts +2 -2
- package/dist/back/auth/storage.js +2 -2
- package/dist/back/auth/utils.d.ts +2 -2
- package/dist/back/logger.js +1 -1
- package/dist/back/rpc/gen.d.ts +2 -0
- package/dist/back/rpc/gen.js +63 -0
- package/dist/back/rpc/rpc.d.ts +49 -0
- package/dist/back/rpc/rpc.js +60 -0
- package/dist/back/server.js +6 -6
- package/dist/back/storage/db.js +1 -1
- package/dist/back/storage/sync.d.ts +2 -2
- package/dist/back/storage/sync.js +1 -1
- package/dist/client/api/api.js +1 -1
- package/dist/client/api/auth.d.ts +2 -2
- package/dist/client/api/auth.js +2 -2
- package/dist/client/rpc.d.ts +21 -0
- package/dist/client/rpc.js +75 -0
- package/dist/client/screens/SignupSigninScreen.js +2 -2
- package/dist/client/state/auth.d.ts +1 -1
- package/dist/client/state/auth.js +1 -1
- package/dist/client/sync.d.ts +1 -1
- package/dist/client/sync.js +1 -1
- package/package.json +9 -3
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { httpErrors } from '@fastify/sensible';
|
|
2
2
|
import fastifyPlugin from 'fastify-plugin';
|
|
3
|
-
import zodToJsonSchema from 'zod-to-json-schema';
|
|
4
|
-
import { API_AUTH_RESPONSE_SCHEMA_V0, API_SIGNIN_REQUEST_SCHEMA_V0, API_SIGNUP_REQUEST_SCHEMA_V0 } from '../../shared/api/auth';
|
|
5
|
-
import { logout, signin, signup } from './utils';
|
|
3
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
4
|
+
import { API_AUTH_RESPONSE_SCHEMA_V0, API_SIGNIN_REQUEST_SCHEMA_V0, API_SIGNUP_REQUEST_SCHEMA_V0 } from '../../shared/api/auth.js';
|
|
5
|
+
import { logout, signin, signup } from './utils.js';
|
|
6
6
|
export const AUTH_API = fastifyPlugin(async function authApi(app, { storage }) {
|
|
7
7
|
app.post('/api/v0/signup', {
|
|
8
8
|
schema: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FastifyRequest } from 'fastify';
|
|
2
2
|
import { Binary, Collection } from 'mongodb';
|
|
3
|
-
import { MongoStorage } from '../storage/db';
|
|
4
|
-
import { StorageTempPassword, StorageUser } from './model';
|
|
3
|
+
import { MongoStorage } from '../storage/db.js';
|
|
4
|
+
import { StorageTempPassword, StorageUser } from './model.js';
|
|
5
5
|
export declare class AuthStorage {
|
|
6
6
|
private readonly logger;
|
|
7
7
|
private readonly mongo;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FastifyRequest } from 'fastify';
|
|
2
|
-
import { ApiAuthResponseV0 } from '../../shared/api/auth';
|
|
3
|
-
import { AuthStorage } from './storage';
|
|
2
|
+
import { ApiAuthResponseV0 } from '../../shared/api/auth.js';
|
|
3
|
+
import { AuthStorage } from './storage.js';
|
|
4
4
|
export declare function signup(storage: AuthStorage, name: string, email: string, password: string): Promise<ApiAuthResponseV0>;
|
|
5
5
|
export declare function signin(storage: AuthStorage, name: string, password: string): Promise<ApiAuthResponseV0 | null>;
|
|
6
6
|
export declare function logout(storage: AuthStorage, userId: string, tempPassword: string): Promise<void>;
|
package/dist/back/logger.js
CHANGED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import ts, { NewLineKind, ScriptKind, ScriptTarget } from 'typescript';
|
|
2
|
+
import { createTypeAlias, zodToTs } from 'zod-to-ts';
|
|
3
|
+
const F = ts.factory;
|
|
4
|
+
export function generateClient(fileName, ...rpcBuilders) {
|
|
5
|
+
const sourceFile = ts.createSourceFile(fileName, '', ScriptTarget.Latest, false, ScriptKind.TS);
|
|
6
|
+
const printer = ts.createPrinter({ newLine: NewLineKind.CarriageReturnLineFeed });
|
|
7
|
+
const p = (node) => {
|
|
8
|
+
return printer.printNode(ts.EmitHint.Unspecified, node, sourceFile);
|
|
9
|
+
};
|
|
10
|
+
const fileContent = [];
|
|
11
|
+
fileContent.push(p(F.createImportDeclaration(undefined, F.createImportClause(false, undefined, F.createNamedImports([
|
|
12
|
+
F.createImportSpecifier(false, undefined, F.createIdentifier('AuthParam')),
|
|
13
|
+
F.createImportSpecifier(false, undefined, F.createIdentifier('rpcCall'))
|
|
14
|
+
])), F.createStringLiteral('rlz-engine/client/rpc.js'), undefined)));
|
|
15
|
+
for (const b of rpcBuilders) {
|
|
16
|
+
for (const e of b.endpoints) {
|
|
17
|
+
fileContent.push(...generateTypes(b.name, e, p));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const props = rpcBuilders.map((b) => {
|
|
21
|
+
const calls = b.endpoints.map((e) => {
|
|
22
|
+
return F.createPropertyAssignment(F.createIdentifier(e.name), F.createArrowFunction([F.createToken(ts.SyntaxKind.AsyncKeyword)], undefined, e.anonimous
|
|
23
|
+
? [
|
|
24
|
+
F.createParameterDeclaration(undefined, undefined, F.createIdentifier('body'), undefined, F.createTypeReferenceNode(F.createIdentifier(createBodyTypeName(b.name, e)), undefined), undefined)
|
|
25
|
+
]
|
|
26
|
+
: [
|
|
27
|
+
F.createParameterDeclaration(undefined, undefined, F.createIdentifier('auth'), undefined, F.createTypeReferenceNode(F.createIdentifier('AuthParam'), undefined), undefined),
|
|
28
|
+
F.createParameterDeclaration(undefined, undefined, F.createIdentifier('body'), undefined, F.createTypeReferenceNode(F.createIdentifier(createBodyTypeName(b.name, e)), undefined), undefined)
|
|
29
|
+
], F.createTypeReferenceNode(F.createIdentifier('Promise'), [F.createTypeReferenceNode(F.createIdentifier(createRespTypeName(b.name, e)), undefined)]), F.createToken(ts.SyntaxKind.EqualsGreaterThanToken), F.createBlock([F.createReturnStatement(F.createAwaitExpression(F.createCallExpression(F.createIdentifier('rpcCall'), undefined, [
|
|
30
|
+
e.anonimous ? F.createNull() : F.createIdentifier('auth'),
|
|
31
|
+
F.createStringLiteral(b.name),
|
|
32
|
+
F.createStringLiteral(e.name),
|
|
33
|
+
F.createNumericLiteral(e.v),
|
|
34
|
+
F.createIdentifier('body')
|
|
35
|
+
])))], true)));
|
|
36
|
+
});
|
|
37
|
+
return F.createPropertyAssignment(F.createIdentifier(b.name), F.createObjectLiteralExpression(calls, false));
|
|
38
|
+
});
|
|
39
|
+
const rpcClientNode = F.createVariableStatement([F.createToken(ts.SyntaxKind.ExportKeyword)], F.createVariableDeclarationList([F.createVariableDeclaration(F.createIdentifier('RPC_CLIENT'), undefined, undefined, F.createObjectLiteralExpression(props, false))], ts.NodeFlags.Const));
|
|
40
|
+
fileContent.push(p(rpcClientNode));
|
|
41
|
+
return fileContent.join('\n');
|
|
42
|
+
}
|
|
43
|
+
function generateTypes(rpcName, e, p) {
|
|
44
|
+
const resp = [];
|
|
45
|
+
const bodyTypeName = createBodyTypeName(rpcName, e);
|
|
46
|
+
const bodyType = zodToTs(e.bodySchema, bodyTypeName);
|
|
47
|
+
const bodyTypeAlias = createTypeAlias(bodyType.node, bodyTypeName);
|
|
48
|
+
resp.push(p(bodyTypeAlias));
|
|
49
|
+
const respTypeName = createRespTypeName(rpcName, e);
|
|
50
|
+
const respType = zodToTs(e.respSchema, respTypeName);
|
|
51
|
+
const respTypeAlias = createTypeAlias(respType.node, respTypeName);
|
|
52
|
+
resp.push(p(respTypeAlias));
|
|
53
|
+
return resp;
|
|
54
|
+
}
|
|
55
|
+
function firstLetterUp(text) {
|
|
56
|
+
return `${text[0].toUpperCase()}${text.substring(1)}`;
|
|
57
|
+
}
|
|
58
|
+
function createBodyTypeName(rpcName, e) {
|
|
59
|
+
return `RpcBody${firstLetterUp(rpcName)}${firstLetterUp(e.name)}V${e.v}`;
|
|
60
|
+
}
|
|
61
|
+
function createRespTypeName(rpcName, e) {
|
|
62
|
+
return `RpcResp${firstLetterUp(rpcName)}${firstLetterUp(e.name)}V${e.v}`;
|
|
63
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { FastifyInstance, FastifyPluginOptions, RawServerBase } from 'fastify';
|
|
2
|
+
import z from 'zod';
|
|
3
|
+
interface RpcEndpointCommon<BodyT extends object, RespT extends object> {
|
|
4
|
+
readonly v: number;
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly bodySchema: z.Schema<BodyT>;
|
|
7
|
+
readonly respSchema: z.Schema<RespT>;
|
|
8
|
+
}
|
|
9
|
+
interface RpcEndpointAnon<BodyT extends object = object, RespT extends object = object, OptsT = never> extends RpcEndpointCommon<BodyT, RespT> {
|
|
10
|
+
readonly anonimous: true;
|
|
11
|
+
readonly action: (body: {
|
|
12
|
+
[k in keyof BodyT]: BodyT[k];
|
|
13
|
+
}, opts: OptsT) => {
|
|
14
|
+
[k in keyof RespT]: RespT[k];
|
|
15
|
+
} | Promise<{
|
|
16
|
+
[k in keyof RespT]: RespT[k];
|
|
17
|
+
}>;
|
|
18
|
+
}
|
|
19
|
+
interface RpcEndpointAuth<BodyT extends object = object, RespT extends object = object, OptsT = never, UserT = never> extends RpcEndpointCommon<BodyT, RespT> {
|
|
20
|
+
readonly anonimous?: false;
|
|
21
|
+
readonly auth: (userId: string, password: string) => UserT | Promise<UserT>;
|
|
22
|
+
readonly action: (user: UserT, body: {
|
|
23
|
+
[k in keyof BodyT]: BodyT[k];
|
|
24
|
+
}, opts: OptsT) => {
|
|
25
|
+
[k in keyof RespT]: RespT[k];
|
|
26
|
+
} | Promise<{
|
|
27
|
+
[k in keyof RespT]: RespT[k];
|
|
28
|
+
}>;
|
|
29
|
+
}
|
|
30
|
+
export type RpcEndpoint<BodyT extends object = object, RespT extends object = object, OptsT = never, UserT = never> = RpcEndpointAnon<BodyT, RespT, OptsT> | RpcEndpointAuth<BodyT, RespT, OptsT, UserT>;
|
|
31
|
+
export interface RpcEndpointInfo {
|
|
32
|
+
v: number;
|
|
33
|
+
name: string;
|
|
34
|
+
anonimous: boolean;
|
|
35
|
+
bodySchema: z.Schema;
|
|
36
|
+
respSchema: z.Schema;
|
|
37
|
+
}
|
|
38
|
+
interface InnerRpcEndpoint<OptsT> extends RpcEndpointInfo {
|
|
39
|
+
reg: <T extends RawServerBase>(app: FastifyInstance<T>, opts: OptsT) => void;
|
|
40
|
+
}
|
|
41
|
+
export declare class RpcPluginBuilder<OptsT extends FastifyPluginOptions = never> {
|
|
42
|
+
readonly name: string;
|
|
43
|
+
readonly endpoints: InnerRpcEndpoint<OptsT>[];
|
|
44
|
+
constructor(name: string);
|
|
45
|
+
add<BodyT extends object, RespT extends object, UserT>(endpoint: RpcEndpoint<BodyT, RespT, OptsT, UserT>): this;
|
|
46
|
+
makeFastifyPlugin(): <T extends RawServerBase>(app: FastifyInstance<T>, opts: OptsT) => void;
|
|
47
|
+
}
|
|
48
|
+
export declare function rpc<OptsT extends FastifyPluginOptions>(name: string): RpcPluginBuilder<OptsT>;
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { httpErrors } from '@fastify/sensible';
|
|
2
|
+
import fastifyPlugin from 'fastify-plugin';
|
|
3
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
4
|
+
function makeReg(pluginName, endpoint) {
|
|
5
|
+
return {
|
|
6
|
+
v: endpoint.v,
|
|
7
|
+
name: endpoint.name,
|
|
8
|
+
anonimous: endpoint.anonimous ?? false,
|
|
9
|
+
bodySchema: endpoint.bodySchema,
|
|
10
|
+
respSchema: endpoint.respSchema,
|
|
11
|
+
reg(app, opts) {
|
|
12
|
+
app.post(`/rpc/${pluginName}/${this.name}/v${this.v}`, {
|
|
13
|
+
schema: {
|
|
14
|
+
body: zodToJsonSchema(this.bodySchema),
|
|
15
|
+
response: {
|
|
16
|
+
200: zodToJsonSchema(this.respSchema)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}, endpoint.anonimous === true
|
|
20
|
+
? async (req, resp) => {
|
|
21
|
+
const body = req.body;
|
|
22
|
+
const respBody = await endpoint.action(body, opts);
|
|
23
|
+
resp.send(respBody);
|
|
24
|
+
}
|
|
25
|
+
: async (req, resp) => {
|
|
26
|
+
const authHeader = req.headers.authorization;
|
|
27
|
+
if (authHeader === undefined) {
|
|
28
|
+
throw httpErrors.forbidden();
|
|
29
|
+
}
|
|
30
|
+
const [userId, password] = authHeader.split(':');
|
|
31
|
+
const user = await endpoint.auth(userId, password);
|
|
32
|
+
const body = req.body;
|
|
33
|
+
const respBody = await endpoint.action(user, body, opts);
|
|
34
|
+
resp.send(respBody);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export class RpcPluginBuilder {
|
|
40
|
+
name;
|
|
41
|
+
endpoints = [];
|
|
42
|
+
constructor(name) {
|
|
43
|
+
this.name = name;
|
|
44
|
+
}
|
|
45
|
+
add(endpoint) {
|
|
46
|
+
this.endpoints.push(makeReg(this.name, endpoint));
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
makeFastifyPlugin() {
|
|
50
|
+
const endpoints = this.endpoints;
|
|
51
|
+
return fastifyPlugin(function makeRpcPlugin(app, opts) {
|
|
52
|
+
for (const e of endpoints) {
|
|
53
|
+
e.reg(app, opts);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function rpc(name) {
|
|
59
|
+
return new RpcPluginBuilder(name);
|
|
60
|
+
}
|
package/dist/back/server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fastifyCompress from '@fastify/compress';
|
|
2
2
|
import fastifyCors from '@fastify/cors';
|
|
3
|
-
import fastifyResponseValidation from '@fastify/response-validation';
|
|
3
|
+
import { fastifyResponseValidation } from '@fastify/response-validation';
|
|
4
4
|
import fastifySensible, { httpErrors } from '@fastify/sensible';
|
|
5
5
|
import fastifyStatic from '@fastify/static';
|
|
6
6
|
import formatsPlugin from 'ajv-formats';
|
|
@@ -9,14 +9,14 @@ import { fastifyAcmeSecurePlugin, fastifyAcmeUnsecurePlugin, getCertAndKey } fro
|
|
|
9
9
|
import { createReadStream } from 'fs';
|
|
10
10
|
import { installIntoGlobal } from 'iterator-helpers-polyfill';
|
|
11
11
|
import path from 'path';
|
|
12
|
-
import { logger } from './logger';
|
|
12
|
+
import { logger } from './logger.js';
|
|
13
13
|
installIntoGlobal();
|
|
14
14
|
const L = logger('init');
|
|
15
15
|
export async function runServer({ production, domain, certDir, staticDir, init }) {
|
|
16
16
|
L.info({ production }, 'runServer');
|
|
17
17
|
const httpServer = fastify({
|
|
18
18
|
loggerInstance: logger('http'),
|
|
19
|
-
ajv: { plugins: [formatsPlugin], customOptions: { useDefaults: false } }
|
|
19
|
+
ajv: { plugins: [formatsPlugin.default], customOptions: { useDefaults: false, coerceTypes: false, allErrors: true } }
|
|
20
20
|
});
|
|
21
21
|
if (!production) {
|
|
22
22
|
await httpServer.register(fastifyCors, {
|
|
@@ -25,7 +25,7 @@ export async function runServer({ production, domain, certDir, staticDir, init }
|
|
|
25
25
|
await httpServer.register(fastifyCompress);
|
|
26
26
|
await httpServer.register(fastifySensible);
|
|
27
27
|
await httpServer.register(fastifyResponseValidation, {
|
|
28
|
-
ajv: { plugins: [formatsPlugin], useDefaults: false }
|
|
28
|
+
ajv: { plugins: [formatsPlugin.default], useDefaults: false, coerceTypes: false, allErrors: true }
|
|
29
29
|
});
|
|
30
30
|
await init(httpServer);
|
|
31
31
|
httpServer.all('/api/*', async () => {
|
|
@@ -48,7 +48,7 @@ export async function runServer({ production, domain, certDir, staticDir, init }
|
|
|
48
48
|
key: certAndKey.pkey
|
|
49
49
|
},
|
|
50
50
|
loggerInstance: logger('https'),
|
|
51
|
-
ajv: { plugins: [formatsPlugin], customOptions: { useDefaults: false } }
|
|
51
|
+
ajv: { plugins: [formatsPlugin.default], customOptions: { useDefaults: false, coerceTypes: false, allErrors: true } }
|
|
52
52
|
});
|
|
53
53
|
await httpsServer.register(fastifyAcmeSecurePlugin, {
|
|
54
54
|
certDir,
|
|
@@ -59,7 +59,7 @@ export async function runServer({ production, domain, certDir, staticDir, init }
|
|
|
59
59
|
});
|
|
60
60
|
await httpsServer.register(fastifyCompress);
|
|
61
61
|
await httpsServer.register(fastifySensible);
|
|
62
|
-
await httpsServer.register(fastifyResponseValidation, { ajv: { plugins: [formatsPlugin], useDefaults: false } });
|
|
62
|
+
await httpsServer.register(fastifyResponseValidation, { ajv: { plugins: [formatsPlugin.default], useDefaults: false, coerceTypes: false, allErrors: true } });
|
|
63
63
|
await init(httpsServer);
|
|
64
64
|
httpsServer.all('/api/*', async () => {
|
|
65
65
|
return httpErrors.notFound();
|
package/dist/back/storage/db.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DateTime } from 'luxon';
|
|
2
2
|
import { Collection } from 'mongodb';
|
|
3
|
-
import { ApiComparisonObjectV0 } from '../../shared/api/sync';
|
|
4
|
-
import { SyncObject } from './model';
|
|
3
|
+
import { ApiComparisonObjectV0 } from '../../shared/api/sync.js';
|
|
4
|
+
import { SyncObject } from './model.js';
|
|
5
5
|
export declare function getAll<T>(c: Collection<SyncObject<T>>, ownerId: string, syncAfter?: DateTime<true>): Promise<ApiComparisonObjectV0[]>;
|
package/dist/client/api/api.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ApiAuthResponseV0 } from '../../shared/api/auth';
|
|
2
|
-
import { AuthParam } from './api';
|
|
1
|
+
import { ApiAuthResponseV0 } from '../../shared/api/auth.js';
|
|
2
|
+
import { AuthParam } from './api.js';
|
|
3
3
|
export declare function apiSignup(name: string, email: string, password: string): Promise<ApiAuthResponseV0>;
|
|
4
4
|
export declare function apiSignin(name: string, password: string): Promise<ApiAuthResponseV0>;
|
|
5
5
|
export declare function apiLogout(auth: AuthParam): Promise<void>;
|
package/dist/client/api/auth.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { API_AUTH_RESPONSE_SCHEMA_V0 } from '../../shared/api/auth';
|
|
3
|
-
import { apiCall } from './api';
|
|
2
|
+
import { API_AUTH_RESPONSE_SCHEMA_V0 } from '../../shared/api/auth.js';
|
|
3
|
+
import { apiCall } from './api.js';
|
|
4
4
|
export async function apiSignup(name, email, password) {
|
|
5
5
|
const req = {
|
|
6
6
|
name,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare class HttpError extends Error {
|
|
2
|
+
readonly method: string;
|
|
3
|
+
readonly url: string;
|
|
4
|
+
readonly status: number;
|
|
5
|
+
readonly statusText: string;
|
|
6
|
+
constructor(method: string, url: string, status: number, statusText: string);
|
|
7
|
+
}
|
|
8
|
+
export declare class Unauthorized extends HttpError {
|
|
9
|
+
constructor(url: string, statusText: string);
|
|
10
|
+
}
|
|
11
|
+
export declare class Forbidden extends HttpError {
|
|
12
|
+
constructor(url: string, statusText: string);
|
|
13
|
+
}
|
|
14
|
+
export declare class NotFound extends HttpError {
|
|
15
|
+
constructor(url: string, statusText: string);
|
|
16
|
+
}
|
|
17
|
+
export interface AuthParam {
|
|
18
|
+
userId: string;
|
|
19
|
+
tempPassword: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function rpcCall<BodyT extends object, RespT extends object>(auth: AuthParam | null, rpcName: string, callName: string, version: number, bodyObject: BodyT): Promise<RespT>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { getFrontConfig } from './config.js';
|
|
2
|
+
export class HttpError extends Error {
|
|
3
|
+
method;
|
|
4
|
+
url;
|
|
5
|
+
status;
|
|
6
|
+
statusText;
|
|
7
|
+
constructor(method, url, status, statusText) {
|
|
8
|
+
super(`Not ok resp (${status} ${statusText}): ${method} ${url}`);
|
|
9
|
+
this.method = method;
|
|
10
|
+
this.url = url;
|
|
11
|
+
this.status = status;
|
|
12
|
+
this.statusText = statusText;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export class Unauthorized extends HttpError {
|
|
16
|
+
constructor(url, statusText) {
|
|
17
|
+
super('post', url, 401, statusText);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class Forbidden extends HttpError {
|
|
21
|
+
constructor(url, statusText) {
|
|
22
|
+
super('post', url, 403, statusText);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export class NotFound extends HttpError {
|
|
26
|
+
constructor(url, statusText) {
|
|
27
|
+
super('post', url, 404, statusText);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function url(rpcName, callName, version) {
|
|
31
|
+
const domain = getFrontConfig().apiDomain;
|
|
32
|
+
return `${domain}rpc/${rpcName}/${callName}/v${version}`;
|
|
33
|
+
}
|
|
34
|
+
const GZIP_THRESHOLD = 16 * 1024;
|
|
35
|
+
async function prepareBody(request) {
|
|
36
|
+
const textBody = JSON.stringify(request);
|
|
37
|
+
if (textBody.length <= GZIP_THRESHOLD) {
|
|
38
|
+
return textBody;
|
|
39
|
+
}
|
|
40
|
+
const bodyStream = new Blob([textBody]).stream();
|
|
41
|
+
const bodyStreamCompressed = bodyStream.pipeThrough(new CompressionStream('gzip'));
|
|
42
|
+
return new Response(bodyStreamCompressed).blob();
|
|
43
|
+
}
|
|
44
|
+
export async function rpcCall(auth, rpcName, callName, version, bodyObject) {
|
|
45
|
+
const headers = {};
|
|
46
|
+
const body = await prepareBody(bodyObject);
|
|
47
|
+
if (body !== undefined) {
|
|
48
|
+
headers['content-type'] = 'application/json';
|
|
49
|
+
if (typeof body !== 'string') {
|
|
50
|
+
headers['content-encoding'] = 'gzip';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (auth !== null) {
|
|
54
|
+
headers['authorization'] = `${auth.userId}:${auth.tempPassword}`;
|
|
55
|
+
}
|
|
56
|
+
const u = url(rpcName, callName, version);
|
|
57
|
+
const resp = await fetch(u, {
|
|
58
|
+
method: 'post',
|
|
59
|
+
headers,
|
|
60
|
+
body
|
|
61
|
+
});
|
|
62
|
+
if (!resp.ok) {
|
|
63
|
+
if (resp.status === 401) {
|
|
64
|
+
throw new Unauthorized(u, resp.statusText);
|
|
65
|
+
}
|
|
66
|
+
if (resp.status === 403) {
|
|
67
|
+
throw new Forbidden(u, resp.statusText);
|
|
68
|
+
}
|
|
69
|
+
if (resp.status === 404) {
|
|
70
|
+
throw new NotFound(u, resp.statusText);
|
|
71
|
+
}
|
|
72
|
+
throw new HttpError('post', u, resp.status, resp.statusText);
|
|
73
|
+
}
|
|
74
|
+
return await resp.json();
|
|
75
|
+
}
|
|
@@ -3,8 +3,8 @@ import React from 'react';
|
|
|
3
3
|
import { useCallback, useState } from 'react';
|
|
4
4
|
import { useLocation, useNavigate } from 'react-router-dom';
|
|
5
5
|
import { z } from 'zod';
|
|
6
|
-
import { apiSignin, apiSignup } from '../api/auth';
|
|
7
|
-
import { useAuthState } from '../state/auth';
|
|
6
|
+
import { apiSignin, apiSignup } from '../api/auth.js';
|
|
7
|
+
import { useAuthState } from '../state/auth.js';
|
|
8
8
|
export function SignupSigninScreen({ appName }) {
|
|
9
9
|
const location = useLocation();
|
|
10
10
|
const navigate = useNavigate();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { create } from 'zustand';
|
|
2
2
|
import { persist } from 'zustand/middleware';
|
|
3
|
-
import { cacheLastResult } from './cached';
|
|
3
|
+
import { cacheLastResult } from './cached.js';
|
|
4
4
|
const AUTH_ID_KEY = 'AUTH_ID';
|
|
5
5
|
const AUTH_NAME_KEY = 'AUTH_NAME';
|
|
6
6
|
const AUTH_EMAIL_KEY = 'AUTH_EMAIL';
|
package/dist/client/sync.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DateTime } from 'luxon';
|
|
2
|
-
import { API_COMPARISON_OBJECT_SCHEMA_V0, ApiItemsResponseV0 } from '../shared/api/sync';
|
|
2
|
+
import { API_COMPARISON_OBJECT_SCHEMA_V0, ApiItemsResponseV0 } from '../shared/api/sync.js';
|
|
3
3
|
export declare function syncItems<T extends {
|
|
4
4
|
id: string;
|
|
5
5
|
lastModified: DateTime<true>;
|
package/dist/client/sync.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DateTime } from 'luxon';
|
|
2
|
-
import { toValid } from '../shared/utils/datetime';
|
|
2
|
+
import { toValid } from '../shared/utils/datetime.js';
|
|
3
3
|
export async function syncItems({ getRemoteLastModified, localItems, pushRemote, getRemote, pushLocal, lastSyncDate }) {
|
|
4
4
|
const remoteItems = (await getRemoteLastModified()).items;
|
|
5
5
|
const remoteItemsMap = Object.fromEntries(remoteItems.map(i => [i.id, toValid(DateTime.fromISO(i.lastModified, { zone: 'utc' }))]));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rlz-engine",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.35",
|
|
4
4
|
"description": "Deps and tools for my style of development",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "tsc",
|
|
@@ -17,13 +17,18 @@
|
|
|
17
17
|
"url": "git+https://github.com/rlz/rlz-engine.git"
|
|
18
18
|
},
|
|
19
19
|
"type": "module",
|
|
20
|
+
"exports": {
|
|
21
|
+
"./back/*": "./dist/back/*",
|
|
22
|
+
"./client/*": "./dist/client/*",
|
|
23
|
+
"./shared/*": "./dist/shared/*"
|
|
24
|
+
},
|
|
20
25
|
"files": [
|
|
21
26
|
"dist"
|
|
22
27
|
],
|
|
23
28
|
"devDependencies": {
|
|
24
|
-
"@stylistic/eslint-plugin": "^
|
|
29
|
+
"@stylistic/eslint-plugin": "^5.0.0",
|
|
25
30
|
"@types/luxon": "^3.4.2",
|
|
26
|
-
"@types/node": "^
|
|
31
|
+
"@types/node": "^24.0.5",
|
|
27
32
|
"@typescript-eslint/parser": "^8.16.0",
|
|
28
33
|
"eslint": "^9.16.0",
|
|
29
34
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
@@ -66,6 +71,7 @@
|
|
|
66
71
|
"uuidv7": "^1.0.2",
|
|
67
72
|
"zod": "^3.23.8",
|
|
68
73
|
"zod-to-json-schema": "^3.23.5",
|
|
74
|
+
"zod-to-ts": "^1.2.0",
|
|
69
75
|
"zustand": "^5.0.3"
|
|
70
76
|
}
|
|
71
77
|
}
|