@dereekb/firebase 13.11.17 → 13.12.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/eslint/index.cjs.js +7229 -1551
- package/eslint/index.esm.js +7203 -1552
- package/eslint/package.json +4 -2
- package/eslint/rollup.alias-internal.config.d.ts +1 -0
- package/eslint/src/lib/firebase-rules-text.d.ts +121 -0
- package/eslint/src/lib/firestore-rules-parser.d.ts +61 -0
- package/eslint/src/lib/index.d.ts +10 -0
- package/eslint/src/lib/plugin.d.ts +16 -0
- package/eslint/src/lib/predicate-evaluator.d.ts +47 -0
- package/eslint/src/lib/require-api-details-for-crud-function.rule.d.ts +83 -0
- package/eslint/src/lib/require-complete-crud-function-config-map.rule.d.ts +61 -0
- package/eslint/src/lib/require-dbx-model-companion-tags.rule.d.ts +47 -0
- package/eslint/src/lib/require-dbx-model-service-factory-tag.rule.d.ts +56 -0
- package/eslint/src/lib/require-firestore-constraint-type-parameter.rule.d.ts +45 -0
- package/eslint/src/lib/require-firestore-rule-for-service-model.rule.d.ts +115 -0
- package/eslint/src/lib/require-service-factory-for-dbx-model.rule.d.ts +80 -0
- package/eslint/src/lib/require-storagefile-policy-matches-rules.rule.d.ts +79 -0
- package/eslint/src/lib/storage-rules-parser.d.ts +38 -0
- package/index.cjs.js +53 -5
- package/index.esm.js +46 -6
- package/package.json +5 -5
- package/src/lib/common/auth/auth.d.ts +8 -0
- package/src/lib/common/auth/oidc/oidc.d.ts +7 -5
- package/src/lib/common/model/function.d.ts +12 -1
- package/src/lib/model/notification/notification.d.ts +6 -0
- package/src/lib/model/oidcmodel/oidcmodel.d.ts +1 -0
- package/src/lib/model/storagefile/storagefile.api.d.ts +113 -2
- package/src/lib/model/storagefile/storagefile.d.ts +2 -0
- package/src/lib/model/storagefile/storagefile.upload.d.ts +33 -1
- package/src/lib/model/system/system.d.ts +1 -0
- package/test/index.cjs.js +2 -4
- package/test/index.esm.js +2 -4
- package/test/package.json +6 -6
- package/eslint/src/lib/comments.d.ts +0 -112
- package/eslint/src/lib/dbx-tag-families.d.ts +0 -280
- package/eslint/src/lib/jsdoc-parser.d.ts +0 -116
package/eslint/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase/eslint",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.12.0",
|
|
4
4
|
"peerDependencies": {
|
|
5
|
+
"@marcbachmann/cel-js": "^7.6.1",
|
|
5
6
|
"@typescript-eslint/utils": "8.59.3"
|
|
6
7
|
},
|
|
7
8
|
"devDependencies": {
|
|
8
|
-
"@dereekb/util": "13.
|
|
9
|
+
"@dereekb/util": "13.12.0",
|
|
10
|
+
"@marcbachmann/cel-js": "^7.6.1",
|
|
9
11
|
"@typescript-eslint/parser": "8.59.3",
|
|
10
12
|
"eslint": "10.4.0"
|
|
11
13
|
},
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function applyInternalAliases(config: any, _options: any): Promise<any>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { Maybe } from '@dereekb/util';
|
|
2
|
+
/**
|
|
3
|
+
* One brace-delimited block extracted by {@link extractTopLevelBlocks}: a `match`, a
|
|
4
|
+
* `function`, a `service`, or any other `<header> { ... }` shape in a Firebase rules
|
|
5
|
+
* source. Offsets are relative to the body that was scanned.
|
|
6
|
+
*/
|
|
7
|
+
export interface RawBlock {
|
|
8
|
+
readonly header: string;
|
|
9
|
+
readonly body: string;
|
|
10
|
+
readonly headerStart: number;
|
|
11
|
+
readonly bodyStart: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Strips `//`-style line comments from a Firebase rules source string so the brace
|
|
15
|
+
* walker doesn't trip on braces / semicolons embedded in comments.
|
|
16
|
+
*
|
|
17
|
+
* @param source - Raw rules source.
|
|
18
|
+
* @returns The source with line comments replaced by equal-length whitespace (so offsets are preserved).
|
|
19
|
+
*/
|
|
20
|
+
export declare function stripLineComments(source: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Masks `{name}` and `{name=**}` path-variable braces with private-use characters so the
|
|
23
|
+
* brace walker never confuses them with block braces. Same-length substitution preserves
|
|
24
|
+
* offsets. Catch-all deny patterns retain a recognizable shape because the inner text
|
|
25
|
+
* (e.g. `allPaths=**`) is untouched.
|
|
26
|
+
*
|
|
27
|
+
* @param source - The (comment-stripped) source.
|
|
28
|
+
* @returns The source with path-variable braces masked.
|
|
29
|
+
*/
|
|
30
|
+
export declare function maskPathVariables(source: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Reverses {@link maskPathVariables} so header / path text reported to callers shows the
|
|
33
|
+
* original `{name}` form.
|
|
34
|
+
*
|
|
35
|
+
* @param text - Text containing masked path variables.
|
|
36
|
+
* @returns The text with `{name}` braces restored.
|
|
37
|
+
*/
|
|
38
|
+
export declare function unmaskPathVariables(text: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Resolves the 1-based line and 1-based column of a character offset in the source string.
|
|
41
|
+
*
|
|
42
|
+
* @param source - The original source.
|
|
43
|
+
* @param index - Zero-based character offset.
|
|
44
|
+
* @returns The line/column pair.
|
|
45
|
+
*/
|
|
46
|
+
export declare function indexToLineColumn(source: string, index: number): {
|
|
47
|
+
line: number;
|
|
48
|
+
column: number;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Finds the matching closing brace for the opening brace at `openIndex` in `source`,
|
|
52
|
+
* respecting nesting. Returns the index of the closing brace, or -1 when unbalanced.
|
|
53
|
+
* `source` must be the masked version so path-variable braces don't pollute the count.
|
|
54
|
+
*
|
|
55
|
+
* @param source - The masked source string.
|
|
56
|
+
* @param openIndex - Index of an opening brace.
|
|
57
|
+
* @returns Index of the matching closing brace, or -1.
|
|
58
|
+
*/
|
|
59
|
+
export declare function findMatchingBrace(source: string, openIndex: number): number;
|
|
60
|
+
/**
|
|
61
|
+
* Walks backward from `openIndex` to find where this block's header starts: just past the
|
|
62
|
+
* previous `;` or `}` (now always a true block-sibling close, since path-variable braces
|
|
63
|
+
* are masked), then forward through whitespace to the first significant char.
|
|
64
|
+
*
|
|
65
|
+
* @param body - The masked source slice being scanned.
|
|
66
|
+
* @param cursor - The search start position (right after the previous sibling's `}`).
|
|
67
|
+
* @param openIndex - Index of this block's opening brace.
|
|
68
|
+
* @returns Start index of the header.
|
|
69
|
+
*/
|
|
70
|
+
export declare function findHeaderStart(body: string, cursor: number, openIndex: number): number;
|
|
71
|
+
/**
|
|
72
|
+
* Extracts top-level brace-delimited blocks inside `body` (path-variable-masked). Each
|
|
73
|
+
* block carries its header text (with masking still applied — callers unmask when
|
|
74
|
+
* reporting) and the inner body. Function definitions, match blocks, and `service` /
|
|
75
|
+
* bucket-root wrappers are all returned as raw blocks.
|
|
76
|
+
*
|
|
77
|
+
* @param body - The masked source slice to scan.
|
|
78
|
+
* @returns The list of top-level child blocks.
|
|
79
|
+
*/
|
|
80
|
+
export declare function extractTopLevelBlocks(body: string): RawBlock[];
|
|
81
|
+
/**
|
|
82
|
+
* Pulls the match-path segment out of a `match /<segment> { ... }` header. The segment is
|
|
83
|
+
* unmasked before being returned so callers see original `{name}` braces.
|
|
84
|
+
*
|
|
85
|
+
* @param header - The (still-masked) header text.
|
|
86
|
+
* @returns The path segment with the leading `/`, or null when the header is not a match.
|
|
87
|
+
*/
|
|
88
|
+
export declare function matchHeaderPath(header: string): Maybe<string>;
|
|
89
|
+
/**
|
|
90
|
+
* Pulls the function name out of a `function <name>() { ... }` header.
|
|
91
|
+
*
|
|
92
|
+
* @param header - The header text.
|
|
93
|
+
* @returns The function name, or null when the header is not a function definition.
|
|
94
|
+
*/
|
|
95
|
+
export declare function functionHeaderName(header: string): Maybe<string>;
|
|
96
|
+
/**
|
|
97
|
+
* Pulls the `return <expression>` body out of a function definition's inner block. The
|
|
98
|
+
* body may span multiple lines (CEL expressions wrap freely across newlines); we capture
|
|
99
|
+
* everything from after `return ` to the closing `}`-relative end of `body`, then strip
|
|
100
|
+
* an optional trailing `;` and surrounding whitespace.
|
|
101
|
+
*
|
|
102
|
+
* @param body - The inner body of a function block (already line-comment-stripped).
|
|
103
|
+
* @returns The expression text after `return`, or null when no `return` is present.
|
|
104
|
+
*/
|
|
105
|
+
export declare function functionReturnExpression(body: string): Maybe<string>;
|
|
106
|
+
/**
|
|
107
|
+
* Joins a child match segment onto a parent path so nested matches resolve to absolute paths.
|
|
108
|
+
*
|
|
109
|
+
* @param parentPath - The accumulated parent path (e.g. `/uploads/u/{uid}`).
|
|
110
|
+
* @param childSegment - The child match's segment (e.g. `/avatar.img`).
|
|
111
|
+
* @returns The combined path.
|
|
112
|
+
*/
|
|
113
|
+
export declare function joinMatchPath(parentPath: string, childSegment: string): string;
|
|
114
|
+
/**
|
|
115
|
+
* Returns true when the unmasked segment is the catch-all `{var=**}` wildcard that means
|
|
116
|
+
* "any path" (used for deny rules like `match /{allPaths=**} { allow read, write: if false; }`).
|
|
117
|
+
*
|
|
118
|
+
* @param segment - The unmasked match segment to test.
|
|
119
|
+
* @returns True for catch-all wildcards.
|
|
120
|
+
*/
|
|
121
|
+
export declare function isCatchAllSegment(segment: string): boolean;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { Maybe } from '@dereekb/util';
|
|
2
|
+
/**
|
|
3
|
+
* One `match /<segment>` block in `firestore.rules`. Nested matches appear as `children`.
|
|
4
|
+
* `collectionName` is the first bare-identifier segment of the match path (e.g. `pr`,
|
|
5
|
+
* `gbe`, `sys`); it is `null` only when the match path is purely a `{path=**}` wildcard
|
|
6
|
+
* with no following collection segment.
|
|
7
|
+
*/
|
|
8
|
+
export interface ParsedFirestoreMatchBlock {
|
|
9
|
+
/**
|
|
10
|
+
* Raw unmasked path segment from `match /<segment>` (e.g. `/pr/{profile}`,
|
|
11
|
+
* `/{path=**}/gbe/{guestbookEntry}`, `/sys/hellosubscheckhqcompany`).
|
|
12
|
+
*/
|
|
13
|
+
readonly pathSegment: string;
|
|
14
|
+
/**
|
|
15
|
+
* First bare-identifier collection token in the path, or `null` when none. Used to pair
|
|
16
|
+
* a model identity's `collectionName` (e.g. `gb`, `gbe`) against a rules block.
|
|
17
|
+
*/
|
|
18
|
+
readonly collectionName: Maybe<string>;
|
|
19
|
+
/**
|
|
20
|
+
* True when the match path starts with `/{path=**}/` — a collection-group rule that
|
|
21
|
+
* matches the collection at any depth.
|
|
22
|
+
*/
|
|
23
|
+
readonly isCollectionGroup: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Children nested inside this block's body, in source order.
|
|
26
|
+
*/
|
|
27
|
+
readonly children: readonly ParsedFirestoreMatchBlock[];
|
|
28
|
+
/**
|
|
29
|
+
* Raw allow directive names declared on this block (e.g. `get`, `list`, `read`, `write`,
|
|
30
|
+
* `create`, `update`, `delete`). Empty when the block declares no `allow` statements at
|
|
31
|
+
* its own scope (children may still declare their own).
|
|
32
|
+
*/
|
|
33
|
+
readonly allowDirectives: readonly string[];
|
|
34
|
+
readonly sourceLine: number;
|
|
35
|
+
readonly sourceColumn: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Parses a `firestore.rules` source string and returns the tree of `match` blocks rooted
|
|
39
|
+
* at the implicit `match /databases/{database}/documents` envelope. Each block's
|
|
40
|
+
* `collectionName` is the first bare-identifier segment of its match path; nested
|
|
41
|
+
* subcollection matches appear as `children`.
|
|
42
|
+
*
|
|
43
|
+
* @param source - The raw rules source text.
|
|
44
|
+
* @returns The list of top-level match blocks in source order.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* const blocks = parseFirestoreRules(`
|
|
49
|
+
* service cloud.firestore {
|
|
50
|
+
* match /databases/{database}/documents {
|
|
51
|
+
* match /gb/{guestbook} {
|
|
52
|
+
* match /gbe/{guestbookEntry} { allow get: if false; }
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
* }
|
|
56
|
+
* `);
|
|
57
|
+
* // blocks[0].collectionName === 'gb'
|
|
58
|
+
* // blocks[0].children[0].collectionName === 'gbe'
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare function parseFirestoreRules(source: string): ParsedFirestoreMatchBlock[];
|
|
@@ -2,5 +2,15 @@ export { FIREBASE_REQUIRE_TAGGED_FIRESTORE_CONSTRAINTS_RULE, type FirebaseRequir
|
|
|
2
2
|
export { FIREBASE_REQUIRE_DBX_MODEL_FIREBASE_INDEX_QUERY_SUFFIX_RULE, type FirebaseRequireDbxModelFirebaseIndexQuerySuffixRuleOptions, type FirebaseRequireDbxModelFirebaseIndexQuerySuffixRuleDefinition } from './require-dbx-model-firebase-index-query-suffix.rule';
|
|
3
3
|
export { FIREBASE_REQUIRE_DBX_MODEL_FIREBASE_INDEX_COMPANION_TAGS_RULE, type FirebaseRequireDbxModelFirebaseIndexCompanionTagsRuleOptions, type FirebaseRequireDbxModelFirebaseIndexCompanionTagsRuleDefinition } from './require-dbx-model-firebase-index-companion-tags.rule';
|
|
4
4
|
export { FIREBASE_REQUIRE_DBX_MODEL_FIREBASE_INDEX_VALID_DISPATCHER_RULE, type FirebaseRequireDbxModelFirebaseIndexValidDispatcherRuleOptions, type FirebaseRequireDbxModelFirebaseIndexValidDispatcherRuleDefinition } from './require-dbx-model-firebase-index-valid-dispatcher.rule';
|
|
5
|
+
export { FIREBASE_REQUIRE_FIRESTORE_CONSTRAINT_TYPE_PARAMETER_RULE, type FirebaseRequireFirestoreConstraintTypeParameterRuleOptions, type FirebaseRequireFirestoreConstraintTypeParameterRuleDefinition } from './require-firestore-constraint-type-parameter.rule';
|
|
6
|
+
export { FIREBASE_REQUIRE_COMPLETE_CRUD_FUNCTION_CONFIG_MAP_RULE, DEFAULT_CRUD_VERB_NAMES, MODEL_FIREBASE_CRUD_FUNCTION_CONFIG_MAP_TYPE_NAME, type FirebaseRequireCompleteCrudFunctionConfigMapRuleOptions, type FirebaseRequireCompleteCrudFunctionConfigMapRuleDefinition } from './require-complete-crud-function-config-map.rule';
|
|
7
|
+
export { FIREBASE_REQUIRE_API_DETAILS_FOR_CRUD_FUNCTION_RULE, DEFAULT_CRUD_FUNCTION_TYPE_VERBS, DEFAULT_API_DETAILS_FACTORY_NAME, type FirebaseRequireApiDetailsForCrudFunctionRuleOptions, type FirebaseRequireApiDetailsForCrudFunctionRuleDefinition } from './require-api-details-for-crud-function.rule';
|
|
8
|
+
export { FIREBASE_REQUIRE_STORAGEFILE_POLICY_MATCHES_RULES_RULE, DEFAULT_STORAGE_FILE_UPLOAD_POLICY_TYPE_NAME, DEFAULT_STORAGE_RULES_FILENAME, type FirebaseRequireStorageFilePolicyMatchesRulesRuleOptions, type FirebaseRequireStorageFilePolicyMatchesRulesRuleDefinition } from './require-storagefile-policy-matches-rules.rule';
|
|
9
|
+
export { FIREBASE_REQUIRE_FIRESTORE_RULE_FOR_SERVICE_MODEL_RULE, DEFAULT_FIRESTORE_RULES_FILENAME, DEFAULT_REGISTRY_FACTORY_CALL_NAME, DEFAULT_IDENTITY_FACTORY_NAME, DEFAULT_MODEL_SEARCH_ROOTS, type FirebaseRequireFirestoreRuleForServiceModelRuleOptions, type FirebaseRequireFirestoreRuleForServiceModelRuleDefinition, type VirtualModelIdentity } from './require-firestore-rule-for-service-model.rule';
|
|
10
|
+
export { FIREBASE_REQUIRE_DBX_MODEL_SERVICE_FACTORY_TAG_RULE, FIREBASE_MODEL_SERVICE_FACTORY_NAME, FIREBASE_MODEL_SERVICE_FACTORY_MODULE, DBX_MODEL_SERVICE_FACTORY_TAG, type FirebaseRequireDbxModelServiceFactoryTagRuleOptions, type FirebaseRequireDbxModelServiceFactoryTagRuleDefinition } from './require-dbx-model-service-factory-tag.rule';
|
|
11
|
+
export { FIREBASE_REQUIRE_SERVICE_FACTORY_FOR_DBX_MODEL_RULE, DEFAULT_FACTORY_SEARCH_ROOTS, DEFAULT_MODEL_MARKER_TAG, DEFAULT_FACTORY_TAG, type FirebaseRequireServiceFactoryForDbxModelRuleOptions, type FirebaseRequireServiceFactoryForDbxModelRuleDefinition } from './require-service-factory-for-dbx-model.rule';
|
|
12
|
+
export { FIREBASE_REQUIRE_DBX_MODEL_COMPANION_TAGS_RULE, type FirebaseRequireDbxModelCompanionTagsRuleOptions, type FirebaseRequireDbxModelCompanionTagsRuleDefinition } from './require-dbx-model-companion-tags.rule';
|
|
13
|
+
export { parseStorageRules, MIRRORS_POLICY_KEY_MARKER_REGEX, type ParsedRuleBranch, type ParsedStorageRulesBlock } from './storage-rules-parser';
|
|
14
|
+
export { parseFirestoreRules, type ParsedFirestoreMatchBlock } from './firestore-rules-parser';
|
|
5
15
|
export { FIREBASE_ESLINT_PLUGIN, firebaseESLintPlugin, type FirebaseEslintPlugin } from './plugin';
|
|
6
16
|
export { DBX_MODEL_FIREBASE_INDEX_MARKER, DEFAULT_CONSTRAINT_FACTORY_NAMES, DEFAULT_INDEX_AFFECTING_CONSTRAINT_NAMES, DEFAULT_PAGINATION_CONSTRAINT_NAMES, FIREBASE_MODULE, QUERY_SUFFIX } from './util';
|
|
@@ -2,6 +2,14 @@ import { FIREBASE_REQUIRE_TAGGED_FIRESTORE_CONSTRAINTS_RULE } from './require-ta
|
|
|
2
2
|
import { FIREBASE_REQUIRE_DBX_MODEL_FIREBASE_INDEX_QUERY_SUFFIX_RULE } from './require-dbx-model-firebase-index-query-suffix.rule';
|
|
3
3
|
import { FIREBASE_REQUIRE_DBX_MODEL_FIREBASE_INDEX_COMPANION_TAGS_RULE } from './require-dbx-model-firebase-index-companion-tags.rule';
|
|
4
4
|
import { FIREBASE_REQUIRE_DBX_MODEL_FIREBASE_INDEX_VALID_DISPATCHER_RULE } from './require-dbx-model-firebase-index-valid-dispatcher.rule';
|
|
5
|
+
import { FIREBASE_REQUIRE_FIRESTORE_CONSTRAINT_TYPE_PARAMETER_RULE } from './require-firestore-constraint-type-parameter.rule';
|
|
6
|
+
import { FIREBASE_REQUIRE_COMPLETE_CRUD_FUNCTION_CONFIG_MAP_RULE } from './require-complete-crud-function-config-map.rule';
|
|
7
|
+
import { FIREBASE_REQUIRE_API_DETAILS_FOR_CRUD_FUNCTION_RULE } from './require-api-details-for-crud-function.rule';
|
|
8
|
+
import { FIREBASE_REQUIRE_STORAGEFILE_POLICY_MATCHES_RULES_RULE } from './require-storagefile-policy-matches-rules.rule';
|
|
9
|
+
import { FIREBASE_REQUIRE_FIRESTORE_RULE_FOR_SERVICE_MODEL_RULE } from './require-firestore-rule-for-service-model.rule';
|
|
10
|
+
import { FIREBASE_REQUIRE_DBX_MODEL_SERVICE_FACTORY_TAG_RULE } from './require-dbx-model-service-factory-tag.rule';
|
|
11
|
+
import { FIREBASE_REQUIRE_SERVICE_FACTORY_FOR_DBX_MODEL_RULE } from './require-service-factory-for-dbx-model.rule';
|
|
12
|
+
import { FIREBASE_REQUIRE_DBX_MODEL_COMPANION_TAGS_RULE } from './require-dbx-model-companion-tags.rule';
|
|
5
13
|
/**
|
|
6
14
|
* ESLint plugin interface for `@dereekb/firebase` rules.
|
|
7
15
|
*/
|
|
@@ -11,6 +19,14 @@ export interface FirebaseEslintPlugin {
|
|
|
11
19
|
readonly 'require-dbx-model-firebase-index-query-suffix': typeof FIREBASE_REQUIRE_DBX_MODEL_FIREBASE_INDEX_QUERY_SUFFIX_RULE;
|
|
12
20
|
readonly 'require-dbx-model-firebase-index-companion-tags': typeof FIREBASE_REQUIRE_DBX_MODEL_FIREBASE_INDEX_COMPANION_TAGS_RULE;
|
|
13
21
|
readonly 'require-dbx-model-firebase-index-valid-dispatcher': typeof FIREBASE_REQUIRE_DBX_MODEL_FIREBASE_INDEX_VALID_DISPATCHER_RULE;
|
|
22
|
+
readonly 'require-firestore-constraint-type-parameter': typeof FIREBASE_REQUIRE_FIRESTORE_CONSTRAINT_TYPE_PARAMETER_RULE;
|
|
23
|
+
readonly 'require-complete-crud-function-config-map': typeof FIREBASE_REQUIRE_COMPLETE_CRUD_FUNCTION_CONFIG_MAP_RULE;
|
|
24
|
+
readonly 'require-api-details-for-crud-function': typeof FIREBASE_REQUIRE_API_DETAILS_FOR_CRUD_FUNCTION_RULE;
|
|
25
|
+
readonly 'require-storagefile-policy-matches-rules': typeof FIREBASE_REQUIRE_STORAGEFILE_POLICY_MATCHES_RULES_RULE;
|
|
26
|
+
readonly 'require-firestore-rule-for-service-model': typeof FIREBASE_REQUIRE_FIRESTORE_RULE_FOR_SERVICE_MODEL_RULE;
|
|
27
|
+
readonly 'require-dbx-model-service-factory-tag': typeof FIREBASE_REQUIRE_DBX_MODEL_SERVICE_FACTORY_TAG_RULE;
|
|
28
|
+
readonly 'require-service-factory-for-dbx-model': typeof FIREBASE_REQUIRE_SERVICE_FACTORY_FOR_DBX_MODEL_RULE;
|
|
29
|
+
readonly 'require-dbx-model-companion-tags': typeof FIREBASE_REQUIRE_DBX_MODEL_COMPANION_TAGS_RULE;
|
|
14
30
|
};
|
|
15
31
|
}
|
|
16
32
|
/**
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One disjunct of an `allow write: if ...` predicate after helper-function expansion
|
|
3
|
+
* and DNF conversion. Always carries a numeric byte cap plus at least one MIME constraint.
|
|
4
|
+
*/
|
|
5
|
+
export interface PredicateBranch {
|
|
6
|
+
readonly maxFileSizeBytes: number;
|
|
7
|
+
readonly allowedMimeLiterals: readonly string[];
|
|
8
|
+
readonly allowedMimeRegexes: readonly string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Result of evaluating a CEL `allow write` predicate. When the predicate cannot be reduced
|
|
12
|
+
* to at least one resource-constraining branch, {@link PredicateEvaluation.branches} is
|
|
13
|
+
* empty and `unsupported` carries a human-readable reason.
|
|
14
|
+
*/
|
|
15
|
+
export interface PredicateEvaluation {
|
|
16
|
+
readonly branches: readonly PredicateBranch[];
|
|
17
|
+
readonly unsupported?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Map of helper-function names → return-expression text. Entries are sourced from the
|
|
21
|
+
* surrounding `storage.rules` scope (function definitions reachable from the `match` block).
|
|
22
|
+
*/
|
|
23
|
+
export interface HelperFunctionTable {
|
|
24
|
+
readonly definitions: ReadonlyMap<string, string>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Evaluates a CEL `allow write` predicate into the list of `(size, MIME)` branches the
|
|
28
|
+
* `require-storagefile-policy-matches-rules` lint rule cross-checks against the TypeScript
|
|
29
|
+
* upload-policy registry.
|
|
30
|
+
*
|
|
31
|
+
* Pipeline: parse with `@marcbachmann/cel-js`, inline zero-arg helper calls at the AST
|
|
32
|
+
* level, expand to disjunctive normal form, then for each DNF clause harvest:
|
|
33
|
+
*
|
|
34
|
+
* - `request.resource.size < N` size caps,
|
|
35
|
+
* - `request.resource.contentType == '...'` literal MIMEs,
|
|
36
|
+
* - `request.resource.contentType.matches('...')` MIME regexes,
|
|
37
|
+
* - `request.resource.contentType in [...]` MIME-list literals.
|
|
38
|
+
*
|
|
39
|
+
* A clause becomes a {@link PredicateBranch} only when it has ≥1 size cap AND ≥1 MIME
|
|
40
|
+
* constraint. Auth-only clauses (e.g. `request.auth.token.a == 1`) are silently dropped —
|
|
41
|
+
* they don't restrict uploads from the storage perspective.
|
|
42
|
+
*
|
|
43
|
+
* @param predicate - The raw predicate text (everything between `if` and `;` in the rules file).
|
|
44
|
+
* @param helpers - Helper-function bodies in scope at the `match` block.
|
|
45
|
+
* @returns Reduced branches, plus an `unsupported` reason when reduction yields zero branches or the predicate fails to parse.
|
|
46
|
+
*/
|
|
47
|
+
export declare function evaluatePredicate(predicate: string, helpers: HelperFunctionTable): PredicateEvaluation;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { type AstNode } from './util';
|
|
2
|
+
/**
|
|
3
|
+
* Default CRUD verb names that combine with the `ModelFunction` suffix to form a type-name
|
|
4
|
+
* pattern this rule treats as a CRUD function declaration (e.g. `OnCallCreateModelFunction`,
|
|
5
|
+
* `DemoUpdateModelFunction`).
|
|
6
|
+
*
|
|
7
|
+
* Mirrors the verbs supported by `ModelFirebaseCrudFunctionConfigMap` — see
|
|
8
|
+
* `packages/firebase/src/lib/client/function/model.function.factory.ts`.
|
|
9
|
+
*/
|
|
10
|
+
export declare const DEFAULT_CRUD_FUNCTION_TYPE_VERBS: readonly string[];
|
|
11
|
+
/**
|
|
12
|
+
* Default factory function name that wraps CRUD function declarations and attaches the
|
|
13
|
+
* `_apiDetails` metadata (`inputType`, `outputType`, `mcp.visibility`, `analytics`) consumed
|
|
14
|
+
* by the MCP manifest builder. Defined in `packages/firebase-server/src/lib/nest/model/api.details.ts`.
|
|
15
|
+
*/
|
|
16
|
+
export declare const DEFAULT_API_DETAILS_FACTORY_NAME: string;
|
|
17
|
+
/**
|
|
18
|
+
* Options for the require-api-details-for-crud-function rule.
|
|
19
|
+
*/
|
|
20
|
+
export interface FirebaseRequireApiDetailsForCrudFunctionRuleOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Verb fragments that pair with the `ModelFunction` suffix to identify a CRUD function
|
|
23
|
+
* type annotation. Defaults to {@link DEFAULT_CRUD_FUNCTION_TYPE_VERBS}.
|
|
24
|
+
*/
|
|
25
|
+
readonly typeVerbs?: readonly string[];
|
|
26
|
+
/**
|
|
27
|
+
* Factory function name expected on the initializer. Defaults to {@link DEFAULT_API_DETAILS_FACTORY_NAME}.
|
|
28
|
+
*/
|
|
29
|
+
readonly factoryName?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Declarator names to exempt from the rule. Mainly an escape hatch for tests.
|
|
32
|
+
*/
|
|
33
|
+
readonly ignoreNames?: readonly string[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* ESLint rule definition for require-api-details-for-crud-function.
|
|
37
|
+
*/
|
|
38
|
+
export interface FirebaseRequireApiDetailsForCrudFunctionRuleDefinition {
|
|
39
|
+
readonly meta: {
|
|
40
|
+
readonly type: 'problem';
|
|
41
|
+
readonly fixable: undefined;
|
|
42
|
+
readonly docs: {
|
|
43
|
+
readonly description: string;
|
|
44
|
+
readonly recommended: boolean;
|
|
45
|
+
};
|
|
46
|
+
readonly messages: Readonly<Record<string, string>>;
|
|
47
|
+
readonly schema: readonly object[];
|
|
48
|
+
};
|
|
49
|
+
create(context: {
|
|
50
|
+
options: FirebaseRequireApiDetailsForCrudFunctionRuleOptions[];
|
|
51
|
+
report: (descriptor: {
|
|
52
|
+
node: AstNode;
|
|
53
|
+
messageId: string;
|
|
54
|
+
data?: Record<string, string>;
|
|
55
|
+
}) => void;
|
|
56
|
+
}): Record<string, (node: AstNode) => void>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* ESLint rule that requires every CRUD function declaration — a variable typed as
|
|
60
|
+
* `On(?:Call)?<Verb>ModelFunction` (or any app-side alias ending with the same `<Verb>ModelFunction`
|
|
61
|
+
* suffix) — to be initialized with a call to `withApiDetails(...)`.
|
|
62
|
+
*
|
|
63
|
+
* Handlers that skip the wrapper compile fine but do not attach the `_apiDetails` metadata
|
|
64
|
+
* (`inputType`, `mcp.visibility`, `analytics`) that downstream tooling — especially the MCP
|
|
65
|
+
* manifest builder in `packages/firebase-server-mcp` — reads. The handler then silently fails
|
|
66
|
+
* to appear in the generated MCP server even though the runtime wires it up.
|
|
67
|
+
*
|
|
68
|
+
* The rule is purely syntactic: it inspects the declarator's TS type annotation and the
|
|
69
|
+
* initializer's `CallExpression` callee name. Type assertions (`as`, `<T>`) on the initializer
|
|
70
|
+
* are unwrapped before the check.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* // OK — wrapped, surfaces to MCP
|
|
75
|
+
* export const fooCreate: FooCreateModelFunction<X> = withApiDetails({
|
|
76
|
+
* inputType, fn: async (req) => ({})
|
|
77
|
+
* });
|
|
78
|
+
*
|
|
79
|
+
* // WARN — missingApiDetails, never reaches MCP
|
|
80
|
+
* export const fooDelete: FooDeleteModelFunction<X> = async (req) => {};
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare const FIREBASE_REQUIRE_API_DETAILS_FOR_CRUD_FUNCTION_RULE: FirebaseRequireApiDetailsForCrudFunctionRuleDefinition;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type AstNode } from './util';
|
|
2
|
+
/**
|
|
3
|
+
* Type-reference name that triggers this rule. Variables whose declared type is
|
|
4
|
+
* `ModelFirebaseCrudFunctionConfigMap<ConfigType, Identity>` will have their
|
|
5
|
+
* initializer validated against the structure of `ConfigType`.
|
|
6
|
+
*/
|
|
7
|
+
export declare const MODEL_FIREBASE_CRUD_FUNCTION_CONFIG_MAP_TYPE_NAME = "ModelFirebaseCrudFunctionConfigMap";
|
|
8
|
+
/**
|
|
9
|
+
* CRUD verb names supported by `ModelFirebaseCrudFunctionConfigMap`. Mirrors the
|
|
10
|
+
* `create | read | update | delete | query` verbs in the type definition at
|
|
11
|
+
* `packages/firebase/src/lib/client/function/model.function.factory.ts`.
|
|
12
|
+
*/
|
|
13
|
+
export declare const DEFAULT_CRUD_VERB_NAMES: readonly string[];
|
|
14
|
+
/**
|
|
15
|
+
* Options for the require-complete-crud-function-config-map rule.
|
|
16
|
+
*/
|
|
17
|
+
export interface FirebaseRequireCompleteCrudFunctionConfigMapRuleOptions {
|
|
18
|
+
readonly typeName?: string;
|
|
19
|
+
readonly verbNames?: readonly string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* ESLint rule definition for require-complete-crud-function-config-map.
|
|
23
|
+
*/
|
|
24
|
+
export interface FirebaseRequireCompleteCrudFunctionConfigMapRuleDefinition {
|
|
25
|
+
readonly meta: {
|
|
26
|
+
readonly type: 'problem';
|
|
27
|
+
readonly fixable: undefined;
|
|
28
|
+
readonly docs: {
|
|
29
|
+
readonly description: string;
|
|
30
|
+
readonly recommended: boolean;
|
|
31
|
+
};
|
|
32
|
+
readonly messages: Readonly<Record<string, string>>;
|
|
33
|
+
readonly schema: readonly object[];
|
|
34
|
+
};
|
|
35
|
+
create(context: {
|
|
36
|
+
options: FirebaseRequireCompleteCrudFunctionConfigMapRuleOptions[];
|
|
37
|
+
report: (descriptor: {
|
|
38
|
+
node: AstNode;
|
|
39
|
+
messageId: string;
|
|
40
|
+
data?: Record<string, string>;
|
|
41
|
+
}) => void;
|
|
42
|
+
}): Record<string, (node: AstNode) => void>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* ESLint rule that verifies every `ModelFirebaseCrudFunctionConfigMap<ConfigType, ...>`
|
|
46
|
+
* variable initializer is structurally complete against its companion `ConfigType`
|
|
47
|
+
* defined in the same file.
|
|
48
|
+
*
|
|
49
|
+
* The rule walks the type alias for `ConfigType` (e.g., `NotificationBoxModelCrudFunctionsConfig`),
|
|
50
|
+
* builds the expected set of model keys, verbs, and specifiers, and then compares it
|
|
51
|
+
* against the object-literal initializer of the variable. Each mismatch — missing model
|
|
52
|
+
* key, missing verb, missing specifier, disabled-but-present key, etc. — is reported as
|
|
53
|
+
* an error so the const stays in sync with its companion type even when the TypeScript
|
|
54
|
+
* mapped-type enforcement decays in larger codebases.
|
|
55
|
+
*
|
|
56
|
+
* Same-file resolution only: the companion type must be declared in the same source
|
|
57
|
+
* file as the const (matching the convention in `notification.api.ts`, `oidcmodel.api.ts`,
|
|
58
|
+
* `storagefile.api.ts`). When the type cannot be located, the rule reports
|
|
59
|
+
* `configTypeNotFound`.
|
|
60
|
+
*/
|
|
61
|
+
export declare const FIREBASE_REQUIRE_COMPLETE_CRUD_FUNCTION_CONFIG_MAP_RULE: FirebaseRequireCompleteCrudFunctionConfigMapRuleDefinition;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
interface AstNode {
|
|
2
|
+
readonly type: string;
|
|
3
|
+
[key: string]: any;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Options for the require-dbx-model-companion-tags rule.
|
|
7
|
+
*/
|
|
8
|
+
export interface FirebaseRequireDbxModelCompanionTagsRuleOptions {
|
|
9
|
+
readonly allowedEncodings?: readonly string[];
|
|
10
|
+
readonly knownCompanions?: readonly string[];
|
|
11
|
+
readonly requireBareMarker?: boolean;
|
|
12
|
+
readonly requireRead?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* ESLint rule definition for require-dbx-model-companion-tags.
|
|
16
|
+
*/
|
|
17
|
+
export interface FirebaseRequireDbxModelCompanionTagsRuleDefinition {
|
|
18
|
+
readonly meta: {
|
|
19
|
+
readonly type: 'suggestion';
|
|
20
|
+
readonly fixable: 'code';
|
|
21
|
+
readonly docs: {
|
|
22
|
+
readonly description: string;
|
|
23
|
+
readonly recommended: boolean;
|
|
24
|
+
};
|
|
25
|
+
readonly messages: Readonly<Record<string, string>>;
|
|
26
|
+
readonly schema: readonly object[];
|
|
27
|
+
};
|
|
28
|
+
create(context: {
|
|
29
|
+
options: FirebaseRequireDbxModelCompanionTagsRuleOptions[];
|
|
30
|
+
report: (descriptor: {
|
|
31
|
+
loc?: AstNode;
|
|
32
|
+
messageId: string;
|
|
33
|
+
data?: Record<string, string>;
|
|
34
|
+
}) => void;
|
|
35
|
+
sourceCode: AstNode;
|
|
36
|
+
}): Record<string, (node: AstNode) => void>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* ESLint rule enforcing `@dbxModel` / `@dbxModelSubObject` / `@dbxModelOrganizationalGroupRoot`
|
|
40
|
+
* companion tags. Mirrors the scanner schema at
|
|
41
|
+
* `packages/dbx-cli/src/lib/mcp-scan/scan/extract-models/find-interfaces.ts`.
|
|
42
|
+
*
|
|
43
|
+
* Does NOT enforce a Slug / Category / Tags shape because the scanner does
|
|
44
|
+
* not consume those for this family.
|
|
45
|
+
*/
|
|
46
|
+
export declare const FIREBASE_REQUIRE_DBX_MODEL_COMPANION_TAGS_RULE: FirebaseRequireDbxModelCompanionTagsRuleDefinition;
|
|
47
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type AstNode } from './util';
|
|
2
|
+
/**
|
|
3
|
+
* Module that exports {@link FIREBASE_MODEL_SERVICE_FACTORY_NAME} — `@dereekb/firebase`.
|
|
4
|
+
*/
|
|
5
|
+
export declare const FIREBASE_MODEL_SERVICE_FACTORY_MODULE = "@dereekb/firebase";
|
|
6
|
+
/**
|
|
7
|
+
* Imported name of the model-service factory whose calls trigger this rule.
|
|
8
|
+
*/
|
|
9
|
+
export declare const FIREBASE_MODEL_SERVICE_FACTORY_NAME = "firebaseModelServiceFactory";
|
|
10
|
+
/**
|
|
11
|
+
* JSDoc tag that declares which Firestore model a `firebaseModelServiceFactory(...)` export
|
|
12
|
+
* implements. Value is the canonical `FirestoreModelIdentity.modelType` string
|
|
13
|
+
* (e.g. `guestbook`, `guestbookEntry`).
|
|
14
|
+
*/
|
|
15
|
+
export declare const DBX_MODEL_SERVICE_FACTORY_TAG = "dbxModelServiceFactory";
|
|
16
|
+
/**
|
|
17
|
+
* Options for the require-dbx-model-service-factory-tag rule.
|
|
18
|
+
*/
|
|
19
|
+
export interface FirebaseRequireDbxModelServiceFactoryTagRuleOptions {
|
|
20
|
+
readonly factoryName?: string;
|
|
21
|
+
readonly allowedImportSources?: readonly string[];
|
|
22
|
+
readonly tagName?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* ESLint rule definition for require-dbx-model-service-factory-tag.
|
|
26
|
+
*/
|
|
27
|
+
export interface FirebaseRequireDbxModelServiceFactoryTagRuleDefinition {
|
|
28
|
+
readonly meta: {
|
|
29
|
+
readonly type: 'problem';
|
|
30
|
+
readonly fixable: undefined;
|
|
31
|
+
readonly docs: {
|
|
32
|
+
readonly description: string;
|
|
33
|
+
readonly recommended: boolean;
|
|
34
|
+
};
|
|
35
|
+
readonly messages: Readonly<Record<string, string>>;
|
|
36
|
+
readonly schema: readonly object[];
|
|
37
|
+
};
|
|
38
|
+
create(context: {
|
|
39
|
+
options: FirebaseRequireDbxModelServiceFactoryTagRuleOptions[];
|
|
40
|
+
report: (descriptor: {
|
|
41
|
+
node: AstNode;
|
|
42
|
+
messageId: string;
|
|
43
|
+
data?: Record<string, string>;
|
|
44
|
+
}) => void;
|
|
45
|
+
sourceCode: AstNode;
|
|
46
|
+
}): Record<string, (node: AstNode) => void>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* ESLint rule that requires every `firebaseModelServiceFactory(...)` export to carry a
|
|
50
|
+
* leading `@dbxModelServiceFactory <modelType>` JSDoc tag.
|
|
51
|
+
*
|
|
52
|
+
* The tag declares which Firestore model the factory implements, enabling the
|
|
53
|
+
* dbx-components-mcp model catalog to join factory metadata onto model entries and powering
|
|
54
|
+
* the orphan-model lint rule.
|
|
55
|
+
*/
|
|
56
|
+
export declare const FIREBASE_REQUIRE_DBX_MODEL_SERVICE_FACTORY_TAG_RULE: FirebaseRequireDbxModelServiceFactoryTagRuleDefinition;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type AstNode } from './util';
|
|
2
|
+
/**
|
|
3
|
+
* Options for the require-firestore-constraint-type-parameter rule.
|
|
4
|
+
*/
|
|
5
|
+
export interface FirebaseRequireFirestoreConstraintTypeParameterRuleOptions {
|
|
6
|
+
readonly constraintNames?: readonly string[];
|
|
7
|
+
readonly additionalConstraintNames?: readonly string[];
|
|
8
|
+
readonly allowedImportSources?: readonly string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* ESLint rule definition for require-firestore-constraint-type-parameter.
|
|
12
|
+
*/
|
|
13
|
+
export interface FirebaseRequireFirestoreConstraintTypeParameterRuleDefinition {
|
|
14
|
+
readonly meta: {
|
|
15
|
+
readonly type: 'suggestion';
|
|
16
|
+
readonly fixable: undefined;
|
|
17
|
+
readonly docs: {
|
|
18
|
+
readonly description: string;
|
|
19
|
+
readonly recommended: boolean;
|
|
20
|
+
};
|
|
21
|
+
readonly messages: Readonly<Record<string, string>>;
|
|
22
|
+
readonly schema: readonly object[];
|
|
23
|
+
};
|
|
24
|
+
create(context: {
|
|
25
|
+
options: FirebaseRequireFirestoreConstraintTypeParameterRuleOptions[];
|
|
26
|
+
report: (descriptor: {
|
|
27
|
+
node: AstNode;
|
|
28
|
+
messageId: string;
|
|
29
|
+
data?: Record<string, string>;
|
|
30
|
+
}) => void;
|
|
31
|
+
}): Record<string, (node: AstNode) => void>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* ESLint rule that warns when an `@dereekb/firebase` field-path-narrowing constraint factory
|
|
35
|
+
* (`where`, `orderBy`) is called without a generic type argument. Without `<Model>`, the
|
|
36
|
+
* overload falls back to a plain `FieldPathOrStringPath`, so field-name typos and renamed
|
|
37
|
+
* fields silently compile.
|
|
38
|
+
*
|
|
39
|
+
* The expected form is `where<Model>('field', '==', value)` / `orderBy<Model>('field')` so
|
|
40
|
+
* the field path is constrained to `StringKeyPropertyKeys<Model>`.
|
|
41
|
+
*
|
|
42
|
+
* Not auto-fixable: the rule cannot safely infer the correct model type from the surrounding
|
|
43
|
+
* function signature in an ESLint autofix.
|
|
44
|
+
*/
|
|
45
|
+
export declare const FIREBASE_REQUIRE_FIRESTORE_CONSTRAINT_TYPE_PARAMETER_RULE: FirebaseRequireFirestoreConstraintTypeParameterRuleDefinition;
|