@produtype/core 1.21.1 → 1.22.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.
@@ -59,10 +59,17 @@ async function detectObservability(ctx) {
59
59
  * these are the same statement in another manifest.
60
60
  */
61
61
  const DOTNET_LOGGING_PACKAGES = ['NLog', 'NLog.Extensions.Logging', 'Serilog', 'Serilog.AspNetCore', 'Microsoft.Extensions.Logging', 'log4net'];
62
+ /**
63
+ * Go names its logging in go.mod, and the same argument as .NET applies: the module
64
+ * path is the ecosystem's, and a project that imports zerolog logs structurally
65
+ * whatever it calls its own logger.
66
+ */
67
+ const GO_LOGGING_PACKAGES = ['rs/zerolog', 'sirupsen/logrus', 'go.uber.org/zap', 'uber-go/zap', 'phuslu/log'];
62
68
  const logDeps = [
63
69
  ...(0, detectContext_1.hasAnyDep)(ctx, LOGGING_PACKAGES),
64
70
  ...(0, detectContext_1.hasAnyElixirDep)(ctx, ELIXIR_LOGGING_PACKAGES),
65
71
  ...(0, detectContext_1.hasAnyDotnetDep)(ctx, DOTNET_LOGGING_PACKAGES),
72
+ ...(0, detectContext_1.hasAnyGoDep)(ctx, GO_LOGGING_PACKAGES),
66
73
  ];
67
74
  const sentryDeps = (0, detectContext_1.hasAnyDep)(ctx, ['@sentry/node', 'sentry-sdk']);
68
75
  for (const d of logDeps)
@@ -177,6 +184,19 @@ async function detectObservability(ctx) {
177
184
  */
178
185
  /Monolog\\Logger|LoggerInterface|->(info|warning|error|debug)\(/,
179
186
  /\bslog\.(Info|Warn|Error|Debug)\(|\bzap\.|\blogrus\.|\blog\.Printf\(/,
187
+ /**
188
+ * zerolog builds the entry instead of formatting it.
189
+ *
190
+ * `log.Error().Err(err).Msg("Error updating last used")` is how gotify logs
191
+ * every line of its Go server, and none of the shapes beside this one is a
192
+ * chain: they all expect the level to take the message. gotify's logging was
193
+ * read from `console.error` in its React admin instead — the frontend
194
+ * describing a failed delete, offered as how the server records what happened.
195
+ *
196
+ * `.Msg(` and `.Msgf(` after a level are zerolog's and zap's sugared API both,
197
+ * and neither is a name the author chose.
198
+ */
199
+ /\b(?:log|logger)\.(?:Info|Warn|Warning|Error|Debug|Fatal|Trace)\(\)(?:\.\w+\([^)]*\))*\.Msgf?\(/,
180
200
  /LoggerFactory\.getLogger|org\.slf4j/,
181
201
  /Rails\.logger/,
182
202
  /\btracing::(info|warn|error|debug)!|\blog::(info|warn|error)!/,
@@ -98,14 +98,37 @@ const NAMES_SOMETHING = /^["']?(?:name|key|label|id|title|field|env|variable)["'
98
98
  * has other arguments and is untouched.
99
99
  */
100
100
  const HTTP_HEADER_NAME = /^[A-Z][A-Za-z0-9]*(?:-[A-Z][A-Za-z0-9]*)+$/;
101
+ /**
102
+ * What is left when a constant's value is taken out of its own name.
103
+ *
104
+ * Stirling-PDF stores a user's second factor under a key, and declares that key as
105
+ * `public static final String MFA_SECRET_KEY = "mfaSecret";`. Normalised, the name is
106
+ * the value plus `key` — it says what the string is *for*. That line was the one
107
+ * `critical` in the report of a careful product: the loudest severity there is, about
108
+ * a map key.
109
+ *
110
+ * A real secret is never its own name. `JWT_SECRET = "jwtSecret"` is somebody naming
111
+ * a slot; the value that matters is random and lives in the environment.
112
+ */
113
+ const NAME_PLUS_WHAT_IT_IS = /^(?:key|name|field|prop|property|attr|attribute|header|param|id|label|const|setting|option)$/;
101
114
  function spellsItsOwnName(trimmed) {
102
115
  const withoutComment = trimmed.replace(/\s*(\/\/|#).*$/, '').replace(/[,;]\s*$/, '');
103
- const assignment = /^(?:(?:public|private|protected|internal|export|const|let|var|final|static|readonly|string)\s+)*([A-Za-z_][\w.]*)\s*(?::\s*[\w<>[\].]+)?\s*=\s*(['"`])([^'"`]+)\2$/.exec(withoutComment);
116
+ /**
117
+ * The type sits between the modifiers and the name in Java, C# and Go, and it is
118
+ * spelled however that language spells it — `String`, not `string`. Listing the
119
+ * declarators alone missed `public static final String MFA_SECRET_KEY = "mfaSecret"`
120
+ * entirely, so one optional word is allowed there instead of a list that would
121
+ * always be short of somebody's type.
122
+ */
123
+ const assignment = /^(?:(?:public|private|protected|internal|export|const|let|var|final|static|readonly)\s+)*(?:[A-Za-z_][\w.<>[\]]*\s+)?([A-Za-z_][\w.]*)\s*(?::\s*[\w<>[\].]+)?\s*=\s*(['"`])([^'"`]+)\2$/.exec(withoutComment);
104
124
  if (!assignment)
105
125
  return false;
106
126
  const plain = (value) => value.toLowerCase().replace(/[-_.\s]/g, '');
107
127
  const declared = /^\s*(?:public|private|protected|internal|export|const|let|var|final|static|readonly)\b/.test(withoutComment);
108
- return plain(assignment[1]) === plain(assignment[3])
128
+ const name = plain(assignment[1]);
129
+ const literal = plain(assignment[3]);
130
+ return name === literal
131
+ || (declared && NAME_PLUS_WHAT_IT_IS.test(name.replace(literal, '')) && name.includes(literal))
109
132
  || (declared && HTTP_HEADER_NAME.test(assignment[3]));
110
133
  }
111
134
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@produtype/core",
3
- "version": "1.21.1",
3
+ "version": "1.22.0",
4
4
  "description": "Deterministic CLI and library that analyzes a web application repository and reports how far it is from production-ready for the kind of product it is meant to be.",
5
5
  "license": "MIT",
6
6
  "bin": {