velocious 1.0.437 → 1.0.439
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/README.md +10 -0
- package/build/configuration.js +31 -0
- package/build/database/query/preloader/has-many.js +29 -1
- package/build/database/record/index.js +4 -2
- package/build/database/record/instance-relationships/has-many.js +6 -1
- package/build/database/record/relationships/base.js +9 -0
- package/build/environment-handlers/node/cli/commands/generate/base-models.js +4 -2
- package/build/frontend-model-controller.js +14 -6
- package/build/src/configuration.d.ts +26 -0
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +27 -1
- package/build/src/database/query/preloader/has-many.d.ts +8 -0
- package/build/src/database/query/preloader/has-many.d.ts.map +1 -1
- package/build/src/database/query/preloader/has-many.js +26 -2
- package/build/src/database/record/index.d.ts.map +1 -1
- package/build/src/database/record/index.js +5 -3
- package/build/src/database/record/instance-relationships/has-many.d.ts.map +1 -1
- package/build/src/database/record/instance-relationships/has-many.js +4 -2
- package/build/src/database/record/relationships/base.d.ts +8 -0
- package/build/src/database/record/relationships/base.d.ts.map +1 -1
- package/build/src/database/record/relationships/base.js +9 -1
- package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/generate/base-models.js +5 -3
- package/build/src/frontend-model-controller.d.ts +2 -2
- package/build/src/frontend-model-controller.d.ts.map +1 -1
- package/build/src/frontend-model-controller.js +15 -7
- package/build/src/utils/deburr-column-name.d.ts +11 -0
- package/build/src/utils/deburr-column-name.d.ts.map +1 -0
- package/build/src/utils/deburr-column-name.js +33 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/utils/deburr-column-name.js +37 -0
- package/package.json +1 -1
- package/src/configuration.js +31 -0
- package/src/database/query/preloader/has-many.js +29 -1
- package/src/database/record/index.js +4 -2
- package/src/database/record/instance-relationships/has-many.js +6 -1
- package/src/database/record/relationships/base.js +9 -0
- package/src/environment-handlers/node/cli/commands/generate/base-models.js +4 -2
- package/src/frontend-model-controller.js +14 -6
- package/src/utils/deburr-column-name.js +37 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transliterates German umlauts (and ß) in a database column name to ASCII so generated and runtime
|
|
3
|
+
* attribute names stay ASCII regardless of whether the column uses the umlaut ("Plätze") or already
|
|
4
|
+
* transliterated ("Plaetze") spelling. Both then map to the same attribute (e.g. "plaetzeVerkauft"),
|
|
5
|
+
* which keeps generated model bases consistent with code that references the ASCII attribute names.
|
|
6
|
+
* The raw column name is still used for the actual SQL, so the underlying column is untouched.
|
|
7
|
+
* @param {string} columnName - Raw database column name.
|
|
8
|
+
* @returns {string} - ASCII-transliterated column name.
|
|
9
|
+
*/
|
|
10
|
+
export default function deburrColumnName(columnName: string): string;
|
|
11
|
+
//# sourceMappingURL=deburr-column-name.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deburr-column-name.d.ts","sourceRoot":"","sources":["../../../src/utils/deburr-column-name.js"],"names":[],"mappings":"AAaA;;;;;;;;GAQG;AACH,qDAHW,MAAM,GACJ,MAAM,CAgBlB"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/** @type {Array<[RegExp, string]>} */
|
|
3
|
+
const UMLAUT_REPLACEMENTS = [
|
|
4
|
+
[/Ä/g, "Ae"],
|
|
5
|
+
[/Ö/g, "Oe"],
|
|
6
|
+
[/Ü/g, "Ue"],
|
|
7
|
+
[/ä/g, "ae"],
|
|
8
|
+
[/ö/g, "oe"],
|
|
9
|
+
[/ü/g, "ue"],
|
|
10
|
+
[/ß/g, "ss"]
|
|
11
|
+
];
|
|
12
|
+
/**
|
|
13
|
+
* Transliterates German umlauts (and ß) in a database column name to ASCII so generated and runtime
|
|
14
|
+
* attribute names stay ASCII regardless of whether the column uses the umlaut ("Plätze") or already
|
|
15
|
+
* transliterated ("Plaetze") spelling. Both then map to the same attribute (e.g. "plaetzeVerkauft"),
|
|
16
|
+
* which keeps generated model bases consistent with code that references the ASCII attribute names.
|
|
17
|
+
* The raw column name is still used for the actual SQL, so the underlying column is untouched.
|
|
18
|
+
* @param {string} columnName - Raw database column name.
|
|
19
|
+
* @returns {string} - ASCII-transliterated column name.
|
|
20
|
+
*/
|
|
21
|
+
export default function deburrColumnName(columnName) {
|
|
22
|
+
let result = columnName;
|
|
23
|
+
for (const [pattern, replacement] of UMLAUT_REPLACEMENTS) {
|
|
24
|
+
result = result.replace(pattern, replacement);
|
|
25
|
+
}
|
|
26
|
+
// An all-caps acronym column (e.g. "IP", "EA") would camelize to "iP"/"eA" because only the first
|
|
27
|
+
// letter is lowercased. Down-case columns that contain no lowercase letters so "IP" becomes "ip".
|
|
28
|
+
if (!/[a-z]/.test(result)) {
|
|
29
|
+
result = result.toLowerCase();
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVidXJyLWNvbHVtbi1uYW1lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3V0aWxzL2RlYnVyci1jb2x1bW4tbmFtZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosc0NBQXNDO0FBQ3RDLE1BQU0sbUJBQW1CLEdBQUc7SUFDMUIsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDO0lBQ1osQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDO0lBQ1osQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDO0lBQ1osQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDO0lBQ1osQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDO0lBQ1osQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDO0lBQ1osQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDO0NBQ2IsQ0FBQTtBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sVUFBVSxnQkFBZ0IsQ0FBQyxVQUFVO0lBQ2pELElBQUksTUFBTSxHQUFHLFVBQVUsQ0FBQTtJQUV2QixLQUFLLE1BQU0sQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDLElBQUksbUJBQW1CLEVBQUUsQ0FBQztRQUN6RCxNQUFNLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDLENBQUE7SUFDL0MsQ0FBQztJQUVELGtHQUFrRztJQUNsRyxrR0FBa0c7SUFDbEcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUMxQixNQUFNLEdBQUcsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFBO0lBQy9CLENBQUM7SUFFRCxPQUFPLE1BQU0sQ0FBQTtBQUNmLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuLyoqIEB0eXBlIHtBcnJheTxbUmVnRXhwLCBzdHJpbmddPn0gKi9cbmNvbnN0IFVNTEFVVF9SRVBMQUNFTUVOVFMgPSBbXG4gIFsvw4QvZywgXCJBZVwiXSxcbiAgWy/Dli9nLCBcIk9lXCJdLFxuICBbL8OcL2csIFwiVWVcIl0sXG4gIFsvw6QvZywgXCJhZVwiXSxcbiAgWy/Dti9nLCBcIm9lXCJdLFxuICBbL8O8L2csIFwidWVcIl0sXG4gIFsvw58vZywgXCJzc1wiXVxuXVxuXG4vKipcbiAqIFRyYW5zbGl0ZXJhdGVzIEdlcm1hbiB1bWxhdXRzIChhbmQgw58pIGluIGEgZGF0YWJhc2UgY29sdW1uIG5hbWUgdG8gQVNDSUkgc28gZ2VuZXJhdGVkIGFuZCBydW50aW1lXG4gKiBhdHRyaWJ1dGUgbmFtZXMgc3RheSBBU0NJSSByZWdhcmRsZXNzIG9mIHdoZXRoZXIgdGhlIGNvbHVtbiB1c2VzIHRoZSB1bWxhdXQgKFwiUGzDpHR6ZVwiKSBvciBhbHJlYWR5XG4gKiB0cmFuc2xpdGVyYXRlZCAoXCJQbGFldHplXCIpIHNwZWxsaW5nLiBCb3RoIHRoZW4gbWFwIHRvIHRoZSBzYW1lIGF0dHJpYnV0ZSAoZS5nLiBcInBsYWV0emVWZXJrYXVmdFwiKSxcbiAqIHdoaWNoIGtlZXBzIGdlbmVyYXRlZCBtb2RlbCBiYXNlcyBjb25zaXN0ZW50IHdpdGggY29kZSB0aGF0IHJlZmVyZW5jZXMgdGhlIEFTQ0lJIGF0dHJpYnV0ZSBuYW1lcy5cbiAqIFRoZSByYXcgY29sdW1uIG5hbWUgaXMgc3RpbGwgdXNlZCBmb3IgdGhlIGFjdHVhbCBTUUwsIHNvIHRoZSB1bmRlcmx5aW5nIGNvbHVtbiBpcyB1bnRvdWNoZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gY29sdW1uTmFtZSAtIFJhdyBkYXRhYmFzZSBjb2x1bW4gbmFtZS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IC0gQVNDSUktdHJhbnNsaXRlcmF0ZWQgY29sdW1uIG5hbWUuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGRlYnVyckNvbHVtbk5hbWUoY29sdW1uTmFtZSkge1xuICBsZXQgcmVzdWx0ID0gY29sdW1uTmFtZVxuXG4gIGZvciAoY29uc3QgW3BhdHRlcm4sIHJlcGxhY2VtZW50XSBvZiBVTUxBVVRfUkVQTEFDRU1FTlRTKSB7XG4gICAgcmVzdWx0ID0gcmVzdWx0LnJlcGxhY2UocGF0dGVybiwgcmVwbGFjZW1lbnQpXG4gIH1cblxuICAvLyBBbiBhbGwtY2FwcyBhY3JvbnltIGNvbHVtbiAoZS5nLiBcIklQXCIsIFwiRUFcIikgd291bGQgY2FtZWxpemUgdG8gXCJpUFwiL1wiZUFcIiBiZWNhdXNlIG9ubHkgdGhlIGZpcnN0XG4gIC8vIGxldHRlciBpcyBsb3dlcmNhc2VkLiBEb3duLWNhc2UgY29sdW1ucyB0aGF0IGNvbnRhaW4gbm8gbG93ZXJjYXNlIGxldHRlcnMgc28gXCJJUFwiIGJlY29tZXMgXCJpcFwiLlxuICBpZiAoIS9bYS16XS8udGVzdChyZXN1bHQpKSB7XG4gICAgcmVzdWx0ID0gcmVzdWx0LnRvTG93ZXJDYXNlKClcbiAgfVxuXG4gIHJldHVybiByZXN1bHRcbn1cbiJdfQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../index.js","../bin/velocious.js","../src/application.js","../src/configuration-resolver.js","../src/configuration-types.js","../src/configuration.js","../src/controller.js","../src/current-configuration.js","../src/current.js","../src/error-logger.js","../src/frontend-model-controller.js","../src/initializer.js","../src/logger.js","../src/mailer.js","../src/record-payload-values.js","../src/velocious-error.js","../src/authorization/ability.js","../src/authorization/base-resource.js","../src/background-jobs/client.js","../src/background-jobs/cron-expression.js","../src/background-jobs/forked-runner-child.js","../src/background-jobs/job-record.js","../src/background-jobs/job-registry.js","../src/background-jobs/job-runner.js","../src/background-jobs/job.js","../src/background-jobs/json-socket.js","../src/background-jobs/main.js","../src/background-jobs/normalize-error.js","../src/background-jobs/scheduler.js","../src/background-jobs/socket-request.js","../src/background-jobs/status-reporter.js","../src/background-jobs/store.js","../src/background-jobs/types.js","../src/background-jobs/worker.js","../src/background-jobs/web/authorization.js","../src/background-jobs/web/controller.js","../src/background-jobs/web/index.js","../src/background-jobs/web/path-matcher.js","../src/background-jobs/web/registry.js","../src/beacon/client.js","../src/beacon/in-process-broker.js","../src/beacon/in-process-client.js","../src/beacon/server.js","../src/beacon/types.js","../src/cli/base-command.js","../src/cli/browser-cli.js","../src/cli/index.js","../src/cli/tenant-database-command-helper.js","../src/cli/use-browser-cli.js","../src/cli/commands/background-jobs-main.js","../src/cli/commands/background-jobs-runner.js","../src/cli/commands/background-jobs-worker.js","../src/cli/commands/beacon.js","../src/cli/commands/console.js","../src/cli/commands/init.js","../src/cli/commands/routes.js","../src/cli/commands/run-script.js","../src/cli/commands/runner.js","../src/cli/commands/server.js","../src/cli/commands/test.js","../src/cli/commands/db/base-command.js","../src/cli/commands/db/create.js","../src/cli/commands/db/drop.js","../src/cli/commands/db/migrate.js","../src/cli/commands/db/reset.js","../src/cli/commands/db/rollback.js","../src/cli/commands/db/seed.js","../src/cli/commands/db/schema/dump.js","../src/cli/commands/db/schema/load.js","../src/cli/commands/db/tenants/check.js","../src/cli/commands/db/tenants/create.js","../src/cli/commands/db/tenants/migrate.js","../src/cli/commands/destroy/migration.js","../src/cli/commands/generate/base-models.js","../src/cli/commands/generate/frontend-models.js","../src/cli/commands/generate/migration.js","../src/cli/commands/generate/model.js","../src/database/annotations-async-hooks.js","../src/database/annotations.js","../src/database/handler.js","../src/database/initializer-from-require-context.js","../src/database/migrator.js","../src/database/use-database.js","../src/database/drivers/base-column.js","../src/database/drivers/base-columns-index.js","../src/database/drivers/base-foreign-key.js","../src/database/drivers/base-table.js","../src/database/drivers/base.js","../src/database/drivers/mssql/column.js","../src/database/drivers/mssql/columns-index.js","../src/database/drivers/mssql/connect-connection.js","../src/database/drivers/mssql/foreign-key.js","../src/database/drivers/mssql/index.js","../src/database/drivers/mssql/options.js","../src/database/drivers/mssql/query-parser.js","../src/database/drivers/mssql/structure-sql.js","../src/database/drivers/mssql/table.js","../src/database/drivers/mssql/sql/alter-table.js","../src/database/drivers/mssql/sql/create-database.js","../src/database/drivers/mssql/sql/create-index.js","../src/database/drivers/mssql/sql/create-table.js","../src/database/drivers/mssql/sql/delete.js","../src/database/drivers/mssql/sql/drop-database.js","../src/database/drivers/mssql/sql/drop-table.js","../src/database/drivers/mssql/sql/insert.js","../src/database/drivers/mssql/sql/update.js","../src/database/drivers/mssql/sql/upsert.js","../src/database/drivers/mysql/column.js","../src/database/drivers/mysql/columns-index.js","../src/database/drivers/mysql/foreign-key.js","../src/database/drivers/mysql/index.js","../src/database/drivers/mysql/options.js","../src/database/drivers/mysql/query-parser.js","../src/database/drivers/mysql/query.js","../src/database/drivers/mysql/structure-sql.js","../src/database/drivers/mysql/table.js","../src/database/drivers/mysql/sql/alter-table.js","../src/database/drivers/mysql/sql/create-database.js","../src/database/drivers/mysql/sql/create-index.js","../src/database/drivers/mysql/sql/create-table.js","../src/database/drivers/mysql/sql/delete.js","../src/database/drivers/mysql/sql/drop-database.js","../src/database/drivers/mysql/sql/drop-table.js","../src/database/drivers/mysql/sql/insert.js","../src/database/drivers/mysql/sql/update.js","../src/database/drivers/mysql/sql/upsert.js","../src/database/drivers/pgsql/column.js","../src/database/drivers/pgsql/columns-index.js","../src/database/drivers/pgsql/foreign-key.js","../src/database/drivers/pgsql/index.js","../src/database/drivers/pgsql/options.js","../src/database/drivers/pgsql/query-parser.js","../src/database/drivers/pgsql/structure-sql.js","../src/database/drivers/pgsql/table.js","../src/database/drivers/pgsql/sql/alter-table.js","../src/database/drivers/pgsql/sql/create-database.js","../src/database/drivers/pgsql/sql/create-index.js","../src/database/drivers/pgsql/sql/create-table.js","../src/database/drivers/pgsql/sql/delete.js","../src/database/drivers/pgsql/sql/drop-database.js","../src/database/drivers/pgsql/sql/drop-table.js","../src/database/drivers/pgsql/sql/insert.js","../src/database/drivers/pgsql/sql/update.js","../src/database/drivers/pgsql/sql/upsert.js","../src/database/drivers/sqlite/base.js","../src/database/drivers/sqlite/column.js","../src/database/drivers/sqlite/columns-index.js","../src/database/drivers/sqlite/connection-sql-js.js","../src/database/drivers/sqlite/foreign-key.js","../src/database/drivers/sqlite/index.js","../src/database/drivers/sqlite/index.native.js","../src/database/drivers/sqlite/index.web.js","../src/database/drivers/sqlite/options.js","../src/database/drivers/sqlite/query-parser.js","../src/database/drivers/sqlite/query.js","../src/database/drivers/sqlite/query.native.js","../src/database/drivers/sqlite/query.web.js","../src/database/drivers/sqlite/structure-sql.js","../src/database/drivers/sqlite/table-rebuilder.js","../src/database/drivers/sqlite/table.js","../src/database/drivers/sqlite/sql/alter-table.js","../src/database/drivers/sqlite/sql/create-index.js","../src/database/drivers/sqlite/sql/create-table.js","../src/database/drivers/sqlite/sql/delete.js","../src/database/drivers/sqlite/sql/drop-table.js","../src/database/drivers/sqlite/sql/insert.js","../src/database/drivers/sqlite/sql/update.js","../src/database/drivers/sqlite/sql/upsert.js","../src/database/drivers/structure-sql/utils.js","../src/database/migration/index.js","../src/database/migrator/files-finder.js","../src/database/migrator/types.js","../src/database/pool/async-tracked-multi-connection.js","../src/database/pool/base-methods-forward.js","../src/database/pool/base.js","../src/database/pool/single-multi-use.js","../src/database/query/alter-table-base.js","../src/database/query/base.js","../src/database/query/create-database-base.js","../src/database/query/create-index-base.js","../src/database/query/create-table-base.js","../src/database/query/delete-base.js","../src/database/query/drop-database-base.js","../src/database/query/drop-table-base.js","../src/database/query/from-base.js","../src/database/query/from-plain.js","../src/database/query/from-table.js","../src/database/query/index.js","../src/database/query/insert-base.js","../src/database/query/join-base.js","../src/database/query/join-object.js","../src/database/query/join-plain.js","../src/database/query/join-tracker.js","../src/database/query/model-class-query.js","../src/database/query/order-base.js","../src/database/query/order-column.js","../src/database/query/order-plain.js","../src/database/query/preloader.js","../src/database/query/query-data.js","../src/database/query/select-base.js","../src/database/query/select-plain.js","../src/database/query/select-table-and-column.js","../src/database/query/update-base.js","../src/database/query/upsert-base.js","../src/database/query/where-base.js","../src/database/query/where-combinator.js","../src/database/query/where-hash.js","../src/database/query/where-model-class-hash.js","../src/database/query/where-not.js","../src/database/query/where-plain.js","../src/database/query/with-count.js","../src/database/query/preloader/belongs-to.js","../src/database/query/preloader/ensure-model-class-initialized.js","../src/database/query/preloader/has-many.js","../src/database/query/preloader/has-one.js","../src/database/query/preloader/selection.js","../src/database/query-parser/base-query-parser.js","../src/database/query-parser/from-parser.js","../src/database/query-parser/group-parser.js","../src/database/query-parser/joins-parser.js","../src/database/query-parser/limit-parser.js","../src/database/query-parser/options.js","../src/database/query-parser/order-parser.js","../src/database/query-parser/select-parser.js","../src/database/query-parser/where-parser.js","../src/database/record/acts-as-list.js","../src/database/record/index.js","../src/database/record/record-not-found-error.js","../src/database/record/state-machine.js","../src/database/record/user-module.js","../src/database/record/attachments/download.js","../src/database/record/attachments/handle.js","../src/database/record/attachments/normalize-input.js","../src/database/record/attachments/store.js","../src/database/record/attachments/storage-drivers/filesystem.js","../src/database/record/attachments/storage-drivers/native.js","../src/database/record/attachments/storage-drivers/s3.js","../src/database/record/instance-relationships/base.js","../src/database/record/instance-relationships/belongs-to.js","../src/database/record/instance-relationships/has-many.js","../src/database/record/instance-relationships/has-one.js","../src/database/record/relationships/base.js","../src/database/record/relationships/belongs-to.js","../src/database/record/relationships/has-many.js","../src/database/record/relationships/has-one.js","../src/database/record/validators/base.js","../src/database/record/validators/format.js","../src/database/record/validators/presence.js","../src/database/record/validators/uniqueness.js","../src/database/table-data/index.js","../src/database/table-data/table-column.js","../src/database/table-data/table-foreign-key.js","../src/database/table-data/table-index.js","../src/database/table-data/table-reference.js","../src/environment-handlers/base.js","../src/environment-handlers/browser.js","../src/environment-handlers/node.js","../src/environment-handlers/node/cli/commands/background-jobs-main.js","../src/environment-handlers/node/cli/commands/background-jobs-runner.js","../src/environment-handlers/node/cli/commands/background-jobs-worker.js","../src/environment-handlers/node/cli/commands/beacon.js","../src/environment-handlers/node/cli/commands/cli-command-context.js","../src/environment-handlers/node/cli/commands/console.js","../src/environment-handlers/node/cli/commands/init.js","../src/environment-handlers/node/cli/commands/routes.js","../src/environment-handlers/node/cli/commands/run-script.js","../src/environment-handlers/node/cli/commands/runner.js","../src/environment-handlers/node/cli/commands/server.js","../src/environment-handlers/node/cli/commands/test.js","../src/environment-handlers/node/cli/commands/db/seed.js","../src/environment-handlers/node/cli/commands/db/schema/dump.js","../src/environment-handlers/node/cli/commands/db/schema/load.js","../src/environment-handlers/node/cli/commands/destroy/migration.js","../src/environment-handlers/node/cli/commands/generate/base-models.js","../src/environment-handlers/node/cli/commands/generate/frontend-models.js","../src/environment-handlers/node/cli/commands/generate/migration.js","../src/environment-handlers/node/cli/commands/generate/model.js","../src/frontend-model-resource/base-resource.js","../src/frontend-models/base.js","../src/frontend-models/clear-pending-debounced-callback.js","../src/frontend-models/event-hook-models.js","../src/frontend-models/model-registry.js","../src/frontend-models/outgoing-event-buffer.js","../src/frontend-models/preloader.js","../src/frontend-models/query.js","../src/frontend-models/resource-config-validation.js","../src/frontend-models/resource-definition.js","../src/frontend-models/transport-serialization.js","../src/frontend-models/use-created-event.js","../src/frontend-models/use-destroyed-event.js","../src/frontend-models/use-model-class-event.js","../src/frontend-models/use-updated-event.js","../src/frontend-models/websocket-channel.js","../src/frontend-models/websocket-publishers.js","../src/http-client/header.js","../src/http-client/index.js","../src/http-client/request.js","../src/http-client/response.js","../src/http-client/websocket-client.js","../src/http-server/cookie.js","../src/http-server/development-reloader.js","../src/http-server/index.js","../src/http-server/remote-address.js","../src/http-server/server-client.js","../src/http-server/server-lock.js","../src/http-server/websocket-channel-subscribers.js","../src/http-server/websocket-channel.js","../src/http-server/websocket-connection.js","../src/http-server/websocket-event-log-store.js","../src/http-server/websocket-events-host.js","../src/http-server/websocket-events.js","../src/http-server/client/index.js","../src/http-server/client/params-to-object.js","../src/http-server/client/request-parser.js","../src/http-server/client/request-runner.js","../src/http-server/client/request-timing.js","../src/http-server/client/request.js","../src/http-server/client/response.js","../src/http-server/client/websocket-request.js","../src/http-server/client/websocket-session.js","../src/http-server/client/request-buffer/form-data-part.js","../src/http-server/client/request-buffer/header.js","../src/http-server/client/request-buffer/index.js","../src/http-server/client/uploaded-file/memory-uploaded-file.js","../src/http-server/client/uploaded-file/temporary-uploaded-file.js","../src/http-server/client/uploaded-file/uploaded-file.js","../src/http-server/worker-handler/channel-subscriber-dispatch.js","../src/http-server/worker-handler/in-process.js","../src/http-server/worker-handler/index.js","../src/http-server/worker-handler/worker-script.js","../src/http-server/worker-handler/worker-thread.js","../src/jobs/mail-delivery.js","../src/logger/base-logger.js","../src/logger/console-logger.js","../src/logger/file-logger.js","../src/logger/outputs/array-output.js","../src/logger/outputs/console-output.js","../src/logger/outputs/file-output.js","../src/logger/outputs/stdout-output.js","../src/mailer/base.js","../src/mailer/delivery.js","../src/mailer/index.js","../src/mailer/backends/smtp.js","../src/plugins/sqljs-wasm-route-controller.js","../src/plugins/sqljs-wasm-route.js","../src/routes/app-routes.js","../src/routes/base-route.js","../src/routes/basic-route.js","../src/routes/get-route.js","../src/routes/index.js","../src/routes/namespace-route.js","../src/routes/plugin-routes.js","../src/routes/post-route.js","../src/routes/resolver.js","../src/routes/resource-route.js","../src/routes/root-route.js","../src/routes/built-in/debug/controller.js","../src/routes/built-in/errors/controller.js","../src/routes/hooks/frontend-model-command-route-hook.js","../src/testing/base-expect.js","../src/testing/browser-frontend-model-event-hook-scenarios.js","../src/testing/browser-test-app.js","../src/testing/expect-to-change.js","../src/testing/expect-utils.js","../src/testing/expect.js","../src/testing/request-client.js","../src/testing/test-files-finder.js","../src/testing/test-filter-parser.js","../src/testing/test-runner.js","../src/testing/test-suite-splitter.js","../src/testing/test.js","../src/types/external-modules.d.ts","../src/utils/backtrace-cleaner-node.js","../src/utils/backtrace-cleaner.js","../src/utils/ensure-error.js","../src/utils/event-emitter.js","../src/utils/file-exists.js","../src/utils/format-value.js","../src/utils/model-scope.js","../src/utils/nest-callbacks.js","../src/utils/plain-object.js","../src/utils/ransack.js","../src/utils/rest-args-error.js","../src/utils/singularize-model-name.js","../src/utils/split-sql-statements.js","../src/utils/to-import-specifier.js","../src/utils/with-tracked-stack-async-hooks.js","../src/utils/with-tracked-stack.js"],"version":"6.0.3"}
|
|
1
|
+
{"root":["../index.js","../bin/velocious.js","../src/application.js","../src/configuration-resolver.js","../src/configuration-types.js","../src/configuration.js","../src/controller.js","../src/current-configuration.js","../src/current.js","../src/error-logger.js","../src/frontend-model-controller.js","../src/initializer.js","../src/logger.js","../src/mailer.js","../src/record-payload-values.js","../src/velocious-error.js","../src/authorization/ability.js","../src/authorization/base-resource.js","../src/background-jobs/client.js","../src/background-jobs/cron-expression.js","../src/background-jobs/forked-runner-child.js","../src/background-jobs/job-record.js","../src/background-jobs/job-registry.js","../src/background-jobs/job-runner.js","../src/background-jobs/job.js","../src/background-jobs/json-socket.js","../src/background-jobs/main.js","../src/background-jobs/normalize-error.js","../src/background-jobs/scheduler.js","../src/background-jobs/socket-request.js","../src/background-jobs/status-reporter.js","../src/background-jobs/store.js","../src/background-jobs/types.js","../src/background-jobs/worker.js","../src/background-jobs/web/authorization.js","../src/background-jobs/web/controller.js","../src/background-jobs/web/index.js","../src/background-jobs/web/path-matcher.js","../src/background-jobs/web/registry.js","../src/beacon/client.js","../src/beacon/in-process-broker.js","../src/beacon/in-process-client.js","../src/beacon/server.js","../src/beacon/types.js","../src/cli/base-command.js","../src/cli/browser-cli.js","../src/cli/index.js","../src/cli/tenant-database-command-helper.js","../src/cli/use-browser-cli.js","../src/cli/commands/background-jobs-main.js","../src/cli/commands/background-jobs-runner.js","../src/cli/commands/background-jobs-worker.js","../src/cli/commands/beacon.js","../src/cli/commands/console.js","../src/cli/commands/init.js","../src/cli/commands/routes.js","../src/cli/commands/run-script.js","../src/cli/commands/runner.js","../src/cli/commands/server.js","../src/cli/commands/test.js","../src/cli/commands/db/base-command.js","../src/cli/commands/db/create.js","../src/cli/commands/db/drop.js","../src/cli/commands/db/migrate.js","../src/cli/commands/db/reset.js","../src/cli/commands/db/rollback.js","../src/cli/commands/db/seed.js","../src/cli/commands/db/schema/dump.js","../src/cli/commands/db/schema/load.js","../src/cli/commands/db/tenants/check.js","../src/cli/commands/db/tenants/create.js","../src/cli/commands/db/tenants/migrate.js","../src/cli/commands/destroy/migration.js","../src/cli/commands/generate/base-models.js","../src/cli/commands/generate/frontend-models.js","../src/cli/commands/generate/migration.js","../src/cli/commands/generate/model.js","../src/database/annotations-async-hooks.js","../src/database/annotations.js","../src/database/handler.js","../src/database/initializer-from-require-context.js","../src/database/migrator.js","../src/database/use-database.js","../src/database/drivers/base-column.js","../src/database/drivers/base-columns-index.js","../src/database/drivers/base-foreign-key.js","../src/database/drivers/base-table.js","../src/database/drivers/base.js","../src/database/drivers/mssql/column.js","../src/database/drivers/mssql/columns-index.js","../src/database/drivers/mssql/connect-connection.js","../src/database/drivers/mssql/foreign-key.js","../src/database/drivers/mssql/index.js","../src/database/drivers/mssql/options.js","../src/database/drivers/mssql/query-parser.js","../src/database/drivers/mssql/structure-sql.js","../src/database/drivers/mssql/table.js","../src/database/drivers/mssql/sql/alter-table.js","../src/database/drivers/mssql/sql/create-database.js","../src/database/drivers/mssql/sql/create-index.js","../src/database/drivers/mssql/sql/create-table.js","../src/database/drivers/mssql/sql/delete.js","../src/database/drivers/mssql/sql/drop-database.js","../src/database/drivers/mssql/sql/drop-table.js","../src/database/drivers/mssql/sql/insert.js","../src/database/drivers/mssql/sql/update.js","../src/database/drivers/mssql/sql/upsert.js","../src/database/drivers/mysql/column.js","../src/database/drivers/mysql/columns-index.js","../src/database/drivers/mysql/foreign-key.js","../src/database/drivers/mysql/index.js","../src/database/drivers/mysql/options.js","../src/database/drivers/mysql/query-parser.js","../src/database/drivers/mysql/query.js","../src/database/drivers/mysql/structure-sql.js","../src/database/drivers/mysql/table.js","../src/database/drivers/mysql/sql/alter-table.js","../src/database/drivers/mysql/sql/create-database.js","../src/database/drivers/mysql/sql/create-index.js","../src/database/drivers/mysql/sql/create-table.js","../src/database/drivers/mysql/sql/delete.js","../src/database/drivers/mysql/sql/drop-database.js","../src/database/drivers/mysql/sql/drop-table.js","../src/database/drivers/mysql/sql/insert.js","../src/database/drivers/mysql/sql/update.js","../src/database/drivers/mysql/sql/upsert.js","../src/database/drivers/pgsql/column.js","../src/database/drivers/pgsql/columns-index.js","../src/database/drivers/pgsql/foreign-key.js","../src/database/drivers/pgsql/index.js","../src/database/drivers/pgsql/options.js","../src/database/drivers/pgsql/query-parser.js","../src/database/drivers/pgsql/structure-sql.js","../src/database/drivers/pgsql/table.js","../src/database/drivers/pgsql/sql/alter-table.js","../src/database/drivers/pgsql/sql/create-database.js","../src/database/drivers/pgsql/sql/create-index.js","../src/database/drivers/pgsql/sql/create-table.js","../src/database/drivers/pgsql/sql/delete.js","../src/database/drivers/pgsql/sql/drop-database.js","../src/database/drivers/pgsql/sql/drop-table.js","../src/database/drivers/pgsql/sql/insert.js","../src/database/drivers/pgsql/sql/update.js","../src/database/drivers/pgsql/sql/upsert.js","../src/database/drivers/sqlite/base.js","../src/database/drivers/sqlite/column.js","../src/database/drivers/sqlite/columns-index.js","../src/database/drivers/sqlite/connection-sql-js.js","../src/database/drivers/sqlite/foreign-key.js","../src/database/drivers/sqlite/index.js","../src/database/drivers/sqlite/index.native.js","../src/database/drivers/sqlite/index.web.js","../src/database/drivers/sqlite/options.js","../src/database/drivers/sqlite/query-parser.js","../src/database/drivers/sqlite/query.js","../src/database/drivers/sqlite/query.native.js","../src/database/drivers/sqlite/query.web.js","../src/database/drivers/sqlite/structure-sql.js","../src/database/drivers/sqlite/table-rebuilder.js","../src/database/drivers/sqlite/table.js","../src/database/drivers/sqlite/sql/alter-table.js","../src/database/drivers/sqlite/sql/create-index.js","../src/database/drivers/sqlite/sql/create-table.js","../src/database/drivers/sqlite/sql/delete.js","../src/database/drivers/sqlite/sql/drop-table.js","../src/database/drivers/sqlite/sql/insert.js","../src/database/drivers/sqlite/sql/update.js","../src/database/drivers/sqlite/sql/upsert.js","../src/database/drivers/structure-sql/utils.js","../src/database/migration/index.js","../src/database/migrator/files-finder.js","../src/database/migrator/types.js","../src/database/pool/async-tracked-multi-connection.js","../src/database/pool/base-methods-forward.js","../src/database/pool/base.js","../src/database/pool/single-multi-use.js","../src/database/query/alter-table-base.js","../src/database/query/base.js","../src/database/query/create-database-base.js","../src/database/query/create-index-base.js","../src/database/query/create-table-base.js","../src/database/query/delete-base.js","../src/database/query/drop-database-base.js","../src/database/query/drop-table-base.js","../src/database/query/from-base.js","../src/database/query/from-plain.js","../src/database/query/from-table.js","../src/database/query/index.js","../src/database/query/insert-base.js","../src/database/query/join-base.js","../src/database/query/join-object.js","../src/database/query/join-plain.js","../src/database/query/join-tracker.js","../src/database/query/model-class-query.js","../src/database/query/order-base.js","../src/database/query/order-column.js","../src/database/query/order-plain.js","../src/database/query/preloader.js","../src/database/query/query-data.js","../src/database/query/select-base.js","../src/database/query/select-plain.js","../src/database/query/select-table-and-column.js","../src/database/query/update-base.js","../src/database/query/upsert-base.js","../src/database/query/where-base.js","../src/database/query/where-combinator.js","../src/database/query/where-hash.js","../src/database/query/where-model-class-hash.js","../src/database/query/where-not.js","../src/database/query/where-plain.js","../src/database/query/with-count.js","../src/database/query/preloader/belongs-to.js","../src/database/query/preloader/ensure-model-class-initialized.js","../src/database/query/preloader/has-many.js","../src/database/query/preloader/has-one.js","../src/database/query/preloader/selection.js","../src/database/query-parser/base-query-parser.js","../src/database/query-parser/from-parser.js","../src/database/query-parser/group-parser.js","../src/database/query-parser/joins-parser.js","../src/database/query-parser/limit-parser.js","../src/database/query-parser/options.js","../src/database/query-parser/order-parser.js","../src/database/query-parser/select-parser.js","../src/database/query-parser/where-parser.js","../src/database/record/acts-as-list.js","../src/database/record/index.js","../src/database/record/record-not-found-error.js","../src/database/record/state-machine.js","../src/database/record/user-module.js","../src/database/record/attachments/download.js","../src/database/record/attachments/handle.js","../src/database/record/attachments/normalize-input.js","../src/database/record/attachments/store.js","../src/database/record/attachments/storage-drivers/filesystem.js","../src/database/record/attachments/storage-drivers/native.js","../src/database/record/attachments/storage-drivers/s3.js","../src/database/record/instance-relationships/base.js","../src/database/record/instance-relationships/belongs-to.js","../src/database/record/instance-relationships/has-many.js","../src/database/record/instance-relationships/has-one.js","../src/database/record/relationships/base.js","../src/database/record/relationships/belongs-to.js","../src/database/record/relationships/has-many.js","../src/database/record/relationships/has-one.js","../src/database/record/validators/base.js","../src/database/record/validators/format.js","../src/database/record/validators/presence.js","../src/database/record/validators/uniqueness.js","../src/database/table-data/index.js","../src/database/table-data/table-column.js","../src/database/table-data/table-foreign-key.js","../src/database/table-data/table-index.js","../src/database/table-data/table-reference.js","../src/environment-handlers/base.js","../src/environment-handlers/browser.js","../src/environment-handlers/node.js","../src/environment-handlers/node/cli/commands/background-jobs-main.js","../src/environment-handlers/node/cli/commands/background-jobs-runner.js","../src/environment-handlers/node/cli/commands/background-jobs-worker.js","../src/environment-handlers/node/cli/commands/beacon.js","../src/environment-handlers/node/cli/commands/cli-command-context.js","../src/environment-handlers/node/cli/commands/console.js","../src/environment-handlers/node/cli/commands/init.js","../src/environment-handlers/node/cli/commands/routes.js","../src/environment-handlers/node/cli/commands/run-script.js","../src/environment-handlers/node/cli/commands/runner.js","../src/environment-handlers/node/cli/commands/server.js","../src/environment-handlers/node/cli/commands/test.js","../src/environment-handlers/node/cli/commands/db/seed.js","../src/environment-handlers/node/cli/commands/db/schema/dump.js","../src/environment-handlers/node/cli/commands/db/schema/load.js","../src/environment-handlers/node/cli/commands/destroy/migration.js","../src/environment-handlers/node/cli/commands/generate/base-models.js","../src/environment-handlers/node/cli/commands/generate/frontend-models.js","../src/environment-handlers/node/cli/commands/generate/migration.js","../src/environment-handlers/node/cli/commands/generate/model.js","../src/frontend-model-resource/base-resource.js","../src/frontend-models/base.js","../src/frontend-models/clear-pending-debounced-callback.js","../src/frontend-models/event-hook-models.js","../src/frontend-models/model-registry.js","../src/frontend-models/outgoing-event-buffer.js","../src/frontend-models/preloader.js","../src/frontend-models/query.js","../src/frontend-models/resource-config-validation.js","../src/frontend-models/resource-definition.js","../src/frontend-models/transport-serialization.js","../src/frontend-models/use-created-event.js","../src/frontend-models/use-destroyed-event.js","../src/frontend-models/use-model-class-event.js","../src/frontend-models/use-updated-event.js","../src/frontend-models/websocket-channel.js","../src/frontend-models/websocket-publishers.js","../src/http-client/header.js","../src/http-client/index.js","../src/http-client/request.js","../src/http-client/response.js","../src/http-client/websocket-client.js","../src/http-server/cookie.js","../src/http-server/development-reloader.js","../src/http-server/index.js","../src/http-server/remote-address.js","../src/http-server/server-client.js","../src/http-server/server-lock.js","../src/http-server/websocket-channel-subscribers.js","../src/http-server/websocket-channel.js","../src/http-server/websocket-connection.js","../src/http-server/websocket-event-log-store.js","../src/http-server/websocket-events-host.js","../src/http-server/websocket-events.js","../src/http-server/client/index.js","../src/http-server/client/params-to-object.js","../src/http-server/client/request-parser.js","../src/http-server/client/request-runner.js","../src/http-server/client/request-timing.js","../src/http-server/client/request.js","../src/http-server/client/response.js","../src/http-server/client/websocket-request.js","../src/http-server/client/websocket-session.js","../src/http-server/client/request-buffer/form-data-part.js","../src/http-server/client/request-buffer/header.js","../src/http-server/client/request-buffer/index.js","../src/http-server/client/uploaded-file/memory-uploaded-file.js","../src/http-server/client/uploaded-file/temporary-uploaded-file.js","../src/http-server/client/uploaded-file/uploaded-file.js","../src/http-server/worker-handler/channel-subscriber-dispatch.js","../src/http-server/worker-handler/in-process.js","../src/http-server/worker-handler/index.js","../src/http-server/worker-handler/worker-script.js","../src/http-server/worker-handler/worker-thread.js","../src/jobs/mail-delivery.js","../src/logger/base-logger.js","../src/logger/console-logger.js","../src/logger/file-logger.js","../src/logger/outputs/array-output.js","../src/logger/outputs/console-output.js","../src/logger/outputs/file-output.js","../src/logger/outputs/stdout-output.js","../src/mailer/base.js","../src/mailer/delivery.js","../src/mailer/index.js","../src/mailer/backends/smtp.js","../src/plugins/sqljs-wasm-route-controller.js","../src/plugins/sqljs-wasm-route.js","../src/routes/app-routes.js","../src/routes/base-route.js","../src/routes/basic-route.js","../src/routes/get-route.js","../src/routes/index.js","../src/routes/namespace-route.js","../src/routes/plugin-routes.js","../src/routes/post-route.js","../src/routes/resolver.js","../src/routes/resource-route.js","../src/routes/root-route.js","../src/routes/built-in/debug/controller.js","../src/routes/built-in/errors/controller.js","../src/routes/hooks/frontend-model-command-route-hook.js","../src/testing/base-expect.js","../src/testing/browser-frontend-model-event-hook-scenarios.js","../src/testing/browser-test-app.js","../src/testing/expect-to-change.js","../src/testing/expect-utils.js","../src/testing/expect.js","../src/testing/request-client.js","../src/testing/test-files-finder.js","../src/testing/test-filter-parser.js","../src/testing/test-runner.js","../src/testing/test-suite-splitter.js","../src/testing/test.js","../src/types/external-modules.d.ts","../src/utils/backtrace-cleaner-node.js","../src/utils/backtrace-cleaner.js","../src/utils/deburr-column-name.js","../src/utils/ensure-error.js","../src/utils/event-emitter.js","../src/utils/file-exists.js","../src/utils/format-value.js","../src/utils/model-scope.js","../src/utils/nest-callbacks.js","../src/utils/plain-object.js","../src/utils/ransack.js","../src/utils/rest-args-error.js","../src/utils/singularize-model-name.js","../src/utils/split-sql-statements.js","../src/utils/to-import-specifier.js","../src/utils/with-tracked-stack-async-hooks.js","../src/utils/with-tracked-stack.js"],"version":"6.0.3"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/** @type {Array<[RegExp, string]>} */
|
|
4
|
+
const UMLAUT_REPLACEMENTS = [
|
|
5
|
+
[/Ä/g, "Ae"],
|
|
6
|
+
[/Ö/g, "Oe"],
|
|
7
|
+
[/Ü/g, "Ue"],
|
|
8
|
+
[/ä/g, "ae"],
|
|
9
|
+
[/ö/g, "oe"],
|
|
10
|
+
[/ü/g, "ue"],
|
|
11
|
+
[/ß/g, "ss"]
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Transliterates German umlauts (and ß) in a database column name to ASCII so generated and runtime
|
|
16
|
+
* attribute names stay ASCII regardless of whether the column uses the umlaut ("Plätze") or already
|
|
17
|
+
* transliterated ("Plaetze") spelling. Both then map to the same attribute (e.g. "plaetzeVerkauft"),
|
|
18
|
+
* which keeps generated model bases consistent with code that references the ASCII attribute names.
|
|
19
|
+
* The raw column name is still used for the actual SQL, so the underlying column is untouched.
|
|
20
|
+
* @param {string} columnName - Raw database column name.
|
|
21
|
+
* @returns {string} - ASCII-transliterated column name.
|
|
22
|
+
*/
|
|
23
|
+
export default function deburrColumnName(columnName) {
|
|
24
|
+
let result = columnName
|
|
25
|
+
|
|
26
|
+
for (const [pattern, replacement] of UMLAUT_REPLACEMENTS) {
|
|
27
|
+
result = result.replace(pattern, replacement)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// An all-caps acronym column (e.g. "IP", "EA") would camelize to "iP"/"eA" because only the first
|
|
31
|
+
// letter is lowercased. Down-case columns that contain no lowercase letters so "IP" becomes "ip".
|
|
32
|
+
if (!/[a-z]/.test(result)) {
|
|
33
|
+
result = result.toLowerCase()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return result
|
|
37
|
+
}
|
package/package.json
CHANGED
package/src/configuration.js
CHANGED
|
@@ -143,6 +143,8 @@ export default class VelociousConfiguration {
|
|
|
143
143
|
this._scheduledBackgroundJobs = scheduledBackgroundJobs
|
|
144
144
|
this._attachments = attachments || {}
|
|
145
145
|
this._backendProjects = backendProjects || []
|
|
146
|
+
/** @type {Array<(args: {context: ?, error: Error, request: ?}) => Promise<Record<string, ?> | void> | Record<string, ?> | void>} */
|
|
147
|
+
this._clientErrorPayloadReporters = []
|
|
146
148
|
this.cors = cors
|
|
147
149
|
this._cookieSecret = cookieSecret
|
|
148
150
|
this.database = database
|
|
@@ -2382,6 +2384,35 @@ export default class VelociousConfiguration {
|
|
|
2382
2384
|
return this._errorEvents
|
|
2383
2385
|
}
|
|
2384
2386
|
|
|
2387
|
+
/**
|
|
2388
|
+
* Registers a reporter that can add client-safe metadata to frontend-model error payloads.
|
|
2389
|
+
* @param {(args: {context: ?, error: Error, request: ?}) => Promise<Record<string, ?> | void> | Record<string, ?> | void} reporter - Reporter callback.
|
|
2390
|
+
* @returns {void}
|
|
2391
|
+
*/
|
|
2392
|
+
addClientErrorPayloadReporter(reporter) {
|
|
2393
|
+
this._clientErrorPayloadReporters.push(reporter)
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2396
|
+
/**
|
|
2397
|
+
* Runs registered client error payload reporters.
|
|
2398
|
+
* @param {{context: ?, error: Error, request: ?}} args - Reporter args.
|
|
2399
|
+
* @returns {Promise<Record<string, ?>>} - Merged client-safe reporter payload.
|
|
2400
|
+
*/
|
|
2401
|
+
async clientErrorPayloadForError(args) {
|
|
2402
|
+
/** @type {Record<string, ?>} */
|
|
2403
|
+
const payload = {}
|
|
2404
|
+
|
|
2405
|
+
for (const reporter of this._clientErrorPayloadReporters) {
|
|
2406
|
+
const reporterPayload = await reporter(args)
|
|
2407
|
+
|
|
2408
|
+
if (reporterPayload && typeof reporterPayload === "object") {
|
|
2409
|
+
Object.assign(payload, reporterPayload)
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
|
|
2413
|
+
return payload
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2385
2416
|
/**
|
|
2386
2417
|
* Runs with connections.
|
|
2387
2418
|
* @template T
|
|
@@ -4,6 +4,34 @@ import ensureModelClassInitialized from "./ensure-model-class-initialized.js"
|
|
|
4
4
|
import PreloaderSelection from "./selection.js"
|
|
5
5
|
import restArgsError from "../../../utils/rest-args-error.js"
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Resolves the target column that references the through model.
|
|
9
|
+
* @param {import("../../record/relationships/has-many.js").default} relationship - Has-many through relationship.
|
|
10
|
+
* @param {typeof import("../../record/index.js").default} throughModelClass - Model used by the through relationship.
|
|
11
|
+
* @param {typeof import("../../record/index.js").default} targetModelClass - Model loaded by the through relationship.
|
|
12
|
+
* @returns {string} Target model foreign key column.
|
|
13
|
+
*/
|
|
14
|
+
export function hasManyThroughTargetForeignKey(relationship, throughModelClass, targetModelClass) {
|
|
15
|
+
// An explicit foreign key on the has-many names the exact target column that references the
|
|
16
|
+
// through model — honor it. The target can have several belongs-to pointing at the through model
|
|
17
|
+
// (e.g. a default plus an alternate), so picking the first match would otherwise be ambiguous.
|
|
18
|
+
const explicitForeignKey = relationship.getExplicitForeignKey()
|
|
19
|
+
|
|
20
|
+
if (explicitForeignKey) return explicitForeignKey
|
|
21
|
+
|
|
22
|
+
for (const targetRelationship of targetModelClass.getRelationships()) {
|
|
23
|
+
if (targetRelationship.getType() != "belongsTo") continue
|
|
24
|
+
|
|
25
|
+
const relationshipTargetModelClass = targetRelationship.getTargetModelClass()
|
|
26
|
+
|
|
27
|
+
if (relationshipTargetModelClass === throughModelClass) {
|
|
28
|
+
return targetRelationship.getForeignKey()
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return relationship.getForeignKey()
|
|
33
|
+
}
|
|
34
|
+
|
|
7
35
|
export default class VelociousDatabaseQueryPreloaderHasMany {
|
|
8
36
|
/**
|
|
9
37
|
* Runs constructor.
|
|
@@ -90,7 +118,7 @@ export default class VelociousDatabaseQueryPreloaderHasMany {
|
|
|
90
118
|
|
|
91
119
|
if (!targetModelClass) throw new Error("No target model class could be gotten from relationship")
|
|
92
120
|
|
|
93
|
-
const targetForeignKey = this.relationship
|
|
121
|
+
const targetForeignKey = hasManyThroughTargetForeignKey(this.relationship, throughModelClass, targetModelClass)
|
|
94
122
|
const {modelsToLoad, satisfiedTargets} = this._partition(targetModelClass, [targetForeignKey])
|
|
95
123
|
|
|
96
124
|
if (modelsToLoad.length == 0) return satisfiedTargets
|
|
@@ -30,6 +30,7 @@ import HasOneInstanceRelationship from "./instance-relationships/has-one.js"
|
|
|
30
30
|
import HasOneRelationship from "./relationships/has-one.js"
|
|
31
31
|
import RecordAttachmentHandle from "./attachments/handle.js"
|
|
32
32
|
import * as inflection from "inflection"
|
|
33
|
+
import deburrColumnName from "../../utils/deburr-column-name.js"
|
|
33
34
|
import ModelClassQuery from "../query/model-class-query.js"
|
|
34
35
|
import Preloader from "../query/preloader.js"
|
|
35
36
|
import {readPayloadAssociationCount, readPayloadComputedAbility, readPayloadQueryData, setPayloadAssociationCount, setPayloadComputedAbility, setPayloadQueryData} from "../../record-payload-values.js"
|
|
@@ -1350,8 +1351,9 @@ class VelociousDatabaseRecord {
|
|
|
1350
1351
|
for (const column of this._columns) {
|
|
1351
1352
|
this._columnsAsHash[column.getName()] = column
|
|
1352
1353
|
|
|
1353
|
-
const
|
|
1354
|
-
const
|
|
1354
|
+
const deburredColumnName = deburrColumnName(column.getName())
|
|
1355
|
+
const camelizedColumnName = inflection.camelize(deburredColumnName, true)
|
|
1356
|
+
const camelizedColumnNameBigFirst = inflection.camelize(deburredColumnName)
|
|
1355
1357
|
|
|
1356
1358
|
attributeNameToColumnName[camelizedColumnName] = column.getName()
|
|
1357
1359
|
columnNameToAttributeName[column.getName()] = camelizedColumnName
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
import BaseInstanceRelationship from "./base.js"
|
|
4
|
+
import {hasManyThroughTargetForeignKey} from "../../query/preloader/has-many.js"
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* A generic query over some model type.
|
|
@@ -192,7 +193,11 @@ export default class VelociousDatabaseRecordHasManyInstanceRelationship extends
|
|
|
192
193
|
|
|
193
194
|
const throughForeignKey = throughRelationship.getForeignKey()
|
|
194
195
|
const throughPrimaryKey = throughRelationship.getPrimaryKey()
|
|
195
|
-
const targetForeignKey =
|
|
196
|
+
const targetForeignKey = hasManyThroughTargetForeignKey(
|
|
197
|
+
/** @type {import("../relationships/has-many.js").default} */ (this.getRelationship()),
|
|
198
|
+
throughModelClass,
|
|
199
|
+
TargetModelClass
|
|
200
|
+
)
|
|
196
201
|
const targetTable = TargetModelClass.tableName()
|
|
197
202
|
const throughTable = throughModelClass.tableName()
|
|
198
203
|
const driver = TargetModelClass.connection()
|
|
@@ -46,6 +46,7 @@ export default class VelociousDatabaseRecordBaseRelationship {
|
|
|
46
46
|
this._counterCache = counterCache || false
|
|
47
47
|
this._dependent = dependent
|
|
48
48
|
this.foreignKey = foreignKey
|
|
49
|
+
this._explicitForeignKey = foreignKey
|
|
49
50
|
this._inverseOf = inverseOf
|
|
50
51
|
this.klass = klass
|
|
51
52
|
this.modelClass = modelClass
|
|
@@ -77,6 +78,14 @@ export default class VelociousDatabaseRecordBaseRelationship {
|
|
|
77
78
|
*/
|
|
78
79
|
getDependent() { return this._dependent }
|
|
79
80
|
|
|
81
|
+
/**
|
|
82
|
+
* The foreign key explicitly passed when the relationship was declared, if any. Unlike
|
|
83
|
+
* `getForeignKey()` this never falls back to a computed default, so callers can tell whether the
|
|
84
|
+
* developer named a specific column (e.g. to disambiguate multiple belongs-to on a through target).
|
|
85
|
+
* @returns {string | undefined} - The explicitly declared foreign key, or undefined.
|
|
86
|
+
*/
|
|
87
|
+
getExplicitForeignKey() { return this._explicitForeignKey }
|
|
88
|
+
|
|
80
89
|
/**
|
|
81
90
|
* Runs get foreign key.
|
|
82
91
|
* @abstract
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import BaseCommand from "../../../../../cli/base-command.js"
|
|
2
|
+
import deburrColumnName from "../../../../../utils/deburr-column-name.js"
|
|
2
3
|
import fileExists from "../../../../../utils/file-exists.js"
|
|
3
4
|
import fs from "fs/promises"
|
|
4
5
|
import * as inflection from "inflection"
|
|
@@ -141,8 +142,9 @@ export default class DbGenerateModel extends BaseCommand {
|
|
|
141
142
|
let methodsCount = 0
|
|
142
143
|
|
|
143
144
|
for (const column of columns) {
|
|
144
|
-
const
|
|
145
|
-
const
|
|
145
|
+
const deburredColumnName = deburrColumnName(column.getName())
|
|
146
|
+
const camelizedColumnName = inflection.camelize(deburredColumnName, true)
|
|
147
|
+
const camelizedColumnNameBigFirst = inflection.camelize(deburredColumnName)
|
|
146
148
|
const jsdocType = this.jsDocTypeFromColumn(column, modelClass)
|
|
147
149
|
|
|
148
150
|
if (methodsCount > 0) {
|
|
@@ -2741,10 +2741,11 @@ export default class FrontendModelController extends Controller {
|
|
|
2741
2741
|
/**
|
|
2742
2742
|
* Runs frontend model client error payload for error.
|
|
2743
2743
|
* @param {?} error - Caught error.
|
|
2744
|
-
* @returns {Record<string,
|
|
2744
|
+
* @returns {Promise<Record<string, ?>>} - Client payload for the current environment.
|
|
2745
2745
|
*/
|
|
2746
|
-
frontendModelClientErrorPayloadForError(error) {
|
|
2746
|
+
async frontendModelClientErrorPayloadForError(error) {
|
|
2747
2747
|
const velociousMetadata = frontendModelVelociousMetadataForError(error)
|
|
2748
|
+
const normalizedError = error instanceof Error ? error : new Error(String(error))
|
|
2748
2749
|
|
|
2749
2750
|
let validationErrorsPayload = {}
|
|
2750
2751
|
|
|
@@ -2778,7 +2779,14 @@ export default class FrontendModelController extends Controller {
|
|
|
2778
2779
|
error
|
|
2779
2780
|
}),
|
|
2780
2781
|
...(velociousMetadata ? {velocious: velociousMetadata} : {}),
|
|
2781
|
-
...validationErrorsPayload
|
|
2782
|
+
...validationErrorsPayload,
|
|
2783
|
+
...(await this.getConfiguration().clientErrorPayloadForError({
|
|
2784
|
+
context: {
|
|
2785
|
+
controller: this.constructor.name
|
|
2786
|
+
},
|
|
2787
|
+
error: normalizedError,
|
|
2788
|
+
request: this.getRequest()
|
|
2789
|
+
}))
|
|
2782
2790
|
}
|
|
2783
2791
|
}
|
|
2784
2792
|
|
|
@@ -2845,7 +2853,7 @@ export default class FrontendModelController extends Controller {
|
|
|
2845
2853
|
await this.render({
|
|
2846
2854
|
json: /**
|
|
2847
2855
|
* Types the following value.
|
|
2848
|
-
@type {Record<string, ?>} */ (serializeFrontendModelTransportValue(this.frontendModelClientErrorPayloadForError(error)))
|
|
2856
|
+
@type {Record<string, ?>} */ (serializeFrontendModelTransportValue(await this.frontendModelClientErrorPayloadForError(error)))
|
|
2849
2857
|
})
|
|
2850
2858
|
}
|
|
2851
2859
|
}
|
|
@@ -3122,7 +3130,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3122
3130
|
|
|
3123
3131
|
responses.push({
|
|
3124
3132
|
requestId,
|
|
3125
|
-
response: this.frontendModelClientErrorPayloadForError(error)
|
|
3133
|
+
response: await this.frontendModelClientErrorPayloadForError(error)
|
|
3126
3134
|
})
|
|
3127
3135
|
}
|
|
3128
3136
|
}
|
|
@@ -3348,7 +3356,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3348
3356
|
await this.render({
|
|
3349
3357
|
json: /**
|
|
3350
3358
|
* Types the following value.
|
|
3351
|
-
@type {Record<string, ?>} */ (serializeFrontendModelTransportValue(this.frontendModelClientErrorPayloadForError(error)))
|
|
3359
|
+
@type {Record<string, ?>} */ (serializeFrontendModelTransportValue(await this.frontendModelClientErrorPayloadForError(error)))
|
|
3352
3360
|
})
|
|
3353
3361
|
}
|
|
3354
3362
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/** @type {Array<[RegExp, string]>} */
|
|
4
|
+
const UMLAUT_REPLACEMENTS = [
|
|
5
|
+
[/Ä/g, "Ae"],
|
|
6
|
+
[/Ö/g, "Oe"],
|
|
7
|
+
[/Ü/g, "Ue"],
|
|
8
|
+
[/ä/g, "ae"],
|
|
9
|
+
[/ö/g, "oe"],
|
|
10
|
+
[/ü/g, "ue"],
|
|
11
|
+
[/ß/g, "ss"]
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Transliterates German umlauts (and ß) in a database column name to ASCII so generated and runtime
|
|
16
|
+
* attribute names stay ASCII regardless of whether the column uses the umlaut ("Plätze") or already
|
|
17
|
+
* transliterated ("Plaetze") spelling. Both then map to the same attribute (e.g. "plaetzeVerkauft"),
|
|
18
|
+
* which keeps generated model bases consistent with code that references the ASCII attribute names.
|
|
19
|
+
* The raw column name is still used for the actual SQL, so the underlying column is untouched.
|
|
20
|
+
* @param {string} columnName - Raw database column name.
|
|
21
|
+
* @returns {string} - ASCII-transliterated column name.
|
|
22
|
+
*/
|
|
23
|
+
export default function deburrColumnName(columnName) {
|
|
24
|
+
let result = columnName
|
|
25
|
+
|
|
26
|
+
for (const [pattern, replacement] of UMLAUT_REPLACEMENTS) {
|
|
27
|
+
result = result.replace(pattern, replacement)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// An all-caps acronym column (e.g. "IP", "EA") would camelize to "iP"/"eA" because only the first
|
|
31
|
+
// letter is lowercased. Down-case columns that contain no lowercase letters so "IP" becomes "ip".
|
|
32
|
+
if (!/[a-z]/.test(result)) {
|
|
33
|
+
result = result.toLowerCase()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return result
|
|
37
|
+
}
|