@dereekb/dbx-cli 13.38.0 → 13.40.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/package.json +8 -8
- package/firebase-api-manifest/package.json +3 -3
- package/firestore-query-manifest/main.js +3 -3
- package/firestore-query-manifest/package.json +3 -3
- package/generate-firestore-indexes/main.js +2 -2
- package/generate-firestore-indexes/package.json +2 -2
- package/generate-mcp-manifest/package.json +3 -3
- package/generate-route-manifest/package.json +2 -2
- package/index.esm.js +1011 -521
- package/lint-cache/package.json +2 -2
- package/manifest-extract/package.json +7 -7
- package/model-test/LICENSE +21 -0
- package/model-test/index.d.ts +1 -0
- package/model-test/index.esm.js +5984 -0
- package/model-test/package.json +21 -0
- package/model-test/src/index.d.ts +41 -0
- package/model-test/src/lib/fixture/archetype.d.ts +33 -0
- package/model-test/src/lib/fixture/extract.d.ts +37 -0
- package/model-test/src/lib/fixture/format.json.d.ts +24 -0
- package/model-test/src/lib/fixture/format.markdown.d.ts +23 -0
- package/model-test/src/lib/fixture/forward.d.ts +48 -0
- package/model-test/src/lib/fixture/framework-fixtures.d.ts +70 -0
- package/model-test/src/lib/fixture/inspect.d.ts +22 -0
- package/model-test/src/lib/fixture/scaffold.d.ts +74 -0
- package/model-test/src/lib/fixture/types.d.ts +175 -0
- package/model-test/src/lib/test/discover.d.ts +81 -0
- package/model-test/src/lib/test/extract.d.ts +49 -0
- package/model-test/src/lib/test/format.hotspots.d.ts +23 -0
- package/model-test/src/lib/test/format.json.d.ts +25 -0
- package/model-test/src/lib/test/format.list-app.d.ts +30 -0
- package/model-test/src/lib/test/format.markdown.d.ts +25 -0
- package/model-test/src/lib/test/hotspots.d.ts +98 -0
- package/model-test/src/lib/test/inspect.d.ts +32 -0
- package/model-test/src/lib/test/search.d.ts +34 -0
- package/model-test/src/lib/test/types.d.ts +179 -0
- package/package.json +18 -22
- package/route/package.json +12 -12
- package/src/lib/firestore/firestore.session.d.ts +40 -0
- package/src/lib/runner/index.d.ts +1 -0
- package/src/lib/runner/lifecycle.d.ts +85 -0
- package/src/lib/runner/run.d.ts +15 -1
- package/test/package.json +14 -14
- package/validate/LICENSE +21 -0
- package/validate/index.js +16641 -0
- package/validate/package.json +11 -0
- package/eslint/index.cjs.default.js +0 -1
- package/eslint/index.cjs.js +0 -1112
- package/eslint/index.cjs.mjs +0 -2
- package/index.cjs.js +0 -65624
- package/manifest-extract/index.cjs.default.js +0 -1
- package/manifest-extract/index.cjs.js +0 -1595
- package/manifest-extract/index.cjs.mjs +0 -2
- package/route/index.cjs.default.js +0 -1
- package/route/index.cjs.js +0 -18
- package/route/index.cjs.mjs +0 -2
- package/test/index.cjs.default.js +0 -1
- package/test/index.cjs.js +0 -383
- package/test/index.cjs.mjs +0 -2
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dereekb/dbx-cli/model-test",
|
|
3
|
+
"version": "13.40.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"sideEffects": false,
|
|
6
|
+
"peerDependencies": {
|
|
7
|
+
"@dereekb/util": "13.40.0",
|
|
8
|
+
"ts-morph": "^21.0.0"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
"./package.json": "./package.json",
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./index.d.ts",
|
|
14
|
+
"import": "./index.esm.js",
|
|
15
|
+
"default": "./index.esm.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"module": "./index.esm.js",
|
|
19
|
+
"main": "./index.esm.js",
|
|
20
|
+
"types": "./index.d.ts"
|
|
21
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public surface of `@dereekb/dbx-cli/model-test`.
|
|
3
|
+
*
|
|
4
|
+
* Pure, dependency-light scanners for an API app's test artifacts:
|
|
5
|
+
*
|
|
6
|
+
* - the `test/*` modules parse, search, and discover `*.spec.ts` files (the
|
|
7
|
+
* `dbx_model_test_*` cluster), and
|
|
8
|
+
* - the `fixture/*` modules parse `src/test/fixture.ts` and scaffold fixture
|
|
9
|
+
* triplets / forwarders (the extraction half of the `dbx_model_fixture_*`
|
|
10
|
+
* cluster).
|
|
11
|
+
*
|
|
12
|
+
* Consumers (the `dbx-components-mcp` tool wrappers, the `dbx-components-cli`
|
|
13
|
+
* commands, and downstream scripts) layer disk I/O, argument parsing, and
|
|
14
|
+
* presentation around these functions.
|
|
15
|
+
*
|
|
16
|
+
* The fixture *validation* layer (`validateAppFixtures`, its diagnostic types,
|
|
17
|
+
* and the validation report formatters) lives in `@dereekb/dbx-components-mcp`
|
|
18
|
+
* because it depends on the rule-catalog remediation layer. The spec-file
|
|
19
|
+
* naming-convention helpers (`classifySpecFile`, `buildCanonicalFilename`,
|
|
20
|
+
* `recommendSpecPath`, `recommendBucketsForGroup`) live in `@dereekb/util` —
|
|
21
|
+
* import them from there.
|
|
22
|
+
*/
|
|
23
|
+
export { discoverSpecFilesByGroup, FUNCTION_DIR_REL, type DiscoveredSpecCatalog, type DiscoveredSpecFile, type DiscoveredSpecGroup } from './lib/test/discover.js';
|
|
24
|
+
export { extractSpecTreeFromText, type ExtractSpecTreeInput } from './lib/test/extract.js';
|
|
25
|
+
export { inspectSpecFile } from './lib/test/inspect.js';
|
|
26
|
+
export { searchSpecTree } from './lib/test/search.js';
|
|
27
|
+
export { findModelTestHotspots, type FindModelTestHotspotsConfig, type ModelTestHotspot, type ModelTestHotspotsResult, type SpecBucket } from './lib/test/hotspots.js';
|
|
28
|
+
export { formatTreeAsJson, formatSearchAsJson } from './lib/test/format.json.js';
|
|
29
|
+
export { formatTreeAsMarkdown, formatSearchAsMarkdown } from './lib/test/format.markdown.js';
|
|
30
|
+
export { formatListAppAsJson, formatListAppAsMarkdown } from './lib/test/format.list-app.js';
|
|
31
|
+
export { formatHotspotsAsJson, formatHotspotsAsMarkdown } from './lib/test/format.hotspots.js';
|
|
32
|
+
export type { HelperDescribe, PrefixSource, SpecFileTree, SpecNode, SpecNodeKind, SpecSearchHit, SpecSearchQuery, SpecSearchResult, SpecTreeFilters, SpecTreeView } from './lib/test/types.js';
|
|
33
|
+
export { classifyFixtureArchetype } from './lib/fixture/archetype.js';
|
|
34
|
+
export { extractAppFixturesFromText, type ExtractAppFixturesInput } from './lib/fixture/extract.js';
|
|
35
|
+
export { FIXTURE_RELATIVE_PATH, inspectAppFixtures } from './lib/fixture/inspect.js';
|
|
36
|
+
export { formatListAsJson, formatLookupAsJson } from './lib/fixture/format.json.js';
|
|
37
|
+
export { formatListAsMarkdown, formatLookupAsMarkdown } from './lib/fixture/format.markdown.js';
|
|
38
|
+
export { renderFixtureScaffold, type RenderFixtureScaffoldInput, type RenderedFixtureScaffold, type RenderedInsertion, type ScaffoldParamsDependency } from './lib/fixture/scaffold.js';
|
|
39
|
+
export { renderForwarders, type RenderForwardersInput, type RenderedForwarder, type RenderedForwarders } from './lib/fixture/forward.js';
|
|
40
|
+
export type { AppFixturesExtraction, FactoryCall, FixtureArchetype, FixtureEntry, FixtureKind, FixtureMethod, FixtureParamsField, FixtureParamsType } from './lib/fixture/types.js';
|
|
41
|
+
export { KNOWN_NON_MODEL_FIXTURE_FAMILIES, NON_MODEL_JSDOC_TAG, findFamilyByBaseClass, findFamilyByFactoryName, type FrameworkNonModelFixtureFamily } from './lib/fixture/framework-fixtures.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure archetype classifier for `modelTestContextFactory(...)` calls.
|
|
3
|
+
*
|
|
4
|
+
* Inputs come from the AST extractor — already-parsed factory call metadata
|
|
5
|
+
* and Params type fields. Output is one of the four archetypes used by the
|
|
6
|
+
* lookup, validate, and scaffold tools to speak the right dialect for each
|
|
7
|
+
* entry.
|
|
8
|
+
*/
|
|
9
|
+
import type { FactoryCall, FixtureArchetype, FixtureParamsType } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Inputs accepted by `classifyFixtureArchetype()`.
|
|
12
|
+
*/
|
|
13
|
+
export interface ClassifyFixtureArchetypeInput {
|
|
14
|
+
readonly factory?: FactoryCall;
|
|
15
|
+
readonly params?: FixtureParamsType;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Classifies a fixture entry into one of the four archetypes.
|
|
19
|
+
*
|
|
20
|
+
* Sub-collection archetypes are detected by the factory's
|
|
21
|
+
* `getCollection(fi, params)` signature reading a parent fixture's document
|
|
22
|
+
* off `params`, OR by the presence of `collectionForDocument`. Top-level
|
|
23
|
+
* variants are split by whether the Params interface holds non-self fixture
|
|
24
|
+
* dependencies.
|
|
25
|
+
*
|
|
26
|
+
* Falls back to `top-level-simple` when the factory call is absent (e.g.
|
|
27
|
+
* the file declares a Fixture/Instance pair but registration was deleted)
|
|
28
|
+
* — the validator surfaces the missing factory separately.
|
|
29
|
+
*
|
|
30
|
+
* @param input - Parsed factory call + params metadata.
|
|
31
|
+
* @returns The archetype enum.
|
|
32
|
+
*/
|
|
33
|
+
export declare function classifyFixtureArchetype(input: ClassifyFixtureArchetypeInput): FixtureArchetype;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AST extractor for the `dbx_model_fixture_*` tool cluster.
|
|
3
|
+
*
|
|
4
|
+
* Parses an app's `src/test/fixture.ts` into the
|
|
5
|
+
* {@link AppFixturesExtraction} consumed by every tool in the cluster.
|
|
6
|
+
*
|
|
7
|
+
* Strategy:
|
|
8
|
+
* 1. Build a single ts-morph in-memory project containing only the fixture
|
|
9
|
+
* file. Fixture files are workspace-local and self-contained for our
|
|
10
|
+
* purposes — no symbol resolution beyond simple identifier lookup.
|
|
11
|
+
* 2. Detect the workspace `<Prefix>` from the base context fixture
|
|
12
|
+
* (the class extending `FirebaseAdminNestTestContextFixture`).
|
|
13
|
+
* 3. Walk every class declaration, group `<Prefix><Model>TestContextFixture`
|
|
14
|
+
* + `<Prefix><Model>TestContextInstance` pairs by model name, then
|
|
15
|
+
* join in the matching `<Prefix><Model>TestContextParams` type and
|
|
16
|
+
* `<prefix><Model>ContextFactory` / `<prefix><Model>Context` exports.
|
|
17
|
+
* 4. Classify each entry's archetype via {@link classifyFixtureArchetype}.
|
|
18
|
+
*
|
|
19
|
+
* The extractor accepts plain text input so specs can build fixtures
|
|
20
|
+
* directly without touching the filesystem.
|
|
21
|
+
*/
|
|
22
|
+
import type { AppFixturesExtraction } from './types.js';
|
|
23
|
+
/**
|
|
24
|
+
* Inputs accepted by {@link extractAppFixturesFromText}.
|
|
25
|
+
*/
|
|
26
|
+
export interface ExtractAppFixturesInput {
|
|
27
|
+
readonly text: string;
|
|
28
|
+
readonly fixturePath: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Pure entry point used by inspect.ts and tests. Parses the supplied fixture
|
|
32
|
+
* text and returns the structured extraction; never touches disk.
|
|
33
|
+
*
|
|
34
|
+
* @param input - The raw fixture text + caller-relative path metadata.
|
|
35
|
+
* @returns The parsed extraction.
|
|
36
|
+
*/
|
|
37
|
+
export declare function extractAppFixturesFromText(input: ExtractAppFixturesInput): AppFixturesExtraction;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON formatters for the `dbx_model_fixture_*` listing + lookup reports.
|
|
3
|
+
*
|
|
4
|
+
* Each renderer mirrors the markdown formatter's information density but
|
|
5
|
+
* emits a deterministic structured payload so downstream tooling can parse
|
|
6
|
+
* results without scraping markdown. The validation report's JSON formatter
|
|
7
|
+
* lives with the validator in `@dereekb/dbx-components-mcp`.
|
|
8
|
+
*/
|
|
9
|
+
import type { AppFixturesExtraction, FixtureEntry } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Renders the listing report as JSON.
|
|
12
|
+
*
|
|
13
|
+
* @param extraction - The parsed fixture file.
|
|
14
|
+
* @returns The JSON body.
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatListAsJson(extraction: AppFixturesExtraction): string;
|
|
17
|
+
/**
|
|
18
|
+
* Renders the per-model lookup report as JSON.
|
|
19
|
+
*
|
|
20
|
+
* @param extraction - The parsed fixture file.
|
|
21
|
+
* @param entry - The matched entry.
|
|
22
|
+
* @returns The JSON body.
|
|
23
|
+
*/
|
|
24
|
+
export declare function formatLookupAsJson(extraction: AppFixturesExtraction, entry: FixtureEntry): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown formatters for the `dbx_model_fixture_*` listing + lookup reports.
|
|
3
|
+
*
|
|
4
|
+
* Each tool emits its own report shape; this file groups the renderers so
|
|
5
|
+
* the per-tool wrappers stay thin. The validation report's markdown formatter
|
|
6
|
+
* lives with the validator in `@dereekb/dbx-components-mcp`.
|
|
7
|
+
*/
|
|
8
|
+
import type { AppFixturesExtraction, FixtureEntry } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Renders the listing report for `dbx_model_fixture_list_app`.
|
|
11
|
+
*
|
|
12
|
+
* @param extraction - The parsed fixture file.
|
|
13
|
+
* @returns The markdown body.
|
|
14
|
+
*/
|
|
15
|
+
export declare function formatListAsMarkdown(extraction: AppFixturesExtraction): string;
|
|
16
|
+
/**
|
|
17
|
+
* Renders the per-model lookup report for `dbx_model_fixture_lookup`.
|
|
18
|
+
*
|
|
19
|
+
* @param extraction - The parsed fixture file.
|
|
20
|
+
* @param entry - The matched entry.
|
|
21
|
+
* @returns The markdown body.
|
|
22
|
+
*/
|
|
23
|
+
export declare function formatLookupAsMarkdown(extraction: AppFixturesExtraction, entry: FixtureEntry): string;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forwarder generator for `dbx_model_fixture_forward`.
|
|
3
|
+
*
|
|
4
|
+
* Pure text generation — given a parsed entry, returns the source of every
|
|
5
|
+
* forwarder method that should be inserted into the Fixture class. Disk
|
|
6
|
+
* mutation is handled by the tool wrapper.
|
|
7
|
+
*/
|
|
8
|
+
import type { FixtureEntry } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* One forwarder method to insert into the Fixture class.
|
|
11
|
+
*/
|
|
12
|
+
export interface RenderedForwarder {
|
|
13
|
+
readonly method: string;
|
|
14
|
+
readonly source: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Inputs accepted by {@link renderForwarders}.
|
|
18
|
+
*/
|
|
19
|
+
export interface RenderForwardersInput {
|
|
20
|
+
readonly entry: FixtureEntry;
|
|
21
|
+
readonly methods?: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Result of {@link renderForwarders}.
|
|
25
|
+
*/
|
|
26
|
+
export interface RenderedForwarders {
|
|
27
|
+
readonly added: readonly RenderedForwarder[];
|
|
28
|
+
readonly skippedAlreadyForwarded: readonly string[];
|
|
29
|
+
readonly missingFromInstance: readonly string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Returns the forwarder source for every public Instance method that
|
|
33
|
+
* doesn't yet have a Fixture counterpart.
|
|
34
|
+
*
|
|
35
|
+
* The forwarder body is a thin wrapper:
|
|
36
|
+
* ```
|
|
37
|
+
* async <name>(<paramText>): <returnType> {
|
|
38
|
+
* return this.instance.<name>(<args>);
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* Existing Fixture methods with the same name are left alone; they're
|
|
43
|
+
* reported in `skippedAlreadyForwarded`.
|
|
44
|
+
*
|
|
45
|
+
* @param input - The entry to forward + optional whitelist of method names.
|
|
46
|
+
* @returns The rendered forwarders + skip metadata.
|
|
47
|
+
*/
|
|
48
|
+
export declare function renderForwarders(input: RenderForwardersInput): RenderedForwarders;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog of framework-provided fixture families that produce
|
|
3
|
+
* `<…>TestContextFixture` / `<…>TestContextInstance` class pairs but are NOT
|
|
4
|
+
* backed by a Firestore model.
|
|
5
|
+
*
|
|
6
|
+
* The fixture validator and lookup/list formatters consult this list to
|
|
7
|
+
* recognize the pattern automatically — downstream apps that subclass these
|
|
8
|
+
* bases (or register via the listed factory) get accurate classification and
|
|
9
|
+
* skip the `triplet-incomplete` / model-registry diagnostics that otherwise
|
|
10
|
+
* fire on every Fixture/Instance pair.
|
|
11
|
+
*
|
|
12
|
+
* Add a new entry here whenever the framework introduces another non-model
|
|
13
|
+
* fixture family. Both the inheritance signal (`baseFixtureClass` /
|
|
14
|
+
* `baseInstanceClass`) and the factory-call signal (`factoryName`) are
|
|
15
|
+
* supported; either alone is sufficient.
|
|
16
|
+
*/
|
|
17
|
+
export interface FrameworkNonModelFixtureFamily {
|
|
18
|
+
/**
|
|
19
|
+
* Discriminator written to {@link FixtureEntry.kind} when the family
|
|
20
|
+
* matches.
|
|
21
|
+
*/
|
|
22
|
+
readonly kind: 'authorized-user';
|
|
23
|
+
/**
|
|
24
|
+
* Variable name of the framework factory used to register the pair, e.g.
|
|
25
|
+
* `authorizedUserContextFactory`. Matched against the call expression
|
|
26
|
+
* inside the entry's factory body.
|
|
27
|
+
*/
|
|
28
|
+
readonly factoryName: string;
|
|
29
|
+
/**
|
|
30
|
+
* Class name of the framework-provided Fixture base that downstream
|
|
31
|
+
* subclasses extend.
|
|
32
|
+
*/
|
|
33
|
+
readonly baseFixtureClass: string;
|
|
34
|
+
/**
|
|
35
|
+
* Class name of the framework-provided Instance base that downstream
|
|
36
|
+
* subclasses extend.
|
|
37
|
+
*/
|
|
38
|
+
readonly baseInstanceClass: string;
|
|
39
|
+
/**
|
|
40
|
+
* Module path the bases and factory are exported from. Surfaced in
|
|
41
|
+
* lookup/list output so consumers know where to import from.
|
|
42
|
+
*/
|
|
43
|
+
readonly module: string;
|
|
44
|
+
/**
|
|
45
|
+
* One-line human description rendered in the fixture lookup/list output.
|
|
46
|
+
*/
|
|
47
|
+
readonly description: string;
|
|
48
|
+
}
|
|
49
|
+
export declare const KNOWN_NON_MODEL_FIXTURE_FAMILIES: readonly FrameworkNonModelFixtureFamily[];
|
|
50
|
+
/**
|
|
51
|
+
* JSDoc tag the extractor honors to mark a Fixture/Instance pair as
|
|
52
|
+
* intentionally non-model. Either Fixture or Instance class can carry the
|
|
53
|
+
* tag; presence on either is sufficient.
|
|
54
|
+
*/
|
|
55
|
+
export declare const NON_MODEL_JSDOC_TAG = "dbxFixtureNotModel";
|
|
56
|
+
/**
|
|
57
|
+
* Looks up a framework family by factory call name.
|
|
58
|
+
*
|
|
59
|
+
* @param factoryCallName - The identifier name appearing in the factory body
|
|
60
|
+
* call expression (e.g. `authorizedUserContextFactory`)
|
|
61
|
+
* @returns The matched family, or `undefined`
|
|
62
|
+
*/
|
|
63
|
+
export declare function findFamilyByFactoryName(factoryCallName: string): FrameworkNonModelFixtureFamily | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Looks up a framework family by Fixture or Instance base class name.
|
|
66
|
+
*
|
|
67
|
+
* @param baseClassName - The class identifier on the `extends` clause.
|
|
68
|
+
* @returns The matched family, or `undefined`
|
|
69
|
+
*/
|
|
70
|
+
export declare function findFamilyByBaseClass(baseClassName: string): FrameworkNonModelFixtureFamily | undefined;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filesystem inspection for the `dbx_model_fixture_*` cluster.
|
|
3
|
+
*
|
|
4
|
+
* Reads `<apiDir>/src/test/fixture.ts` from disk and feeds the text through
|
|
5
|
+
* `extractAppFixtures()`. Centralising the I/O keeps the pure layers free of
|
|
6
|
+
* file-system concerns; specs build extractions directly without touching
|
|
7
|
+
* the disk.
|
|
8
|
+
*/
|
|
9
|
+
import type { AppFixturesExtraction } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Conventional location of the test fixture file inside an API app.
|
|
12
|
+
*/
|
|
13
|
+
export declare const FIXTURE_RELATIVE_PATH = "src/test/fixture.ts";
|
|
14
|
+
/**
|
|
15
|
+
* Reads `<apiDir>/src/test/fixture.ts` and returns the parsed extraction.
|
|
16
|
+
*
|
|
17
|
+
* @param apiAbs - Absolute path to the API app root.
|
|
18
|
+
* @param apiRel - Caller-supplied relative path (used for messages and
|
|
19
|
+
* path metadata; unused for I/O)
|
|
20
|
+
* @returns The parsed extraction.
|
|
21
|
+
*/
|
|
22
|
+
export declare function inspectAppFixtures(apiAbs: string, apiRel: string): Promise<AppFixturesExtraction>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scaffold renderer for `dbx_model_fixture_scaffold`.
|
|
3
|
+
*
|
|
4
|
+
* Pure text generation — given a parsed extraction and an archetype-aware
|
|
5
|
+
* scaffold spec, produces the snippet that the tool wrapper appends to
|
|
6
|
+
* `fixture.ts`. Direct disk mutation lives in the tool wrapper; this module
|
|
7
|
+
* stays testable without touching the filesystem.
|
|
8
|
+
*
|
|
9
|
+
* Each archetype owns a templated factory call; the Params interface,
|
|
10
|
+
* Instance class, and Fixture class are shared shapes.
|
|
11
|
+
*/
|
|
12
|
+
import type { AppFixturesExtraction, FixtureArchetype } from './types.js';
|
|
13
|
+
/**
|
|
14
|
+
* One fixture dependency declared on the new Params interface.
|
|
15
|
+
*
|
|
16
|
+
* `field` is the param field name (e.g. `'sg'`); `fixtureModel` is the
|
|
17
|
+
* bare model name of the parent fixture (e.g. `'SchoolGroup'`). `optional`
|
|
18
|
+
* and `array` toggle the field's modality.
|
|
19
|
+
*/
|
|
20
|
+
export interface ScaffoldParamsDependency {
|
|
21
|
+
readonly field: string;
|
|
22
|
+
readonly fixtureModel: string;
|
|
23
|
+
readonly optional?: boolean;
|
|
24
|
+
readonly array?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Inputs accepted by {@link renderFixtureScaffold}.
|
|
28
|
+
*/
|
|
29
|
+
export interface RenderFixtureScaffoldInput {
|
|
30
|
+
readonly model: string;
|
|
31
|
+
readonly prefix: string;
|
|
32
|
+
readonly archetype: FixtureArchetype;
|
|
33
|
+
readonly parentFixture?: string;
|
|
34
|
+
readonly parentFixtureField?: string;
|
|
35
|
+
readonly paramsDependsOn?: readonly ScaffoldParamsDependency[];
|
|
36
|
+
readonly withInitDocument?: boolean;
|
|
37
|
+
readonly collectionGenericArg?: string;
|
|
38
|
+
readonly modelDocumentTypeName?: string;
|
|
39
|
+
readonly factoryNamePrefix?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Output of {@link renderFixtureScaffold}.
|
|
43
|
+
*/
|
|
44
|
+
export interface RenderedFixtureScaffold {
|
|
45
|
+
readonly snippet: string;
|
|
46
|
+
readonly todos: readonly string[];
|
|
47
|
+
readonly inserted: readonly RenderedInsertion[];
|
|
48
|
+
readonly paramsTypeName: string;
|
|
49
|
+
readonly fixtureClassName: string;
|
|
50
|
+
readonly instanceClassName: string;
|
|
51
|
+
readonly factoryName: string;
|
|
52
|
+
readonly singletonName: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* One emitted code block reported back to the caller for follow-up edits.
|
|
56
|
+
*/
|
|
57
|
+
export interface RenderedInsertion {
|
|
58
|
+
readonly kind: 'params' | 'instance' | 'fixture' | 'factory' | 'singleton';
|
|
59
|
+
readonly name: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Builds the scaffold snippet for a new fixture triplet.
|
|
63
|
+
*
|
|
64
|
+
* The snippet is appended to `fixture.ts` as one block (with a leading
|
|
65
|
+
* `// MARK:` divider) so all five entities — Params, Instance, Fixture,
|
|
66
|
+
* Factory, Singleton — land in one logical section. The disk-mutation tool
|
|
67
|
+
* wrapper inserts this string at the end of the file.
|
|
68
|
+
*
|
|
69
|
+
* @param extraction - The current parse of `fixture.ts` (used only to
|
|
70
|
+
* detect import collisions and pick context fixture/instance names)
|
|
71
|
+
* @param input - Scaffold spec.
|
|
72
|
+
* @returns The rendered snippet plus a placeholder checklist.
|
|
73
|
+
*/
|
|
74
|
+
export declare function renderFixtureScaffold(extraction: AppFixturesExtraction, input: RenderFixtureScaffoldInput): RenderedFixtureScaffold;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extraction types shared by the `dbx_model_fixture_*` tool cluster.
|
|
3
|
+
*
|
|
4
|
+
* The cluster reads an app's `<root>/src/test/fixture.ts`, identifies every
|
|
5
|
+
* `<Prefix><Model>TestContext{Fixture,Instance,Params}` triplet plus its
|
|
6
|
+
* `modelTestContextFactory(...)` call, and returns information used by the
|
|
7
|
+
* lookup, list, validate, scaffold, and forward tools.
|
|
8
|
+
*
|
|
9
|
+
* The classifier (see `archetype.ts`) sorts each entry into one of four
|
|
10
|
+
* archetypes. The validator and scaffold tools speak the dialect of the
|
|
11
|
+
* archetype so 8-generic sub-collection factories aren't conflated with the
|
|
12
|
+
* 7-generic top-level shape.
|
|
13
|
+
*
|
|
14
|
+
* The validation diagnostic types (`FixtureDiagnostic`, `FixtureValidationResult`,
|
|
15
|
+
* the diagnostic-code union, and the model registry) live alongside the
|
|
16
|
+
* `validateAppFixtures` implementation in `@dereekb/dbx-components-mcp`, since
|
|
17
|
+
* they depend on the rule-catalog remediation layer.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Configuration archetypes for `modelTestContextFactory(...)` calls.
|
|
21
|
+
*
|
|
22
|
+
* - `top-level-simple` — 7 generics, `getCollection(fi)` is single-arg, no
|
|
23
|
+
* parent-fixture dependency on `Params`.
|
|
24
|
+
* - `top-level-with-deps` — top-level model whose `Params` interface adds
|
|
25
|
+
* sibling fixture refs (e.g. an authorized user). `getCollection` remains
|
|
26
|
+
* single-arg.
|
|
27
|
+
* - `sub-collection` — 8 generics with the explicit `FirestoreCollection`
|
|
28
|
+
* generic; `getCollection(fi, params)` reads a parent fixture's document
|
|
29
|
+
* off `params`.
|
|
30
|
+
* - `sub-collection-traversal` — sub-collection variant that also wires
|
|
31
|
+
* `collectionForDocument` so the framework can traverse a child document
|
|
32
|
+
* back to its parent collection.
|
|
33
|
+
*/
|
|
34
|
+
export type FixtureArchetype = 'top-level-simple' | 'top-level-with-deps' | 'sub-collection' | 'sub-collection-traversal';
|
|
35
|
+
/**
|
|
36
|
+
* Classification of a Fixture/Instance pair by what it represents.
|
|
37
|
+
*
|
|
38
|
+
* - `firestore-model` — the default; the pair is registered via
|
|
39
|
+
* `modelTestContextFactory(...)` and corresponds to a Firestore document
|
|
40
|
+
* model. All validator rules apply.
|
|
41
|
+
* - `authorized-user` — the pair is part of the framework's `AuthorizedUser`
|
|
42
|
+
* family (extends `AuthorizedUserTestContextFixture`/`Instance` or is
|
|
43
|
+
* registered via `authorizedUserContextFactory`). Model-specific rules
|
|
44
|
+
* (`triplet-incomplete`, `archetype-inconsistent`, etc.) are skipped.
|
|
45
|
+
* - `non-model` — the pair is explicitly opted out of model validation via
|
|
46
|
+
* the `@dbxFixtureNotModel` JSDoc tag on the Fixture or Instance class.
|
|
47
|
+
* Same rule gating as `authorized-user`.
|
|
48
|
+
*/
|
|
49
|
+
export type FixtureKind = 'firestore-model' | 'authorized-user' | 'non-model';
|
|
50
|
+
/**
|
|
51
|
+
* One method declared on an Instance or Fixture class. `signature` is the raw
|
|
52
|
+
* parameter list copied verbatim from ts-morph (including parameter types and
|
|
53
|
+
* default values) so the forward tool can reproduce it without rewriting type
|
|
54
|
+
* text.
|
|
55
|
+
*/
|
|
56
|
+
export interface FixtureMethod {
|
|
57
|
+
readonly name: string;
|
|
58
|
+
readonly isStatic: boolean;
|
|
59
|
+
readonly isAsync: boolean;
|
|
60
|
+
readonly visibility: 'public' | 'private' | 'protected';
|
|
61
|
+
readonly parameterText: string;
|
|
62
|
+
readonly returnTypeText?: string;
|
|
63
|
+
readonly line: number;
|
|
64
|
+
readonly endLine: number;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* One field on a `<Prefix><Model>TestContextParams` interface.
|
|
68
|
+
*
|
|
69
|
+
* `fixtureModel` is set when the field's type resolves to a sibling
|
|
70
|
+
* `<Prefix><Model>TestContextFixture`. The pair `{ field, fixtureModel }`
|
|
71
|
+
* forms a dependency edge consumed by the validator's parent-fixture-naming
|
|
72
|
+
* rule.
|
|
73
|
+
*/
|
|
74
|
+
export interface FixtureParamsField {
|
|
75
|
+
readonly name: string;
|
|
76
|
+
readonly typeText: string;
|
|
77
|
+
readonly optional: boolean;
|
|
78
|
+
readonly fixtureModel?: string;
|
|
79
|
+
readonly array?: boolean;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Parsed metadata for a `<Prefix><Model>TestContextParams` interface or type
|
|
83
|
+
* alias.
|
|
84
|
+
*
|
|
85
|
+
* `extendsPartial` is `true` when the interface extends `Partial<Model>` (the
|
|
86
|
+
* common case for top-level models). `aliasOfPartial` is `true` for the
|
|
87
|
+
* `type Foo = Partial<Bar>` alias pattern used by simple guestbook-style
|
|
88
|
+
* params. Standalone interfaces with no `extends` clause set both to `false`
|
|
89
|
+
* — typical for sub-collection params that don't carry the model's own
|
|
90
|
+
* fields.
|
|
91
|
+
*/
|
|
92
|
+
export interface FixtureParamsType {
|
|
93
|
+
readonly name: string;
|
|
94
|
+
readonly kind: 'interface' | 'alias';
|
|
95
|
+
readonly extendsPartial: boolean;
|
|
96
|
+
readonly aliasOfPartial: boolean;
|
|
97
|
+
readonly modelName?: string;
|
|
98
|
+
readonly fields: readonly FixtureParamsField[];
|
|
99
|
+
readonly line: number;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The two-arg metadata for the `modelTestContextFactory<...>(...)` call.
|
|
103
|
+
*
|
|
104
|
+
* The validator compares `genericArgs[0]`/`genericArgs[1]` (model + document
|
|
105
|
+
* type) against the Fixture/Instance class generic args; the scaffold tool
|
|
106
|
+
* reproduces the same generic count when adding new entries.
|
|
107
|
+
*/
|
|
108
|
+
export interface FactoryCall {
|
|
109
|
+
readonly factoryName: string;
|
|
110
|
+
readonly singletonName?: string;
|
|
111
|
+
readonly genericArgs: readonly string[];
|
|
112
|
+
readonly hasParamsGetCollection: boolean;
|
|
113
|
+
readonly hasCollectionForDocument: boolean;
|
|
114
|
+
readonly hasInitDocument: boolean;
|
|
115
|
+
readonly parentFixtureFieldFromGetCollection?: string;
|
|
116
|
+
readonly line: number;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* One `<Prefix><Model>TestContext{Fixture,Instance,Params}` triplet.
|
|
120
|
+
*
|
|
121
|
+
* The triplet is keyed by `model` (the bare model name with the workspace
|
|
122
|
+
* prefix stripped). All five anchors must be present for the validator to
|
|
123
|
+
* treat the triplet as complete.
|
|
124
|
+
*/
|
|
125
|
+
export interface FixtureEntry {
|
|
126
|
+
readonly model: string;
|
|
127
|
+
readonly prefix: string;
|
|
128
|
+
readonly archetype: FixtureArchetype;
|
|
129
|
+
/**
|
|
130
|
+
* Classification of what the Fixture/Instance pair represents. Defaults to
|
|
131
|
+
* `firestore-model`; framework-provided non-model families and pairs
|
|
132
|
+
* tagged with `@dbxFixtureNotModel` opt out of model-specific validator
|
|
133
|
+
* rules.
|
|
134
|
+
*/
|
|
135
|
+
readonly kind: FixtureKind;
|
|
136
|
+
/**
|
|
137
|
+
* When `kind !== 'firestore-model'`, identifies the framework family that
|
|
138
|
+
* matched (e.g. `'authorized-user'`) so lookup/list output can describe
|
|
139
|
+
* the pair. Set together with `kind`.
|
|
140
|
+
*/
|
|
141
|
+
readonly nonModelFamily?: 'authorized-user' | 'jsdoc-tag';
|
|
142
|
+
readonly fixtureClassName: string;
|
|
143
|
+
readonly instanceClassName: string;
|
|
144
|
+
readonly paramsTypeName: string;
|
|
145
|
+
readonly factoryName?: string;
|
|
146
|
+
readonly singletonName?: string;
|
|
147
|
+
readonly fixtureExtendsGenerics: readonly string[];
|
|
148
|
+
readonly instanceExtendsGenerics: readonly string[];
|
|
149
|
+
readonly fixtureMethods: readonly FixtureMethod[];
|
|
150
|
+
readonly instanceMethods: readonly FixtureMethod[];
|
|
151
|
+
readonly params?: FixtureParamsType;
|
|
152
|
+
readonly factory?: FactoryCall;
|
|
153
|
+
readonly fixtureLine: number;
|
|
154
|
+
readonly fixtureEndLine: number;
|
|
155
|
+
readonly instanceLine: number;
|
|
156
|
+
readonly instanceEndLine: number;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Aggregate result returned by `extractAppFixtures()`.
|
|
160
|
+
*
|
|
161
|
+
* `prefix` is detected from the `<Prefix>ContextFixture` class in the file —
|
|
162
|
+
* scaffolding and validation derive everything from this single anchor so no
|
|
163
|
+
* tool hard-codes `DemoApi` or `HellosubsApi`.
|
|
164
|
+
*
|
|
165
|
+
* `unrecognizedClassNames` collects classes that match the
|
|
166
|
+
* `*TestContextFixture` / `*TestContextInstance` suffix but couldn't be
|
|
167
|
+
* paired into a triplet, so the validator can flag orphans.
|
|
168
|
+
*/
|
|
169
|
+
export interface AppFixturesExtraction {
|
|
170
|
+
readonly fixturePath: string;
|
|
171
|
+
readonly prefix?: string;
|
|
172
|
+
readonly entries: readonly FixtureEntry[];
|
|
173
|
+
readonly unrecognizedClassNames: readonly string[];
|
|
174
|
+
readonly identityImports: readonly string[];
|
|
175
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec-file discovery for the `dbx_model_test_list_app` tool.
|
|
3
|
+
*
|
|
4
|
+
* Walks `<apiDir>/src/app/function/` and returns every `*.spec.ts` file
|
|
5
|
+
* grouped by its parent folder, with each file pre-classified via
|
|
6
|
+
* {@link classifySpecFile} so the wrapper can render listings and drift
|
|
7
|
+
* reports without re-parsing filenames.
|
|
8
|
+
*
|
|
9
|
+
* The walker is shallow (one level deep — exactly the model-group folders),
|
|
10
|
+
* matching the convention used across hellosubs / demo-api. Files nested
|
|
11
|
+
* deeper are still picked up but reported under their immediate parent
|
|
12
|
+
* folder so the classifier's group-vs-folder check stays meaningful.
|
|
13
|
+
*/
|
|
14
|
+
import { type SpecFileClassification } from '@dereekb/util';
|
|
15
|
+
/**
|
|
16
|
+
* Conventional subdirectory under an API app that houses model-group tests.
|
|
17
|
+
*/
|
|
18
|
+
export declare const FUNCTION_DIR_REL = "src/app/function";
|
|
19
|
+
/**
|
|
20
|
+
* One discovered model group with its spec files (classified).
|
|
21
|
+
*/
|
|
22
|
+
export interface DiscoveredSpecGroup {
|
|
23
|
+
readonly group: string;
|
|
24
|
+
/**
|
|
25
|
+
* Caller-relative path to the group folder (e.g.
|
|
26
|
+
* `apps/hellosubs-api/src/app/function/job`).
|
|
27
|
+
*/
|
|
28
|
+
readonly folderRel: string;
|
|
29
|
+
readonly files: readonly DiscoveredSpecFile[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* One discovered spec file with its classification + caller-relative path.
|
|
33
|
+
*/
|
|
34
|
+
export interface DiscoveredSpecFile {
|
|
35
|
+
readonly filename: string;
|
|
36
|
+
/**
|
|
37
|
+
* Caller-relative path to the file (e.g.
|
|
38
|
+
* `apps/hellosubs-api/src/app/function/job/job.crud.spec.ts`).
|
|
39
|
+
*/
|
|
40
|
+
readonly fileRel: string;
|
|
41
|
+
readonly classification: SpecFileClassification;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Aggregate result of {@link discoverSpecFilesByGroup}.
|
|
45
|
+
*/
|
|
46
|
+
export interface DiscoveredSpecCatalog {
|
|
47
|
+
/**
|
|
48
|
+
* Caller-relative path to the API app (echoed for the formatter).
|
|
49
|
+
*/
|
|
50
|
+
readonly apiRel: string;
|
|
51
|
+
/**
|
|
52
|
+
* Caller-relative path to the function-tests root (e.g.
|
|
53
|
+
* `apps/hellosubs-api/src/app/function`).
|
|
54
|
+
*/
|
|
55
|
+
readonly functionDirRel: string;
|
|
56
|
+
readonly groups: readonly DiscoveredSpecGroup[];
|
|
57
|
+
/**
|
|
58
|
+
* Total `.spec.ts` files discovered across all groups (canonical + drift).
|
|
59
|
+
*/
|
|
60
|
+
readonly totalSpecFiles: number;
|
|
61
|
+
/**
|
|
62
|
+
* Total drift entries — i.e. classifications with `isCanonical === false`
|
|
63
|
+
* that are not `non-spec` / `non-group`.
|
|
64
|
+
*/
|
|
65
|
+
readonly totalDriftFiles: number;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Walks `<apiAbs>/src/app/function/` and returns the grouped, classified
|
|
69
|
+
* catalog. Folders with no `.spec.ts` files are omitted. Files in the
|
|
70
|
+
* function root that don't live under a group folder are also omitted (the
|
|
71
|
+
* convention is one group folder per top-level entry).
|
|
72
|
+
*
|
|
73
|
+
* @param config - Inputs.
|
|
74
|
+
* @param config.apiAbs - Absolute path to the API app root.
|
|
75
|
+
* @param config.apiRel - Caller-relative API-app path (used for output paths).
|
|
76
|
+
* @returns The discovered catalog.
|
|
77
|
+
*/
|
|
78
|
+
export declare function discoverSpecFilesByGroup(config: {
|
|
79
|
+
readonly apiAbs: string;
|
|
80
|
+
readonly apiRel: string;
|
|
81
|
+
}): Promise<DiscoveredSpecCatalog>;
|