@produtype/core 0.33.1 → 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.
@@ -160,7 +160,10 @@ function isTestOrExamplePath(file) {
160
160
  // `__mocks__` was missing, and a mock is the most misleading file in a repository:
161
161
  // `application_fee_percent: null` inside a Stripe fixture made an open-source CRM read
162
162
  // as a marketplace taking a cut. A field set to null is evidence of absence.
163
- return /(^|\/)(__tests__|__mocks__|mocks?|tests?|test-data|fixtures|frontend-example)(\/|$)/i.test(file)
163
+ // `fixtures` was listed and `fixture` was not, so `extra/fixture/authsources.php`
164
+ // made PHP one of the languages of an Elixir analytics product — and of cal.com,
165
+ // which is TypeScript.
166
+ return /(^|\/)(__tests__|__mocks__|mocks?|tests?|test-data|fixtures?|frontend-example)(\/|$)/i.test(file)
164
167
  || /(^|\/)test[-_][^/]+\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(file)
165
168
  /**
166
169
  * The other half of the convention.
@@ -744,7 +747,16 @@ async function analyzeProject(projectPath) {
744
747
  : []),
745
748
  ],
746
749
  workspaces: workspaceStacks,
747
- files: allFiles,
750
+ /**
751
+ * The files this reading actually covers, not every file on disk.
752
+ *
753
+ * Built from `allFiles`, a single `extra/fixture/authsources.php` made PHP one of
754
+ * the languages of an Elixir analytics product and of cal.com, which is
755
+ * TypeScript. The languages a report names should be the ones it read; test
756
+ * fixtures and generated output are excluded from the reading and belong out of
757
+ * this list for the same reason.
758
+ */
759
+ files: sourceFiles,
748
760
  }),
749
761
  packageJson,
750
762
  pythonDeps,
@@ -230,8 +230,29 @@ async function detectAuth(ctx) {
230
230
  * `const teamId = 'W7LPPWA48L'` in its notarization script.
231
231
  */
232
232
  const STRONG_TENANCY = [/organizationId/i, /organization_id/i, /tenantId/i, /tenant_id/i];
233
- const WEAK_TENANCY = [/workspaceId/i, /workspace_id/i, /companyId/i];
234
- const strongOrganization = await (0, textSearch_1.searchInFiles)(ctx.root, sourceFiles, STRONG_TENANCY, 25);
233
+ const WEAK_TENANCY = [/workspaceId/i, /workspace_id/i, /companyId/i, /teamId/i, /team_id/i];
234
+ /**
235
+ * A team that has members is an account.
236
+ *
237
+ * "Team" is the third word products use for a tenant, after organization and
238
+ * workspace — and unlike those two it also means a team: a sports application has
239
+ * teams and no tenants. Documenso is the case that made it matter: `teamId` in three
240
+ * hundred and eighty-eight files, `TeamMember` in seventy-nine, `organizationId` in
241
+ * none, and no tenancy detected at all.
242
+ *
243
+ * The pairing is what disambiguates. A membership table beside the team turns a
244
+ * domain entity into an account boundary, which is the same reasoning the detector
245
+ * already applies to weak words: never on its own, always with something that means
246
+ * only one thing.
247
+ */
248
+ const teamMembership = await (0, textSearch_1.searchInFiles)(ctx.root, sourceFiles, [/teamMember/i, /team_member/i, /teamMembership/i], 10);
249
+ const teamAsTenant = teamMembership.length > 0
250
+ ? await (0, textSearch_1.searchInFiles)(ctx.root, sourceFiles, [/teamId/i, /team_id/i], 25)
251
+ : [];
252
+ const strongOrganization = [
253
+ ...(await (0, textSearch_1.searchInFiles)(ctx.root, sourceFiles, STRONG_TENANCY, 25)),
254
+ ...teamAsTenant,
255
+ ];
235
256
  const weakOrganization = await (0, textSearch_1.searchInFiles)(ctx.root, sourceFiles, WEAK_TENANCY, 25);
236
257
  // A weak word never stands on its own, however many files it appears in. Bruno says
237
258
  // `workspaceId` in three — it has workspaces, and they are local folders, not
@@ -248,7 +269,10 @@ async function detectAuth(ctx) {
248
269
  * already states the principle: a weak word never stands on its own, however many
249
270
  * files it appears in.
250
271
  */
251
- const strongMembership = await (0, textSearch_1.searchInFiles)(ctx.root, sourceFiles, STRONG_TENANCY, 25);
272
+ const strongMembership = [
273
+ ...(await (0, textSearch_1.searchInFiles)(ctx.root, sourceFiles, STRONG_TENANCY, 25)),
274
+ ...teamAsTenant,
275
+ ];
252
276
  const weakMembership = await (0, textSearch_1.searchInFiles)(ctx.root, sourceFiles, [/memberId/i, ...WEAK_TENANCY], 25);
253
277
  const membershipSignals = strongMembership.length > 0 ? [...strongMembership, ...weakMembership] : [];
254
278
  const b2bSignals = await (0, textSearch_1.searchInFiles)(ctx.root, sourceFiles, [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@produtype/core",
3
- "version": "0.33.1",
3
+ "version": "0.34.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": {