@astram/engine 0.5.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/pipe/stages/validate.d.ts.map +1 -1
- package/dist/pipe/stages/validate.js +8 -5
- package/dist/uuid.d.ts +14 -0
- package/dist/uuid.d.ts.map +1 -0
- package/dist/uuid.js +21 -0
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
*/
|
|
20
20
|
export type { RecordEngine, AccessDeclaration, FieldSpec, FieldType, TrustedSource, IdentityRole, PkStrategy, JunctionSpec, RecordInput, RecordId, RecordView, ListQuery, RecordPage, Principal, ReadScope, ReadScopeCreateMode, } from './types.js';
|
|
21
21
|
export { READ_SCOPE_NODES_TOKEN } from './types.js';
|
|
22
|
+
export { canonicalUuid } from './uuid.js';
|
|
22
23
|
export { EngineError, CapabilityNotSupportedError, RegistrationError, AuthorizationDeniedError, ValidationError, EngineUnavailableError, } from './errors.js';
|
|
23
24
|
export { ObjectType, Field, PrimaryKey, reflectObjectType, type ObjectTypeOptions, type FieldOptions, type PrimaryKeyOptions, } from './decorators/object-type.decorator.js';
|
|
24
25
|
export { AccessBundle, reflectAccessBundle, type AccessBundleOptions, type AccessBundlePermission, type AccessBundleSpec, } from './decorators/access-bundle.decorator.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,aAAa,EACb,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,UAAU,EACV,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAKpB,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,aAAa,EACb,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,UAAU,EACV,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAKpB,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAKpD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EACL,WAAW,EACX,2BAA2B,EAC3B,iBAAiB,EACjB,wBAAwB,EACxB,eAAe,EACf,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAiBrB,OAAO,EACL,UAAU,EACV,KAAK,EACL,UAAU,EACV,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACvB,MAAM,uCAAuC,CAAC;AAO/C,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,GACtB,MAAM,yCAAyC,CAAC;AAEjD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,wBAAwB,EACxB,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,eAAe,GACrB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EACL,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,WAAW,EACX,cAAc,EACd,aAAa,EACb,WAAW,GACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAClF,OAAO,EACL,cAAc,EACd,YAAY,EACZ,KAAK,sBAAsB,EAC3B,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AAGnC,YAAY,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAC1F,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC/E,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -19,12 +19,17 @@
|
|
|
19
19
|
* `@astram/engine/internal`, which only the composition root may import.
|
|
20
20
|
*/
|
|
21
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.MariaDbAuditSink = exports.SERVICE_ACCOUNT_RESOLVER = exports.BoundRecords = exports.RecordsService = exports.RecordEngineImpl = exports.requireRole = exports.columnForRole = exports.tenantColumnOf = exports.ownerColumn = exports.isOwned = exports.uuidPkColumn = exports.columnOf = exports.TableRegistry = exports.ENGINE_ALL_ACCESS_BUNDLES = exports.ENGINE_ALL_REGISTRATIONS = exports.RECORD_ENGINE = exports.EngineModule = exports.reflectAccessBundle = exports.AccessBundle = exports.reflectObjectType = exports.PrimaryKey = exports.Field = exports.ObjectType = exports.EngineUnavailableError = exports.ValidationError = exports.AuthorizationDeniedError = exports.RegistrationError = exports.CapabilityNotSupportedError = exports.EngineError = exports.READ_SCOPE_NODES_TOKEN = void 0;
|
|
22
|
+
exports.MariaDbAuditSink = exports.SERVICE_ACCOUNT_RESOLVER = exports.BoundRecords = exports.RecordsService = exports.RecordEngineImpl = exports.requireRole = exports.columnForRole = exports.tenantColumnOf = exports.ownerColumn = exports.isOwned = exports.uuidPkColumn = exports.columnOf = exports.TableRegistry = exports.ENGINE_ALL_ACCESS_BUNDLES = exports.ENGINE_ALL_REGISTRATIONS = exports.RECORD_ENGINE = exports.EngineModule = exports.reflectAccessBundle = exports.AccessBundle = exports.reflectObjectType = exports.PrimaryKey = exports.Field = exports.ObjectType = exports.EngineUnavailableError = exports.ValidationError = exports.AuthorizationDeniedError = exports.RegistrationError = exports.CapabilityNotSupportedError = exports.EngineError = exports.canonicalUuid = exports.READ_SCOPE_NODES_TOKEN = void 0;
|
|
23
23
|
// The read-scope subtree-id placeholder token (ADR-0027) — a `subtreeSubquery` template
|
|
24
24
|
// uses it; the engine expands it to a `?`-list. Exported so per-type declarations can
|
|
25
25
|
// reference the canonical token (rather than a stringly-typed duplicate).
|
|
26
26
|
var types_js_1 = require("./types.js");
|
|
27
27
|
Object.defineProperty(exports, "READ_SCOPE_NODES_TOKEN", { enumerable: true, get: function () { return types_js_1.READ_SCOPE_NODES_TOKEN; } });
|
|
28
|
+
// The ONE uuid canonicaliser (Phase 11 #1): strict 8-4-4-4-12 ASCII hex, returned lower-cased;
|
|
29
|
+
// anything else (padded, fullwidth, ...) is null. Guard's `UuidPipe` and the identity body checks
|
|
30
|
+
// use it; consumers may too.
|
|
31
|
+
var uuid_js_1 = require("./uuid.js");
|
|
32
|
+
Object.defineProperty(exports, "canonicalUuid", { enumerable: true, get: function () { return uuid_js_1.canonicalUuid; } });
|
|
28
33
|
var errors_js_1 = require("./errors.js");
|
|
29
34
|
Object.defineProperty(exports, "EngineError", { enumerable: true, get: function () { return errors_js_1.EngineError; } });
|
|
30
35
|
Object.defineProperty(exports, "CapabilityNotSupportedError", { enumerable: true, get: function () { return errors_js_1.CapabilityNotSupportedError; } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/pipe/stages/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/pipe/stages/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AAiDzD,wBAAgB,aAAa,IAAI,KAAK,CAmCrC"}
|
|
@@ -11,6 +11,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
11
11
|
exports.validateStage = validateStage;
|
|
12
12
|
const errors_js_1 = require("../../errors.js");
|
|
13
13
|
const registry_js_1 = require("../../registry.js");
|
|
14
|
+
const uuid_js_1 = require("../../uuid.js");
|
|
14
15
|
const SUPPORTED = new Set([
|
|
15
16
|
'string',
|
|
16
17
|
'number',
|
|
@@ -19,7 +20,6 @@ const SUPPORTED = new Set([
|
|
|
19
20
|
'timestamp',
|
|
20
21
|
'json',
|
|
21
22
|
]);
|
|
22
|
-
const UUID_RE = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
23
23
|
/** Validate + coerce one value against a field type. Returns the coerced value. */
|
|
24
24
|
function coerce(field, value) {
|
|
25
25
|
switch (field.type) {
|
|
@@ -36,11 +36,14 @@ function coerce(field, value) {
|
|
|
36
36
|
if (typeof value === 'boolean')
|
|
37
37
|
return value ? 1 : 0; // MariaDB tinyint
|
|
38
38
|
throw new errors_js_1.ValidationError(field.key, 'expected a boolean');
|
|
39
|
-
case 'uuid':
|
|
40
|
-
|
|
39
|
+
case 'uuid': {
|
|
40
|
+
// Phase 11 #1: stored uuids are always canonical. A valid upper-case uuid is accepted and
|
|
41
|
+
// lower-cased (existing writers keep working); padded/fullwidth/other spellings are rejected.
|
|
42
|
+
const canonical = (0, uuid_js_1.canonicalUuid)(value);
|
|
43
|
+
if (canonical === null)
|
|
41
44
|
throw new errors_js_1.ValidationError(field.key, 'expected a uuid');
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
return canonical;
|
|
46
|
+
}
|
|
44
47
|
case 'timestamp':
|
|
45
48
|
if (value instanceof Date)
|
|
46
49
|
return value;
|
package/dist/uuid.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE uuid canonicaliser (Phase 11 #1). Every framework uuid that crosses a trust boundary
|
|
3
|
+
* (route param, body field, engine `uuid` field) goes through it.
|
|
4
|
+
*
|
|
5
|
+
* Why strict: the uuid columns are `utf8mb4_unicode_ci`, which compares ignoring letter case,
|
|
6
|
+
* trailing spaces (PAD SPACE) and character width (fullwidth digits/letters). A non-canonical
|
|
7
|
+
* spelling therefore reaches the stored row in SQL while every JS-side comparison (own root,
|
|
8
|
+
* platform administrators, `JSON_CONTAINS`, Redis keys, Sets) sees a different id. So: no trimming,
|
|
9
|
+
* no Unicode normalisation; only the 8-4-4-4-12 ASCII hex form is accepted, and it is returned
|
|
10
|
+
* lower-cased (the one canonical spelling). Anything else is `null`.
|
|
11
|
+
*/
|
|
12
|
+
/** The canonical (lower-case) form of a uuid, or `null` when `v` is not exactly a uuid. */
|
|
13
|
+
export declare function canonicalUuid(v: unknown): string | null;
|
|
14
|
+
//# sourceMappingURL=uuid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../src/uuid.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,2FAA2F;AAC3F,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAEvD"}
|
package/dist/uuid.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The ONE uuid canonicaliser (Phase 11 #1). Every framework uuid that crosses a trust boundary
|
|
4
|
+
* (route param, body field, engine `uuid` field) goes through it.
|
|
5
|
+
*
|
|
6
|
+
* Why strict: the uuid columns are `utf8mb4_unicode_ci`, which compares ignoring letter case,
|
|
7
|
+
* trailing spaces (PAD SPACE) and character width (fullwidth digits/letters). A non-canonical
|
|
8
|
+
* spelling therefore reaches the stored row in SQL while every JS-side comparison (own root,
|
|
9
|
+
* platform administrators, `JSON_CONTAINS`, Redis keys, Sets) sees a different id. So: no trimming,
|
|
10
|
+
* no Unicode normalisation; only the 8-4-4-4-12 ASCII hex form is accepted, and it is returned
|
|
11
|
+
* lower-cased (the one canonical spelling). Anything else is `null`.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.canonicalUuid = canonicalUuid;
|
|
15
|
+
// ASCII hex only: without the `u` flag, `i` never folds a non-ASCII character onto A-F, and `$`
|
|
16
|
+
// matches only at the end of input (a trailing newline or space fails).
|
|
17
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
18
|
+
/** The canonical (lower-case) form of a uuid, or `null` when `v` is not exactly a uuid. */
|
|
19
|
+
function canonicalUuid(v) {
|
|
20
|
+
return typeof v === 'string' && UUID_RE.test(v) ? v.toLowerCase() : null;
|
|
21
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astram/engine",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Astram framework — the paved road. ONE unbypassable write pipe (resolve-schema → permission gate → derive-write-context → validate → compute → write → junction-sync → audit → emit-event) over real physical tables, that every feature's CRUD flows through. Feature code receives ONLY the RecordEngine facade — never a raw pool/DataSource/QueryRunner (the physical wall). Security-gate + audit are mandatory stages. Missing capability → a typed CapabilityNotSupportedError (the gap-flag STOP). Builds on @astram/core (metadata contract, decide(), audit) + @astram/guard (decision authority).",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"mariadb": "^3.5.4",
|
|
35
|
-
"@astram/core": "1.
|
|
35
|
+
"@astram/core": "1.5.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@nestjs/common": "^11",
|