@suss/contract-serverless 0.3.2-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/dist/index.cjs ADDED
@@ -0,0 +1,623 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ EVENT_TRANSLATIONS: () => EVENT_TRANSLATIONS,
34
+ PROGRAM_SERVICE_FILE_NAMES: () => PROGRAM_SERVICE_FILE_NAMES,
35
+ SERVICE_FILE_NAMES: () => SERVICE_FILE_NAMES,
36
+ createVariableResolver: () => createVariableResolver,
37
+ findServiceFile: () => findServiceFile,
38
+ loadServerlessDocument: () => loadServerlessDocument,
39
+ locateServiceFile: () => locateServiceFile,
40
+ serverlessFileToSummaries: () => serverlessFileToSummaries,
41
+ serverlessToSummaries: () => serverlessToSummaries,
42
+ translateService: () => translateService
43
+ });
44
+ module.exports = __toCommonJS(index_exports);
45
+ var import_node_path2 = __toESM(require("path"), 1);
46
+ var import_behavioral_ir = require("@suss/behavioral-ir");
47
+ var import_contract_cloudformation = require("@suss/contract-cloudformation");
48
+
49
+ // src/document.ts
50
+ var import_node_fs = __toESM(require("fs"), 1);
51
+ var import_node_path = __toESM(require("path"), 1);
52
+ var import_yaml = __toESM(require("yaml"), 1);
53
+ var import_manifest_aws = require("@suss/manifest-aws");
54
+ var SERVICE_FILE_NAMES = [
55
+ "serverless.yml",
56
+ "serverless.yaml",
57
+ "serverless.json"
58
+ ];
59
+ var PROGRAM_SERVICE_FILE_NAMES = [
60
+ "serverless.ts",
61
+ "serverless.js"
62
+ ];
63
+ function locateServiceFile(candidate) {
64
+ const resolved = import_node_path.default.resolve(candidate);
65
+ if (!import_node_fs.default.existsSync(resolved)) {
66
+ return { kind: "missing" };
67
+ }
68
+ if (import_node_fs.default.statSync(resolved).isFile()) {
69
+ return isProgram(resolved) ? { kind: "program", file: resolved } : { kind: "readable", file: resolved };
70
+ }
71
+ for (const name of SERVICE_FILE_NAMES) {
72
+ const file = import_node_path.default.join(resolved, name);
73
+ if (import_node_fs.default.existsSync(file)) {
74
+ return { kind: "readable", file };
75
+ }
76
+ }
77
+ for (const name of PROGRAM_SERVICE_FILE_NAMES) {
78
+ const file = import_node_path.default.join(resolved, name);
79
+ if (import_node_fs.default.existsSync(file)) {
80
+ return { kind: "program", file };
81
+ }
82
+ }
83
+ return { kind: "missing" };
84
+ }
85
+ function isProgram(file) {
86
+ const name = import_node_path.default.basename(file);
87
+ return PROGRAM_SERVICE_FILE_NAMES.includes(name);
88
+ }
89
+ function findServiceFile(candidate) {
90
+ const located = locateServiceFile(candidate);
91
+ return located.kind === "readable" ? located.file : null;
92
+ }
93
+ function loadServerlessDocument(servicePath) {
94
+ const file = findServiceFile(servicePath);
95
+ if (file === null) {
96
+ throw new Error(`Serverless service file not found: ${servicePath}`);
97
+ }
98
+ const raw = import_node_fs.default.readFileSync(file, "utf-8");
99
+ const parsed = file.endsWith(".json") ? JSON.parse(raw) : import_yaml.default.parse(raw, { customTags: import_manifest_aws.CLOUDFORMATION_YAML_TAGS });
100
+ if (parsed === null || typeof parsed !== "object") {
101
+ throw new Error(`Serverless service file is not an object: ${file}`);
102
+ }
103
+ return parsed;
104
+ }
105
+
106
+ // src/events.ts
107
+ function readString(raw, ctx) {
108
+ if (typeof raw !== "string") {
109
+ return null;
110
+ }
111
+ const resolved = ctx.resolver.resolveString(raw);
112
+ return resolved.kind === "resolved" ? { value: resolved.value, symbolic: false } : { value: resolved.token, symbolic: true };
113
+ }
114
+ function asMap(raw) {
115
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
116
+ return null;
117
+ }
118
+ return raw;
119
+ }
120
+ function readRoute(raw, ctx) {
121
+ const asString = readString(raw, ctx);
122
+ if (asString !== null) {
123
+ if (asString.symbolic) {
124
+ return {
125
+ abstain: `route is written as ${asString.value}, which the document does not state`
126
+ };
127
+ }
128
+ const space = asString.value.trim().indexOf(" ");
129
+ if (space === -1) {
130
+ return {
131
+ abstain: `route "${asString.value}" names no method and path`
132
+ };
133
+ }
134
+ return {
135
+ method: asString.value.slice(0, space).trim().toUpperCase(),
136
+ path: withLeadingSlash(asString.value.slice(space + 1).trim())
137
+ };
138
+ }
139
+ const map = asMap(raw);
140
+ if (map === null) {
141
+ return { abstain: "event is neither a route string nor a map" };
142
+ }
143
+ const method = readString(map.method, ctx);
144
+ const path3 = readString(map.path, ctx);
145
+ if (method === null || path3 === null) {
146
+ return { abstain: "event names no method or no path" };
147
+ }
148
+ if (method.symbolic || path3.symbolic) {
149
+ return {
150
+ abstain: `route method or path is written as ${method.symbolic ? method.value : path3.value}, which the document does not state`
151
+ };
152
+ }
153
+ return {
154
+ method: method.value.toUpperCase(),
155
+ path: withLeadingSlash(path3.value)
156
+ };
157
+ }
158
+ function withLeadingSlash(path3) {
159
+ return path3.startsWith("/") ? path3 : `/${path3}`;
160
+ }
161
+ function readReference(raw, ctx) {
162
+ if (typeof raw !== "string") {
163
+ return raw;
164
+ }
165
+ const resolved = ctx.resolver.resolveString(raw);
166
+ return resolved.kind === "resolved" ? resolved.value : resolved.token;
167
+ }
168
+ var httpApiEvent = (raw, ctx) => {
169
+ const route = readRoute(raw, ctx);
170
+ if ("abstain" in route) {
171
+ return { kind: "abstained", reason: route.abstain };
172
+ }
173
+ return {
174
+ kind: "event",
175
+ event: {
176
+ Type: "HttpApi",
177
+ Properties: { Method: route.method, Path: route.path }
178
+ }
179
+ };
180
+ };
181
+ var httpEvent = (raw, ctx) => {
182
+ const route = readRoute(raw, ctx);
183
+ if ("abstain" in route) {
184
+ return { kind: "abstained", reason: route.abstain };
185
+ }
186
+ return {
187
+ kind: "event",
188
+ event: {
189
+ Type: "Api",
190
+ Properties: { Method: route.method, Path: route.path }
191
+ }
192
+ };
193
+ };
194
+ var sqsEvent = (raw, ctx) => {
195
+ const map = asMap(raw);
196
+ const arn = map === null ? raw : map.arn;
197
+ const queue = readReference(arn, ctx);
198
+ if (queue === void 0 || queue === null || queue === "") {
199
+ return { kind: "abstained", reason: "sqs event names no queue" };
200
+ }
201
+ return {
202
+ kind: "event",
203
+ event: { Type: "SQS", Properties: { Queue: queue } }
204
+ };
205
+ };
206
+ var snsEvent = (raw, ctx) => {
207
+ const map = asMap(raw);
208
+ const named = map === null ? raw : map.arn ?? map.topicName;
209
+ const topic = readReference(named, ctx);
210
+ if (topic === void 0 || topic === null || topic === "") {
211
+ return { kind: "abstained", reason: "sns event names no topic" };
212
+ }
213
+ const filterPolicy = map?.filterPolicy;
214
+ return {
215
+ kind: "event",
216
+ event: {
217
+ Type: "SNS",
218
+ Properties: {
219
+ Topic: topic,
220
+ ...filterPolicy !== void 0 ? { FilterPolicy: filterPolicy } : {}
221
+ }
222
+ }
223
+ };
224
+ };
225
+ var scheduleEvent = (raw, ctx) => {
226
+ const map = asMap(raw);
227
+ const rate = map === null ? raw : map.rate ?? map.schedule;
228
+ const expression = Array.isArray(rate) ? rate[0] : rate;
229
+ const stated = readReference(expression, ctx);
230
+ const enabled = map?.enabled;
231
+ return {
232
+ kind: "event",
233
+ event: {
234
+ Type: "Schedule",
235
+ Properties: {
236
+ ...typeof stated === "string" ? { Schedule: stated } : {},
237
+ ...typeof enabled === "boolean" ? { Enabled: enabled } : {}
238
+ }
239
+ }
240
+ };
241
+ };
242
+ var eventBridgeEvent = (raw, ctx) => {
243
+ const map = asMap(raw);
244
+ if (map === null) {
245
+ return { kind: "abstained", reason: "eventBridge event is not a map" };
246
+ }
247
+ if (map.schedule !== void 0 && map.pattern === void 0) {
248
+ return scheduleEvent({ rate: map.schedule, enabled: map.enabled }, ctx);
249
+ }
250
+ if (map.pattern === void 0) {
251
+ return {
252
+ kind: "abstained",
253
+ reason: "eventBridge event states neither a pattern nor a schedule"
254
+ };
255
+ }
256
+ const eventBus = readReference(map.eventBus, ctx);
257
+ return {
258
+ kind: "event",
259
+ event: {
260
+ Type: "EventBridgeRule",
261
+ Properties: {
262
+ Pattern: map.pattern,
263
+ ...eventBus !== void 0 && eventBus !== null ? { EventBusName: eventBus } : {}
264
+ }
265
+ }
266
+ };
267
+ };
268
+ var EVENT_TRANSLATIONS = {
269
+ httpApi: httpApiEvent,
270
+ http: httpEvent,
271
+ sqs: sqsEvent,
272
+ sns: snsEvent,
273
+ schedule: scheduleEvent,
274
+ eventBridge: eventBridgeEvent
275
+ };
276
+
277
+ // src/variables.ts
278
+ var REFERENCE = /\$\{([^{}]*)\}/g;
279
+ var FRAMEWORK_SOURCES = [
280
+ "self",
281
+ "env",
282
+ "opt",
283
+ "cf",
284
+ "s3",
285
+ "ssm",
286
+ "aws",
287
+ "param",
288
+ "sls",
289
+ "file",
290
+ "git"
291
+ ];
292
+ function namesFrameworkSource(body) {
293
+ const source = body.trim().split(/[:(]/, 1)[0].trim();
294
+ return FRAMEWORK_SOURCES.includes(source);
295
+ }
296
+ function createVariableResolver(document) {
297
+ function resolveString(raw, inProgress) {
298
+ const value = resolveValue(raw, inProgress);
299
+ if (value.kind === "symbolic") {
300
+ return value;
301
+ }
302
+ if (typeof value.value === "string") {
303
+ return { kind: "resolved", value: value.value };
304
+ }
305
+ if (typeof value.value === "number" || typeof value.value === "boolean") {
306
+ return { kind: "resolved", value: String(value.value) };
307
+ }
308
+ return { kind: "symbolic", token: raw };
309
+ }
310
+ function resolveValue(raw, inProgress) {
311
+ if (typeof raw !== "string") {
312
+ return { kind: "resolved", value: raw };
313
+ }
314
+ if (!raw.includes("${")) {
315
+ return { kind: "resolved", value: raw };
316
+ }
317
+ const wholeReference = wholeReferenceBody(raw);
318
+ if (wholeReference !== null) {
319
+ return resolveReference(wholeReference, inProgress);
320
+ }
321
+ let anyUnresolved = false;
322
+ const substituted = raw.replace(REFERENCE, (whole, body) => {
323
+ const resolved = resolveReference(body, inProgress);
324
+ if (resolved.kind === "resolved" && (typeof resolved.value === "string" || typeof resolved.value === "number" || typeof resolved.value === "boolean")) {
325
+ return String(resolved.value);
326
+ }
327
+ anyUnresolved = true;
328
+ return whole;
329
+ });
330
+ return anyUnresolved || substituted.includes("${") ? { kind: "symbolic", token: substituted } : { kind: "resolved", value: substituted };
331
+ }
332
+ function resolveReference(body, inProgress) {
333
+ const { primary, fallback } = splitFallback(body);
334
+ if (!primary.startsWith("self:")) {
335
+ return { kind: "symbolic", token: primary };
336
+ }
337
+ const path3 = primary.slice("self:".length);
338
+ if (inProgress.has(path3)) {
339
+ return { kind: "symbolic", token: primary };
340
+ }
341
+ const target = documentPath(document, path3);
342
+ if (target !== void 0) {
343
+ inProgress.add(path3);
344
+ const resolved = resolveValue(target, inProgress);
345
+ inProgress.delete(path3);
346
+ return resolved;
347
+ }
348
+ if (fallback !== null) {
349
+ const literal = literalFallback(fallback);
350
+ if (literal !== null) {
351
+ return { kind: "resolved", value: literal };
352
+ }
353
+ }
354
+ return { kind: "symbolic", token: primary };
355
+ }
356
+ function resolveTemplateString(raw) {
357
+ const whole = wholeReferenceBody(raw);
358
+ if (whole !== null && !namesFrameworkSource(whole)) {
359
+ return raw;
360
+ }
361
+ const resolved = resolveValue(raw, /* @__PURE__ */ new Set());
362
+ return resolved.kind === "resolved" ? resolved.value : resolved.token;
363
+ }
364
+ function resolveTemplateTree(value) {
365
+ if (typeof value === "string") {
366
+ return resolveTemplateString(value);
367
+ }
368
+ if (Array.isArray(value)) {
369
+ return value.map(resolveTemplateTree);
370
+ }
371
+ if (value === null || typeof value !== "object") {
372
+ return value;
373
+ }
374
+ const out = {};
375
+ for (const [key, entry] of Object.entries(
376
+ value
377
+ )) {
378
+ out[key] = resolveTemplateTree(entry);
379
+ }
380
+ return out;
381
+ }
382
+ return {
383
+ resolveValue: (raw) => resolveValue(raw, /* @__PURE__ */ new Set()),
384
+ resolveString: (raw) => resolveString(raw, /* @__PURE__ */ new Set()),
385
+ resolveTemplateTree
386
+ };
387
+ }
388
+ function wholeReferenceBody(raw) {
389
+ const trimmed = raw.trim();
390
+ const match = /^\$\{([^{}]*)\}$/.exec(trimmed);
391
+ return match === null ? null : match[1];
392
+ }
393
+ function splitFallback(body) {
394
+ const comma = body.indexOf(",");
395
+ if (comma === -1) {
396
+ return { primary: body.trim(), fallback: null };
397
+ }
398
+ return {
399
+ primary: body.slice(0, comma).trim(),
400
+ fallback: body.slice(comma + 1).trim()
401
+ };
402
+ }
403
+ function literalFallback(fallback) {
404
+ const quoted = /^'([^']*)'$/.exec(fallback) ?? /^"([^"]*)"$/.exec(fallback);
405
+ if (quoted !== null) {
406
+ return quoted[1];
407
+ }
408
+ if (/^-?\d+(\.\d+)?$/.test(fallback)) {
409
+ return fallback;
410
+ }
411
+ return null;
412
+ }
413
+ function documentPath(document, path3) {
414
+ if (path3 === "") {
415
+ return void 0;
416
+ }
417
+ let current = document;
418
+ for (const segment of path3.split(".")) {
419
+ if (current === null || typeof current !== "object") {
420
+ return void 0;
421
+ }
422
+ current = current[segment];
423
+ }
424
+ return current;
425
+ }
426
+
427
+ // src/translate.ts
428
+ var IMPLICIT_HTTP_API = "HttpApi";
429
+ var IMPLICIT_REST_API = "RestApi";
430
+ var IMPLICIT_API_FOR_EVENT = {
431
+ HttpApi: IMPLICIT_HTTP_API,
432
+ Api: IMPLICIT_REST_API
433
+ };
434
+ var IMPLICIT_API_TYPE = {
435
+ [IMPLICIT_HTTP_API]: "AWS::Serverless::HttpApi",
436
+ [IMPLICIT_REST_API]: "AWS::Serverless::Api"
437
+ };
438
+ function translateService(document) {
439
+ const resolver = createVariableResolver(document);
440
+ const unread = [];
441
+ const resources = {};
442
+ const implicitApis = /* @__PURE__ */ new Set();
443
+ if (document.plugins !== void 0) {
444
+ unread.push({
445
+ functionName: null,
446
+ kind: "plugins",
447
+ reason: "the service loads plugins, which can add, rename or rewrite functions and events; what they declare is not in this document"
448
+ });
449
+ }
450
+ for (const [functionName, definition] of Object.entries(
451
+ document.functions ?? {}
452
+ )) {
453
+ if (definition === null || typeof definition !== "object") {
454
+ continue;
455
+ }
456
+ const handler = resolver.resolveValue(definition.handler);
457
+ if (handler.kind !== "resolved" || typeof handler.value !== "string") {
458
+ unread.push({
459
+ functionName,
460
+ kind: "handler",
461
+ reason: "the function's handler is not a string this document states, so nothing names the code behind it"
462
+ });
463
+ continue;
464
+ }
465
+ const events = {};
466
+ const declared = Array.isArray(definition.events) ? definition.events : [];
467
+ for (const [index, entry] of declared.entries()) {
468
+ if (entry === null || typeof entry !== "object") {
469
+ continue;
470
+ }
471
+ for (const [kind, raw] of Object.entries(
472
+ entry
473
+ )) {
474
+ const translate = EVENT_TRANSLATIONS[kind];
475
+ if (translate === void 0) {
476
+ unread.push({
477
+ functionName,
478
+ kind,
479
+ reason: "this reader does not translate that event kind yet"
480
+ });
481
+ continue;
482
+ }
483
+ const translated = translate(raw, { resolver });
484
+ if (translated.kind === "abstained") {
485
+ unread.push({ functionName, kind, reason: translated.reason });
486
+ continue;
487
+ }
488
+ events[`${kind}${index}`] = translated.event;
489
+ const implicitApi = IMPLICIT_API_FOR_EVENT[translated.event.Type];
490
+ if (implicitApi !== void 0) {
491
+ implicitApis.add(implicitApi);
492
+ }
493
+ }
494
+ }
495
+ const runtime = statedString(resolver.resolveValue(definition.runtime));
496
+ resources[functionName] = {
497
+ Type: "AWS::Serverless::Function",
498
+ Properties: {
499
+ Handler: handler.value,
500
+ ...runtime !== null ? { Runtime: runtime } : {},
501
+ ...Object.keys(events).length > 0 ? { Events: events } : {},
502
+ Environment: {
503
+ Variables: environmentVariables(definition.environment, resolver)
504
+ }
505
+ }
506
+ };
507
+ }
508
+ for (const apiId of implicitApis) {
509
+ resources[apiId] = { Type: IMPLICIT_API_TYPE[apiId], Properties: {} };
510
+ }
511
+ return {
512
+ functions: {
513
+ Globals: providerGlobals(document, resolver),
514
+ Resources: resources
515
+ },
516
+ resources: rawResources(document, resolver),
517
+ unread
518
+ };
519
+ }
520
+ function providerGlobals(document, resolver) {
521
+ const provider = document.provider ?? {};
522
+ const runtime = statedString(resolver.resolveValue(provider.runtime));
523
+ return {
524
+ Function: {
525
+ CodeUri: ".",
526
+ ...runtime !== null ? { Runtime: runtime } : {},
527
+ Environment: {
528
+ Variables: environmentVariables(provider.environment, resolver)
529
+ }
530
+ }
531
+ };
532
+ }
533
+ function statedString(resolved) {
534
+ return resolved.kind === "resolved" && typeof resolved.value === "string" ? resolved.value : null;
535
+ }
536
+ function environmentVariables(raw, resolver) {
537
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
538
+ return {};
539
+ }
540
+ const out = {};
541
+ for (const [name, value] of Object.entries(raw)) {
542
+ const resolved = resolver.resolveValue(value);
543
+ out[name] = resolved.kind === "resolved" ? resolved.value : resolved.token;
544
+ }
545
+ return out;
546
+ }
547
+ function rawResources(document, resolver) {
548
+ const block = document.resources;
549
+ if (block === null || typeof block !== "object" || Array.isArray(block)) {
550
+ return null;
551
+ }
552
+ const declared = block.Resources;
553
+ if (declared === null || typeof declared !== "object") {
554
+ return null;
555
+ }
556
+ return {
557
+ Resources: resolver.resolveTemplateTree(declared)
558
+ };
559
+ }
560
+
561
+ // src/index.ts
562
+ var RECOGNITION = "serverless";
563
+ var RESOURCES_DOCUMENT = "resources";
564
+ function serverlessToSummaries(document, options = {}) {
565
+ const translated = translateService(document);
566
+ const report = options.onUnread ?? reportUnread;
567
+ for (const wiring of translated.unread) {
568
+ report(wiring);
569
+ }
570
+ const rootLabel = options.source ?? "serverless";
571
+ const summaries = (0, import_contract_cloudformation.cloudFormationToSummaries)(translated.functions, {
572
+ source: rootLabel,
573
+ recognition: RECOGNITION
574
+ });
575
+ if (translated.resources === null) {
576
+ return summaries;
577
+ }
578
+ return [
579
+ ...summaries,
580
+ ...(0, import_contract_cloudformation.cloudFormationToSummaries)(translated.resources, {
581
+ source: (0, import_behavioral_ir.nestedDocumentLabel)(rootLabel, [RESOURCES_DOCUMENT]),
582
+ recognition: RECOGNITION
583
+ })
584
+ ];
585
+ }
586
+ function serverlessFileToSummaries(servicePath, options = {}) {
587
+ const located = locateServiceFile(servicePath);
588
+ if (located.kind === "missing") {
589
+ throw new Error(`Serverless service file not found: ${servicePath}`);
590
+ }
591
+ if (located.kind === "program") {
592
+ const report = options.onUnread ?? reportUnread;
593
+ report({
594
+ functionName: null,
595
+ kind: import_node_path2.default.basename(located.file),
596
+ reason: "a program declares this service, and a reader does not run one to find out what it says"
597
+ });
598
+ return [];
599
+ }
600
+ const document = loadServerlessDocument(located.file);
601
+ return serverlessToSummaries(document, {
602
+ ...options,
603
+ source: options.source ?? (0, import_contract_cloudformation.documentSourceLabel)("serverless", located.file)
604
+ });
605
+ }
606
+ function reportUnread(wiring) {
607
+ const where = wiring.functionName === null ? wiring.kind : `${wiring.functionName}.${wiring.kind}`;
608
+ process.stderr.write(`[suss] serverless: ${where}: ${wiring.reason}
609
+ `);
610
+ }
611
+ // Annotate the CommonJS export names for ESM import in node:
612
+ 0 && (module.exports = {
613
+ EVENT_TRANSLATIONS,
614
+ PROGRAM_SERVICE_FILE_NAMES,
615
+ SERVICE_FILE_NAMES,
616
+ createVariableResolver,
617
+ findServiceFile,
618
+ loadServerlessDocument,
619
+ locateServiceFile,
620
+ serverlessFileToSummaries,
621
+ serverlessToSummaries,
622
+ translateService
623
+ });