@filipebraida/adonis-function-points 0.6.0 → 0.7.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/CHANGELOG.md +68 -0
- package/README.md +1 -1
- package/build/commands/main.js +6 -6
- package/build/{fp_calibrate-EAuAtdbq.js → fp_calibrate-3TxGdS1b.js} +1 -1
- package/build/{fp_count-CZ0cUUBQ.js → fp_count-arGLnVlY.js} +1 -1
- package/build/{fp_diff-BTg_LX0r.js → fp_diff-DBBvzq5x.js} +1 -1
- package/build/{fp_explain-D6QvDLKQ.js → fp_explain-aNFApwiT.js} +1 -1
- package/build/{fp_inventory-C43fU39x.js → fp_inventory-DIjKIC9t.js} +1 -1
- package/build/{fp_metrics-DEMPk4xC.js → fp_metrics-BpU61waG.js} +1 -1
- package/build/index.js +2 -2
- package/build/{pipeline-Cq4dNTNE.js → pipeline-DO2301fV.js} +1414 -122
- package/build/{resolvers-DlKJOZnk.js → resolvers-DaU4uAqT.js} +323 -150
- package/build/{runners-FYmPIPub.js → runners-Dm7cWGa-.js} +2 -2
- package/build/src/albrecht/counter.d.ts +8 -1
- package/build/src/cli.js +2 -2
- package/build/src/inventory/graph/call_graph.d.ts +15 -0
- package/build/src/inventory/graph/deliveries.d.ts +88 -0
- package/build/src/inventory/graph/output_fields.d.ts +45 -1
- package/build/src/inventory/resolvers/index.js +1 -1
- package/build/src/inventory/resolvers/job_dispatch.d.ts +20 -0
- package/build/src/inventory/resolvers/local_function.d.ts +24 -0
- package/build/src/inventory/resolvers/transformer.d.ts +0 -23
- package/build/src/inventory/sources/commands.d.ts +14 -0
- package/build/src/inventory/sources/jobs.d.ts +27 -0
- package/build/src/pipeline.js +1 -1
- package/build/src/types.d.ts +19 -0
- package/package.json +1 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Node } from 'ts-morph';
|
|
2
|
+
import type { CallExpression, SourceFile } from 'ts-morph';
|
|
3
|
+
import type { RelationMap, StoreSymbols } from '../detectors/lucid.js';
|
|
4
|
+
import type { HandlerRef } from '../../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* What a transaction DELIVERS — counting-decisions §6, plan 0.7 §A′.
|
|
7
|
+
*
|
|
8
|
+
* The DETs of an output are the fields that cross the boundary, and the place
|
|
9
|
+
* they cross is the delivery: the props handed to `inertia.render` /
|
|
10
|
+
* `inertia.modal` / `view.render`, the payload of `response.json|ok|created|send`,
|
|
11
|
+
* a literal the handler returns. Before this, "what leaves" was every column of
|
|
12
|
+
* every store the transaction touched — a `findOrFail` made to authorise handed
|
|
13
|
+
* the whole table to the screen, and a derived `total` handed nothing.
|
|
14
|
+
*
|
|
15
|
+
* Measured on three applications first: no delivered collection is a variable
|
|
16
|
+
* bound to a store; they come out of query objects the graph already follows.
|
|
17
|
+
* So a delivered value that comes from a followed call is resolved to what that
|
|
18
|
+
* body returns — the graph does that in `run()`, once the bodies are known; this
|
|
19
|
+
* module only says WHAT was delivered and where it came from.
|
|
20
|
+
*/
|
|
21
|
+
export type Delivery =
|
|
22
|
+
/** a variable bound to a store: its columns leave */
|
|
23
|
+
{
|
|
24
|
+
kind: 'store';
|
|
25
|
+
store: string;
|
|
26
|
+
path: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The result of a call a strategy followed: what that body returns leaves.
|
|
30
|
+
* `args` are the call's arguments, classified — a body that returns no literal
|
|
31
|
+
* and reads no store (a CSV builder) delivers what was handed INTO it.
|
|
32
|
+
*/
|
|
33
|
+
| {
|
|
34
|
+
kind: 'call';
|
|
35
|
+
refs: HandlerRef[];
|
|
36
|
+
path: string;
|
|
37
|
+
expression: string;
|
|
38
|
+
args: Delivery[];
|
|
39
|
+
/**
|
|
40
|
+
* One key of what the call returns — `const { data } = await q.handle()`,
|
|
41
|
+
* `relatorio.linhas` — rather than the whole result. Resolved against the
|
|
42
|
+
* body's classified return, keeping only that key.
|
|
43
|
+
*/
|
|
44
|
+
pick?: string;
|
|
45
|
+
}
|
|
46
|
+
/** a scalar, a property, an expression: one DET */
|
|
47
|
+
| {
|
|
48
|
+
kind: 'scalar';
|
|
49
|
+
path: string;
|
|
50
|
+
}
|
|
51
|
+
/** an input echoed back — the validated payload, a field read off the request: counts once, on entry */
|
|
52
|
+
| {
|
|
53
|
+
kind: 'echo';
|
|
54
|
+
path: string;
|
|
55
|
+
}
|
|
56
|
+
/** something the classifier cannot read: one DET as a floor, reported */
|
|
57
|
+
| {
|
|
58
|
+
kind: 'opaque';
|
|
59
|
+
path: string;
|
|
60
|
+
expression: string;
|
|
61
|
+
};
|
|
62
|
+
/** keys of a result that carry its rows: picking one of these is not picking one value */
|
|
63
|
+
export declare const PASSES_ROWS: Set<string>;
|
|
64
|
+
export type DeliveryContext = {
|
|
65
|
+
body: Node;
|
|
66
|
+
file: SourceFile;
|
|
67
|
+
symbols: StoreSymbols;
|
|
68
|
+
relations: RelationMap;
|
|
69
|
+
followed: Map<CallExpression, HandlerRef[]>;
|
|
70
|
+
};
|
|
71
|
+
export type BodyDeliveries = {
|
|
72
|
+
/** props handed to a renderer or a response method, anywhere in the body */
|
|
73
|
+
calls: Delivery[];
|
|
74
|
+
/** a delivery call was found, even with nothing readable in it */
|
|
75
|
+
anyCall: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* What a `return` hands back that is not one of those calls — meaningful for
|
|
78
|
+
* the ENTRY body only, where returning a value is delivering it; a followed
|
|
79
|
+
* body's return is read by `returnedLeavesOf` instead.
|
|
80
|
+
*/
|
|
81
|
+
returns: Delivery[];
|
|
82
|
+
anyReturn: boolean;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* The deliveries of a body: every props argument handed to a renderer or a
|
|
86
|
+
* response method, and what a `return` hands back that is not one of those calls.
|
|
87
|
+
*/
|
|
88
|
+
export declare function deliveriesIn(ctx: DeliveryContext): BodyDeliveries;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Node } from 'ts-morph';
|
|
2
|
-
import type { CallExpression, ClassDeclaration } from 'ts-morph';
|
|
2
|
+
import type { CallExpression, ClassDeclaration, Expression, ObjectLiteralExpression } from 'ts-morph';
|
|
3
3
|
import type { CollectedDataStore } from '../sources/data_stores.js';
|
|
4
4
|
/**
|
|
5
5
|
* What an output transaction actually EMITS — counting-decisions §6.
|
|
@@ -77,6 +77,49 @@ export declare function transformerResourceOf(cls: ClassDeclaration): string | n
|
|
|
77
77
|
* the same reason `isPrimary` is not one on the data function.
|
|
78
78
|
*/
|
|
79
79
|
export declare function outputFieldsIn(body: Node, owner: ClassDeclaration | undefined, stores: Map<string, CollectedDataStore>, followed: (call: CallExpression) => boolean): OutputFacts;
|
|
80
|
+
/**
|
|
81
|
+
* The leaves of the object literal ANY body returns — a query object building a
|
|
82
|
+
* summary, a module function assembling a view model. Same walker as the
|
|
83
|
+
* transformer's, unqualified: the caller prefixes the path the value was
|
|
84
|
+
* delivered under. `null` when the body returns no literal.
|
|
85
|
+
*/
|
|
86
|
+
export declare function returnedLeavesOf(body: Node, followed: (call: CallExpression) => boolean): {
|
|
87
|
+
leaves: string[];
|
|
88
|
+
opaque: string[];
|
|
89
|
+
} | null;
|
|
90
|
+
type LeafOptions = {
|
|
91
|
+
/** prefixed to every leaf, with a dot; empty for an unqualified walk */
|
|
92
|
+
qualifier: string;
|
|
93
|
+
/** top-level names that are not DETs (the resource's key, its stamps) */
|
|
94
|
+
excluded: Set<string>;
|
|
95
|
+
followed: (call: CallExpression) => boolean;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* The leaves of object literals, by the §7 rules:
|
|
99
|
+
*
|
|
100
|
+
* { titulo: l.titulo } 1 — `titulo`
|
|
101
|
+
* { autor: AutorTransformer.transform } 0 here; the followed body contributes
|
|
102
|
+
* { endereco: { rua, cidade } } leaves individually
|
|
103
|
+
* { tags: xs.map((t) => t.nome) } 1 — a repeating group of one attribute
|
|
104
|
+
* { itens: xs.map((i) => ({ a, b })) } the leaves, once
|
|
105
|
+
* ...this.pick(this.resource, [...]) the listed names
|
|
106
|
+
* ...this.toObject() 0 here; the followed body contributes
|
|
107
|
+
* ...anythingElse 1, opaque, reported
|
|
108
|
+
*/
|
|
109
|
+
export declare function collectLeaves(literals: ObjectLiteralExpression[], options: LeafOptions): {
|
|
110
|
+
leaves: string[];
|
|
111
|
+
opaque: string[];
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Object literals the body itself returns — not the ones returned by arrow
|
|
115
|
+
* functions inside it, which belong to `.map()` callbacks and are read as
|
|
116
|
+
* repeating groups where they occur.
|
|
117
|
+
*/
|
|
118
|
+
export declare function returnedLiteralsOf(body: Node): ObjectLiteralExpression[];
|
|
119
|
+
/** `xs.map((x) => ({ a, b }))` -> the literal; null for a scalar map or anything else */
|
|
120
|
+
export declare function mappedLiteralOf(value: Expression): ObjectLiteralExpression | null;
|
|
121
|
+
/** strips parentheses, `as`, `satisfies` and non-null assertions */
|
|
122
|
+
export declare function unwrap(node: Node | undefined | null): Expression | null;
|
|
80
123
|
/**
|
|
81
124
|
* The shape of the chain an access belongs to — read from the WHOLE chain, root
|
|
82
125
|
* to end, because every call on it is detected as an access and each must reach
|
|
@@ -97,3 +140,4 @@ export type ChainShape = {
|
|
|
97
140
|
}[];
|
|
98
141
|
};
|
|
99
142
|
export declare function chainShapeOf(access: CallExpression): ChainShape;
|
|
143
|
+
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as resolveCall, n as ignoreCalls, r as isTechnicalWrite, t as BUILTIN_CALL_RESOLVERS } from "../../../resolvers-
|
|
1
|
+
import { i as resolveCall, n as ignoreCalls, r as isTechnicalWrite, t as BUILTIN_CALL_RESOLVERS } from "../../../resolvers-DaU4uAqT.js";
|
|
2
2
|
export { BUILTIN_CALL_RESOLVERS, ignoreCalls, isTechnicalWrite, resolveCall };
|
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
import type { CallResolver } from './types.js';
|
|
2
|
+
export declare const DISPATCH_METHODS: Set<string>;
|
|
3
|
+
/**
|
|
4
|
+
* The method that actually runs the job, by queue package.
|
|
5
|
+
*
|
|
6
|
+
* There is no single name, and this list grew twice by measurement rather than by
|
|
7
|
+
* reasoning. `@rlanz/bull-queue` uses `handle`; `@nemoventures/adonis-jobs` calls
|
|
8
|
+
* it `process`; `@adonisjs/queue` — the official package — generates
|
|
9
|
+
* `async execute()` in its own `make:job` stub. Each omission cost the same: the
|
|
10
|
+
* file resolved, no body was found, the dispatch was reported as an unknown, and
|
|
11
|
+
* every write inside the job went uncounted.
|
|
12
|
+
*
|
|
13
|
+
* `execute` surfaced only once event dispatch started being followed, because the
|
|
14
|
+
* listener was what enqueued the job and that path had never been walked. Which is
|
|
15
|
+
* the argument for adding a name when a real application shows it: a list written
|
|
16
|
+
* from imagination would have missed this one too.
|
|
17
|
+
*
|
|
18
|
+
* Ordered: a class declaring more than one is answering the dispatcher with the
|
|
19
|
+
* first, and `handle` is the most common.
|
|
20
|
+
*/
|
|
21
|
+
export declare const EXECUTION_METHODS: readonly ["handle", "execute", "process", "run", "perform"];
|
|
2
22
|
/**
|
|
3
23
|
* "Job" pattern: the write happens asynchronously.
|
|
4
24
|
*
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { CallExpression } from 'ts-morph';
|
|
2
|
+
import type { CallResolver } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* "Local function" pattern: a helper declared in the same file, not imported.
|
|
5
|
+
*
|
|
6
|
+
* const lista = await proximos(id) // function proximos() { … }
|
|
7
|
+
* return rows.map(paraLinha) // const paraLinha = (row) => …
|
|
8
|
+
*
|
|
9
|
+
* A query object that keeps its helpers beside it is common, and before this
|
|
10
|
+
* every such call was unresolved: the store a helper read was reached by nobody
|
|
11
|
+
* from that route, and a value built by it left as a whole table handed in.
|
|
12
|
+
*
|
|
13
|
+
* Only module-level declarations: a closure declared inside a body is part of
|
|
14
|
+
* that body, and the graph already walks it.
|
|
15
|
+
*/
|
|
16
|
+
export declare const localFunctionResolver: CallResolver;
|
|
17
|
+
/**
|
|
18
|
+
* The function a call names: `proximos(id)` names `proximos`; `rows.map(paraLinha)`
|
|
19
|
+
* names `paraLinha`, called once per row — the body the graph must read is the
|
|
20
|
+
* same, whichever way it was reached.
|
|
21
|
+
*/
|
|
22
|
+
export declare function calledFunctionOf(call: CallExpression): import('ts-morph').Identifier | null;
|
|
23
|
+
/** `function name() {}` or `const name = () => {}` / `function () {}` at module level */
|
|
24
|
+
export declare function declaresFunction(file: import('ts-morph').SourceFile, name: string): boolean;
|
|
@@ -1,25 +1,2 @@
|
|
|
1
1
|
import type { CallResolver } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* "Transformer" pattern: the package supplies the API, the application
|
|
4
|
-
* supplies the body.
|
|
5
|
-
*
|
|
6
|
-
* class InviteTransformer extends BaseTransformer<Invite> {
|
|
7
|
-
* toObject() { … }
|
|
8
|
-
* }
|
|
9
|
-
*
|
|
10
|
-
* InviteTransformer.transform(invite)
|
|
11
|
-
*
|
|
12
|
-
* `transform()` and `paginate()` live in `@adonisjs/core`, so resolving the
|
|
13
|
-
* symbol lands on the application file and finds no body there. The naive
|
|
14
|
-
* reading is that the tracer must step into node_modules; it does not. Those
|
|
15
|
-
* methods call BACK into `toObject()`, which the application writes, so the
|
|
16
|
-
* body worth analysing was in the application all along.
|
|
17
|
-
*
|
|
18
|
-
* It is the same shape as `job-dispatch`, where `dispatch` enqueues and
|
|
19
|
-
* `handle` executes.
|
|
20
|
-
*
|
|
21
|
-
* COUNTING DECISION: the write a transformer performs belongs to the
|
|
22
|
-
* transaction that serialised through it. Without this, a table written only
|
|
23
|
-
* inside `toObject()` is reached by nobody and drops out under AFP §6.5.4.
|
|
24
|
-
*/
|
|
25
2
|
export declare const transformerResolver: CallResolver;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ClassDeclaration } from 'ts-morph';
|
|
2
|
+
import type { AppContext } from '../app_context.js';
|
|
3
|
+
import type { CollectedEntryPoint } from './routes_ast.js';
|
|
4
|
+
export declare const GENERATES_DATA_HINT = "imports @faker-js/faker: generates data, probably a development tool";
|
|
5
|
+
export declare function collectCommands(app: AppContext): CollectedEntryPoint[];
|
|
6
|
+
/**
|
|
7
|
+
* The input DETs of a command: its `@flags.*` and `@args.*`, named as the
|
|
8
|
+
* operator types them — `flagName` / `argumentName` when given, the property
|
|
9
|
+
* otherwise. Returned as `flags.<name>` / `args.<name>` so the counter can say
|
|
10
|
+
* which is which.
|
|
11
|
+
*/
|
|
12
|
+
export declare function commandFieldsOf(cls: ClassDeclaration): string[];
|
|
13
|
+
/** is this class an ace command? — the graph asks, to read its flags as input */
|
|
14
|
+
export declare function isCommandClass(cls: ClassDeclaration): boolean;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { AppContext } from '../app_context.js';
|
|
2
|
+
/**
|
|
3
|
+
* The application's queue jobs, and who dispatches each — plan 0.7 §D.
|
|
4
|
+
*
|
|
5
|
+
* A job dispatched by a handler is part of that handler's transaction (§9): the
|
|
6
|
+
* user clicks, the effect happens, asynchronously or not. A job that NO
|
|
7
|
+
* transaction reaches is one of two things, and the code cannot say which:
|
|
8
|
+
*
|
|
9
|
+
* scheduled `PodarAuditoriaJob.schedule({}).cron('0 3 * * *')` in a start
|
|
10
|
+
* file — an elementary process nobody is counting
|
|
11
|
+
* dead code dispatched by nothing at all
|
|
12
|
+
*
|
|
13
|
+
* Reported, not counted: inventing an elementary process is the error this
|
|
14
|
+
* package exists to avoid. When a scheduler appears on a real application, it
|
|
15
|
+
* becomes an entry point `job:<Class>` with the identity §5 already decided.
|
|
16
|
+
*/
|
|
17
|
+
export type CollectedJob = {
|
|
18
|
+
/** the class name */
|
|
19
|
+
name: string;
|
|
20
|
+
/** absolute, posix */
|
|
21
|
+
file: string;
|
|
22
|
+
/** files that dispatch it (`X.dispatch(…)`), absolute posix — inside a transaction or not */
|
|
23
|
+
dispatchedFrom: string[];
|
|
24
|
+
/** files that schedule it (`X.schedule({}).cron(…)`): a scheduler, which no transaction is */
|
|
25
|
+
scheduledFrom: string[];
|
|
26
|
+
};
|
|
27
|
+
export declare function collectJobs(app: AppContext): CollectedJob[];
|
package/build/src/pipeline.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as analyze, t as CoverageTooLowError } from "../pipeline-
|
|
1
|
+
import { n as analyze, t as CoverageTooLowError } from "../pipeline-DO2301fV.js";
|
|
2
2
|
export { CoverageTooLowError, analyze };
|
package/build/src/types.d.ts
CHANGED
|
@@ -74,6 +74,12 @@ export type EntryPoint = {
|
|
|
74
74
|
/** route name when present; not the identity used across versions */
|
|
75
75
|
name?: string;
|
|
76
76
|
handler: HandlerRef | null;
|
|
77
|
+
/**
|
|
78
|
+
* What the collector noticed and the counter cannot decide: an ace command that
|
|
79
|
+
* imports a data generator is probably a development tool. Printed beside the
|
|
80
|
+
* function, so a person excludes it with `boundary.ignoreEntryPoints`.
|
|
81
|
+
*/
|
|
82
|
+
hints?: string[];
|
|
77
83
|
provenance: Provenance;
|
|
78
84
|
};
|
|
79
85
|
export type HandlerRef = {
|
|
@@ -114,6 +120,12 @@ export type HandlerBehavior = {
|
|
|
114
120
|
* user-recognisable field crossing the boundary, which is §7.2's definition.
|
|
115
121
|
*/
|
|
116
122
|
requestFields: Field[];
|
|
123
|
+
/**
|
|
124
|
+
* The `@flags.*` / `@args.*` an ace command declares — its input DETs, exact.
|
|
125
|
+
* Named `flags.<name>` / `args.<name>`, as the operator types them. Absent on
|
|
126
|
+
* an HTTP transaction.
|
|
127
|
+
*/
|
|
128
|
+
commandFields?: Field[];
|
|
117
129
|
/** the transaction reads the request in a way that enumerates nothing */
|
|
118
130
|
opaqueRequest: boolean;
|
|
119
131
|
/**
|
|
@@ -125,6 +137,13 @@ export type HandlerBehavior = {
|
|
|
125
137
|
opaqueOutputFields: Field[];
|
|
126
138
|
/** stores a transformer on the path is for: their keys leave, not their columns */
|
|
127
139
|
transformedStores: string[];
|
|
140
|
+
/** what the transaction delivers: derived fields, raw stores, values nobody could read */
|
|
141
|
+
delivered: {
|
|
142
|
+
any: boolean;
|
|
143
|
+
fields: string[];
|
|
144
|
+
opaqueFields: string[];
|
|
145
|
+
stores: string[];
|
|
146
|
+
};
|
|
128
147
|
/**
|
|
129
148
|
* How each store was read: rows whole, `.select()` columns, or one aggregate
|
|
130
149
|
* scalar; by its own chain (`direct`) or preloaded through another store (`via`).
|