@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 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 says where the two disagree.
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
- Generate 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 saw none of them: no deployable unit, no environment contract, no event wiring.
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 restates the service in SAM's form and hands that to [`@suss/contract-cloudformation`](../cloudformation/), rather than growing a second set of summary builders that would drift from it. A queue wired in a serverless.yml and the same queue wired in a SAM template come out as the same summary.
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 it resolves here, fallback and all. Every other source (`env:`, `opt:`, `cf:`, `ssm:`, `param:`, `file(...)`, and whatever a plugin registers) refers to a value that a deploy supplies, so the reader keeps the reference as a symbolic token instead of resolving it, guessing at it, or dropping it: an `sqs` event whose ARN is `${env:AUDIT_QUEUE_ARN}` gets the channel `env:AUDIT_QUEUE_ARN`. The token says which binding would ground the boundary, where a null would only say that the wiring is specified somewhere else.
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: a table written `TableName: ${self:custom.tableName}` is a name by the time CloudFormation sees it, not the reference text. One reference is left exactly as written there: the one whose source is not the framework's. `Fn::Sub` writes `${AWS::Region}` in the same syntax, and rewriting it would turn an intrinsic that the document meant into a token that nothing resolves.
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 a single stack, so a logical id means the same thing in both and a queue declared under `resources:` is the queue an `sqs` event points at. They have different provenance labels, built the way a nested stack's label is: `serverless:services/orders/serverless.yml` and `serverless:services/orders/serverless.yml#resources`. 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 says where the service file lives in the repository, so a monorepo full of services keeps them apart.
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 abstains on, and says so
52
+ ## What it does not read, and how it reports that
53
53
 
54
- Each of these writes a line to stderr giving 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.
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, 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 a reader does not run one to find out what it says. When a directory has a parseable service file alongside one of these, the reader reads the parseable one, the way the framework prefers it. 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 reported, not dropped.
59
- - **A route whose method or path a deploy supplies.** A path such as `/${env:PREFIX}/orders` describes no route this document states, and a token substituted into a path would pair with a route nobody wrote. The rest of the function's events still read.
60
- - **A handler the document does not state.** The function is skipped: nothing says which code runs it.
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, which this reader does not read. A service that sets it gets a scope wider than what deploys.
65
- - **`provider.region` is read and left symbolic.** No boundary keys on a region today.
66
- - **Cross-block routing is not composed.** An EventBridge rule declared under `resources:` that targets a queue an `sqs` event drains does not lend the consumer its subject, the way it would inside one CloudFormation template. Each block is read as its own document.
67
- - **`stage` and multi-stage overrides are not applied.** A value that differs per stage comes out as whatever the document states, with no stage bound.
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
- Depends on `@suss/contract-cloudformation` (which owns every summary builder this reader reaches), `@suss/manifest-aws` (for the CloudFormation intrinsic tags the `resources:` block uses), `@suss/behavioral-ir`, and `yaml`.
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
- /** In the framework's own order of preference. */
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
- /** Recognized in order to be reported rather than read. */
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 that points at a file is taken as that file. A directory is
39
- * searched parseable spellings first, so a service with both a yml and
40
- * a ts is read from the yml.
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 for a service-level abstention. */
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
- /** A whole `${self:...}` reference resolves to whatever is at that
84
- * path, object or scalar. */
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
- /** A whole reference resolving to an object or array is symbolic, since no string was stated. */
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
- /** A reference to anything the framework does not define is left
89
- * exactly as written. */
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
- /** A SAM `Events` entry, which is what the CloudFormation reader consumes. */
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
- /** Called once per wiring the reader did not translate. Defaults to
117
- * printing a line on stderr. */
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
- /** The path may be the service file itself or the directory it is in. */
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
- /** In the framework's own order of preference. */
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
- /** Recognized in order to be reported rather than read. */
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 that points at a file is taken as that file. A directory is
39
- * searched parseable spellings first, so a service with both a yml and
40
- * a ts is read from the yml.
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 for a service-level abstention. */
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
- /** A whole `${self:...}` reference resolves to whatever is at that
84
- * path, object or scalar. */
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
- /** A whole reference resolving to an object or array is symbolic, since no string was stated. */
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
- /** A reference to anything the framework does not define is left
89
- * exactly as written. */
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
- /** A SAM `Events` entry, which is what the CloudFormation reader consumes. */
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
- /** Called once per wiring the reader did not translate. Defaults to
117
- * printing a line on stderr. */
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
- /** The path may be the service file itself or the directory it is in. */
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.33.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://github.com/nimbuscloud-ai/suss/tree/main/packages/contract/serverless#readme",
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.33.0",
52
- "@suss/contract-aws-apigateway": "0.33.0",
53
- "@suss/contract-cloudformation": "0.33.0",
54
- "@suss/ir-core": "0.33.0",
55
- "@suss/manifest-aws": "0.33.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": {