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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# pcsc-mini
# pcsc-mini • <a href="https://npmjs.com/package/pcsc-mini"><img alt="NPM Version" height="21px" src="https://img.shields.io/npm/v/pcsc-mini?style=for-the-badge&logo=npm&logoColor=%23333&logoSize=auto&labelColor=%23eee&color=%23a85270"></a>

` › NodeJS PC/SC API bindings for smart card access on Linux / MacOS / Win32 `

Expand Down
1 change: 1 addition & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ fn addDocs(
"--includeVersion", "lib",
});
docs_ts.step.dependOn(steps.deps);
docs_zig.step.dependOn(&docs_ts.step);

steps.docs.dependOn(&docs_ts.step);
steps.docs.dependOn(&docs_zig.step);
Expand Down
66 changes: 59 additions & 7 deletions lib/client.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,51 @@ describe("Client", () => {
assert.equal(mockOnError.mock.callCount(), 1);
});

test("emits initial reader status event", async () => {
/** @type {pcsc.ReaderChangeHandler | undefined} */
let onStateChange;

const mockClient = /** @type {pcsc.Client} */ ({
start(onChange, _onErr) {
onStateChange = onChange;
},
});

const mockAtr = Uint8Array.of(0xca, 0xfe);
const mockStatusRaw = ReaderStatus.PRESENT | ReaderStatus.IN_USE;
const mockOnChange = mock.fn(
/**
* @param {ReaderStatusFlags} status
* @param {Uint8Array} atr
*/
(status, atr) => {
assert.deepEqual(status, new ReaderStatusFlags(mockStatusRaw));
assert.strictEqual(atr, mockAtr);
},
);

const client = new Client(
/** @type {pcsc} */ ({ newClient: () => mockClient }),
);

/** @type {Reader | undefined} */
let reader;

client.on("reader", r => {
reader = r;
reader.on("change", mockOnChange);
});

client.start();
assert(onStateChange);
assert.equal(reader, undefined);

onStateChange("iReadCards", mockStatusRaw, mockAtr);
assert(reader);

assert.equal(mockOnChange.mock.callCount(), 1);
});

test("emits reader status events", async () => {
/** @type {pcsc.ReaderChangeHandler | undefined} */
let onStateChange;
Expand All @@ -134,9 +179,7 @@ describe("Client", () => {
});

const client = new Client(
/** @type {pcsc} */ ({
newClient: () => mockClient,
}),
/** @type {pcsc} */ ({ newClient: () => mockClient }),
);

/** @type {Reader | undefined} */
Expand All @@ -145,22 +188,31 @@ describe("Client", () => {
client.on("reader", r => (reader = r)).start();
assert(onStateChange);

// Set up initial detection state change:
onStateChange("iReadCards", ReaderStatus.EMPTY, Uint8Array.of());
assert(reader);

const mockAtr = Uint8Array.of(0xca, 0xfe);
const mockStatusRaw = ReaderStatus.PRESENT | ReaderStatus.IN_USE;
const mockOnChange = mock.fn(
/** @param {ReaderStatusFlags} status */
status => assert.deepEqual(status, new ReaderStatusFlags(mockStatusRaw)),
/**
* @param {ReaderStatusFlags} status
* @param {Uint8Array} atr
*/
(status, atr) => {
assert.deepEqual(status, new ReaderStatusFlags(mockStatusRaw));
assert.strictEqual(atr, mockAtr);
},
);

reader.on("change", mockOnChange);
assert.equal(mockOnChange.mock.callCount(), 0);

onStateChange("other reader", mockStatusRaw, Uint8Array.of());
client.removeAllListeners("reader");
onStateChange("other reader", mockStatusRaw, mockAtr);
assert.equal(mockOnChange.mock.callCount(), 0);

onStateChange("iReadCards", mockStatusRaw, Uint8Array.of());
onStateChange("iReadCards", mockStatusRaw, mockAtr);
assert.equal(mockOnChange.mock.callCount(), 1);
});

Expand Down
44 changes: 38 additions & 6 deletions typedoc.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,43 @@
{
"$schema": "https://typedoc.org/schema.json",
"headings": {
"readme": false
"readme": false
},
"hostedBaseUrl": "https://kofi-q.github.io/pcsc-mini",
"kindSortOrder": [
"Class",
"Enum",
"Interface",
"Reference",
"Project",
"Module",
"Namespace",
"EnumMember",
"TypeAlias",
"Constructor",
"Property",
"Variable",
"Function",
"Accessor",
"Method",
"Parameter",
"TypeParameter",
"TypeLiteral",
"CallSignature",
"ConstructorSignature",
"IndexSignature",
"GetSignature",
"SetSignature"
],
"outputs": [
{
"name": "html",
"path": "./docs"
}
]
{
"name": "html",
"path": "./docs"
}
],
"navigationLinks": {
"Zig Docs": "https://kofi-q.github.io/pcsc-mini/zig",
"NPM": "https://npmjs.com/package/pcsc-mini",
"GitHub": "https://github.com/kofi-q/pcsc-mini"
},
}
12 changes: 12 additions & 0 deletions website/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,18 @@ code.tsd-tag {
}
}

.tsd-accordion-details {
>a {
/*
* A little hacky, but typedoc pulls in the NPM badge logo in the readme
* title into the sidebar as escaped HTML.
* [TODO] Figure out a way around this, or do it in JS instead to avoid
* hiding on all pages.
*/
display: none;
}
}

ul.tsd-parameter-list {
li {
span {
Expand Down