Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/real-clowns-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@nodesecure/contact": minor
"@nodesecure/mama": minor
"@nodesecure/scanner": patch
---

Refactor highlight extractors to make them work in a web env. Add unit-test to scanner to ensure compatibility and CI break.
54 changes: 1 addition & 53 deletions workspaces/contact/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ console.log({ illuminated, expired });
## API

- [NsResolver](./docs/NsResolver.md)
- [Utilities](./docs/utils.md) (compareContact, toContactWithMetadata, extractMetadataContacts, parseRegExp)

Contact is defined by the following TypeScript interface:
```ts
Expand Down Expand Up @@ -104,59 +105,6 @@ export interface ContactWithMetadata extends Contact {
flags: ContactFlag[];
}

```
### compareContact(contactA: Partial< Contact > | ContactWithMetadata, contactB: Partial< Contact > | ContactWithMetadata, options?: CompareOptions): boolean

Compare two contacts and return `true` if they are the same person

```ts
import {
compareContact
} from "@nodesecure/contact";
import assert from "node:assert";

assert.ok(
compareContact(
{ name: "john doe" },
{ name: "John Doe" }
)
);
```

Each string is trimmed, converted to lowercase, and any multiple spaces are reduced to a single space.

#### Options

```ts
interface CompareOptions {
/**
* @default true
*/
compareName?: boolean;
}
```

### toContactWithMetadata<T extends Partial<Contact>>(contact: T): T & {flags: ContactFlag[] }

Apply some transformation on a contact such as adding a flag when the contact use a free email service

```ts
import {
toContactWithMetadata
} from "@nodesecure/contact";
import assert from "node:assert";

assert.deepEqual(
toContactWithMetadata({
name:"john doe",
email: "johndoe@gmail.com"
}),
{
name:"john doe",
email: "johndoe@gmail.com",
flags: ["free-email-service"]
}
);
```

## License
Expand Down
113 changes: 113 additions & 0 deletions workspaces/contact/docs/utils.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Utilities

Contact is defined by the following TypeScript interface:
```ts
interface Contact {
email?: string;
url?: string;
name: string;
}
```

## compareContact(contactA: Partial< Contact > | ContactWithMetadata, contactB: Partial< Contact > | ContactWithMetadata, options?: CompareOptions): boolean

Compare two contacts and return `true` if they are the same person

```ts
import {
compareContact
} from "@nodesecure/contact";
import assert from "node:assert";

assert.ok(
compareContact(
{ name: "john doe" },
{ name: "John Doe" }
)
);
```

Each string is trimmed, converted to lowercase, and any multiple spaces are reduced to a single space.

### Options

```ts
interface CompareOptions {
/**
* @default true
*/
compareName?: boolean;
}
```

## toContactWithMetadata<T extends Partial<Contact>>(contact: T): T & { flags: ContactFlag[] }

Apply some transformation on a contact such as adding a flag when the contact use a free email service

```ts
import {
toContactWithMetadata
} from "@nodesecure/contact";
import assert from "node:assert";

assert.deepEqual(
toContactWithMetadata({
name:"john doe",
email: "johndoe@gmail.com"
}),
{
name:"john doe",
email: "johndoe@gmail.com",
flags: ["free-email-service"]
}
);
```

## extractMetadataContacts(metadata: ContactPackageMetaData): ContactWithMetadata[]

Extract the author (if any) and maintainers of a package metadata object as a flat array of `ContactWithMetadata`, applying `toContactWithMetadata` on each of them. The author (when present) is always returned first, followed by the maintainers.

```ts
import {
extractMetadataContacts
} from "@nodesecure/contact";
import assert from "node:assert";

assert.deepEqual(
extractMetadataContacts({
author: { name: "john doe", email: "john@gmail.com" },
maintainers: [{ name: "jane doe" }]
}),
[
{ name: "john doe", email: "john@gmail.com", flags: ["free-email-service"] },
{ name: "jane doe", flags: [] }
]
);
```

```ts
interface ContactExtractorPackageMetadata {
author?: Contact | null;
maintainers: Contact[];
}

type ContactPackageMetaData = Partial<ContactExtractorPackageMetadata>;
```

## parseRegExp(input: string): RegExp | null

Parse a string containing a literal RegExp (e.g. `"/^hello/i"`) into a `RegExp` instance. Returns `null` when the input doesn't match the literal RegExp syntax. Only the `gimsuy` flags are kept, any other character found after the closing slash is ignored.

```ts
import {
parseRegExp
} from "@nodesecure/contact";
import assert from "node:assert";

const regexp = parseRegExp("/^hello/i");

assert.ok(regexp instanceof RegExp);
assert.ok(regexp.test("Hello World"));

assert.strictEqual(parseRegExp("hello"), null);
```
13 changes: 10 additions & 3 deletions workspaces/contact/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@
"version": "3.2.0",
"description": "Utilities to extract/fetch data on NPM contacts (author, maintainers ..)",
"type": "module",
"exports": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js"
},
"./web": {
"types": "./dist/web.d.ts",
"import": "./dist/web.js"
}
},
"engines": {
"node": ">=20"
},
"scripts": {
"build": "tsc -b",
"prepublishOnly": "npm run build",
"test-only": "node --test \"./test/**/*.spec.ts\"",
"test-types": "npm run build && tsd && attw --pack . --profile esm-only",
"test-types": "npm run build && attw --pack . --profile esm-only",
"test": "c8 -r html npm run test-only && npm run test-types"
},
"publishConfig": {
Expand Down
24 changes: 5 additions & 19 deletions workspaces/contact/src/ContactExtractor.class.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Import Third-party Dependencies
import type { Contact, PackumentVersion, Packument } from "@nodesecure/npm-types";
import type { PackumentVersion, Packument } from "@nodesecure/npm-types";

// Import Internal Dependencies
import {
Expand All @@ -8,21 +8,17 @@ import {
type IlluminatedContact
} from "./UnlitContact.class.ts";
import { NsResolver } from "./NsResolver.class.ts";
import { toContactWithMetadata } from "./utils/index.ts";
import {
extractMetadataContacts,
type ContactExtractorPackageMetadata
} from "./utils/index.ts";
import type { ContactWithMetadata } from "./types.ts";

export type {
IlluminatedContact,
EnforcedContact
};

export interface ContactExtractorPackageMetadata {
author?: Contact | null;
maintainers: Contact[];
}

type ContactPackageMetaData = Partial<ContactExtractorPackageMetadata>;

export interface ContactExtractorFromDependenciesResult {
illuminated: IlluminatedContact[];
/**
Expand Down Expand Up @@ -126,13 +122,3 @@ export class ContactExtractor {
};
}
}

export function extractMetadataContacts(
metadata: ContactPackageMetaData
): ContactWithMetadata[] {
return [
...(metadata.author ? [toContactWithMetadata<Contact>(metadata.author)] : []),
...(metadata.maintainers ? metadata.maintainers.map(toContactWithMetadata) : [])
];
}

10 changes: 5 additions & 5 deletions workspaces/contact/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export * from "./ContactExtractor.class.ts";
export {
compareContact,
toContactWithMetadata
} from "./utils/index.ts";
export * from "./utils/index.ts";
export { NsResolver } from "./NsResolver.class.ts";
export { UnlitContact } from "./UnlitContact.class.ts";
export { type ContactWithMetadata } from "./types.ts";
export type {
ContactWithMetadata,
ContactFlag
} from "./types.ts";
22 changes: 22 additions & 0 deletions workspaces/contact/src/utils/extractMetadataContacts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Import Third-party Dependencies
import type { Contact } from "@nodesecure/npm-types";

// Import Internal Dependencies
import { toContactWithMetadata } from "./toContactWithMetadata.ts";
import type { ContactWithMetadata } from "../types.ts";

export interface ContactExtractorPackageMetadata {
author?: Contact | null;
maintainers: Contact[];
}

export type ContactPackageMetaData = Partial<ContactExtractorPackageMetadata>;

export function extractMetadataContacts(
metadata: ContactPackageMetaData
): ContactWithMetadata[] {
return [
...(metadata.author ? [toContactWithMetadata<Contact>(metadata.author)] : []),
...(metadata.maintainers ? metadata.maintainers.map(toContactWithMetadata) : [])
];
}
1 change: 1 addition & 0 deletions workspaces/contact/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./compareContact.ts";
export * from "./parseRegexp.ts";
export * from "./toContactWithMetadata.ts";
export * from "./extractMetadataContacts.ts";
12 changes: 12 additions & 0 deletions workspaces/contact/src/web.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export * from "./utils/index.ts";
export {
UnlitContact
} from "./UnlitContact.class.ts";
export type {
EnforcedContact,
IlluminatedContact
} from "./ContactExtractor.class.ts";
export type {
ContactFlag,
ContactWithMetadata
} from "./types.ts";
2 changes: 1 addition & 1 deletion workspaces/contact/test/ContactExtractor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import { faker } from "@faker-js/faker";
// Import Internal Dependencies
import {
ContactExtractor,
NsResolver,
type ContactExtractorPackageMetadata
} from "../src/index.ts";
import { NsResolver } from "../src/NsResolver.class.ts";

// CONSTANTS
const kManifestFixturePath = join(import.meta.dirname, "fixtures", "manifest");
Expand Down
12 changes: 12 additions & 0 deletions workspaces/contact/test/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "..",
"noEmit": true,
"composite": false
},
"include": [
"../src",
"."
]
}
2 changes: 1 addition & 1 deletion workspaces/contact/test/utils/compareContact.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { describe, test } from "node:test";
import type { Contact } from "@nodesecure/npm-types";

// Import Internal Dependencies
import { compareContact } from "../../src/utils/index.ts";
import { compareContact } from "../../src/index.ts";

describe("compareContact", () => {
test("Given Contacts with the same name, it must return true", () => {
Expand Down
Loading