remult 0.25.6-exp.4 → 0.25.6-exp.6

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.
@@ -29,6 +29,8 @@ export class PostgresDataProvider {
29
29
  this.wrapIdentifier = options.wrapIdentifier;
30
30
  if (!options?.wrapIdentifier && options?.caseInsensitiveIdentifiers)
31
31
  this.wrapIdentifier = (name) => name;
32
+ if (options.orderByNullsFirst)
33
+ this.orderByNullsFirst = options.orderByNullsFirst;
32
34
  if (options?.schema) {
33
35
  this.pool = new PostgresSchemaWrapper(pool, options.schema);
34
36
  }
@@ -42,6 +44,7 @@ export class PostgresDataProvider {
42
44
  var sb = new PostgresSchemaBuilder(db, this.options?.schema);
43
45
  await sb.ensureSchema(entities);
44
46
  }
47
+ orderByNullsFirst;
45
48
  async transaction(action) {
46
49
  let client = await this.pool.connect();
47
50
  try {
@@ -57,6 +60,7 @@ export class PostgresDataProvider {
57
60
  //@ts-ignore
58
61
  pool: client,
59
62
  wrapIdentifier: this.wrapIdentifier,
63
+ orderByNullsFirst: this.orderByNullsFirst,
60
64
  });
61
65
  await client.query('COMMIT');
62
66
  }
@@ -129,6 +133,7 @@ export async function createPostgresDataProvider(options) {
129
133
  wrapIdentifier: options.wrapIdentifier,
130
134
  caseInsensitiveIdentifiers: options.caseInsensitiveIdentifiers,
131
135
  schema: options.schema,
136
+ orderByNullsFirst: options.orderByNullsFirst,
132
137
  }));
133
138
  let remult = new Remult();
134
139
  remult.dataProvider = db;
@@ -0,0 +1,104 @@
1
+ import { Hono } from 'hono';
2
+ import { streamSSE } from 'hono/streaming';
3
+ import { createRemultServer, } from './server/index.js';
4
+ export function remultHono(options) {
5
+ let app = new Hono();
6
+ const api = createRemultServer(options, {
7
+ buildGenericRequestInfo: (c) => {
8
+ return {
9
+ method: c.req.method,
10
+ params: c.req.param(),
11
+ query: new Proxy(c.req, {
12
+ get: (target, prop) => {
13
+ const r = c.req.queries(prop);
14
+ if (r?.length == 1)
15
+ return r[0];
16
+ return r;
17
+ },
18
+ }),
19
+ url: c.req.url,
20
+ on: (e, do1) => {
21
+ c['_tempOnClose'](() => do1());
22
+ // c.req.on('close', do1)
23
+ },
24
+ };
25
+ },
26
+ getRequestBody: async (c) => {
27
+ return c.req.json();
28
+ },
29
+ });
30
+ let honoRouter = {
31
+ route(path) {
32
+ if (path.endsWith('*'))
33
+ path = path.substring(0, path.length - 1) + '.*';
34
+ let r = {
35
+ get(handler) {
36
+ app.get(path, honoHandler(handler));
37
+ return r;
38
+ },
39
+ post(handler) {
40
+ app.post(path, honoHandler(handler));
41
+ return r;
42
+ },
43
+ put(handler) {
44
+ app.put(path, honoHandler(handler));
45
+ return r;
46
+ },
47
+ delete(handler) {
48
+ app.delete(path, honoHandler(handler));
49
+ return r;
50
+ },
51
+ };
52
+ return r;
53
+ function honoHandler(handler) {
54
+ return (c) => {
55
+ return new Promise((res, rej) => {
56
+ try {
57
+ let result;
58
+ let sse;
59
+ const gRes = {
60
+ json: (data) => {
61
+ res(c.json(data));
62
+ },
63
+ status: (status) => {
64
+ result = c.status(status);
65
+ return gRes;
66
+ },
67
+ end: () => {
68
+ if (sse)
69
+ sse.close();
70
+ else
71
+ res(c.text(''));
72
+ },
73
+ send: (data) => {
74
+ res(c.html(data));
75
+ },
76
+ write: (data) => {
77
+ sse.write(data);
78
+ },
79
+ writeHead: (status, headers) => {
80
+ res(streamSSE(c, (s) => {
81
+ sse = s;
82
+ return new Promise((res) => {
83
+ c['_tempOnClose'] = (x) => sse.onAbort(() => x);
84
+ });
85
+ }));
86
+ },
87
+ };
88
+ handler(c, gRes, () => { });
89
+ }
90
+ catch (err) {
91
+ rej(err);
92
+ }
93
+ });
94
+ };
95
+ }
96
+ },
97
+ };
98
+ api.registerRouter(honoRouter);
99
+ return Object.assign(app, {
100
+ getRemult: (c) => api.getRemult(c),
101
+ openApiDoc: (options) => api.openApiDoc(options),
102
+ withRemult: async (c, what) => api.withRemultAsync(c, what),
103
+ });
104
+ }
@@ -249,6 +249,12 @@ class ActualSQLServerDataProvider {
249
249
  select += e.$dbNameOf(c.field);
250
250
  if (c.isDescending)
251
251
  select += ' desc';
252
+ if (this.sql._getSourceSql().orderByNullsFirst) {
253
+ if (c.isDescending)
254
+ select += ' nulls last';
255
+ else
256
+ select += ' nulls first';
257
+ }
252
258
  }
253
259
  }
254
260
  if (options.limit) {
@@ -89,12 +89,12 @@ export function createValueValidator(validate, defaultMessage) {
89
89
  }, defaultMessage);
90
90
  }
91
91
  export function createValueValidatorWithArgs(validate, defaultMessage) {
92
- const result = createValidatorWithArgs((_, e, args) => {
92
+ const result = createValidatorWithArgsInternal((_, e, args) => {
93
93
  if (e.value === undefined || e.value === null)
94
94
  return true;
95
95
  return validate(e.value, args);
96
96
  }, (_, e, args) => (typeof defaultMessage === 'function' && defaultMessage(args)) ||
97
- defaultMessage);
97
+ defaultMessage, true);
98
98
  return Object.assign((entity, e) => result(entity, e), {
99
99
  get defaultMessage() {
100
100
  return defaultMessage;
@@ -105,13 +105,21 @@ export function createValueValidatorWithArgs(validate, defaultMessage) {
105
105
  });
106
106
  }
107
107
  export function createValidatorWithArgs(validate, defaultMessage) {
108
+ return createValidatorWithArgsInternal(validate, defaultMessage);
109
+ }
110
+ function createValidatorWithArgsInternal(validate, defaultMessage, isValueValidator = false) {
108
111
  const result = (args, message) => async (entity, e) => {
109
112
  const valid = await validate(entity, e, args);
110
113
  if (typeof valid === 'string')
111
114
  e.error = valid;
112
115
  else if (!valid)
113
- e.error =
114
- message || defaultMessage
116
+ e.error = message
117
+ ? typeof message === 'function'
118
+ ? isValueValidator
119
+ ? message(args)
120
+ : message(entity, e, args)
121
+ : message
122
+ : defaultMessage
115
123
  ? typeof defaultMessage === 'function'
116
124
  ? defaultMessage(entity, e, args)
117
125
  : defaultMessage
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remult",
3
- "version": "0.25.6-exp.4",
3
+ "version": "0.25.6-exp.6",
4
4
  "description": "A CRUD framework for full-stack TypeScript",
5
5
  "homepage": "https://remult.dev",
6
6
  "repository": {
@@ -61,6 +61,11 @@
61
61
  "import": "./esm/remult-hapi.js",
62
62
  "types": "./remult-hapi.d.ts"
63
63
  },
64
+ "./remult-hono": {
65
+ "require": "./remult-hono.js",
66
+ "import": "./esm/remult-hono.js",
67
+ "types": "./remult-hono.d.ts"
68
+ },
64
69
  "./remult-fresh": {
65
70
  "require": "./remult-fresh.js",
66
71
  "import": "./esm/remult-fresh.js",
@@ -21,9 +21,11 @@ export declare class PostgresDataProvider implements SqlImplementation {
21
21
  wrapIdentifier?: (name: string) => string;
22
22
  caseInsensitiveIdentifiers?: boolean;
23
23
  schema?: string;
24
+ orderByNullsFirst?: boolean;
24
25
  });
25
26
  wrapIdentifier: (name: any) => any;
26
27
  ensureSchema(entities: EntityMetadata<any>[]): Promise<void>;
28
+ orderByNullsFirst?: boolean;
27
29
  transaction(action: (dataProvider: SqlImplementation) => Promise<void>): Promise<void>;
28
30
  }
29
31
  export interface PostgresCommandSource {
@@ -37,6 +39,7 @@ export declare function createPostgresDataProvider(options?: {
37
39
  wrapIdentifier?: (name: string) => string;
38
40
  caseInsensitiveIdentifiers?: boolean;
39
41
  schema?: string;
42
+ orderByNullsFirst?: boolean;
40
43
  }): Promise<SqlDatabase>;
41
44
  export declare function preparePostgresQueueStorage(sql: SqlDatabase): Promise<import("../server/expressBridge.js").EntityQueueStorage>;
42
45
  export declare class PostgresSchemaWrapper implements PostgresPool {
@@ -24,6 +24,8 @@ var PostgresDataProvider = /** @class */ (function () {
24
24
  this.wrapIdentifier = options.wrapIdentifier;
25
25
  if (!(options === null || options === void 0 ? void 0 : options.wrapIdentifier) && (options === null || options === void 0 ? void 0 : options.caseInsensitiveIdentifiers))
26
26
  this.wrapIdentifier = function (name) { return name; };
27
+ if (options.orderByNullsFirst)
28
+ this.orderByNullsFirst = options.orderByNullsFirst;
27
29
  if (options === null || options === void 0 ? void 0 : options.schema) {
28
30
  this.pool = new PostgresSchemaWrapper(pool, options.schema);
29
31
  }
@@ -89,6 +91,7 @@ var PostgresDataProvider = /** @class */ (function () {
89
91
  //@ts-ignore
90
92
  pool: client,
91
93
  wrapIdentifier: this.wrapIdentifier,
94
+ orderByNullsFirst: this.orderByNullsFirst,
92
95
  })];
93
96
  case 4:
94
97
  _a.sent();
@@ -185,6 +188,7 @@ function createPostgresDataProvider(options) {
185
188
  wrapIdentifier: options.wrapIdentifier,
186
189
  caseInsensitiveIdentifiers: options.caseInsensitiveIdentifiers,
187
190
  schema: options.schema,
191
+ orderByNullsFirst: options.orderByNullsFirst,
188
192
  }));
189
193
  remult = new context_js_1.Remult();
190
194
  remult.dataProvider = db;
@@ -0,0 +1,7 @@
1
+ import { type Context, type Env, Hono } from 'hono';
2
+ import type { BlankInput } from 'hono/types';
3
+ import { type RemultServerOptions, type RemultServerCore } from './server/index.js';
4
+ export declare function remultHono(options: RemultServerOptions<Context<Env, '', BlankInput>>): RemultHonoServer;
5
+ export type RemultHonoServer = Hono & RemultServerCore<Context<Env, '', BlankInput>> & {
6
+ withRemult: <T>(c: Context<Env, '', BlankInput>, what: () => Promise<T>) => Promise<T>;
7
+ };
package/remult-hono.js ADDED
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.remultHono = void 0;
4
+ var tslib_1 = require("tslib");
5
+ var hono_1 = require("hono");
6
+ var streaming_1 = require("hono/streaming");
7
+ var index_js_1 = require("./server/index.js");
8
+ function remultHono(options) {
9
+ var _this = this;
10
+ var app = new hono_1.Hono();
11
+ var api = (0, index_js_1.createRemultServer)(options, {
12
+ buildGenericRequestInfo: function (c) {
13
+ return {
14
+ method: c.req.method,
15
+ params: c.req.param(),
16
+ query: new Proxy(c.req, {
17
+ get: function (target, prop) {
18
+ var r = c.req.queries(prop);
19
+ if ((r === null || r === void 0 ? void 0 : r.length) == 1)
20
+ return r[0];
21
+ return r;
22
+ },
23
+ }),
24
+ url: c.req.url,
25
+ on: function (e, do1) {
26
+ c['_tempOnClose'](function () { return do1(); });
27
+ // c.req.on('close', do1)
28
+ },
29
+ };
30
+ },
31
+ getRequestBody: function (c) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
32
+ return tslib_1.__generator(this, function (_a) {
33
+ return [2 /*return*/, c.req.json()];
34
+ });
35
+ }); },
36
+ });
37
+ var honoRouter = {
38
+ route: function (path) {
39
+ if (path.endsWith('*'))
40
+ path = path.substring(0, path.length - 1) + '.*';
41
+ var r = {
42
+ get: function (handler) {
43
+ app.get(path, honoHandler(handler));
44
+ return r;
45
+ },
46
+ post: function (handler) {
47
+ app.post(path, honoHandler(handler));
48
+ return r;
49
+ },
50
+ put: function (handler) {
51
+ app.put(path, honoHandler(handler));
52
+ return r;
53
+ },
54
+ delete: function (handler) {
55
+ app.delete(path, honoHandler(handler));
56
+ return r;
57
+ },
58
+ };
59
+ return r;
60
+ function honoHandler(handler) {
61
+ return function (c) {
62
+ return new Promise(function (res, rej) {
63
+ try {
64
+ var result_1;
65
+ var sse_1;
66
+ var gRes_1 = {
67
+ json: function (data) {
68
+ res(c.json(data));
69
+ },
70
+ status: function (status) {
71
+ result_1 = c.status(status);
72
+ return gRes_1;
73
+ },
74
+ end: function () {
75
+ if (sse_1)
76
+ sse_1.close();
77
+ else
78
+ res(c.text(''));
79
+ },
80
+ send: function (data) {
81
+ res(c.html(data));
82
+ },
83
+ write: function (data) {
84
+ sse_1.write(data);
85
+ },
86
+ writeHead: function (status, headers) {
87
+ res((0, streaming_1.streamSSE)(c, function (s) {
88
+ sse_1 = s;
89
+ return new Promise(function (res) {
90
+ c['_tempOnClose'] = function (x) { return sse_1.onAbort(function () { return x; }); };
91
+ });
92
+ }));
93
+ },
94
+ };
95
+ handler(c, gRes_1, function () { });
96
+ }
97
+ catch (err) {
98
+ rej(err);
99
+ }
100
+ });
101
+ };
102
+ }
103
+ },
104
+ };
105
+ api.registerRouter(honoRouter);
106
+ return Object.assign(app, {
107
+ getRemult: function (c) { return api.getRemult(c); },
108
+ openApiDoc: function (options) { return api.openApiDoc(options); },
109
+ withRemult: function (c, what) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) {
110
+ return [2 /*return*/, api.withRemultAsync(c, what)];
111
+ }); }); },
112
+ });
113
+ }
114
+ exports.remultHono = remultHono;
@@ -386,6 +386,12 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
386
386
  select += e.$dbNameOf(c.field);
387
387
  if (c.isDescending)
388
388
  select += ' desc';
389
+ if (this.sql._getSourceSql().orderByNullsFirst) {
390
+ if (c.isDescending)
391
+ select += ' nulls last';
392
+ else
393
+ select += ' nulls first';
394
+ }
389
395
  }
390
396
  }
391
397
  catch (e_3_1) { e_3 = { error: e_3_1 }; }
@@ -6,6 +6,7 @@ export interface SqlImplementation extends HasWrapIdentifier {
6
6
  entityIsUsedForTheFirstTime(entity: EntityMetadata): Promise<void>;
7
7
  ensureSchema?(entities: EntityMetadata[]): Promise<void>;
8
8
  supportsJsonColumnType?: boolean;
9
+ orderByNullsFirst?: boolean;
9
10
  afterMutation?: VoidFunction;
10
11
  }
11
12
  export interface HasWrapIdentifier {
package/src/validators.js CHANGED
@@ -146,14 +146,14 @@ function createValueValidator(validate, defaultMessage) {
146
146
  }
147
147
  exports.createValueValidator = createValueValidator;
148
148
  function createValueValidatorWithArgs(validate, defaultMessage) {
149
- var result = createValidatorWithArgs(function (_, e, args) {
149
+ var result = createValidatorWithArgsInternal(function (_, e, args) {
150
150
  if (e.value === undefined || e.value === null)
151
151
  return true;
152
152
  return validate(e.value, args);
153
153
  }, function (_, e, args) {
154
154
  return (typeof defaultMessage === 'function' && defaultMessage(args)) ||
155
155
  defaultMessage;
156
- });
156
+ }, true);
157
157
  return Object.assign(function (entity, e) { return result(entity, e); }, {
158
158
  get defaultMessage() {
159
159
  return defaultMessage;
@@ -165,7 +165,12 @@ function createValueValidatorWithArgs(validate, defaultMessage) {
165
165
  }
166
166
  exports.createValueValidatorWithArgs = createValueValidatorWithArgs;
167
167
  function createValidatorWithArgs(validate, defaultMessage) {
168
+ return createValidatorWithArgsInternal(validate, defaultMessage);
169
+ }
170
+ exports.createValidatorWithArgs = createValidatorWithArgs;
171
+ function createValidatorWithArgsInternal(validate, defaultMessage, isValueValidator) {
168
172
  var _this = this;
173
+ if (isValueValidator === void 0) { isValueValidator = false; }
169
174
  var result = function (args, message) {
170
175
  return function (entity, e) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
171
176
  var valid;
@@ -177,8 +182,13 @@ function createValidatorWithArgs(validate, defaultMessage) {
177
182
  if (typeof valid === 'string')
178
183
  e.error = valid;
179
184
  else if (!valid)
180
- e.error =
181
- message || defaultMessage
185
+ e.error = message
186
+ ? typeof message === 'function'
187
+ ? isValueValidator
188
+ ? message(args)
189
+ : message(entity, e, args)
190
+ : message
191
+ : defaultMessage
182
192
  ? typeof defaultMessage === 'function'
183
193
  ? defaultMessage(entity, e, args)
184
194
  : defaultMessage
@@ -197,4 +207,3 @@ function createValidatorWithArgs(validate, defaultMessage) {
197
207
  },
198
208
  });
199
209
  }
200
- exports.createValidatorWithArgs = createValidatorWithArgs;