@opensaas/stack-core 0.39.2 → 0.41.0
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +189 -0
- package/CLAUDE.md +103 -0
- package/dist/access/access-filter.d.ts +157 -14
- package/dist/access/access-filter.d.ts.map +1 -1
- package/dist/access/access-filter.js +470 -42
- package/dist/access/access-filter.js.map +1 -1
- package/dist/access/access-filter.test.js +982 -17
- package/dist/access/access-filter.test.js.map +1 -1
- package/dist/access/denied-relation-visibility.test.d.ts +2 -0
- package/dist/access/denied-relation-visibility.test.d.ts.map +1 -0
- package/dist/access/denied-relation-visibility.test.js +114 -0
- package/dist/access/denied-relation-visibility.test.js.map +1 -0
- package/dist/access/engine.d.ts +54 -1
- package/dist/access/engine.d.ts.map +1 -1
- package/dist/access/engine.js +84 -0
- package/dist/access/engine.js.map +1 -1
- package/dist/access/engine.test.d.ts +2 -0
- package/dist/access/engine.test.d.ts.map +1 -0
- package/dist/access/engine.test.js +56 -0
- package/dist/access/engine.test.js.map +1 -0
- package/dist/access/errors.d.ts +62 -0
- package/dist/access/errors.d.ts.map +1 -1
- package/dist/access/errors.js +85 -2
- package/dist/access/errors.js.map +1 -1
- package/dist/access/field-access.d.ts +12 -0
- package/dist/access/field-access.d.ts.map +1 -1
- package/dist/access/field-access.js +22 -2
- package/dist/access/field-access.js.map +1 -1
- package/dist/access/field-access.test.js +66 -0
- package/dist/access/field-access.test.js.map +1 -1
- package/dist/access/field-visibility.d.ts +2 -1
- package/dist/access/field-visibility.d.ts.map +1 -1
- package/dist/access/field-visibility.js +107 -15
- package/dist/access/field-visibility.js.map +1 -1
- package/dist/access/index.d.ts +9 -2
- package/dist/access/index.d.ts.map +1 -1
- package/dist/access/index.js +11 -2
- package/dist/access/index.js.map +1 -1
- package/dist/access/multi-column-read-write.test.js.map +1 -1
- package/dist/access/query-validation.d.ts +31 -0
- package/dist/access/query-validation.d.ts.map +1 -1
- package/dist/access/query-validation.js +75 -16
- package/dist/access/query-validation.js.map +1 -1
- package/dist/access/relationship-count.d.ts +41 -3
- package/dist/access/relationship-count.d.ts.map +1 -1
- package/dist/access/relationship-count.js +44 -7
- package/dist/access/relationship-count.js.map +1 -1
- package/dist/access/relationship-count.test.js +62 -0
- package/dist/access/relationship-count.test.js.map +1 -1
- package/dist/access/synthetic-include-read.test.d.ts +2 -0
- package/dist/access/synthetic-include-read.test.d.ts.map +1 -0
- package/dist/access/synthetic-include-read.test.js +121 -0
- package/dist/access/synthetic-include-read.test.js.map +1 -0
- package/dist/config/types.d.ts +98 -32
- package/dist/config/types.d.ts.map +1 -1
- package/dist/context/hook-pipeline.d.ts +2 -2
- package/dist/context/hook-pipeline.d.ts.map +1 -1
- package/dist/context/hook-pipeline.js.map +1 -1
- package/dist/context/index.d.ts +35 -2
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +121 -27
- package/dist/context/index.js.map +1 -1
- package/dist/context/nested-operations.d.ts +2 -2
- package/dist/context/nested-operations.d.ts.map +1 -1
- package/dist/context/nested-operations.js +74 -15
- package/dist/context/nested-operations.js.map +1 -1
- package/dist/context/write-pipeline.d.ts +3 -2
- package/dist/context/write-pipeline.d.ts.map +1 -1
- package/dist/context/write-pipeline.js +31 -34
- package/dist/context/write-pipeline.js.map +1 -1
- package/dist/fields/index.d.ts +13 -1
- package/dist/fields/index.d.ts.map +1 -1
- package/dist/fields/index.js +50 -5
- package/dist/fields/index.js.map +1 -1
- package/dist/fields/relationship-foreign-key.test.d.ts +2 -0
- package/dist/fields/relationship-foreign-key.test.d.ts.map +1 -0
- package/dist/fields/relationship-foreign-key.test.js +18 -0
- package/dist/fields/relationship-foreign-key.test.js.map +1 -0
- package/dist/hooks/index.d.ts +16 -15
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/case-utils.d.ts +15 -0
- package/dist/lib/case-utils.d.ts.map +1 -1
- package/dist/lib/case-utils.js +21 -0
- package/dist/lib/case-utils.js.map +1 -1
- package/dist/lib/case-utils.test.js +23 -1
- package/dist/lib/case-utils.test.js.map +1 -1
- package/dist/lib/prisma-errors.d.ts +38 -0
- package/dist/lib/prisma-errors.d.ts.map +1 -0
- package/dist/lib/prisma-errors.js +53 -0
- package/dist/lib/prisma-errors.js.map +1 -0
- package/dist/mcp/constants.d.ts +23 -0
- package/dist/mcp/constants.d.ts.map +1 -0
- package/dist/mcp/constants.js +23 -0
- package/dist/mcp/constants.js.map +1 -0
- package/dist/mcp/field-schema.d.ts +8 -0
- package/dist/mcp/field-schema.d.ts.map +1 -0
- package/dist/mcp/field-schema.js +69 -0
- package/dist/mcp/field-schema.js.map +1 -0
- package/dist/mcp/handler.d.ts.map +1 -1
- package/dist/mcp/handler.js +76 -90
- package/dist/mcp/handler.js.map +1 -1
- package/dist/mcp/projection.d.ts +62 -0
- package/dist/mcp/projection.d.ts.map +1 -0
- package/dist/mcp/projection.js +390 -0
- package/dist/mcp/projection.js.map +1 -0
- package/dist/utils/password.d.ts +3 -1
- package/dist/utils/password.d.ts.map +1 -1
- package/dist/utils/password.js +4 -2
- package/dist/utils/password.js.map +1 -1
- package/package.json +2 -2
- package/src/access/access-filter.test.ts +1528 -18
- package/src/access/access-filter.ts +708 -42
- package/src/access/denied-relation-visibility.test.ts +173 -0
- package/src/access/engine.test.ts +67 -0
- package/src/access/engine.ts +109 -1
- package/src/access/errors.ts +97 -2
- package/src/access/field-access.test.ts +78 -0
- package/src/access/field-access.ts +34 -2
- package/src/access/field-visibility.ts +171 -25
- package/src/access/index.ts +25 -0
- package/src/access/multi-column-read-write.test.ts +3 -2
- package/src/access/query-validation.ts +136 -9
- package/src/access/relationship-count.test.ts +75 -0
- package/src/access/relationship-count.ts +53 -10
- package/src/access/synthetic-include-read.test.ts +179 -0
- package/src/config/types.ts +98 -32
- package/src/context/hook-pipeline.ts +4 -2
- package/src/context/index.ts +203 -42
- package/src/context/nested-operations.ts +96 -27
- package/src/context/write-pipeline.ts +60 -36
- package/src/fields/index.ts +55 -5
- package/src/fields/relationship-foreign-key.test.ts +29 -0
- package/src/hooks/index.ts +22 -15
- package/src/index.ts +17 -1
- package/src/lib/case-utils.test.ts +32 -0
- package/src/lib/case-utils.ts +26 -0
- package/src/lib/prisma-errors.ts +86 -0
- package/src/mcp/constants.ts +24 -0
- package/src/mcp/field-schema.ts +84 -0
- package/src/mcp/handler.ts +109 -107
- package/src/mcp/projection.ts +497 -0
- package/src/utils/password.ts +5 -3
- package/tests/access-relationships.test.ts +3 -3
- package/tests/access.test.ts +83 -0
- package/tests/context.test.ts +452 -17
- package/tests/field-types.test.ts +113 -0
- package/tests/hook-context-secured.test.ts +424 -0
- package/tests/mcp-fields-projection-access.test.ts +250 -0
- package/tests/mcp-handler.test.ts +695 -4
- package/tests/nested-access-and-hooks.test.ts +389 -0
- package/tests/nested-write-synthetic-relation.test.ts +437 -0
- package/tests/password-types.test.ts +28 -0
- package/tests/password.test.ts +16 -2
- package/tests/prisma-errors.test.ts +141 -0
- package/tests/singleton.test.ts +9 -1
- package/tests/to-one-include-access-filter.test.ts +172 -0
- package/tests/with-session.test.ts +243 -0
- package/tests/write-pipeline.test.ts +29 -0
- package/tsconfig.tsbuildinfo +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3,13 +3,16 @@ export type { OpenSaasConfig, OutputConfig, ListConfig, DatabaseConfig, ListInde
|
|
|
3
3
|
export type { AccessControl, FieldAccess, Session, AccessContext, PrismaFilter, } from './access/index.js';
|
|
4
4
|
export { getContext } from './context/index.js';
|
|
5
5
|
export type { StackContext, TransactionOptions, TransactionIsolationLevel, } from './context/index.js';
|
|
6
|
-
export { getDbKey, getUrlKey, getListKeyFromUrl } from './lib/case-utils.js';
|
|
6
|
+
export { getDbKey, getUrlKey, getListKeyFromUrl, resolveListKeyFromUrl } from './lib/case-utils.js';
|
|
7
7
|
export { getLabelFieldName, getItemLabel } from './config/label.js';
|
|
8
8
|
export { resolveNavCounts, isListQueryStaticallyDenied } from './config/nav-count.js';
|
|
9
9
|
export { ValidationError } from './hooks/index.js';
|
|
10
|
+
export { uniqueConstraintOf } from './lib/prisma-errors.js';
|
|
11
|
+
export type { UniqueConstraintInfo } from './lib/prisma-errors.js';
|
|
10
12
|
export { AccessScopeDepthExceededError } from './access/index.js';
|
|
11
13
|
export { ResolveOutputCycleError } from './access/index.js';
|
|
12
14
|
export { InvalidFieldAccessResultError } from './access/index.js';
|
|
15
|
+
export { InvalidCreateAccessResultError } from './access/index.js';
|
|
13
16
|
export { RelationFilterAccessDeniedError } from './access/index.js';
|
|
14
17
|
export { validateFieldConfig, validateConfigFields } from './validation/field-config.js';
|
|
15
18
|
export type { FieldConfigValidationError } from './validation/field-config.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AAKhD,YAAY,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,cAAc,EACd,SAAS,EACT,iBAAiB,EACjB,WAAW,EACX,eAAe,EAIf,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,mBAAmB,CAAA;AAG1B,YAAY,EACV,aAAa,EACb,WAAW,EACX,OAAO,EACP,aAAa,EACb,YAAY,GACb,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AAKhD,YAAY,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,cAAc,EACd,SAAS,EACT,iBAAiB,EACjB,WAAW,EACX,eAAe,EAIf,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,mBAAmB,CAAA;AAG1B,YAAY,EACV,aAAa,EACb,WAAW,EACX,OAAO,EACP,aAAa,EACb,YAAY,GACb,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAKnG,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAInE,OAAO,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AAGrF,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAOlD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAC3D,YAAY,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAMlE,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAA;AAKjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAQ3D,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAA;AAQjE,OAAO,EAAE,8BAA8B,EAAE,MAAM,mBAAmB,CAAA;AAQlE,OAAO,EAAE,+BAA+B,EAAE,MAAM,mBAAmB,CAAA;AAMnE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AACxF,YAAY,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;AAO9E,OAAO,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAA;AACpG,YAAY,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAA;AAQtE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACxE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAK7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AACxE,YAAY,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAA;AAOlG,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,cAAc,EACd,WAAW,EACX,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,qBAAqB,EACrB,6BAA6B,EAC7B,gBAAgB,GACjB,MAAM,mBAAmB,CAAA;AAM1B,OAAO,EACL,4BAA4B,EAC5B,+BAA+B,EAC/B,yBAAyB,GAC1B,MAAM,gCAAgC,CAAA;AAQvC,OAAO,EACL,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,uCAAuC,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ export { config, list } from './config/index.js';
|
|
|
12
12
|
// Context factory
|
|
13
13
|
export { getContext } from './context/index.js';
|
|
14
14
|
// Naming utilities (documented public helpers; used for URLs and db keys)
|
|
15
|
-
export { getDbKey, getUrlKey, getListKeyFromUrl } from './lib/case-utils.js';
|
|
15
|
+
export { getDbKey, getUrlKey, getListKeyFromUrl, resolveListKeyFromUrl } from './lib/case-utils.js';
|
|
16
16
|
// Label seam — resolves the field that represents a row as a single label
|
|
17
17
|
// (projection) and reads it off a row (render). Used by the admin UI for
|
|
18
18
|
// relationship cells, dropdown options, and page headings.
|
|
@@ -22,6 +22,12 @@ export { getLabelFieldName, getItemLabel } from './config/label.js';
|
|
|
22
22
|
export { resolveNavCounts, isListQueryStaticallyDenied } from './config/nav-count.js';
|
|
23
23
|
// Validation error surfaced by write operations
|
|
24
24
|
export { ValidationError } from './hooks/index.js';
|
|
25
|
+
// Resolves which columns (and, where recoverable, which named constraint) a
|
|
26
|
+
// caught P2002 unique-constraint violation hit — normalising Prisma 7 driver
|
|
27
|
+
// adapters' undocumented error shape to the documented `meta.target` one, so
|
|
28
|
+
// a caller of `context.db.*` never needs to reach into adapter internals
|
|
29
|
+
// (see issue #979).
|
|
30
|
+
export { uniqueConstraintOf } from './lib/prisma-errors.js';
|
|
25
31
|
// Thrown by a read when a caller-supplied `include` names a relation nested
|
|
26
32
|
// deeper than the Access Filter can scope (see ADR-0022). Distinct from
|
|
27
33
|
// `ValidationError` — this is the engine refusing to return unscoped data, not
|
|
@@ -38,6 +44,13 @@ export { ResolveOutputCycleError } from './access/index.js';
|
|
|
38
44
|
// a result it cannot treat as an allow/deny decision, not a user-input
|
|
39
45
|
// validation failure.
|
|
40
46
|
export { InvalidFieldAccessResultError } from './access/index.js';
|
|
47
|
+
// Thrown by the write pipeline's create strategy and by the nested-create
|
|
48
|
+
// path when operation-level `create` access returns anything other than a
|
|
49
|
+
// strict boolean (see #1009, ADR-0022, and ADR-0030). A filter — the shape
|
|
50
|
+
// `query`/`update`/`delete` legitimately return — cannot be honoured on
|
|
51
|
+
// create: there is no existing row and no way to test it against input data,
|
|
52
|
+
// so it is refused loudly rather than silently treated as a full allow.
|
|
53
|
+
export { InvalidCreateAccessResultError } from './access/index.js';
|
|
41
54
|
// Thrown by a read when a caller-supplied `where` filters on a relation whose
|
|
42
55
|
// related list denies operation-level `query` access outright (see #916 and
|
|
43
56
|
// ADR-0022). Distinct from `ValidationError` for the same reason as
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,8CAA8C;AAC9C,EAAE;AACF,kEAAkE;AAClE,gEAAgE;AAChE,gEAAgE;AAChE,6DAA6D;AAC7D,yEAAyE;AACzE,kEAAkE;AAElE,kBAAkB;AAClB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AAgChD,kBAAkB;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAO/C,0EAA0E;AAC1E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/case-utils.d.ts
CHANGED
|
@@ -14,4 +14,19 @@ export declare function kebabToCamel(str: string): string;
|
|
|
14
14
|
export declare function getDbKey(listKey: string): string;
|
|
15
15
|
export declare function getUrlKey(listKey: string): string;
|
|
16
16
|
export declare function getListKeyFromUrl(urlSegment: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Resolves a URL segment back to the list key that produced it, by checking
|
|
19
|
+
* each candidate key against `getUrlKey` — the same helper that builds the
|
|
20
|
+
* URL — rather than reconstructing a key by string transformation the way
|
|
21
|
+
* `getListKeyFromUrl` does. That reconstruction is lossy for any list key
|
|
22
|
+
* that isn't strict PascalCase (e.g. a camelCase key from a derived list),
|
|
23
|
+
* so this is the config-aware resolver route lookups should use instead.
|
|
24
|
+
*
|
|
25
|
+
* Returns `undefined` when no candidate key's URL matches — callers render
|
|
26
|
+
* their usual "not found" state rather than treating this as an error.
|
|
27
|
+
* Throws if more than one candidate key produces the same URL segment: that
|
|
28
|
+
* is a configuration error (two list keys collide once case-folded to a
|
|
29
|
+
* URL) and must be reported, not resolved by silently picking one.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveListKeyFromUrl(urlSegment: string, listKeys: string[]): string | undefined;
|
|
17
32
|
//# sourceMappingURL=case-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"case-utils.d.ts","sourceRoot":"","sources":["../../src/lib/case-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIjD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE5D"}
|
|
1
|
+
{"version":3,"file":"case-utils.d.ts","sourceRoot":"","sources":["../../src/lib/case-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIjD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAUhG"}
|
package/dist/lib/case-utils.js
CHANGED
|
@@ -33,4 +33,25 @@ export function getUrlKey(listKey) {
|
|
|
33
33
|
export function getListKeyFromUrl(urlSegment) {
|
|
34
34
|
return kebabToPascal(urlSegment);
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Resolves a URL segment back to the list key that produced it, by checking
|
|
38
|
+
* each candidate key against `getUrlKey` — the same helper that builds the
|
|
39
|
+
* URL — rather than reconstructing a key by string transformation the way
|
|
40
|
+
* `getListKeyFromUrl` does. That reconstruction is lossy for any list key
|
|
41
|
+
* that isn't strict PascalCase (e.g. a camelCase key from a derived list),
|
|
42
|
+
* so this is the config-aware resolver route lookups should use instead.
|
|
43
|
+
*
|
|
44
|
+
* Returns `undefined` when no candidate key's URL matches — callers render
|
|
45
|
+
* their usual "not found" state rather than treating this as an error.
|
|
46
|
+
* Throws if more than one candidate key produces the same URL segment: that
|
|
47
|
+
* is a configuration error (two list keys collide once case-folded to a
|
|
48
|
+
* URL) and must be reported, not resolved by silently picking one.
|
|
49
|
+
*/
|
|
50
|
+
export function resolveListKeyFromUrl(urlSegment, listKeys) {
|
|
51
|
+
const matches = listKeys.filter((listKey) => getUrlKey(listKey) === urlSegment);
|
|
52
|
+
if (matches.length > 1) {
|
|
53
|
+
throw new Error(`Ambiguous list URL "${urlSegment}": list keys ${matches.map((key) => `"${key}"`).join(', ')} all resolve to this URL. Rename these lists so their URLs are unique.`);
|
|
54
|
+
}
|
|
55
|
+
return matches[0];
|
|
56
|
+
}
|
|
36
57
|
//# sourceMappingURL=case-utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"case-utils.js","sourceRoot":"","sources":["../../src/lib/case-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AACnD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,OAAO,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE;QACnD,OAAO,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,CAAA;IAC/D,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,OAAO,GAAG;SACP,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3D,IAAI,CAAC,EAAE,CAAC,CAAA;AACb,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAA;AAClE,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAe;IACtC,OAAO,aAAa,CAAC,OAAO,CAAC,CAAA;AAC/B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,OAAO,aAAa,CAAC,OAAO,CAAC,CAAA;AAC/B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IAClD,OAAO,aAAa,CAAC,UAAU,CAAC,CAAA;AAClC,CAAC"}
|
|
1
|
+
{"version":3,"file":"case-utils.js","sourceRoot":"","sources":["../../src/lib/case-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AACnD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,OAAO,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE;QACnD,OAAO,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,CAAA;IAC/D,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,OAAO,GAAG;SACP,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3D,IAAI,CAAC,EAAE,CAAC,CAAA;AACb,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAA;AAClE,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAe;IACtC,OAAO,aAAa,CAAC,OAAO,CAAC,CAAA;AAC/B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,OAAO,aAAa,CAAC,OAAO,CAAC,CAAA;AAC/B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IAClD,OAAO,aAAa,CAAC,UAAU,CAAC,CAAA;AAClC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,qBAAqB,CAAC,UAAkB,EAAE,QAAkB;IAC1E,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,UAAU,CAAC,CAAA;IAE/E,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,uBAAuB,UAAU,gBAAgB,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,wEAAwE,CACrK,CAAA;IACH,CAAC;IAED,OAAO,OAAO,CAAC,CAAC,CAAC,CAAA;AACnB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { pascalToCamel, pascalToKebab, kebabToPascal, kebabToCamel, getDbKey, getUrlKey, getListKeyFromUrl, } from './case-utils.js';
|
|
2
|
+
import { pascalToCamel, pascalToKebab, kebabToPascal, kebabToCamel, getDbKey, getUrlKey, getListKeyFromUrl, resolveListKeyFromUrl, } from './case-utils.js';
|
|
3
3
|
describe('Case Conversion Utilities', () => {
|
|
4
4
|
describe('pascalToCamel', () => {
|
|
5
5
|
it('should convert single word PascalCase to camelCase', () => {
|
|
@@ -74,6 +74,28 @@ describe('Case Conversion Utilities', () => {
|
|
|
74
74
|
expect(getListKeyFromUrl('blog-post')).toBe('BlogPost');
|
|
75
75
|
});
|
|
76
76
|
});
|
|
77
|
+
describe('resolveListKeyFromUrl', () => {
|
|
78
|
+
it('resolves a PascalCase list key from its URL segment', () => {
|
|
79
|
+
expect(resolveListKeyFromUrl('blog-post', ['User', 'BlogPost'])).toBe('BlogPost');
|
|
80
|
+
});
|
|
81
|
+
it('resolves a camelCase list key (e.g. a derived plugin list) from its URL segment', () => {
|
|
82
|
+
// getListKeyFromUrl('oauth-application') would reconstruct 'OauthApplication',
|
|
83
|
+
// which isn't a key in this list — that's the bug this resolver fixes.
|
|
84
|
+
expect(resolveListKeyFromUrl('oauth-application', ['oauthApplication'])).toBe('oauthApplication');
|
|
85
|
+
});
|
|
86
|
+
it('returns undefined for a URL segment matching no list key', () => {
|
|
87
|
+
expect(resolveListKeyFromUrl('does-not-exist', ['User', 'BlogPost'])).toBeUndefined();
|
|
88
|
+
});
|
|
89
|
+
it('throws when two distinct list keys produce the same URL segment', () => {
|
|
90
|
+
expect(() => resolveListKeyFromUrl('oauth-application', ['oauthApplication', 'OauthApplication'])).toThrow(/Ambiguous list URL/);
|
|
91
|
+
});
|
|
92
|
+
it('is derived from getUrlKey, so it cannot drift from how URLs are built', () => {
|
|
93
|
+
const listKeys = ['User', 'AuthUser', 'BlogPost', 'oauthApplication'];
|
|
94
|
+
for (const listKey of listKeys) {
|
|
95
|
+
expect(resolveListKeyFromUrl(getUrlKey(listKey), listKeys)).toBe(listKey);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
});
|
|
77
99
|
describe('Round-trip conversions', () => {
|
|
78
100
|
it('should maintain consistency: PascalCase -> kebab-case -> PascalCase', () => {
|
|
79
101
|
const original = 'BlogPost';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"case-utils.test.js","sourceRoot":"","sources":["../../src/lib/case-utils.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,iBAAiB,
|
|
1
|
+
{"version":3,"file":"case-utils.test.js","sourceRoot":"","sources":["../../src/lib/case-utils.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface UniqueConstraintInfo {
|
|
2
|
+
/** Column names covered by the violated constraint, quote-stripped. */
|
|
3
|
+
fields: string[];
|
|
4
|
+
/**
|
|
5
|
+
* The violated constraint's name, when recoverable from the error.
|
|
6
|
+
*
|
|
7
|
+
* Known limit: this is parsed out of Postgres' English-locale error text
|
|
8
|
+
* (`cause.originalMessage`) — the adapter exposes no structured field for
|
|
9
|
+
* it. A server running under a non-English `lc_messages` locale will not
|
|
10
|
+
* match, leaving this `undefined` while `fields` (structured data) still
|
|
11
|
+
* resolves correctly.
|
|
12
|
+
*/
|
|
13
|
+
constraintName?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Resolve which columns — and, where recoverable, which named constraint — a
|
|
17
|
+
* Prisma `P2002` unique-constraint violation hit.
|
|
18
|
+
*
|
|
19
|
+
* Prisma documents `error.meta.target` for this. Under Prisma 7 driver
|
|
20
|
+
* adapters (verified against `@prisma/adapter-pg` and PGlite; see issue #979)
|
|
21
|
+
* that field is `undefined` instead — the same information sits at
|
|
22
|
+
* `error.meta.driverAdapterError.cause`, with the constraint name only
|
|
23
|
+
* recoverable as free text inside `cause.originalMessage`. This normalises
|
|
24
|
+
* both shapes to one stable result so callers never need to reach into that
|
|
25
|
+
* adapter-specific structure themselves.
|
|
26
|
+
*
|
|
27
|
+
* A derived constraint name is truncated by Postgres at its 63-character
|
|
28
|
+
* identifier limit, and one row can violate two unique indexes at once (with
|
|
29
|
+
* Postgres reporting whichever it checked first) — an index an application
|
|
30
|
+
* means to branch on should be named explicitly, and a caller may still need
|
|
31
|
+
* to re-read the colliding row to fully disambiguate.
|
|
32
|
+
*
|
|
33
|
+
* Returns `undefined` when `error` isn't a `P2002` with any recoverable
|
|
34
|
+
* column or constraint information — never throws, since the adapter error
|
|
35
|
+
* shape is untrusted and every level of it may be absent.
|
|
36
|
+
*/
|
|
37
|
+
export declare function uniqueConstraintOf(error: unknown): UniqueConstraintInfo | undefined;
|
|
38
|
+
//# sourceMappingURL=prisma-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prisma-errors.d.ts","sourceRoot":"","sources":["../../src/lib/prisma-errors.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,oBAAoB;IACnC,uEAAuE;IACvE,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,GAAG,SAAS,CA8BnF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Postgres quotes an identifier in `constraint.fields` only when it needed
|
|
2
|
+
// quoting (e.g. camelCase columns), so `"tenantId"` and `slug` are both valid
|
|
3
|
+
// entries for the same array.
|
|
4
|
+
function stripIdentifierQuotes(field) {
|
|
5
|
+
const match = field.match(/^"(.*)"$/);
|
|
6
|
+
return match ? match[1] : field;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Resolve which columns — and, where recoverable, which named constraint — a
|
|
10
|
+
* Prisma `P2002` unique-constraint violation hit.
|
|
11
|
+
*
|
|
12
|
+
* Prisma documents `error.meta.target` for this. Under Prisma 7 driver
|
|
13
|
+
* adapters (verified against `@prisma/adapter-pg` and PGlite; see issue #979)
|
|
14
|
+
* that field is `undefined` instead — the same information sits at
|
|
15
|
+
* `error.meta.driverAdapterError.cause`, with the constraint name only
|
|
16
|
+
* recoverable as free text inside `cause.originalMessage`. This normalises
|
|
17
|
+
* both shapes to one stable result so callers never need to reach into that
|
|
18
|
+
* adapter-specific structure themselves.
|
|
19
|
+
*
|
|
20
|
+
* A derived constraint name is truncated by Postgres at its 63-character
|
|
21
|
+
* identifier limit, and one row can violate two unique indexes at once (with
|
|
22
|
+
* Postgres reporting whichever it checked first) — an index an application
|
|
23
|
+
* means to branch on should be named explicitly, and a caller may still need
|
|
24
|
+
* to re-read the colliding row to fully disambiguate.
|
|
25
|
+
*
|
|
26
|
+
* Returns `undefined` when `error` isn't a `P2002` with any recoverable
|
|
27
|
+
* column or constraint information — never throws, since the adapter error
|
|
28
|
+
* shape is untrusted and every level of it may be absent.
|
|
29
|
+
*/
|
|
30
|
+
export function uniqueConstraintOf(error) {
|
|
31
|
+
if (!error ||
|
|
32
|
+
typeof error !== 'object' ||
|
|
33
|
+
!('code' in error) ||
|
|
34
|
+
error.code !== 'P2002') {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
const meta = error.meta;
|
|
38
|
+
if (meta?.target && Array.isArray(meta.target)) {
|
|
39
|
+
return { fields: meta.target };
|
|
40
|
+
}
|
|
41
|
+
const cause = meta?.driverAdapterError?.cause;
|
|
42
|
+
const rawFields = cause?.constraint?.fields;
|
|
43
|
+
const fields = Array.isArray(rawFields)
|
|
44
|
+
? rawFields.filter((f) => typeof f === 'string').map(stripIdentifierQuotes)
|
|
45
|
+
: [];
|
|
46
|
+
const constraintName = typeof cause?.originalMessage === 'string'
|
|
47
|
+
? cause.originalMessage.match(/unique constraint "([^"]+)"/)?.[1]
|
|
48
|
+
: undefined;
|
|
49
|
+
if (fields.length === 0 && !constraintName)
|
|
50
|
+
return undefined;
|
|
51
|
+
return constraintName ? { fields, constraintName } : { fields };
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=prisma-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prisma-errors.js","sourceRoot":"","sources":["../../src/lib/prisma-errors.ts"],"names":[],"mappings":"AAUA,2EAA2E;AAC3E,8EAA8E;AAC9E,8BAA8B;AAC9B,SAAS,qBAAqB,CAAC,KAAa;IAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;IACrC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;AACjC,CAAC;AAiBD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,IACE,CAAC,KAAK;QACN,OAAO,KAAK,KAAK,QAAQ;QACzB,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC;QACjB,KAA4B,CAAC,IAAI,KAAK,OAAO,EAC9C,CAAC;QACD,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,IAAI,GAAI,KAAoC,CAAC,IAAI,CAAA;IAEvD,IAAI,IAAI,EAAE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/C,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAA;IAChC,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,EAAE,kBAAkB,EAAE,KAAK,CAAA;IAC7C,MAAM,SAAS,GAAG,KAAK,EAAE,UAAU,EAAE,MAAM,CAAA;IAC3C,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;QACrC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,qBAAqB,CAAC;QACxF,CAAC,CAAC,EAAE,CAAA;IAEN,MAAM,cAAc,GAClB,OAAO,KAAK,EAAE,eAAe,KAAK,QAAQ;QACxC,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,6BAA6B,CAAC,EAAE,CAAC,CAAC,CAAC;QACjE,CAAC,CAAC,SAAS,CAAA;IAEf,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,cAAc;QAAE,OAAO,SAAS,CAAA;IAE5D,OAAO,cAAc,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAA;AACjE,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How many levels deep the `query` tool's `fields` projection schema
|
|
3
|
+
* enumerates a list's relations: the root list's own fields (level 1), and
|
|
4
|
+
* for each relation, the related list's own scalar/virtual fields (level 2).
|
|
5
|
+
* A relation named at level 2 is not itself selectable further — reaching
|
|
6
|
+
* past it is a second tool call, the same round-trip a bare read already
|
|
7
|
+
* assumes. Deliberately shallower than `READ_INCLUDE_MAX_DEPTH` (5) so no
|
|
8
|
+
* schema-conforming request can reach the engine's depth refusal.
|
|
9
|
+
*
|
|
10
|
+
* Fixed (not configurable) by design (ADR-0033, ADR-0026's position on the
|
|
11
|
+
* depth cap) — `generateFieldsProjectionSchema` and `resolveFieldsProjection`
|
|
12
|
+
* (`projection.ts`) are hand-written for exactly this depth (one loop over
|
|
13
|
+
* the root list's fields, one nested loop over a relation's), not driven by
|
|
14
|
+
* this value at runtime. It exists so the depth has one documented, tested
|
|
15
|
+
* name rather than an unexplained "2" in two places; changing it is a
|
|
16
|
+
* deliberate rewrite of both functions, not a config knob.
|
|
17
|
+
*/
|
|
18
|
+
export declare const MCP_FIELDS_SCHEMA_DEPTH = 2;
|
|
19
|
+
/** Row cap applied to a nested to-many relation in a `fields` projection when the caller omits `take`. */
|
|
20
|
+
export declare const MCP_NESTED_TAKE_DEFAULT = 5;
|
|
21
|
+
/** Hard ceiling a nested to-many relation's `take` is clamped to, regardless of what the caller requests. */
|
|
22
|
+
export declare const MCP_NESTED_TAKE_MAX = 50;
|
|
23
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/mcp/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC,0GAA0G;AAC1G,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC,6GAA6G;AAC7G,eAAO,MAAM,mBAAmB,KAAK,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How many levels deep the `query` tool's `fields` projection schema
|
|
3
|
+
* enumerates a list's relations: the root list's own fields (level 1), and
|
|
4
|
+
* for each relation, the related list's own scalar/virtual fields (level 2).
|
|
5
|
+
* A relation named at level 2 is not itself selectable further — reaching
|
|
6
|
+
* past it is a second tool call, the same round-trip a bare read already
|
|
7
|
+
* assumes. Deliberately shallower than `READ_INCLUDE_MAX_DEPTH` (5) so no
|
|
8
|
+
* schema-conforming request can reach the engine's depth refusal.
|
|
9
|
+
*
|
|
10
|
+
* Fixed (not configurable) by design (ADR-0033, ADR-0026's position on the
|
|
11
|
+
* depth cap) — `generateFieldsProjectionSchema` and `resolveFieldsProjection`
|
|
12
|
+
* (`projection.ts`) are hand-written for exactly this depth (one loop over
|
|
13
|
+
* the root list's fields, one nested loop over a relation's), not driven by
|
|
14
|
+
* this value at runtime. It exists so the depth has one documented, tested
|
|
15
|
+
* name rather than an unexplained "2" in two places; changing it is a
|
|
16
|
+
* deliberate rewrite of both functions, not a config knob.
|
|
17
|
+
*/
|
|
18
|
+
export const MCP_FIELDS_SCHEMA_DEPTH = 2;
|
|
19
|
+
/** Row cap applied to a nested to-many relation in a `fields` projection when the caller omits `take`. */
|
|
20
|
+
export const MCP_NESTED_TAKE_DEFAULT = 5;
|
|
21
|
+
/** Hard ceiling a nested to-many relation's `take` is clamped to, regardless of what the caller requests. */
|
|
22
|
+
export const MCP_NESTED_TAKE_MAX = 50;
|
|
23
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/mcp/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAA;AAExC,0GAA0G;AAC1G,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAA;AAExC,6GAA6G;AAC7G,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FieldConfig } from '../config/types.js';
|
|
2
|
+
/** JSON Schema for one field's own value — shared by the create/update `data` schema and the `query` tool's `fields` projection schema. */
|
|
3
|
+
export declare function fieldToJsonSchema(fieldName: string, fieldConfig: any): Record<string, unknown>;
|
|
4
|
+
export declare function generateFieldSchemas(fields: Record<string, FieldConfig>, operation: 'create' | 'update'): {
|
|
5
|
+
properties: Record<string, unknown>;
|
|
6
|
+
required: string[];
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=field-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-schema.d.ts","sourceRoot":"","sources":["../../src/mcp/field-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD,2IAA2I;AAC3I,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EAEjB,WAAW,EAAE,GAAG,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgDzB;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACnC,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAC7B;IACD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACnC,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB,CAoBA"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** JSON Schema for one field's own value — shared by the create/update `data` schema and the `query` tool's `fields` projection schema. */
|
|
2
|
+
export function fieldToJsonSchema(fieldName,
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Field configs have varying structures
|
|
4
|
+
fieldConfig) {
|
|
5
|
+
const baseSchema = {};
|
|
6
|
+
switch (fieldConfig.type) {
|
|
7
|
+
case 'text':
|
|
8
|
+
case 'password':
|
|
9
|
+
baseSchema.type = 'string';
|
|
10
|
+
if (fieldConfig.validation?.length) {
|
|
11
|
+
if (fieldConfig.validation.length.min)
|
|
12
|
+
baseSchema.minLength = fieldConfig.validation.length.min;
|
|
13
|
+
if (fieldConfig.validation.length.max)
|
|
14
|
+
baseSchema.maxLength = fieldConfig.validation.length.max;
|
|
15
|
+
}
|
|
16
|
+
break;
|
|
17
|
+
case 'integer':
|
|
18
|
+
baseSchema.type = 'number';
|
|
19
|
+
if (fieldConfig.validation?.min !== undefined)
|
|
20
|
+
baseSchema.minimum = fieldConfig.validation.min;
|
|
21
|
+
if (fieldConfig.validation?.max !== undefined)
|
|
22
|
+
baseSchema.maximum = fieldConfig.validation.max;
|
|
23
|
+
break;
|
|
24
|
+
case 'checkbox':
|
|
25
|
+
baseSchema.type = 'boolean';
|
|
26
|
+
break;
|
|
27
|
+
case 'timestamp':
|
|
28
|
+
baseSchema.type = 'string';
|
|
29
|
+
baseSchema.format = 'date-time';
|
|
30
|
+
break;
|
|
31
|
+
case 'select':
|
|
32
|
+
baseSchema.type = 'string';
|
|
33
|
+
if (fieldConfig.options) {
|
|
34
|
+
baseSchema.enum = fieldConfig.options.map((opt) => opt.value);
|
|
35
|
+
}
|
|
36
|
+
break;
|
|
37
|
+
case 'relationship':
|
|
38
|
+
baseSchema.type = 'object';
|
|
39
|
+
baseSchema.properties = {
|
|
40
|
+
connect: {
|
|
41
|
+
type: 'object',
|
|
42
|
+
properties: {
|
|
43
|
+
id: { type: 'string' },
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
break;
|
|
48
|
+
default:
|
|
49
|
+
baseSchema.type = 'string';
|
|
50
|
+
}
|
|
51
|
+
return baseSchema;
|
|
52
|
+
}
|
|
53
|
+
export function generateFieldSchemas(fields, operation) {
|
|
54
|
+
const properties = {};
|
|
55
|
+
const required = [];
|
|
56
|
+
for (const [fieldName, fieldConfig] of Object.entries(fields)) {
|
|
57
|
+
if (['id', 'createdAt', 'updatedAt'].includes(fieldName))
|
|
58
|
+
continue;
|
|
59
|
+
properties[fieldName] = fieldToJsonSchema(fieldName, fieldConfig);
|
|
60
|
+
if (operation === 'create' &&
|
|
61
|
+
'validation' in fieldConfig &&
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Validation property varies by field type
|
|
63
|
+
fieldConfig.validation?.isRequired) {
|
|
64
|
+
required.push(fieldName);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { properties, required };
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=field-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-schema.js","sourceRoot":"","sources":["../../src/mcp/field-schema.ts"],"names":[],"mappings":"AAEA,2IAA2I;AAC3I,MAAM,UAAU,iBAAiB,CAC/B,SAAiB;AACjB,uGAAuG;AACvG,WAAgB;IAEhB,MAAM,UAAU,GAA4B,EAAE,CAAA;IAE9C,QAAQ,WAAW,CAAC,IAAI,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC;QACZ,KAAK,UAAU;YACb,UAAU,CAAC,IAAI,GAAG,QAAQ,CAAA;YAC1B,IAAI,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;gBACnC,IAAI,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG;oBACnC,UAAU,CAAC,SAAS,GAAG,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAA;gBAC1D,IAAI,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG;oBACnC,UAAU,CAAC,SAAS,GAAG,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAA;YAC5D,CAAC;YACD,MAAK;QACP,KAAK,SAAS;YACZ,UAAU,CAAC,IAAI,GAAG,QAAQ,CAAA;YAC1B,IAAI,WAAW,CAAC,UAAU,EAAE,GAAG,KAAK,SAAS;gBAAE,UAAU,CAAC,OAAO,GAAG,WAAW,CAAC,UAAU,CAAC,GAAG,CAAA;YAC9F,IAAI,WAAW,CAAC,UAAU,EAAE,GAAG,KAAK,SAAS;gBAAE,UAAU,CAAC,OAAO,GAAG,WAAW,CAAC,UAAU,CAAC,GAAG,CAAA;YAC9F,MAAK;QACP,KAAK,UAAU;YACb,UAAU,CAAC,IAAI,GAAG,SAAS,CAAA;YAC3B,MAAK;QACP,KAAK,WAAW;YACd,UAAU,CAAC,IAAI,GAAG,QAAQ,CAAA;YAC1B,UAAU,CAAC,MAAM,GAAG,WAAW,CAAA;YAC/B,MAAK;QACP,KAAK,QAAQ;YACX,UAAU,CAAC,IAAI,GAAG,QAAQ,CAAA;YAC1B,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;gBACxB,UAAU,CAAC,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAsB,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YAClF,CAAC;YACD,MAAK;QACP,KAAK,cAAc;YACjB,UAAU,CAAC,IAAI,GAAG,QAAQ,CAAA;YAC1B,UAAU,CAAC,UAAU,GAAG;gBACtB,OAAO,EAAE;oBACP,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;qBACvB;iBACF;aACF,CAAA;YACD,MAAK;QACP;YACE,UAAU,CAAC,IAAI,GAAG,QAAQ,CAAA;IAC9B,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,MAAmC,EACnC,SAA8B;IAK9B,MAAM,UAAU,GAA4B,EAAE,CAAA;IAC9C,MAAM,QAAQ,GAAa,EAAE,CAAA;IAE7B,KAAK,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9D,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,SAAQ;QAElE,UAAU,CAAC,SAAS,CAAC,GAAG,iBAAiB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;QAEjE,IACE,SAAS,KAAK,QAAQ;YACtB,YAAY,IAAI,WAAW;YAC3B,0GAA0G;YACzG,WAAW,CAAC,UAAkB,EAAE,UAAU,EAC3C,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAA;AACjC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/mcp/handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/mcp/handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,oBAAoB,CAAA;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAKvD,OAAO,KAAK,EAAc,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAShE;;;;GAIG;AACH,KAAK,cAAc,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAA;AAqChE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,MAAM,EAAE,cAAc,CAAA;IACtB,UAAU,EAAE,kBAAkB,CAAA;IAC9B,UAAU,EAAE,CAAC,OAAO,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,aAAa,CAAC,CAAA;CACjE,GAAG;IACF,GAAG,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IACxC,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IACzC,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CAC5C,CAkFA"}
|