@suss/packs 0.35.1 → 0.37.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/rails.js CHANGED
@@ -29,7 +29,7 @@ import {
29
29
  symbolValue
30
30
  } from "@suss/adapter-ruby";
31
31
 
32
- // ../ir-core/dist/chunk-A46EUIKC.js
32
+ // ../ir-core/dist/chunk-OROVMQY2.js
33
33
  import { z as z13 } from "zod";
34
34
  import { z as z12 } from "zod";
35
35
  import { z } from "zod";
@@ -257,7 +257,11 @@ var MessageBusSemanticsSchema = z5.object({
257
257
  "aws_kinesis",
258
258
  "aws_firehose",
259
259
  "gcp_pubsub",
260
+ // Job queues. The header says what their channel is.
260
261
  "bullmq",
262
+ "activejob",
263
+ "sidekiq",
264
+ "celery",
261
265
  "kafka",
262
266
  "nats",
263
267
  "cloudflare-queues",
@@ -273,6 +277,26 @@ var MessageBusSemanticsSchema = z5.object({
273
277
  */
274
278
  channel: z5.string().min(1).nullable()
275
279
  });
280
+ var MESSAGES = { jobQueue: false };
281
+ var JOBS = { jobQueue: true };
282
+ var MESSAGE_BUS_TRAITS = {
283
+ aws_sqs: MESSAGES,
284
+ "aws.sns": MESSAGES,
285
+ s3: MESSAGES,
286
+ eventbridge: MESSAGES,
287
+ aws_kinesis: MESSAGES,
288
+ aws_firehose: MESSAGES,
289
+ gcp_pubsub: MESSAGES,
290
+ bullmq: JOBS,
291
+ activejob: JOBS,
292
+ sidekiq: JOBS,
293
+ celery: JOBS,
294
+ kafka: MESSAGES,
295
+ nats: MESSAGES,
296
+ "cloudflare-queues": MESSAGES,
297
+ "cloudflare-cron": MESSAGES,
298
+ "cloudflare-tail": MESSAGES
299
+ };
276
300
  var messageBusSemantics = defineBoundarySemantics({
277
301
  name: "message-bus",
278
302
  schema: MessageBusSemanticsSchema,
@@ -289,6 +313,8 @@ var messageBusSemantics = defineBoundarySemantics({
289
313
  * the generic unmatched list leaves them out.
290
314
  */
291
315
  reportsUnpairedItself: true,
316
+ consumedAs: ["reads"],
317
+ unsettledJob: (semantics) => semantics.channel === null && MESSAGE_BUS_TRAITS[semantics.messageBus].jobQueue,
292
318
  /**
293
319
  * A channel that is null here can still pair. The dedicated pass
294
320
  * follows environment variable chains before comparing, so a
@@ -1070,6 +1096,7 @@ var runtimeConfigSemantics = defineBoundarySemantics({
1070
1096
  // comes from outside the code.
1071
1097
  leavesTheProcess: true,
1072
1098
  reportsUnpairedItself: false,
1099
+ findingsAreReadsByName: true,
1073
1100
  identityKey: () => null,
1074
1101
  // A reader sees which deployable's environment this is. Code that
1075
1102
  // reads a variable does not say which deployable runs it, so a read
@@ -1309,7 +1336,21 @@ var SourceLocationSchema = z13.object({
1309
1336
  * project's `suss.json` gives it. Set only when the project lists its
1310
1337
  * modules, and then on every unit whose file is under a module's root.
1311
1338
  */
1312
- module: z13.string().optional()
1339
+ module: z13.string().optional(),
1340
+ /**
1341
+ * The git repository the extract ran in. Summaries from several
1342
+ * repositories can share a folder, and two of them can both have
1343
+ * `src/index.ts::handler`; this says which one each came from, and
1344
+ * which commit, so a link opens the file that was read. `path` is
1345
+ * where `file` is measured from, relative to the repository's top.
1346
+ * Absent outside a repository.
1347
+ */
1348
+ repository: z13.object({
1349
+ name: z13.string(),
1350
+ path: z13.string(),
1351
+ remote: z13.string().optional(),
1352
+ commit: z13.string().optional()
1353
+ }).optional()
1313
1354
  });
1314
1355
  var BoundaryBindingSchema = z13.object({
1315
1356
  transport: z13.string(),
@@ -1401,6 +1442,13 @@ var SuppressionRuleSchema = z22.object({
1401
1442
  * only intent findings about a scenario with that title.
1402
1443
  */
1403
1444
  scenario: z22.string().optional(),
1445
+ /**
1446
+ * The deployments, by name, that a finding about one environment read
1447
+ * is accepted for. The rule takes them off the finding's list, and
1448
+ * the finding stays while any deployment it lists is left. Without
1449
+ * this, a rule covers every deployment.
1450
+ */
1451
+ deployments: z22.array(z22.string().min(1)).min(1).optional(),
1404
1452
  /**
1405
1453
  * "narrow", the default, requires `kind` plus one of `boundary`,
1406
1454
  * `scenario`, `consumer.transitionId` or `provider.transitionId`, so
@@ -2657,7 +2705,8 @@ function railsFramework(options = {}) {
2657
2705
  const displayPathOf = (file) => path5.isAbsolute(file) ? path5.relative(railsRoot, file) : file;
2658
2706
  const engineRoots = () => expandPatterns(options.configDirectory, options.engineRoots);
2659
2707
  const extraRoutesFiles = () => expandPatterns(options.configDirectory, options.routesFiles);
2660
- const inflections = options.configDirectory === void 0 ? EMPTY_INFLECTIONS : readInflections(options.configDirectory);
2708
+ const appRoot = options.configDirectory === void 0 ? void 0 : railsRoot;
2709
+ const inflections = appRoot === void 0 ? EMPTY_INFLECTIONS : readInflections(appRoot);
2661
2710
  const acronyms = inflections.acronyms;
2662
2711
  const routesInput = () => ({
2663
2712
  routesFile: {
@@ -2685,7 +2734,7 @@ function railsFramework(options = {}) {
2685
2734
  ...options.baseClassNames ?? []
2686
2735
  ],
2687
2736
  root,
2688
- autoloadRoots: options.configDirectory === void 0 ? [] : readAutoloadRoots(options.configDirectory),
2737
+ autoloadRoots: appRoot === void 0 ? [] : readAutoloadRoots(appRoot),
2689
2738
  pathConvention: "railsUnderscore",
2690
2739
  acronyms,
2691
2740
  ancestryRootClassNames: [...RAILS_ROOT_CLASS_NAMES],
@@ -2716,6 +2765,7 @@ function railsFramework(options = {}) {
2716
2765
  inflections,
2717
2766
  // An action reads the request through these, and is handed nothing.
2718
2767
  requestAccessors: ["params", "request"],
2768
+ blankToNil: ["presence"],
2719
2769
  // Rails merges the path, the query string and the body into `params`,
2720
2770
  // so an action's read of one cannot be told from the others and all
2721
2771
  // of them are spelled `params`.
@@ -2723,6 +2773,7 @@ function railsFramework(options = {}) {
2723
2773
  headers: { path: ["request", "headers"], saysWhichField: true },
2724
2774
  params: { path: ["params"], saysWhichField: true }
2725
2775
  },
2776
+ bootTemplates: () => configTemplates(railsRoot),
2726
2777
  // These files change an action's binding without being walked, so the
2727
2778
  // cache key has to list them. This runs before the grammar loads, so
2728
2779
  // nothing here parses Ruby.
@@ -2731,10 +2782,7 @@ function railsFramework(options = {}) {
2731
2782
  ...drawableRoutesFiles(routesFile),
2732
2783
  ...engineRoots().flatMap(engineSourceFiles),
2733
2784
  ...extraRoutesFiles(),
2734
- ...options.configDirectory === void 0 ? [] : [
2735
- ...inflectionFiles(options.configDirectory),
2736
- ...applicationFile(options.configDirectory)
2737
- ]
2785
+ ...appRoot === void 0 ? [] : [...inflectionFiles(appRoot), ...applicationFile(appRoot)]
2738
2786
  ]
2739
2787
  };
2740
2788
  }
@@ -2743,6 +2791,13 @@ function expandPatterns(configDirectory, patterns) {
2743
2791
  (pattern) => expandPathPattern(resolveAgainst(configDirectory, pattern))
2744
2792
  );
2745
2793
  }
2794
+ function configTemplates(railsRoot) {
2795
+ const directory = path5.join(railsRoot, "config");
2796
+ if (!fs5.existsSync(directory)) {
2797
+ return [];
2798
+ }
2799
+ return fs5.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".yml")).map((entry) => path5.join(directory, entry.name)).sort();
2800
+ }
2746
2801
  function drawableRoutesFiles(routesFile) {
2747
2802
  const directory = drawDirectoryOf(routesFile);
2748
2803
  if (!fs5.existsSync(directory)) {
@@ -2759,7 +2814,7 @@ var declares = {
2759
2814
  { ecosystem: "rubygems", name: "rails" },
2760
2815
  { ecosystem: "rubygems", name: "railties" }
2761
2816
  ],
2762
- reads: "Rails controller actions (Ruby), bound to the method and path `config/routes.rb` gives each one. An action the routes file does not reach is still discovered, with no boundary.",
2817
+ reads: "Rails controller actions (Ruby), bound to the method and path `config/routes.rb` gives each one. An action the routes file does not reach is still discovered, with no boundary. The YAML files under `config/` that Rails renders through ERB at boot are read as code that runs when the app loads.",
2763
2818
  configuration: {
2764
2819
  file: "suss.rails.json",
2765
2820
  example: {
@@ -2770,7 +2825,8 @@ var declares = {
2770
2825
  },
2771
2826
  required: false,
2772
2827
  why: "the app directory a controller is defined under and the routes file suss reads each action's method and path from; rails new scaffolds both at these paths. engineRoots lists where the project keeps engines it mounts, and routesFiles any other file that adds routes, when it has either.",
2773
- defaults: { root: "app", routesFile: "config/routes.rb" }
2828
+ defaults: { root: "app", routesFile: "config/routes.rb" },
2829
+ paths: ["root", "routesFile", "engineRoots", "routesFiles"]
2774
2830
  }
2775
2831
  };
2776
2832
  var index_default = railsFramework;
@@ -0,0 +1 @@
1
+ export { declares, default, optionsSchema } from '@suss/framework-sidekiq';
@@ -0,0 +1,37 @@
1
+ // ../framework/sidekiq/dist/index.js
2
+ import { z } from "zod";
3
+ var optionsSchema = z.object({}).strict();
4
+ function sidekiqFramework(_options = {}) {
5
+ return {
6
+ name: "sidekiq",
7
+ protocol: "sidekiq",
8
+ discovery: [],
9
+ jobs: [
10
+ {
11
+ type: "jobClasses",
12
+ messageBus: "sidekiq",
13
+ baseClasses: [],
14
+ modules: ["Sidekiq::Job", "Sidekiq::Worker"],
15
+ performMethod: "perform",
16
+ // `perform_in` and `perform_at` take the delay or the time first.
17
+ enqueueMethods: { perform_async: 0, perform_in: 1, perform_at: 1 },
18
+ optionMethods: ["set"],
19
+ queueDeclarations: [
20
+ { call: "sidekiq_options", queue: { at: 0, keyword: "queue" } }
21
+ ]
22
+ }
23
+ ]
24
+ };
25
+ }
26
+ var declares = {
27
+ kind: "framework",
28
+ package: "@suss/framework-sidekiq",
29
+ dependencies: [{ ecosystem: "rubygems", name: "sidekiq" }],
30
+ reads: "Sidekiq jobs (Ruby): each job's perform is a consumer of a sidekiq channel, and perform_async, perform_in or perform_at a send to it."
31
+ };
32
+ var index_default = sidekiqFramework;
33
+ export {
34
+ declares,
35
+ index_default as default,
36
+ optionsSchema
37
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suss/packs",
3
- "version": "0.35.1",
3
+ "version": "0.37.0",
4
4
  "type": "module",
5
5
  "description": "Every pack suss ships in one install, so it can read Express, Hono, NestJS, FastAPI, Rails, Prisma, OpenAPI and the rest.",
6
6
  "keywords": [
@@ -49,6 +49,14 @@
49
49
  "types": "./dist/aws-lambda.d.ts",
50
50
  "import": "./dist/aws-lambda.js"
51
51
  },
52
+ "./aws-lambda-python": {
53
+ "types": "./dist/aws-lambda-python.d.ts",
54
+ "import": "./dist/aws-lambda-python.js"
55
+ },
56
+ "./aws-lambda-ruby": {
57
+ "types": "./dist/aws-lambda-ruby.d.ts",
58
+ "import": "./dist/aws-lambda-ruby.js"
59
+ },
52
60
  "./aws-s3": {
53
61
  "types": "./dist/aws-s3.d.ts",
54
62
  "import": "./dist/aws-s3.js"
@@ -85,6 +93,14 @@
85
93
  "types": "./dist/bigquery-python.d.ts",
86
94
  "import": "./dist/bigquery-python.js"
87
95
  },
96
+ "./celery": {
97
+ "types": "./dist/celery.d.ts",
98
+ "import": "./dist/celery.js"
99
+ },
100
+ "./bullmq": {
101
+ "types": "./dist/bullmq.d.ts",
102
+ "import": "./dist/bullmq.js"
103
+ },
88
104
  "./cloudflare-workers": {
89
105
  "types": "./dist/cloudflare-workers.d.ts",
90
106
  "import": "./dist/cloudflare-workers.js"
@@ -181,6 +197,14 @@
181
197
  "types": "./dist/rspec.d.ts",
182
198
  "import": "./dist/rspec.js"
183
199
  },
200
+ "./activejob": {
201
+ "types": "./dist/activejob.d.ts",
202
+ "import": "./dist/activejob.js"
203
+ },
204
+ "./sidekiq": {
205
+ "types": "./dist/sidekiq.d.ts",
206
+ "import": "./dist/sidekiq.js"
207
+ },
184
208
  "./factory-bot": {
185
209
  "types": "./dist/factory-bot.d.ts",
186
210
  "import": "./dist/factory-bot.js"
@@ -267,15 +291,16 @@
267
291
  },
268
292
  "dependencies": {
269
293
  "@mrleebo/prisma-ast": "^0.15.0",
270
- "@suss/adapter-python": "0.35.1",
271
- "@suss/adapter-ruby": "0.35.1",
272
- "@suss/adapter-typescript": "0.35.1",
273
- "@suss/behavioral-ir": "0.35.1",
274
- "@suss/contract-graphql": "0.35.1",
275
- "@suss/extractor": "0.35.1",
276
- "@suss/manifest-aws": "0.35.1",
277
- "@suss/recognize": "0.35.1",
278
- "@suss/sql": "0.35.1",
294
+ "@suss/adapter-python": "0.37.0",
295
+ "@suss/adapter-ruby": "0.37.0",
296
+ "@suss/adapter-typescript": "0.37.0",
297
+ "@suss/behavioral-ir": "0.37.0",
298
+ "@suss/contract-graphql": "0.37.0",
299
+ "@suss/contract-serverless": "0.37.0",
300
+ "@suss/extractor": "0.37.0",
301
+ "@suss/manifest-aws": "0.37.0",
302
+ "@suss/recognize": "0.37.0",
303
+ "@suss/sql": "0.37.0",
279
304
  "zod": "^4.0.0"
280
305
  },
281
306
  "devDependencies": {
@@ -300,6 +325,8 @@
300
325
  "@suss/framework-bigquery": "*",
301
326
  "@suss/framework-bigquery-python": "*",
302
327
  "@suss/framework-bigquery-ruby": "*",
328
+ "@suss/framework-bullmq": "*",
329
+ "@suss/framework-celery": "*",
303
330
  "@suss/framework-cloudflare-workers": "*",
304
331
  "@suss/framework-drizzle": "*",
305
332
  "@suss/framework-express": "*",
@@ -318,7 +345,9 @@
318
345
  "@suss/framework-pg": "*",
319
346
  "@suss/framework-pg-ruby": "*",
320
347
  "@suss/framework-rspec": "*",
348
+ "@suss/framework-activejob": "*",
321
349
  "@suss/framework-factory-bot": "*",
350
+ "@suss/framework-sidekiq": "*",
322
351
  "@suss/framework-fabrication": "*",
323
352
  "@suss/framework-minitest": "*",
324
353
  "@suss/framework-prisma": "*",