@suss/contract-serverless 0.33.0 → 0.34.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/README.md +18 -18
- package/dist/index.d.cts +96 -15
- package/dist/index.d.ts +96 -15
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# @suss/contract-serverless
|
|
2
2
|
|
|
3
|
-
Part of [suss](https://github.com/nimbuscloud-ai/suss), which reads both sides of every call in a repository and
|
|
3
|
+
Part of [suss](https://github.com/nimbuscloud-ai/suss), which reads both sides of every call in a repository and reports where the two disagree.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
This package builds suss `BehavioralSummary[]` from a [Serverless Framework](https://www.serverless.com/framework/docs) service file. A `serverless.yml` deploys working Lambdas, and before this reader existed suss could not see any of them. It had no deployable unit, environment contract or event wiring for them.
|
|
6
6
|
|
|
7
7
|
## What this package is
|
|
8
8
|
|
|
9
|
-
The framework compiles a service file into one CloudFormation stack. Each function becomes a Lambda, each event becomes the resource that triggers it, and the `resources:` block is copied in as written. So this reader
|
|
9
|
+
The framework compiles a service file into one CloudFormation stack. Each function becomes a Lambda, each event becomes the resource that triggers it, and the `resources:` block is copied in as written. So this reader rewrites the service in SAM's form and passes it to [`@suss/contract-cloudformation`](../cloudformation/), instead of adding a second set of summary builders that would drift away from that package's. A queue wired in a serverless.yml and the same queue wired in a SAM template come out as the same summary.
|
|
10
10
|
|
|
11
11
|
| Service file | What it becomes |
|
|
12
12
|
|---|---|
|
|
@@ -22,15 +22,15 @@ The framework compiles a service file into one CloudFormation stack. Each functi
|
|
|
22
22
|
|
|
23
23
|
## Variables
|
|
24
24
|
|
|
25
|
-
`${self:...}` points at a path inside the same document, so
|
|
25
|
+
`${self:...}` points at a path inside the same document, so the reader resolves it, fallback included. Every other source (`env:`, `opt:`, `cf:`, `ssm:`, `param:`, `file(...)`, and anything a plugin registers) refers to a value a deploy supplies. For those, the reader keeps the reference as a symbolic token. It does not resolve it, guess at it or drop it. An `sqs` event whose ARN is `${env:AUDIT_QUEUE_ARN}` gets the channel `env:AUDIT_QUEUE_ARN`. The token shows which binding would ground the boundary, where a null would only show that the wiring is set somewhere else.
|
|
26
26
|
|
|
27
27
|
A fallback resolves only for a `self:` reference, where the document states both sides. `${opt:region, 'us-east-1'}` stays symbolic, because the document does not state which way an invocation went.
|
|
28
28
|
|
|
29
|
-
The framework resolves its variables across the whole document before it compiles anything, so the `resources:` block goes through the same resolver
|
|
29
|
+
The framework resolves its variables across the whole document before it compiles anything, so the `resources:` block goes through the same resolver. A table written `TableName: ${self:custom.tableName}` is a name by the time CloudFormation sees it, and no longer the reference text. One kind of reference is left exactly as written there: one whose source is outside the framework. `Fn::Sub` writes `${AWS::Region}` in the same syntax, and rewriting it would turn an intrinsic the document meant into a token that nothing resolves.
|
|
30
30
|
|
|
31
31
|
## Two documents, one service
|
|
32
32
|
|
|
33
|
-
The functions block and the `resources:` block deploy into
|
|
33
|
+
The functions block and the `resources:` block deploy into one stack. A logical id means the same thing in both, and a queue declared under `resources:` is the queue an `sqs` event points at. The two get different provenance labels, built the same way as a nested stack's label: `serverless:services/orders/serverless.yml` and `serverless:services/orders/serverless.yml#resources`. So a reader can tell which block declared what, and the flow walk still scopes both to one service, since it scopes on the part before the `#`. The label includes where the service file is in the repository, so a monorepo full of services keeps them apart.
|
|
34
34
|
|
|
35
35
|
## Minimal usage
|
|
36
36
|
|
|
@@ -49,26 +49,26 @@ From the CLI:
|
|
|
49
49
|
suss contract --from serverless serverless.yml -o service.json
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
## What it
|
|
52
|
+
## What it does not read, and how it reports that
|
|
53
53
|
|
|
54
|
-
Each of these
|
|
54
|
+
Each of these prints a line to stderr with the function, the block, and what stopped the read, so wiring that nobody read is never mistaken for wiring that nobody wrote. Pass `onUnread` to collect them instead.
|
|
55
55
|
|
|
56
|
-
- **Plugins.** A service that loads plugins is reported once. A plugin can add, rename
|
|
57
|
-
- **A service file that is a program.** The reader recognizes a `serverless.ts` or `serverless.js` and reports it
|
|
58
|
-
- **Event kinds outside the list above.** `kinesis`, `stream`, `alb`, `websocket`, `cognitoUserPool
|
|
59
|
-
- **A route whose method or path a deploy supplies.** A path such as `/${env:PREFIX}/orders`
|
|
60
|
-
- **A handler the document does not state.** The function is skipped
|
|
56
|
+
- **Plugins.** A service that loads plugins is reported once. A plugin can add, rename or rewrite functions and events, and what it declares is not in the document.
|
|
57
|
+
- **A service file that is a program.** The reader recognizes a `serverless.ts` or `serverless.js` and reports it. A program declares the service, and the reader does not run one to find out what it declares. When a directory has a parseable service file next to one of these, the reader reads the parseable one, which is also the one the framework prefers. A path with no service file at all is an error, since the caller pointed at it.
|
|
58
|
+
- **Event kinds outside the list above.** `kinesis`, `stream`, `alb`, `websocket`, `cognitoUserPool` and the rest are each reported.
|
|
59
|
+
- **A route whose method or path a deploy supplies.** A path such as `/${env:PREFIX}/orders` does not describe any route this document states, and a token substituted into a path would pair with a route nobody wrote. The function's other events are still read.
|
|
60
|
+
- **A handler the document does not state.** The function is skipped, because nothing shows which code runs it.
|
|
61
61
|
|
|
62
62
|
## Limitations (v0)
|
|
63
63
|
|
|
64
|
-
- **Code scope is the service directory.** The framework packages the whole service into every function's artifact unless `package.individually` narrows it per function,
|
|
65
|
-
- **`provider.region` is read and left symbolic.** No boundary
|
|
66
|
-
- **
|
|
67
|
-
- **`stage` and
|
|
64
|
+
- **Code scope is the service directory.** The framework packages the whole service into every function's artifact unless `package.individually` narrows it per function, and this reader does not read that setting. A service that sets it gets a scope wider than what deploys.
|
|
65
|
+
- **`provider.region` is read and left symbolic.** No boundary is keyed on a region today.
|
|
66
|
+
- **Routing across the two blocks is not combined.** An EventBridge rule declared under `resources:` that targets a queue an `sqs` event drains does not give the consumer its subject, as it would inside one CloudFormation template. Each block is read as its own document.
|
|
67
|
+
- **`stage` and overrides per stage are not applied.** A value that differs per stage comes out as whatever the document states, with no stage bound.
|
|
68
68
|
|
|
69
69
|
## Where it fits in suss
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
The package depends on `@suss/contract-cloudformation`, which contains every summary builder this reader uses, on `@suss/manifest-aws` for the CloudFormation intrinsic tags the `resources:` block uses, on `@suss/behavioral-ir`, and on `yaml`.
|
|
72
72
|
|
|
73
73
|
## More
|
|
74
74
|
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import { CloudFormationTemplate } from '@suss/manifest-aws';
|
|
2
2
|
import { BehavioralSummary } from '@suss/behavioral-ir';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Finding and parsing a Serverless Framework service file.
|
|
6
|
+
*
|
|
7
|
+
* The framework reads `serverless.yml`, `serverless.yaml`,
|
|
8
|
+
* `serverless.json` and `serverless.ts`, in that order. This reader
|
|
9
|
+
* parses the YAML and JSON files. A `.ts` or `.js` service file is a
|
|
10
|
+
* program, so the reader reports it and does not run it.
|
|
11
|
+
*
|
|
12
|
+
* The `resources:` block contains raw CloudFormation, so the parse
|
|
13
|
+
* registers the CloudFormation intrinsic tags. A serverless.yml usually
|
|
14
|
+
* writes the full form (`Fn::GetAtt: [Q, Arn]`), and the short form
|
|
15
|
+
* works too.
|
|
16
|
+
*/
|
|
4
17
|
/** One entry in a function's `events` list, as written. */
|
|
5
18
|
type ServerlessEvent = Record<string, unknown>;
|
|
6
19
|
/** One entry of the `functions` block, as written. */
|
|
@@ -21,9 +34,9 @@ interface ServerlessDocument {
|
|
|
21
34
|
resources?: Record<string, unknown>;
|
|
22
35
|
[key: string]: unknown;
|
|
23
36
|
}
|
|
24
|
-
/**
|
|
37
|
+
/** The parseable service file names, in the framework's order of preference. */
|
|
25
38
|
declare const SERVICE_FILE_NAMES: readonly ["serverless.yml", "serverless.yaml", "serverless.json"];
|
|
26
|
-
/**
|
|
39
|
+
/** Service files that are programs. The reader reports these and does not run them. */
|
|
27
40
|
declare const PROGRAM_SERVICE_FILE_NAMES: readonly ["serverless.ts", "serverless.js"];
|
|
28
41
|
type ServiceLocation = {
|
|
29
42
|
kind: "readable";
|
|
@@ -35,9 +48,9 @@ type ServiceLocation = {
|
|
|
35
48
|
kind: "missing";
|
|
36
49
|
};
|
|
37
50
|
/**
|
|
38
|
-
* A path
|
|
39
|
-
*
|
|
40
|
-
*
|
|
51
|
+
* A path to a file is used as it is. A directory is searched for the
|
|
52
|
+
* parseable files first, so a service with both a yml and a ts file is
|
|
53
|
+
* read from the yml.
|
|
41
54
|
*/
|
|
42
55
|
declare function locateServiceFile(candidate: string): ServiceLocation;
|
|
43
56
|
/** Null when the path contains no service file this reader can parse. */
|
|
@@ -45,9 +58,24 @@ declare function findServiceFile(candidate: string): string | null;
|
|
|
45
58
|
/** Throws when the file is missing or does not parse to an object. */
|
|
46
59
|
declare function loadServerlessDocument(servicePath: string): ServerlessDocument;
|
|
47
60
|
|
|
61
|
+
/**
|
|
62
|
+
* A Serverless Framework service, rewritten as the CloudFormation
|
|
63
|
+
* resources it deploys, for the CloudFormation reader to summarize.
|
|
64
|
+
*
|
|
65
|
+
* `provider.environment` becomes SAM's `Globals.Function.Environment`.
|
|
66
|
+
* Both give every function a default that its own block can override,
|
|
67
|
+
* so an inherited variable gets `globals` provenance, which fits a
|
|
68
|
+
* variable written once for the whole service. `provider.runtime` and
|
|
69
|
+
* the service directory become `Globals.Function.Runtime` and `CodeUri`.
|
|
70
|
+
*
|
|
71
|
+
* A function's identity is the key it is written under. People type
|
|
72
|
+
* that key to deploy, invoke or tail the function, and the framework
|
|
73
|
+
* builds its logical id from it.
|
|
74
|
+
*/
|
|
75
|
+
|
|
48
76
|
/** A wiring the document declares that this reader did not translate. */
|
|
49
77
|
interface UnreadWiring {
|
|
50
|
-
/** Null
|
|
78
|
+
/** Null when the wiring belongs to the whole service. */
|
|
51
79
|
functionName: string | null;
|
|
52
80
|
/** The event kind as the framework spells it, or the block name. */
|
|
53
81
|
kind: string;
|
|
@@ -62,6 +90,20 @@ interface TranslatedService {
|
|
|
62
90
|
}
|
|
63
91
|
declare function translateService(document: ServerlessDocument): TranslatedService;
|
|
64
92
|
|
|
93
|
+
/**
|
|
94
|
+
* The Serverless Framework's `${...}` variable syntax, resolved as far
|
|
95
|
+
* as the document itself allows.
|
|
96
|
+
*
|
|
97
|
+
* `${self:...}` points inside the same document, so it resolves here.
|
|
98
|
+
* Every other source, such as `env:` or `ssm:`, gets its value at deploy
|
|
99
|
+
* time, so the reference stays as a symbolic token: the reference text
|
|
100
|
+
* without the `${}` wrapper. `env:AUDIT_QUEUE_ARN` tells a reader what
|
|
101
|
+
* to look up, where null would only say the value is set elsewhere.
|
|
102
|
+
*
|
|
103
|
+
* A fallback applies only to a `self:` reference. The framework uses a
|
|
104
|
+
* deploy-time fallback only when the CLI supplies nothing, and the
|
|
105
|
+
* document cannot say whether it did.
|
|
106
|
+
*/
|
|
65
107
|
/** A symbolic token is the reference text as written, minus the wrapper. */
|
|
66
108
|
type ResolvedString = {
|
|
67
109
|
kind: "resolved";
|
|
@@ -80,18 +122,37 @@ type ResolvedValue = {
|
|
|
80
122
|
};
|
|
81
123
|
/** Resolves `${...}` references against one parsed serverless.yml document. */
|
|
82
124
|
interface VariableResolver {
|
|
83
|
-
/**
|
|
84
|
-
*
|
|
125
|
+
/**
|
|
126
|
+
* A whole `${self:...}` reference resolves to whatever is at that path,
|
|
127
|
+
* object or scalar.
|
|
128
|
+
*/
|
|
85
129
|
resolveValue(raw: unknown): ResolvedValue;
|
|
86
|
-
/**
|
|
130
|
+
/**
|
|
131
|
+
* A whole reference that resolves to an object or array comes back
|
|
132
|
+
* symbolic, since the document states no string there.
|
|
133
|
+
*/
|
|
87
134
|
resolveString(raw: string): ResolvedString;
|
|
88
|
-
/**
|
|
89
|
-
*
|
|
135
|
+
/**
|
|
136
|
+
* Resolves every string in a tree. A reference whose source the
|
|
137
|
+
* framework does not define, such as `${AWS::Region}` inside an
|
|
138
|
+
* `Fn::Sub`, is left exactly as written.
|
|
139
|
+
*/
|
|
90
140
|
resolveTemplateTree(value: unknown): unknown;
|
|
91
141
|
}
|
|
92
142
|
declare function createVariableResolver(document: Record<string, unknown>): VariableResolver;
|
|
93
143
|
|
|
94
|
-
/**
|
|
144
|
+
/**
|
|
145
|
+
* Translates one function's `events` list into the SAM event entries
|
|
146
|
+
* the CloudFormation reader reads.
|
|
147
|
+
*
|
|
148
|
+
* Each event kind maps onto the resource the framework compiles it
|
|
149
|
+
* into, so a serverless.yml and a SAM template with the same wiring
|
|
150
|
+
* produce the same summary. When this reader does not translate an
|
|
151
|
+
* event, the reason goes back to the caller, which reports it, so a
|
|
152
|
+
* wiring nobody read is never mistaken for one nobody wrote.
|
|
153
|
+
*/
|
|
154
|
+
|
|
155
|
+
/** A SAM `Events` entry, in the form the CloudFormation reader reads. */
|
|
95
156
|
interface SamEvent {
|
|
96
157
|
Type: string;
|
|
97
158
|
Properties?: Record<string, unknown>;
|
|
@@ -110,15 +171,35 @@ interface EventContext {
|
|
|
110
171
|
/** Keyed by the name the framework's own schema uses for each event kind. */
|
|
111
172
|
declare const EVENT_TRANSLATIONS: Record<string, (raw: unknown, ctx: EventContext) => EventTranslation>;
|
|
112
173
|
|
|
174
|
+
/**
|
|
175
|
+
* @suss/contract-serverless: behavioral summaries from a Serverless
|
|
176
|
+
* Framework service file.
|
|
177
|
+
*
|
|
178
|
+
* This reader rewrites the service as SAM resources and passes them to
|
|
179
|
+
* @suss/contract-cloudformation, so a service file and a SAM template
|
|
180
|
+
* with the same wiring produce the same summaries.
|
|
181
|
+
*
|
|
182
|
+
* The functions block and the `resources:` block deploy into one stack
|
|
183
|
+
* but are read as two documents, labelled `serverless:<file>` and
|
|
184
|
+
* `serverless:<file>#resources` the way a nested stack is, so the flow
|
|
185
|
+
* walk still scopes both to one service. The README maps each block to
|
|
186
|
+
* what it becomes.
|
|
187
|
+
*/
|
|
188
|
+
|
|
113
189
|
interface ServerlessToSummariesOptions {
|
|
114
190
|
/** Override the logical source file recorded on each summary. */
|
|
115
191
|
source?: string;
|
|
116
|
-
/**
|
|
117
|
-
*
|
|
192
|
+
/**
|
|
193
|
+
* Called once for each wiring the reader did not translate. Defaults to
|
|
194
|
+
* printing a line on stderr.
|
|
195
|
+
*/
|
|
118
196
|
onUnread?: (wiring: UnreadWiring) => void;
|
|
119
197
|
}
|
|
120
198
|
declare function serverlessToSummaries(document: ServerlessDocument, options?: ServerlessToSummariesOptions): BehavioralSummary[];
|
|
121
|
-
/**
|
|
199
|
+
/**
|
|
200
|
+
* Reads a service file and returns its summaries. The path may be the
|
|
201
|
+
* service file itself or the directory it is in.
|
|
202
|
+
*/
|
|
122
203
|
declare function serverlessFileToSummaries(servicePath: string, options?: ServerlessToSummariesOptions): BehavioralSummary[];
|
|
123
204
|
|
|
124
205
|
export { EVENT_TRANSLATIONS, PROGRAM_SERVICE_FILE_NAMES, type ResolvedString, type ResolvedValue, SERVICE_FILE_NAMES, type ServerlessDocument, type ServerlessEvent, type ServerlessFunctionDefinition, type ServerlessToSummariesOptions, type ServiceLocation, type TranslatedService, type UnreadWiring, type VariableResolver, createVariableResolver, findServiceFile, loadServerlessDocument, locateServiceFile, serverlessFileToSummaries, serverlessToSummaries, translateService };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import { CloudFormationTemplate } from '@suss/manifest-aws';
|
|
2
2
|
import { BehavioralSummary } from '@suss/behavioral-ir';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Finding and parsing a Serverless Framework service file.
|
|
6
|
+
*
|
|
7
|
+
* The framework reads `serverless.yml`, `serverless.yaml`,
|
|
8
|
+
* `serverless.json` and `serverless.ts`, in that order. This reader
|
|
9
|
+
* parses the YAML and JSON files. A `.ts` or `.js` service file is a
|
|
10
|
+
* program, so the reader reports it and does not run it.
|
|
11
|
+
*
|
|
12
|
+
* The `resources:` block contains raw CloudFormation, so the parse
|
|
13
|
+
* registers the CloudFormation intrinsic tags. A serverless.yml usually
|
|
14
|
+
* writes the full form (`Fn::GetAtt: [Q, Arn]`), and the short form
|
|
15
|
+
* works too.
|
|
16
|
+
*/
|
|
4
17
|
/** One entry in a function's `events` list, as written. */
|
|
5
18
|
type ServerlessEvent = Record<string, unknown>;
|
|
6
19
|
/** One entry of the `functions` block, as written. */
|
|
@@ -21,9 +34,9 @@ interface ServerlessDocument {
|
|
|
21
34
|
resources?: Record<string, unknown>;
|
|
22
35
|
[key: string]: unknown;
|
|
23
36
|
}
|
|
24
|
-
/**
|
|
37
|
+
/** The parseable service file names, in the framework's order of preference. */
|
|
25
38
|
declare const SERVICE_FILE_NAMES: readonly ["serverless.yml", "serverless.yaml", "serverless.json"];
|
|
26
|
-
/**
|
|
39
|
+
/** Service files that are programs. The reader reports these and does not run them. */
|
|
27
40
|
declare const PROGRAM_SERVICE_FILE_NAMES: readonly ["serverless.ts", "serverless.js"];
|
|
28
41
|
type ServiceLocation = {
|
|
29
42
|
kind: "readable";
|
|
@@ -35,9 +48,9 @@ type ServiceLocation = {
|
|
|
35
48
|
kind: "missing";
|
|
36
49
|
};
|
|
37
50
|
/**
|
|
38
|
-
* A path
|
|
39
|
-
*
|
|
40
|
-
*
|
|
51
|
+
* A path to a file is used as it is. A directory is searched for the
|
|
52
|
+
* parseable files first, so a service with both a yml and a ts file is
|
|
53
|
+
* read from the yml.
|
|
41
54
|
*/
|
|
42
55
|
declare function locateServiceFile(candidate: string): ServiceLocation;
|
|
43
56
|
/** Null when the path contains no service file this reader can parse. */
|
|
@@ -45,9 +58,24 @@ declare function findServiceFile(candidate: string): string | null;
|
|
|
45
58
|
/** Throws when the file is missing or does not parse to an object. */
|
|
46
59
|
declare function loadServerlessDocument(servicePath: string): ServerlessDocument;
|
|
47
60
|
|
|
61
|
+
/**
|
|
62
|
+
* A Serverless Framework service, rewritten as the CloudFormation
|
|
63
|
+
* resources it deploys, for the CloudFormation reader to summarize.
|
|
64
|
+
*
|
|
65
|
+
* `provider.environment` becomes SAM's `Globals.Function.Environment`.
|
|
66
|
+
* Both give every function a default that its own block can override,
|
|
67
|
+
* so an inherited variable gets `globals` provenance, which fits a
|
|
68
|
+
* variable written once for the whole service. `provider.runtime` and
|
|
69
|
+
* the service directory become `Globals.Function.Runtime` and `CodeUri`.
|
|
70
|
+
*
|
|
71
|
+
* A function's identity is the key it is written under. People type
|
|
72
|
+
* that key to deploy, invoke or tail the function, and the framework
|
|
73
|
+
* builds its logical id from it.
|
|
74
|
+
*/
|
|
75
|
+
|
|
48
76
|
/** A wiring the document declares that this reader did not translate. */
|
|
49
77
|
interface UnreadWiring {
|
|
50
|
-
/** Null
|
|
78
|
+
/** Null when the wiring belongs to the whole service. */
|
|
51
79
|
functionName: string | null;
|
|
52
80
|
/** The event kind as the framework spells it, or the block name. */
|
|
53
81
|
kind: string;
|
|
@@ -62,6 +90,20 @@ interface TranslatedService {
|
|
|
62
90
|
}
|
|
63
91
|
declare function translateService(document: ServerlessDocument): TranslatedService;
|
|
64
92
|
|
|
93
|
+
/**
|
|
94
|
+
* The Serverless Framework's `${...}` variable syntax, resolved as far
|
|
95
|
+
* as the document itself allows.
|
|
96
|
+
*
|
|
97
|
+
* `${self:...}` points inside the same document, so it resolves here.
|
|
98
|
+
* Every other source, such as `env:` or `ssm:`, gets its value at deploy
|
|
99
|
+
* time, so the reference stays as a symbolic token: the reference text
|
|
100
|
+
* without the `${}` wrapper. `env:AUDIT_QUEUE_ARN` tells a reader what
|
|
101
|
+
* to look up, where null would only say the value is set elsewhere.
|
|
102
|
+
*
|
|
103
|
+
* A fallback applies only to a `self:` reference. The framework uses a
|
|
104
|
+
* deploy-time fallback only when the CLI supplies nothing, and the
|
|
105
|
+
* document cannot say whether it did.
|
|
106
|
+
*/
|
|
65
107
|
/** A symbolic token is the reference text as written, minus the wrapper. */
|
|
66
108
|
type ResolvedString = {
|
|
67
109
|
kind: "resolved";
|
|
@@ -80,18 +122,37 @@ type ResolvedValue = {
|
|
|
80
122
|
};
|
|
81
123
|
/** Resolves `${...}` references against one parsed serverless.yml document. */
|
|
82
124
|
interface VariableResolver {
|
|
83
|
-
/**
|
|
84
|
-
*
|
|
125
|
+
/**
|
|
126
|
+
* A whole `${self:...}` reference resolves to whatever is at that path,
|
|
127
|
+
* object or scalar.
|
|
128
|
+
*/
|
|
85
129
|
resolveValue(raw: unknown): ResolvedValue;
|
|
86
|
-
/**
|
|
130
|
+
/**
|
|
131
|
+
* A whole reference that resolves to an object or array comes back
|
|
132
|
+
* symbolic, since the document states no string there.
|
|
133
|
+
*/
|
|
87
134
|
resolveString(raw: string): ResolvedString;
|
|
88
|
-
/**
|
|
89
|
-
*
|
|
135
|
+
/**
|
|
136
|
+
* Resolves every string in a tree. A reference whose source the
|
|
137
|
+
* framework does not define, such as `${AWS::Region}` inside an
|
|
138
|
+
* `Fn::Sub`, is left exactly as written.
|
|
139
|
+
*/
|
|
90
140
|
resolveTemplateTree(value: unknown): unknown;
|
|
91
141
|
}
|
|
92
142
|
declare function createVariableResolver(document: Record<string, unknown>): VariableResolver;
|
|
93
143
|
|
|
94
|
-
/**
|
|
144
|
+
/**
|
|
145
|
+
* Translates one function's `events` list into the SAM event entries
|
|
146
|
+
* the CloudFormation reader reads.
|
|
147
|
+
*
|
|
148
|
+
* Each event kind maps onto the resource the framework compiles it
|
|
149
|
+
* into, so a serverless.yml and a SAM template with the same wiring
|
|
150
|
+
* produce the same summary. When this reader does not translate an
|
|
151
|
+
* event, the reason goes back to the caller, which reports it, so a
|
|
152
|
+
* wiring nobody read is never mistaken for one nobody wrote.
|
|
153
|
+
*/
|
|
154
|
+
|
|
155
|
+
/** A SAM `Events` entry, in the form the CloudFormation reader reads. */
|
|
95
156
|
interface SamEvent {
|
|
96
157
|
Type: string;
|
|
97
158
|
Properties?: Record<string, unknown>;
|
|
@@ -110,15 +171,35 @@ interface EventContext {
|
|
|
110
171
|
/** Keyed by the name the framework's own schema uses for each event kind. */
|
|
111
172
|
declare const EVENT_TRANSLATIONS: Record<string, (raw: unknown, ctx: EventContext) => EventTranslation>;
|
|
112
173
|
|
|
174
|
+
/**
|
|
175
|
+
* @suss/contract-serverless: behavioral summaries from a Serverless
|
|
176
|
+
* Framework service file.
|
|
177
|
+
*
|
|
178
|
+
* This reader rewrites the service as SAM resources and passes them to
|
|
179
|
+
* @suss/contract-cloudformation, so a service file and a SAM template
|
|
180
|
+
* with the same wiring produce the same summaries.
|
|
181
|
+
*
|
|
182
|
+
* The functions block and the `resources:` block deploy into one stack
|
|
183
|
+
* but are read as two documents, labelled `serverless:<file>` and
|
|
184
|
+
* `serverless:<file>#resources` the way a nested stack is, so the flow
|
|
185
|
+
* walk still scopes both to one service. The README maps each block to
|
|
186
|
+
* what it becomes.
|
|
187
|
+
*/
|
|
188
|
+
|
|
113
189
|
interface ServerlessToSummariesOptions {
|
|
114
190
|
/** Override the logical source file recorded on each summary. */
|
|
115
191
|
source?: string;
|
|
116
|
-
/**
|
|
117
|
-
*
|
|
192
|
+
/**
|
|
193
|
+
* Called once for each wiring the reader did not translate. Defaults to
|
|
194
|
+
* printing a line on stderr.
|
|
195
|
+
*/
|
|
118
196
|
onUnread?: (wiring: UnreadWiring) => void;
|
|
119
197
|
}
|
|
120
198
|
declare function serverlessToSummaries(document: ServerlessDocument, options?: ServerlessToSummariesOptions): BehavioralSummary[];
|
|
121
|
-
/**
|
|
199
|
+
/**
|
|
200
|
+
* Reads a service file and returns its summaries. The path may be the
|
|
201
|
+
* service file itself or the directory it is in.
|
|
202
|
+
*/
|
|
122
203
|
declare function serverlessFileToSummaries(servicePath: string, options?: ServerlessToSummariesOptions): BehavioralSummary[];
|
|
123
204
|
|
|
124
205
|
export { EVENT_TRANSLATIONS, PROGRAM_SERVICE_FILE_NAMES, type ResolvedString, type ResolvedValue, SERVICE_FILE_NAMES, type ServerlessDocument, type ServerlessEvent, type ServerlessFunctionDefinition, type ServerlessToSummariesOptions, type ServiceLocation, type TranslatedService, type UnreadWiring, type VariableResolver, createVariableResolver, findServiceFile, loadServerlessDocument, locateServiceFile, serverlessFileToSummaries, serverlessToSummaries, translateService };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/contract-serverless",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Turn a Serverless Framework serverless.yml into a suss contract and check it against the Lambda handlers and clients behind it.",
|
|
6
6
|
"keywords": [
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
],
|
|
16
16
|
"license": "Apache-2.0",
|
|
17
17
|
"author": "Nimbus Cloud AI LLC",
|
|
18
|
-
"homepage": "https://
|
|
18
|
+
"homepage": "https://suss.sh",
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|
|
21
21
|
"url": "git+https://github.com/nimbuscloud-ai/suss.git",
|
|
@@ -48,11 +48,11 @@
|
|
|
48
48
|
"typecheck": "tsc --noEmit"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@suss/behavioral-ir": "0.
|
|
52
|
-
"@suss/contract-aws-apigateway": "0.
|
|
53
|
-
"@suss/contract-cloudformation": "0.
|
|
54
|
-
"@suss/ir-core": "0.
|
|
55
|
-
"@suss/manifest-aws": "0.
|
|
51
|
+
"@suss/behavioral-ir": "0.34.0",
|
|
52
|
+
"@suss/contract-aws-apigateway": "0.34.0",
|
|
53
|
+
"@suss/contract-cloudformation": "0.34.0",
|
|
54
|
+
"@suss/ir-core": "0.34.0",
|
|
55
|
+
"@suss/manifest-aws": "0.34.0",
|
|
56
56
|
"yaml": "^2.4.0"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|