@dereekb/firebase 13.12.1 → 13.12.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/eslint/index.cjs.js +3628 -3071
- package/eslint/index.esm.js +3588 -3033
- package/eslint/package.json +7 -5
- package/eslint/src/lib/index.d.ts +1 -1
- package/eslint/src/lib/require-firestore-rule-for-service-model.rule.d.ts +1 -1
- package/eslint/src/lib/require-service-factory-for-dbx-model.rule.d.ts +10 -4
- package/eslint/src/lib/require-storagefile-policy-matches-rules.rule.d.ts +25 -5
- package/eslint/src/lib/storage-rules-parser.d.ts +25 -9
- package/eslint/src/lib/storagefile-import-resolver.d.ts +33 -0
- package/eslint/src/lib/storagefile-path-fold.d.ts +121 -0
- package/eslint/src/lib/util.d.ts +44 -0
- package/package.json +10 -5
- package/test/package.json +6 -6
package/eslint/package.json
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase/eslint",
|
|
3
|
-
"version": "13.12.
|
|
3
|
+
"version": "13.12.3",
|
|
4
4
|
"peerDependencies": {
|
|
5
|
+
"@dereekb/util": "13.12.3",
|
|
6
|
+
"@marcbachmann/cel-js": "^7.6.1",
|
|
7
|
+
"@typescript-eslint/parser": "8.59.3",
|
|
5
8
|
"@typescript-eslint/utils": "8.59.3"
|
|
6
9
|
},
|
|
7
10
|
"devDependencies": {
|
|
8
|
-
"@dereekb/
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"eslint": "10.4.0"
|
|
11
|
+
"@dereekb/firebase": "13.12.3",
|
|
12
|
+
"eslint": "10.4.0",
|
|
13
|
+
"firebase": "^12.12.1"
|
|
12
14
|
},
|
|
13
15
|
"exports": {
|
|
14
16
|
"./package.json": "./package.json",
|
|
@@ -14,4 +14,4 @@ export { FIREBASE_REQUIRE_DBX_MODEL_COMPANION_TAGS_RULE, type FirebaseRequireDbx
|
|
|
14
14
|
export { parseStorageRules, MIRRORS_POLICY_KEY_MARKER_REGEX, type ParsedRuleBranch, type ParsedStorageRulesBlock } from './storage-rules-parser';
|
|
15
15
|
export { parseFirestoreRules, type ParsedFirestoreMatchBlock } from './firestore-rules-parser';
|
|
16
16
|
export { FIREBASE_ESLINT_PLUGIN, firebaseESLintPlugin, type FirebaseEslintPlugin } from './plugin';
|
|
17
|
-
export { DBX_MODEL_FIREBASE_INDEX_MARKER, DEFAULT_CONSTRAINT_FACTORY_NAMES, DEFAULT_INDEX_AFFECTING_CONSTRAINT_NAMES, DEFAULT_PAGINATION_CONSTRAINT_NAMES, FIREBASE_MODULE, QUERY_SUFFIX, DEFAULT_CRUD_FUNCTION_TYPE_VERBS, DEFAULT_API_DETAILS_FACTORY_NAME, INPUT_TYPE_PROPERTY_NAME, API_DETAILS_IMPORT_MODULE } from './util';
|
|
17
|
+
export { DBX_MODEL_FIREBASE_INDEX_MARKER, DEFAULT_CONSTRAINT_FACTORY_NAMES, DEFAULT_DISCOVERY_EXCLUDED_DIRS, DEFAULT_INDEX_AFFECTING_CONSTRAINT_NAMES, DEFAULT_PAGINATION_CONSTRAINT_NAMES, FIREBASE_MODULE, QUERY_SUFFIX, DEFAULT_CRUD_FUNCTION_TYPE_VERBS, DEFAULT_API_DETAILS_FACTORY_NAME, INPUT_TYPE_PROPERTY_NAME, API_DETAILS_IMPORT_MODULE, discoveryGlobExcludeFilter } from './util';
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AstNode } from './util';
|
|
2
2
|
/**
|
|
3
|
-
* Default glob
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Default glob pattern (relative to ESLint `cwd`) used to locate `@dbxModelServiceFactory` source
|
|
4
|
+
* files. A single layout-agnostic `**\/*.ts` scan finds a consumer's own factory declarations no
|
|
5
|
+
* matter where they live, rather than assuming the dbx-components monorepo layout
|
|
6
|
+
* (`components/*\/src/lib/model`, `apps/*\/src/app`) — which a downstream consumer of
|
|
7
|
+
* `@dereekb/firebase` does not share. The walk prunes `node_modules`/build dirs
|
|
8
|
+
* (see {@link discoveryGlobExcludeFilter}) and the cheap `text.includes('@'+factoryTag)` pre-filter
|
|
9
|
+
* in {@link collectFactoryModelTypesFromFile} keeps it from parsing files that carry no tag, so the
|
|
10
|
+
* broad glob stays fast even in a large consumer repo. In-repo this is a superset of the former
|
|
11
|
+
* monorepo-specific roots, so the demo app's framework + local factories still resolve.
|
|
6
12
|
*/
|
|
7
13
|
export declare const DEFAULT_FACTORY_SEARCH_ROOTS: readonly string[];
|
|
8
14
|
/**
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { Maybe } from '@dereekb/util';
|
|
1
2
|
import { type AstNode } from './util';
|
|
3
|
+
import { type ParserServicesLike } from './storagefile-import-resolver';
|
|
2
4
|
/**
|
|
3
5
|
* Default type name the rule looks for on top-level declarators. Variables whose type
|
|
4
6
|
* annotation resolves to this identifier are treated as upload policies and validated
|
|
@@ -27,6 +29,12 @@ export interface FirebaseRequireStorageFilePolicyMatchesRulesRuleOptions {
|
|
|
27
29
|
* {@link DEFAULT_STORAGE_FILE_UPLOAD_POLICY_TYPE_NAME}.
|
|
28
30
|
*/
|
|
29
31
|
readonly policyTypeName?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Policies whose `buildUploadPath` is legitimately dynamic (e.g. injects a runtime timestamp)
|
|
34
|
+
* and cannot be statically folded. Each entry matches a policy's `purpose` key or its
|
|
35
|
+
* declarator name; matching policies are skipped instead of reporting `unresolvablePolicyPath`.
|
|
36
|
+
*/
|
|
37
|
+
readonly allowUnresolvablePolicies?: readonly string[];
|
|
30
38
|
}
|
|
31
39
|
/**
|
|
32
40
|
* ESLint rule definition for require-storagefile-policy-matches-rules.
|
|
@@ -47,6 +55,10 @@ export interface FirebaseRequireStorageFilePolicyMatchesRulesRuleDefinition {
|
|
|
47
55
|
interface RuleContext {
|
|
48
56
|
readonly options: FirebaseRequireStorageFilePolicyMatchesRulesRuleOptions[];
|
|
49
57
|
readonly cwd?: string;
|
|
58
|
+
readonly sourceCode?: {
|
|
59
|
+
readonly parserServices?: Maybe<ParserServicesLike>;
|
|
60
|
+
};
|
|
61
|
+
readonly parserServices?: Maybe<ParserServicesLike>;
|
|
50
62
|
readonly report: (descriptor: {
|
|
51
63
|
node: AstNode;
|
|
52
64
|
messageId: string;
|
|
@@ -55,17 +67,25 @@ interface RuleContext {
|
|
|
55
67
|
}
|
|
56
68
|
/**
|
|
57
69
|
* ESLint rule that cross-checks every `StorageFilePurposeUploadPolicy`-typed declaration in
|
|
58
|
-
* a `*-firebase` component against the workspace's `storage.rules`.
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
70
|
+
* a `*-firebase` component against the workspace's `storage.rules`. The policy's
|
|
71
|
+
* `buildUploadPath` builder is statically folded to a concrete path template (an ordered list
|
|
72
|
+
* of literal / wildcard segments) and paired with the `storage.rules` `allow write` match
|
|
73
|
+
* block at the same path. On the paired block the `request.resource.size` cap and
|
|
74
|
+
* `request.resource.contentType` predicate must be at least as permissive as the policy's
|
|
75
|
+
* `maxFileSizeBytes` and `allowedMimeTypes`.
|
|
76
|
+
*
|
|
77
|
+
* Pairing is derived from the resolved path — not a marker comment — so the linker proves the
|
|
78
|
+
* policy's actual upload path lands in the rules block rather than trusting an unchecked
|
|
79
|
+
* assertion. When the builder cannot be folded (unknown const, unmodeled call, runtime value)
|
|
80
|
+
* the rule reports `unresolvablePolicyPath` and never guesses; genuinely dynamic builders opt
|
|
81
|
+
* out via `allowUnresolvablePolicies`.
|
|
62
82
|
*
|
|
63
83
|
* Reports on the TS side so drift surfaces in the normal lint pipeline; mismatches almost
|
|
64
84
|
* always originate from editing one side and forgetting the other.
|
|
65
85
|
*
|
|
66
86
|
* @example
|
|
67
87
|
* ```ts
|
|
68
|
-
* // OK — storage.rules has `
|
|
88
|
+
* // OK — storage.rules has `match /uploads/u/{uid}/avatar.img` with matching constraints
|
|
69
89
|
* export const USER_AVATAR_UPLOAD_POLICY: StorageFilePurposeUploadPolicy = {
|
|
70
90
|
* purpose: USER_AVATAR_PURPOSE,
|
|
71
91
|
* allowedMimeTypes: ['image/jpeg', 'image/png'],
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { Maybe } from '@dereekb/util';
|
|
1
2
|
import { type PredicateBranch } from './predicate-evaluator';
|
|
3
|
+
import type { FoldedPathSegment } from './storagefile-path-fold';
|
|
2
4
|
/**
|
|
3
5
|
* Marker comment that pairs a `storage.rules` match block with a TypeScript policy key
|
|
4
6
|
* in `STORAGE_FILE_PURPOSE_UPLOAD_POLICIES`. The capture group is the policy key constant
|
|
@@ -14,13 +16,15 @@ export declare const MIRRORS_POLICY_KEY_MARKER_REGEX: RegExp;
|
|
|
14
16
|
*/
|
|
15
17
|
export type ParsedRuleBranch = PredicateBranch;
|
|
16
18
|
/**
|
|
17
|
-
* One `match /<path>` block in `storage.rules`
|
|
18
|
-
* `branches` carries the disjunction of (size, MIME) tuples extracted from the
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* One leaf `match /<path>` block in `storage.rules` that carries an `allow write|create|update`
|
|
20
|
+
* predicate. `branches` carries the disjunction of (size, MIME) tuples extracted from the
|
|
21
|
+
* predicate; `unsupported` is set when the parser cannot reduce the predicate to >=1 valid
|
|
22
|
+
* branch. `matchPath` is the full accumulated path stack used to pair the block with a folded
|
|
23
|
+
* upload-policy path. `mirrorsPolicyKey` is the legacy `// Mirrors ...` marker key when present
|
|
24
|
+
* — purely informational now that pairing is by path, retained for backward compatibility.
|
|
21
25
|
*/
|
|
22
26
|
export interface ParsedStorageRulesBlock {
|
|
23
|
-
readonly mirrorsPolicyKey
|
|
27
|
+
readonly mirrorsPolicyKey?: Maybe<string>;
|
|
24
28
|
readonly matchPath: string;
|
|
25
29
|
readonly branches: readonly ParsedRuleBranch[];
|
|
26
30
|
readonly sourceLine: number;
|
|
@@ -28,11 +32,23 @@ export interface ParsedStorageRulesBlock {
|
|
|
28
32
|
readonly unsupported?: string;
|
|
29
33
|
}
|
|
30
34
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* are
|
|
35
|
+
* Converts a parsed leaf block's `matchPath` (e.g. `/uploads/u/{uid}/jr/{shortKey}`) into a
|
|
36
|
+
* structural segment list for comparison against a folded upload-policy path. Empty segments
|
|
37
|
+
* (leading/trailing/duplicate slashes) are dropped; `{var}` / `{var=**}` path variables become
|
|
38
|
+
* wildcards; every other segment is a literal.
|
|
39
|
+
*
|
|
40
|
+
* @param matchPath - The accumulated match-path string.
|
|
41
|
+
* @returns The structural segment list.
|
|
42
|
+
*/
|
|
43
|
+
export declare function rulesMatchPathToSegments(matchPath: string): FoldedPathSegment[];
|
|
44
|
+
/**
|
|
45
|
+
* Parses a `storage.rules` source string and returns every leaf `match` block that carries an
|
|
46
|
+
* `allow write|create|update` predicate, each with its full accumulated `matchPath`. Catch-all
|
|
47
|
+
* deny blocks are skipped; the rest of the tree is walked normally. Pairing with TypeScript
|
|
48
|
+
* upload policies is by path (see {@link rulesMatchPathToSegments}); the `// Mirrors ...` marker
|
|
49
|
+
* is no longer required.
|
|
34
50
|
*
|
|
35
51
|
* @param source - The raw rules source text.
|
|
36
|
-
* @returns Parsed
|
|
52
|
+
* @returns Parsed leaf blocks in source order.
|
|
37
53
|
*/
|
|
38
54
|
export declare function parseStorageRules(source: string): ParsedStorageRulesBlock[];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Maybe } from '@dereekb/util';
|
|
2
|
+
import { type AstNode } from './util';
|
|
3
|
+
import { type ImportedBindingResolver } from './storagefile-path-fold';
|
|
4
|
+
/**
|
|
5
|
+
* The slice of `@typescript-eslint` parser services the cross-module resolver needs: the TS
|
|
6
|
+
* `Program` and the ESTree→TS node map. Typed loosely so the resolver stays decoupled from a
|
|
7
|
+
* specific `@typescript-eslint` version.
|
|
8
|
+
*/
|
|
9
|
+
export interface ParserServicesLike {
|
|
10
|
+
readonly program?: {
|
|
11
|
+
getTypeChecker(): unknown;
|
|
12
|
+
};
|
|
13
|
+
readonly esTreeNodeToTSNodeMap?: {
|
|
14
|
+
get(node: AstNode): unknown;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Builds an {@link ImportedBindingResolver} backed by the TypeScript type checker, or null when
|
|
19
|
+
* type information is unavailable (e.g. a lint config without `parserOptions.project`, or a
|
|
20
|
+
* pure-AST test harness). The resolver performs a single hop: it maps an imported identifier in
|
|
21
|
+
* the linted file to the declaration's source file, re-parses that file to ESTree (cached), and
|
|
22
|
+
* returns the named binding plus that module's scope. Identifiers local to the resolved module
|
|
23
|
+
* fold via the re-parsed program directly; transitive re-imports from a third module are not
|
|
24
|
+
* followed.
|
|
25
|
+
*
|
|
26
|
+
* Every failure mode (no symbol, unreadable file, parse error, identifier from an already
|
|
27
|
+
* re-parsed module) returns null so the analyzer falls back to reporting an unresolvable path —
|
|
28
|
+
* it never throws into the lint pass.
|
|
29
|
+
*
|
|
30
|
+
* @param services - The parser services, when present.
|
|
31
|
+
* @returns A resolver, or null when type information is unavailable.
|
|
32
|
+
*/
|
|
33
|
+
export declare function createImportedBindingResolver(services: Maybe<ParserServicesLike>): Maybe<ImportedBindingResolver>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { Maybe } from '@dereekb/util';
|
|
2
|
+
import { type AstNode, type ImportRegistry } from './util';
|
|
3
|
+
/**
|
|
4
|
+
* One segment of a folded upload path. A `literal` segment carries its fixed text (e.g.
|
|
5
|
+
* `uploads`, `jr`, `photo.img`); a `wildcard` segment stands in for any single path segment
|
|
6
|
+
* (a destructured param, a positional argument, a `mergeSlashPaths` variadic element) and
|
|
7
|
+
* compares equal to a Firebase rules `{var}` / `{var=**}` path variable.
|
|
8
|
+
*/
|
|
9
|
+
export interface FoldedPathSegment {
|
|
10
|
+
readonly kind: 'literal' | 'wildcard';
|
|
11
|
+
readonly value: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The result of statically folding a `buildUploadPath` builder: an ordered list of
|
|
15
|
+
* {@link FoldedPathSegment}s with leading/trailing/duplicate `/` collapsed.
|
|
16
|
+
*/
|
|
17
|
+
export interface FoldedUploadPath {
|
|
18
|
+
readonly segments: readonly FoldedPathSegment[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Outcome of {@link foldUploadPath}: either a folded path or a human-readable reason the
|
|
22
|
+
* builder could not be reduced to a constant path template. The rule reports the reason via
|
|
23
|
+
* the `unresolvablePolicyPath` diagnostic so authors either make the builder foldable or opt
|
|
24
|
+
* out explicitly — the analyzer never guesses.
|
|
25
|
+
*/
|
|
26
|
+
export type FoldUploadPathResult = {
|
|
27
|
+
readonly ok: true;
|
|
28
|
+
readonly path: FoldedUploadPath;
|
|
29
|
+
} | {
|
|
30
|
+
readonly ok: false;
|
|
31
|
+
readonly reason: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Resolves an imported binding (const declarator or function/arrow declaration) to its
|
|
35
|
+
* declaration node in another module, plus the scope that node lives in so further
|
|
36
|
+
* identifiers inside it resolve against that module's own imports/consts.
|
|
37
|
+
*
|
|
38
|
+
* Supplied by the rule when type information is available; absent in pure-AST contexts
|
|
39
|
+
* (e.g. the unit tests), in which case cross-module references fold to "unresolvable".
|
|
40
|
+
*/
|
|
41
|
+
export interface ImportedBindingResolver {
|
|
42
|
+
resolve(name: string, referenceNode: AstNode, fromScope: FoldScope): Maybe<ResolvedBinding>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A binding resolved to its declaration node plus the scope it belongs to.
|
|
46
|
+
*/
|
|
47
|
+
export interface ResolvedBinding {
|
|
48
|
+
readonly node: AstNode;
|
|
49
|
+
readonly scope: FoldScope;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The lexical scope a node is folded in: the Program it belongs to and the import registry
|
|
53
|
+
* for that module. Threaded through folding so an inlined cross-module function resolves its
|
|
54
|
+
* own identifiers against its own module.
|
|
55
|
+
*/
|
|
56
|
+
export interface FoldScope {
|
|
57
|
+
readonly program: AstNode;
|
|
58
|
+
readonly importRegistry: ImportRegistry;
|
|
59
|
+
readonly resolver: Maybe<ImportedBindingResolver>;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Statically folds a `StorageFilePurposeUploadPolicy.buildUploadPath` builder to an abstract
|
|
63
|
+
* path template. The builder is an arrow `(input) => <path expression>` whose destructured /
|
|
64
|
+
* positional params become wildcards and whose body is a composition of string literals,
|
|
65
|
+
* `const`s, `@dereekb/util` path combinators, and foldable single-`return` helper functions.
|
|
66
|
+
*
|
|
67
|
+
* @param builderNode - The `buildUploadPath` value node (arrow / function expression, possibly behind a type assertion).
|
|
68
|
+
* @param scope - The lexical scope the builder lives in.
|
|
69
|
+
* @returns The folded path, or a reason the builder is unresolvable.
|
|
70
|
+
*/
|
|
71
|
+
export declare function foldUploadPath(builderNode: AstNode, scope: FoldScope): FoldUploadPathResult;
|
|
72
|
+
/**
|
|
73
|
+
* Folds an expression to a concrete string literal value, reusing the same fragment folder the
|
|
74
|
+
* path evaluator uses (literals, template literals, `const`s — local + cross-module — `+`
|
|
75
|
+
* concatenation, modeled combinators, inlinable helpers). Returns null when the expression cannot
|
|
76
|
+
* be reduced to a wildcard-free constant string, so callers preserve the sound "never guess"
|
|
77
|
+
* contract.
|
|
78
|
+
*
|
|
79
|
+
* @param node - The expression node.
|
|
80
|
+
* @param scope - The lexical scope the expression lives in.
|
|
81
|
+
* @returns The folded string, or null when unresolvable.
|
|
82
|
+
*/
|
|
83
|
+
export declare function foldStringExpression(node: AstNode, scope: FoldScope): Maybe<string>;
|
|
84
|
+
/**
|
|
85
|
+
* Folds an expression to a list of concrete strings: an inline array literal (each element folded
|
|
86
|
+
* via {@link foldStringExpression}, spreads of statically-known lists expanded), or an identifier
|
|
87
|
+
* resolving to such an array const (local or cross-module). Returns null when any element is
|
|
88
|
+
* unfoldable, so a genuinely dynamic element (e.g. a function call) still surfaces as unresolvable.
|
|
89
|
+
*
|
|
90
|
+
* @param node - The expression node (e.g. an `allowedMimeTypes` value).
|
|
91
|
+
* @param scope - The lexical scope the expression lives in.
|
|
92
|
+
* @returns The folded string list, or null when unresolvable.
|
|
93
|
+
*/
|
|
94
|
+
export declare function foldStringArrayExpression(node: AstNode, scope: FoldScope): Maybe<readonly string[]>;
|
|
95
|
+
/**
|
|
96
|
+
* Folds a numeric expression to a number: literals, unary `-`/`+`, binary `*`/`+`/`-`/`/`,
|
|
97
|
+
* type-assertion see-through, and identifiers resolving to a numeric `const` (local or
|
|
98
|
+
* cross-module, read from the AST initializer). Returns null when any operand is unresolvable.
|
|
99
|
+
*
|
|
100
|
+
* @param node - The expression node (e.g. a `maxFileSizeBytes` value).
|
|
101
|
+
* @param scope - The lexical scope the expression lives in.
|
|
102
|
+
* @returns The folded number, or null when unresolvable.
|
|
103
|
+
*/
|
|
104
|
+
export declare function foldNumericExpression(node: AstNode, scope: FoldScope): Maybe<number>;
|
|
105
|
+
/**
|
|
106
|
+
* Structurally compares a folded upload path against a Firebase rules match-path segment list
|
|
107
|
+
* (`{var}` / `{var=**}` → wildcard, otherwise literal). Literal segments must match value;
|
|
108
|
+
* wildcard segments compare equal to one another.
|
|
109
|
+
*
|
|
110
|
+
* @param folded - The folded upload path.
|
|
111
|
+
* @param ruleSegments - The rules match-path segments.
|
|
112
|
+
* @returns True when the two segment lists match position-for-position.
|
|
113
|
+
*/
|
|
114
|
+
export declare function foldedPathMatchesRuleSegments(folded: FoldedUploadPath, ruleSegments: readonly FoldedPathSegment[]): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Renders a folded path for diagnostics, e.g. `uploads/u/{*}/jr/{*}`.
|
|
117
|
+
*
|
|
118
|
+
* @param folded - The folded path.
|
|
119
|
+
* @returns The display string.
|
|
120
|
+
*/
|
|
121
|
+
export declare function describeFoldedPath(folded: FoldedUploadPath): string;
|
package/eslint/src/lib/util.d.ts
CHANGED
|
@@ -3,6 +3,50 @@ import type { Maybe } from '@dereekb/util';
|
|
|
3
3
|
* Module that publishes the `@dereekb/firebase` Firestore constraint factories (`where`, `orderBy`, etc.).
|
|
4
4
|
*/
|
|
5
5
|
export declare const FIREBASE_MODULE = "@dereekb/firebase";
|
|
6
|
+
/**
|
|
7
|
+
* Directory names the layout-agnostic discovery globs never descend into: installed dependencies
|
|
8
|
+
* and build/cache output. Excluding these keeps a broad `**\/*.ts` scan from walking a downstream
|
|
9
|
+
* consumer's `node_modules` (which can hold tens of thousands of declaration files) and from
|
|
10
|
+
* double-counting compiled output under `dist`.
|
|
11
|
+
*/
|
|
12
|
+
export declare const DEFAULT_DISCOVERY_EXCLUDED_DIRS: readonly string[];
|
|
13
|
+
/**
|
|
14
|
+
* Builds the `exclude` predicate passed to `fs.globSync(pattern, { cwd, exclude })` for the broad,
|
|
15
|
+
* layout-agnostic discovery globs. Node invokes the predicate on each visited path (directories
|
|
16
|
+
* included) and prunes the subtree when it returns true, so excluding a directory name here stops
|
|
17
|
+
* the walk from ever descending into it.
|
|
18
|
+
*
|
|
19
|
+
* @param excludedDirs - Directory names to prune. Defaults to {@link DEFAULT_DISCOVERY_EXCLUDED_DIRS}.
|
|
20
|
+
* @returns A predicate that returns true for any path containing an excluded directory segment.
|
|
21
|
+
*/
|
|
22
|
+
export declare function discoveryGlobExcludeFilter(excludedDirs?: readonly string[]): (path: string) => boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Resolves the absolute path to the installed `@dereekb/firebase` package's `src/lib/model`
|
|
25
|
+
* directory, as seen from the ESLint `cwd`. Used by rules that need to read the framework model
|
|
26
|
+
* declarations (identities, service factories) directly from the package a consumer has installed —
|
|
27
|
+
* the downstream case where these live under `node_modules/@dereekb/firebase/...` as compiled
|
|
28
|
+
* bundles plus `.d.ts` rather than a scannable source tree.
|
|
29
|
+
*
|
|
30
|
+
* Resolution uses Node's own module resolver (`require.resolve('@dereekb/firebase/package.json')`
|
|
31
|
+
* anchored at `cwd`), so it transparently handles hoisting / nested `node_modules`. Returns null
|
|
32
|
+
* when `@dereekb/firebase` is not resolvable as a dependency from `cwd` (e.g. inside the
|
|
33
|
+
* dbx-components monorepo itself, where it is consumed via TS path mapping rather than
|
|
34
|
+
* `node_modules`) — callers fall back to their cwd-relative source globs in that case.
|
|
35
|
+
*
|
|
36
|
+
* @param cwd - The ESLint working directory to resolve the dependency from.
|
|
37
|
+
* @returns The absolute model directory, or null when it cannot be resolved.
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveInstalledFirebaseModelDir(cwd: string): Maybe<string>;
|
|
40
|
+
/**
|
|
41
|
+
* Resolves the referenced type name from either a `TSTypeReference` (`Foo<…>` / `ns.Foo<…>`) or a
|
|
42
|
+
* `TSImportType` (`import("…").Foo<…>` — the form the TypeScript compiler emits in declaration
|
|
43
|
+
* files for cross-module type references). Returns the rightmost identifier name in a qualified
|
|
44
|
+
* name.
|
|
45
|
+
*
|
|
46
|
+
* @param node - A `TSTypeReference` or `TSImportType` node (or anything else).
|
|
47
|
+
* @returns The referenced type name, or null when the node is neither shape.
|
|
48
|
+
*/
|
|
49
|
+
export declare function referencedTypeName(node: AstNode): Maybe<string>;
|
|
6
50
|
/**
|
|
7
51
|
* JSDoc tag name that marks an exported query factory whose body should be scanned by
|
|
8
52
|
* `dbx-components-mcp`'s index extractor (`packages/dbx-components-mcp/src/scan/model-firebase-index-extract.ts`).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase",
|
|
3
|
-
"version": "13.12.
|
|
3
|
+
"version": "13.12.3",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"exports": {
|
|
6
6
|
"./test": {
|
|
@@ -24,11 +24,13 @@
|
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"@dereekb/
|
|
28
|
-
"@dereekb/
|
|
29
|
-
"@dereekb/
|
|
30
|
-
"@dereekb/
|
|
27
|
+
"@dereekb/date": "13.12.3",
|
|
28
|
+
"@dereekb/model": "13.12.3",
|
|
29
|
+
"@dereekb/rxjs": "13.12.3",
|
|
30
|
+
"@dereekb/util": "13.12.3",
|
|
31
31
|
"@firebase/rules-unit-testing": "5.0.0",
|
|
32
|
+
"@marcbachmann/cel-js": "^7.6.1",
|
|
33
|
+
"@typescript-eslint/parser": "8.59.3",
|
|
32
34
|
"arktype": "^2.2.0",
|
|
33
35
|
"date-fns": "^4.1.0",
|
|
34
36
|
"firebase": "^12.12.1",
|
|
@@ -36,6 +38,9 @@
|
|
|
36
38
|
"rxjs": "^7.8.2",
|
|
37
39
|
"ts-essentials": "^10.2.0"
|
|
38
40
|
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"eslint": "10.4.0"
|
|
43
|
+
},
|
|
39
44
|
"module": "./index.esm.js",
|
|
40
45
|
"main": "./index.cjs.js",
|
|
41
46
|
"types": "./index.d.ts"
|
package/test/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase/test",
|
|
3
|
-
"version": "13.12.
|
|
3
|
+
"version": "13.12.3",
|
|
4
4
|
"peerDependencies": {
|
|
5
|
-
"@dereekb/date": "13.12.
|
|
6
|
-
"@dereekb/firebase": "13.12.
|
|
7
|
-
"@dereekb/model": "13.12.
|
|
8
|
-
"@dereekb/rxjs": "13.12.
|
|
9
|
-
"@dereekb/util": "13.12.
|
|
5
|
+
"@dereekb/date": "13.12.3",
|
|
6
|
+
"@dereekb/firebase": "13.12.3",
|
|
7
|
+
"@dereekb/model": "13.12.3",
|
|
8
|
+
"@dereekb/rxjs": "13.12.3",
|
|
9
|
+
"@dereekb/util": "13.12.3",
|
|
10
10
|
"@firebase/rules-unit-testing": "5.0.0",
|
|
11
11
|
"date-fns": "^4.1.0",
|
|
12
12
|
"firebase": "^12.12.1",
|