FRE-600: Fix code review blockers

- Consolidated duplicate UndoManagers to single instance
- Fixed connection promise to only resolve on 'connected' status
- Fixed WebSocketProvider import (WebsocketProvider)
- Added proper doc.destroy() cleanup
- Renamed isPresenceInitialized property to avoid conflict

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
2026-04-25 00:08:01 -04:00
parent 65b552bb08
commit 7c684a42cc
48450 changed files with 5679671 additions and 383 deletions

202
node_modules/@wallet-standard/errors/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

73
node_modules/@wallet-standard/errors/README.md generated vendored Normal file
View File

@@ -0,0 +1,73 @@
# `@wallet-standard/errors`
This package brings together every error message across all Wallet Standard JavaScript modules.
## Reading error messages
### In development mode
When your bundler sets the environment variable `NODE_ENV` to `development`, every error message will be included in the bundle. As such, you will be able to read them in plain language wherever they appear.
> [!WARNING]
> The size of your JavaScript bundle will increase significantly with the inclusion of every error message in development mode. Be sure to build your bundle with `NODE_ENV` set to `production` when you go to production.
### In production mode
When your bundler sets the environment variable `NODE_ENV` to anything other than `development`, error messages will be stripped from the bundle to save space. Only the error code will appear when an error is encountered. Follow the instructions in the error message to convert the error code back to the human-readable error message.
For instance, to recover the error text for the error with code `123`:
```shell
npx @wallet-standard/errors decode -- 123
```
## Adding a new error
1. Add a new exported error code constant to `src/codes.ts`.
2. Add that new constant to the `WalletStandardErrorCode` union in `src/codes.ts`.
3. If you would like the new error to encapsulate context about the error itself (eg. the public keys for which a transaction is missing signatures) define the shape of that context in `src/context.ts`.
4. Add the error's message to `src/messages.ts`. Any context values that you defined above will be interpolated into the message wherever you write `$key`, where `key` is the index of a value in the context (eg. ``'Missing a signature for account `$address`'``).
5. Publish a new version of `@wallet-standard/errors`.
6. Bump the version of `@wallet-standard/errors` in the package from which the error is thrown.
## Removing an error message
- Don't remove errors.
- Don't change the meaning of an error message.
- Don't change or reorder error codes.
- Don't change or remove members of an error's context.
When an older client throws an error, we want to make sure that they can always decode the error. If you make any of the changes above, old clients will, by definition, not have received your changes. This could make the errors that they throw impossible to decode going forward.
## Catching errors
When you catch a `WalletStandardError` and assert its error code using `isWalletStandardError()`, TypeScript will refine the error's context to the type associated with that error code. You can use that context to render useful error messages, or to make context-aware decisions that help your application to recover from the error.
```tsx
import { WALLET_STANDARD_ERROR__ACCOUNT__FEATURE_NOT_SUPPORTED, isWalletStandardError } from '@wallet-standard/errors';
function MyComponent(props) {
return (
<ErrorBoundary FallbackComponent={ErrorComponent}>
<SignMessageForm account={props.account} />
</ErrorBoundary>
);
}
function ErrorComponent({ error }) {
if (
isWalletStandardError(error, WALLET_STANDARD_ERROR__ACCOUNT__FEATURE_NOT_SUPPORTED) &&
error.context.featureName === 'solana:signMessage'
) {
return (
<span>
The account <AccountLink account={error.account} /> does not support signing messages. Please choose
another account.
</span>
);
} else if (error && typeof error === 'object' && 'message' in error) {
return <span>{String(error.message)}</span>;
} else {
return <span>Something went wrong</span>;
}
}
```

7
node_modules/@wallet-standard/errors/bin/cli.mjs generated vendored Executable file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/env -S node
import process from 'node:process';
import { run } from '../lib/cli.mjs';
run(process.argv);

41
node_modules/@wallet-standard/errors/lib/cjs/codes.js generated vendored Normal file
View File

@@ -0,0 +1,41 @@
"use strict";
/**
* To add a new error, follow the instructions at
* https://github.com/wallet-standard/wallet-standard/tree/master/packages/core/errors/#adding-a-new-error
*
* WARNING:
* - Don't remove error codes
* - Don't change or reorder error codes.
*
* Good naming conventions:
* - Prefixing common errors — e.g. under the same package — can be a good way to namespace them. E.g. All codec-related errors start with `WALLET_STANDARD_ERROR__ACCOUNT__`.
* - Use consistent names — e.g. choose `PDA` or `PROGRAM_DERIVED_ADDRESS` and stick with it. Ensure your names are consistent with existing error codes. The decision might have been made for you.
* - Recommended prefixes and suffixes:
* - `MALFORMED_`: Some input was not constructed properly. E.g. `MALFORMED_BASE58_ENCODED_ADDRESS`.
* - `INVALID_`: Some input is invalid (other than because it was MALFORMED). E.g. `INVALID_NUMBER_OF_BYTES`.
* - `EXPECTED_`: Some input was different than expected, no need to specify the "GOT" part unless necessary. E.g. `EXPECTED_DECODED_ACCOUNT`.
* - `_CANNOT_`: Some operation cannot be performed or some input cannot be used due to some condition. E.g. `CANNOT_DECODE_EMPTY_BYTE_ARRAY` or `PDA_CANNOT_END_WITH_PDA_MARKER`.
* - `_MUST_BE_`: Some condition must be true. E.g. `NONCE_TRANSACTION_FIRST_INSTRUCTION_MUST_BE_ADVANCE_NONCE`.
* - `_FAILED_TO_`: Tried to perform some operation and failed. E.g. `FAILED_TO_DECODE_ACCOUNT`.
* - `_NOT_FOUND`: Some operation lead to not finding something. E.g. `ACCOUNT_NOT_FOUND`.
* - `_OUT_OF_RANGE`: Some value is out of range. E.g. `ENUM_DISCRIMINATOR_OUT_OF_RANGE`.
* - `_EXCEEDED`: Some limit was exceeded. E.g. `PDA_MAX_SEED_LENGTH_EXCEEDED`.
* - `_MISMATCH`: Some elements do not match. E.g. `ENCODER_DECODER_FIXED_SIZE_MISMATCH`.
* - `_MISSING`: Some required input is missing. E.g. `TRANSACTION_FEE_PAYER_MISSING`.
* - `_UNIMPLEMENTED`: Some required component is not available in the environment. E.g. `SUBTLE_CRYPTO_VERIFY_FUNCTION_UNIMPLEMENTED`.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED = exports.WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED = exports.WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED = exports.WALLET_STANDARD_ERROR__USER__REQUEST_REJECTED = exports.WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND = exports.WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND = void 0;
// Registry-related errors.
// Reserve error codes in the range [3834000-3834999].
exports.WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND = 3834000;
exports.WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND = 3834001;
// User-related errors.
// Reserve error codes in the range [4001000-4001999].
exports.WALLET_STANDARD_ERROR__USER__REQUEST_REJECTED = 4001000;
// Feature-related errors.
// Reserve error codes in the range [6160000-6160999].
exports.WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED = 6160000;
exports.WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED = 6160001;
exports.WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED = 6160002;
//# sourceMappingURL=codes.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"codes.js","sourceRoot":"","sources":["../../src/codes.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;;;AAEH,2BAA2B;AAC3B,sDAAsD;AACzC,QAAA,iDAAiD,GAAG,OAAgB,CAAC;AACrE,QAAA,yDAAyD,GAAG,OAAgB,CAAC;AAE1F,uBAAuB;AACvB,sDAAsD;AACzC,QAAA,6CAA6C,GAAG,OAAgB,CAAC;AAE9E,0BAA0B;AAC1B,sDAAsD;AACzC,QAAA,iEAAiE,GAAG,OAAgB,CAAC;AACrF,QAAA,qEAAqE,GAAG,OAAgB,CAAC;AACzF,QAAA,6DAA6D,GAAG,OAAgB,CAAC"}

View File

@@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decodeEncodedContext = decodeEncodedContext;
exports.encodeContextObject = encodeContextObject;
function decodeEncodedContext(encodedContext) {
const decodedUrlString = atob(encodedContext);
return Object.fromEntries(new URLSearchParams(decodedUrlString).entries());
}
function encodeValue(value) {
if (Array.isArray(value)) {
const commaSeparatedValues = value.map(encodeValue).join('%2C%20' /* ", " */);
return '%5B' /* "[" */ + commaSeparatedValues + /* "]" */ '%5D';
}
else if (typeof value === 'bigint') {
return `${value}n`;
}
else {
return encodeURIComponent(String(value != null && Object.getPrototypeOf(value) === null
? // Plain objects with no prototype don't have a `toString` method.
Object.assign({}, value) : value));
}
}
function encodeObjectContextEntry([key, value]) {
return `${key}=${encodeValue(value)}`;
}
function encodeContextObject(context) {
const searchParamsString = Object.entries(context).map(encodeObjectContextEntry).join('&');
return btoa(searchParamsString);
}
//# sourceMappingURL=context.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/context.ts"],"names":[],"mappings":";;AA6CA,oDAGC;AAyBD,kDAGC;AA/BD,SAAgB,oBAAoB,CAAC,cAAsB;IACvD,MAAM,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC;IAC9C,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,eAAe,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,oBAAoB,GAAG,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC9E,OAAO,KAAK,CAAC,SAAS,GAAG,oBAAoB,GAAG,SAAS,CAAC,KAAK,CAAC;IACpE,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACnC,OAAO,GAAG,KAAK,GAAG,CAAC;IACvB,CAAC;SAAM,CAAC;QACJ,OAAO,kBAAkB,CACrB,MAAM,CACF,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,IAAI;YAClD,CAAC,CAAC,kEAAkE;+BAE5D,KAAgB,EACxB,CAAC,CAAC,KAAK,CACd,CACJ,CAAC;IACN,CAAC;AACL,CAAC;AAED,SAAS,wBAAwB,CAAC,CAAC,GAAG,EAAE,KAAK,CAAoB;IAC7D,OAAO,GAAG,GAAG,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;AAC1C,CAAC;AAED,SAAgB,mBAAmB,CAAC,OAAe;IAC/C,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3F,OAAO,IAAI,CAAC,kBAAkB,CAAC,CAAC;AACpC,CAAC"}

50
node_modules/@wallet-standard/errors/lib/cjs/error.js generated vendored Normal file
View File

@@ -0,0 +1,50 @@
"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WalletStandardError = void 0;
exports.isWalletStandardError = isWalletStandardError;
const message_formatter_js_1 = require("./message-formatter.js");
function isWalletStandardError(e, code) {
const isWalletStandardError = e instanceof Error && e.name === 'WalletStandardError';
if (isWalletStandardError) {
if (code !== undefined) {
return e.context.__code === code;
}
return true;
}
return false;
}
class WalletStandardError extends Error {
constructor(...[code, contextAndErrorOptions]) {
let context;
let errorOptions;
if (contextAndErrorOptions) {
// If the `ErrorOptions` type ever changes, update this code.
const { cause } = contextAndErrorOptions, contextRest = __rest(contextAndErrorOptions, ["cause"]);
if (cause) {
errorOptions = { cause };
}
if (Object.keys(contextRest).length > 0) {
context = contextRest;
}
}
const message = (0, message_formatter_js_1.getErrorMessage)(code, context);
super(message, errorOptions);
this.context = Object.assign({ __code: code }, context);
// This is necessary so that `isWalletStandardError()` can identify a `WalletStandardError`
// without having to import the class for use in an `instanceof` check.
this.name = 'WalletStandardError';
}
}
exports.WalletStandardError = WalletStandardError;
//# sourceMappingURL=error.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/error.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAIA,sDAYC;AAdD,iEAAyD;AAEzD,SAAgB,qBAAqB,CACjC,CAAU,EACV,IAAiB;IAEjB,MAAM,qBAAqB,GAAG,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,IAAI,KAAK,qBAAqB,CAAC;IACrF,IAAI,qBAAqB,EAAE,CAAC;QACxB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACrB,OAAQ,CAAqC,CAAC,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC;QAC1E,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAUD,MAAa,mBAA0F,SAAQ,KAAK;IAEhH,YACI,GAAG,CAAC,IAAI,EAAE,sBAAsB,CAKzB;QAEP,IAAI,OAA2D,CAAC;QAChE,IAAI,YAAsC,CAAC;QAC3C,IAAI,sBAAsB,EAAE,CAAC;YACzB,6DAA6D;YAC7D,MAAM,EAAE,KAAK,KAAqB,sBAAsB,EAAtC,WAAW,UAAK,sBAAsB,EAAlD,SAAyB,CAAyB,CAAC;YACzD,IAAI,KAAK,EAAE,CAAC;gBACR,YAAY,GAAG,EAAE,KAAK,EAAE,CAAC;YAC7B,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtC,OAAO,GAAG,WAAqD,CAAC;YACpE,CAAC;QACL,CAAC;QACD,MAAM,OAAO,GAAG,IAAA,sCAAe,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC/C,KAAK,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,gBACX,MAAM,EAAE,IAAI,IACT,OAAO,CACkC,CAAC;QACjD,2FAA2F;QAC3F,uEAAuE;QACvE,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACtC,CAAC;CACJ;AAhCD,kDAgCC"}

20
node_modules/@wallet-standard/errors/lib/cjs/index.js generated vendored Normal file
View File

@@ -0,0 +1,20 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./codes.js"), exports);
__exportStar(require("./error.js"), exports);
__exportStar(require("./stack-trace.js"), exports);
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA2B;AAC3B,6CAA2B;AAC3B,mDAAiC"}

View File

@@ -0,0 +1,95 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getHumanReadableErrorMessage = getHumanReadableErrorMessage;
exports.getErrorMessage = getErrorMessage;
const context_js_1 = require("./context.js");
const messages_js_1 = require("./messages.js");
var StateType;
(function (StateType) {
StateType[StateType["EscapeSequence"] = 0] = "EscapeSequence";
StateType[StateType["Text"] = 1] = "Text";
StateType[StateType["Variable"] = 2] = "Variable";
})(StateType || (StateType = {}));
const START_INDEX = 'i';
const TYPE = 't';
function getHumanReadableErrorMessage(code, context = {}) {
const messageFormatString = messages_js_1.WalletStandardErrorMessages[code];
if (messageFormatString.length === 0) {
return '';
}
let state;
function commitStateUpTo(endIndex) {
if (state[TYPE] === StateType.Variable) {
const variableName = messageFormatString.slice(state[START_INDEX] + 1, endIndex);
fragments.push(variableName in context ? `${context[variableName]}` : `$${variableName}`);
}
else if (state[TYPE] === StateType.Text) {
fragments.push(messageFormatString.slice(state[START_INDEX], endIndex));
}
}
const fragments = [];
messageFormatString.split('').forEach((char, ii) => {
if (ii === 0) {
state = {
[START_INDEX]: 0,
[TYPE]: messageFormatString[0] === '\\'
? StateType.EscapeSequence
: messageFormatString[0] === '$'
? StateType.Variable
: StateType.Text,
};
return;
}
let nextState;
switch (state[TYPE]) {
case StateType.EscapeSequence:
nextState = { [START_INDEX]: ii, [TYPE]: StateType.Text };
break;
case StateType.Text:
if (char === '\\') {
nextState = { [START_INDEX]: ii, [TYPE]: StateType.EscapeSequence };
}
else if (char === '$') {
nextState = { [START_INDEX]: ii, [TYPE]: StateType.Variable };
}
break;
case StateType.Variable:
if (char === '\\') {
nextState = { [START_INDEX]: ii, [TYPE]: StateType.EscapeSequence };
}
else if (char === '$') {
nextState = { [START_INDEX]: ii, [TYPE]: StateType.Variable };
}
else if (!char.match(/\w/)) {
nextState = { [START_INDEX]: ii, [TYPE]: StateType.Text };
}
break;
}
if (nextState) {
if (state !== nextState) {
commitStateUpTo(ii);
}
state = nextState;
}
});
commitStateUpTo();
return fragments.join('');
}
function getErrorMessage(code, context = {}) {
if (process.env.NODE_ENV !== 'production') {
return getHumanReadableErrorMessage(code, context);
}
else {
let decodingAdviceMessage = `Wallet Standard error #${code}; Decode this error by running \`npx @wallet-standard/errors decode -- ${code}`;
if (Object.keys(context).length) {
/**
* DANGER: Be sure that the shell command is escaped in such a way that makes it
* impossible for someone to craft malicious context values that would result in
* an exploit against anyone who bindly copy/pastes it into their terminal.
*/
decodingAdviceMessage += ` '${(0, context_js_1.encodeContextObject)(context)}'`;
}
return `${decodingAdviceMessage}\``;
}
}
//# sourceMappingURL=message-formatter.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"message-formatter.js","sourceRoot":"","sources":["../../src/message-formatter.ts"],"names":[],"mappings":";;AAgBA,oEAgEC;AAED,0CAkBC;AAnGD,6CAAmD;AACnD,+CAA4D;AAE5D,IAAW,SAIV;AAJD,WAAW,SAAS;IAChB,6DAAc,CAAA;IACd,yCAAI,CAAA;IACJ,iDAAQ,CAAA;AACZ,CAAC,EAJU,SAAS,KAAT,SAAS,QAInB;AAKD,MAAM,WAAW,GAAG,GAAG,CAAC;AACxB,MAAM,IAAI,GAAG,GAAG,CAAC;AAEjB,SAAgB,4BAA4B,CACxC,IAAgB,EAChB,UAAkB,EAAE;IAEpB,MAAM,mBAAmB,GAAG,yCAA2B,CAAC,IAAI,CAAC,CAAC;IAC9D,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,CAAC;IACd,CAAC;IACD,IAAI,KAAY,CAAC;IACjB,SAAS,eAAe,CAAC,QAAiB;QACtC,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,QAAQ,EAAE,CAAC;YACrC,MAAM,YAAY,GAAG,mBAAmB,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;YACjF,SAAS,CAAC,IAAI,CACV,YAAY,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAoC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,YAAY,EAAE,CACpG,CAAC;QACN,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YACxC,SAAS,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC5E,CAAC;IACL,CAAC;IACD,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE;QAC/C,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;YACX,KAAK,GAAG;gBACJ,CAAC,WAAW,CAAC,EAAE,CAAC;gBAChB,CAAC,IAAI,CAAC,EACF,mBAAmB,CAAC,CAAC,CAAC,KAAK,IAAI;oBAC3B,CAAC,CAAC,SAAS,CAAC,cAAc;oBAC1B,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,KAAK,GAAG;wBAC9B,CAAC,CAAC,SAAS,CAAC,QAAQ;wBACpB,CAAC,CAAC,SAAS,CAAC,IAAI;aAC7B,CAAC;YACF,OAAO;QACX,CAAC;QACD,IAAI,SAAS,CAAC;QACd,QAAQ,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAClB,KAAK,SAAS,CAAC,cAAc;gBACzB,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC;gBAC1D,MAAM;YACV,KAAK,SAAS,CAAC,IAAI;gBACf,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBAChB,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,cAAc,EAAE,CAAC;gBACxE,CAAC;qBAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;oBACtB,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC;gBAClE,CAAC;gBACD,MAAM;YACV,KAAK,SAAS,CAAC,QAAQ;gBACnB,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBAChB,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,cAAc,EAAE,CAAC;gBACxE,CAAC;qBAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;oBACtB,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC;gBAClE,CAAC;qBAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC3B,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC;gBAC9D,CAAC;gBACD,MAAM;QACd,CAAC;QACD,IAAI,SAAS,EAAE,CAAC;YACZ,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACtB,eAAe,CAAC,EAAE,CAAC,CAAC;YACxB,CAAC;YACD,KAAK,GAAG,SAAS,CAAC;QACtB,CAAC;IACL,CAAC,CAAC,CAAC;IACH,eAAe,EAAE,CAAC;IAClB,OAAO,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED,SAAgB,eAAe,CAC3B,IAAgB,EAChB,UAAkB,EAAE;IAEpB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QACxC,OAAO,4BAA4B,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC;SAAM,CAAC;QACJ,IAAI,qBAAqB,GAAG,0BAA0B,IAAI,0EAA0E,IAAI,EAAE,CAAC;QAC3I,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;YAC9B;;;;eAIG;YACH,qBAAqB,IAAI,KAAK,IAAA,gCAAmB,EAAC,OAAO,CAAC,GAAG,CAAC;QAClE,CAAC;QACD,OAAO,GAAG,qBAAqB,IAAI,CAAC;IACxC,CAAC;AACL,CAAC"}

View File

@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WalletStandardErrorMessages = void 0;
const codes_js_1 = require("./codes.js");
/**
* To add a new error, follow the instructions at
* https://github.com/wallet-standard/wallet-standard/tree/master/packages/core/errors#adding-a-new-error
*
* WARNING:
* - Don't change the meaning of an error message.
*/
exports.WalletStandardErrorMessages = {
[codes_js_1.WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED]: 'The wallet account $address does not support the chain `$chain`',
[codes_js_1.WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED]: 'The wallet account $address does not support the `$featureName` feature',
[codes_js_1.WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED]: "The wallet '$walletName' does not support the `$featureName` feature",
[codes_js_1.WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND]: "No account with address $address could be found in the '$walletName' wallet",
[codes_js_1.WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND]: 'No underlying Wallet Standard wallet could be found for this handle. This can happen if ' +
'the wallet associated with the handle has been unregistered.',
[codes_js_1.WALLET_STANDARD_ERROR__USER__REQUEST_REJECTED]: 'The user rejected the request',
};
//# sourceMappingURL=messages.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/messages.ts"],"names":[],"mappings":";;;AACA,yCAOoB;AAEpB;;;;;;GAMG;AACU,QAAA,2BAA2B,GAInC;IACD,CAAC,4EAAiE,CAAC,EAC/D,iEAAiE;IACrE,CAAC,gFAAqE,CAAC,EACnE,yEAAyE;IAC7E,CAAC,wEAA6D,CAAC,EAC3D,sEAAsE;IAC1E,CAAC,oEAAyD,CAAC,EACvD,6EAA6E;IACjF,CAAC,4DAAiD,CAAC,EAC/C,0FAA0F;QAC1F,8DAA8D;IAClE,CAAC,wDAA6C,CAAC,EAAE,+BAA+B;CACnF,CAAC"}

View File

@@ -0,0 +1 @@
{ "type": "commonjs" }

View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.safeCaptureStackTrace = safeCaptureStackTrace;
function safeCaptureStackTrace(...args) {
if ('captureStackTrace' in Error && typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(...args);
}
}
//# sourceMappingURL=stack-trace.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stack-trace.js","sourceRoot":"","sources":["../../src/stack-trace.ts"],"names":[],"mappings":";;AAAA,sDAIC;AAJD,SAAgB,qBAAqB,CAAC,GAAG,IAAgD;IACrF,IAAI,mBAAmB,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,iBAAiB,KAAK,UAAU,EAAE,CAAC;QAChF,KAAK,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAC,CAAC;IACrC,CAAC;AACL,CAAC"}

182
node_modules/@wallet-standard/errors/lib/cli.mjs generated vendored Normal file
View File

@@ -0,0 +1,182 @@
import $3Sr93$chalk from "chalk";
import {Command as $3Sr93$Command, InvalidArgumentError as $3Sr93$InvalidArgumentError} from "commander";
var $a2eff9e01820a9b9$exports = {};
$a2eff9e01820a9b9$exports = JSON.parse("{\"name\":\"@wallet-standard/errors\",\"version\":\"0.1.1\",\"author\":\"Solana Maintainers <maintainers@solana.foundation>\",\"repository\":\"https://github.com/wallet-standard/wallet-standard\",\"license\":\"Apache-2.0\",\"publishConfig\":{\"access\":\"public\"},\"files\":[\"bin\",\"lib\",\"src\",\"LICENSE\"],\"engines\":{\"node\":\">=16\"},\"type\":\"module\",\"sideEffects\":false,\"bin\":\"./bin/cli.mjs\",\"main\":\"./lib/cjs/index.js\",\"module\":\"./lib/esm/index.js\",\"types\":\"./lib/types/index.d.ts\",\"exports\":{\"require\":\"./lib/cjs/index.js\",\"import\":\"./lib/esm/index.js\",\"types\":\"./lib/types/index.d.ts\"},\"targets\":{\"bin\":{\"context\":\"node\",\"distDir\":\"lib/\",\"isLibrary\":true,\"optimize\":false,\"sourceMap\":false}},\"scripts\":{\"clean\":\"shx mkdir -p lib && shx rm -rf lib\",\"build\":\"parcel build --target bin src/cli.ts\",\"package\":\"shx mkdir -p lib/cjs && shx echo '{ \\\"type\\\": \\\"commonjs\\\" }' > lib/cjs/package.json\",\"test\":\"jest -c ../../../node_modules/@wallet-standard/test-config/jest.config.ts --rootDir .\"},\"dependencies\":{\"chalk\":\"^5.4.1\",\"commander\":\"^13.1.0\"},\"devDependencies\":{\"parcel\":\"^2.14.4\",\"shx\":\"^0.4.0\"}}");
function $a9fe8b2a0a510d92$export$5cdc53290040c8ea(encodedContext) {
const decodedUrlString = atob(encodedContext);
return Object.fromEntries(new URLSearchParams(decodedUrlString).entries());
}
function $a9fe8b2a0a510d92$var$encodeValue(value) {
if (Array.isArray(value)) {
const commaSeparatedValues = value.map($a9fe8b2a0a510d92$var$encodeValue).join('%2C%20' /* ", " */ );
return '%5B' /* "[" */ + commaSeparatedValues + /* "]" */ '%5D';
} else if (typeof value === 'bigint') return `${value}n`;
else return encodeURIComponent(String(value != null && Object.getPrototypeOf(value) === null ? // Convert them before stringifying them.
{
...value
} : value));
}
function $a9fe8b2a0a510d92$var$encodeObjectContextEntry([key, value]) {
return `${key}=${$a9fe8b2a0a510d92$var$encodeValue(value)}`;
}
function $a9fe8b2a0a510d92$export$718674e070bbe277(context) {
const searchParamsString = Object.entries(context).map($a9fe8b2a0a510d92$var$encodeObjectContextEntry).join('&');
return btoa(searchParamsString);
}
/**
* To add a new error, follow the instructions at
* https://github.com/wallet-standard/wallet-standard/tree/master/packages/core/errors/#adding-a-new-error
*
* WARNING:
* - Don't remove error codes
* - Don't change or reorder error codes.
*
* Good naming conventions:
* - Prefixing common errors — e.g. under the same package — can be a good way to namespace them. E.g. All codec-related errors start with `WALLET_STANDARD_ERROR__ACCOUNT__`.
* - Use consistent names — e.g. choose `PDA` or `PROGRAM_DERIVED_ADDRESS` and stick with it. Ensure your names are consistent with existing error codes. The decision might have been made for you.
* - Recommended prefixes and suffixes:
* - `MALFORMED_`: Some input was not constructed properly. E.g. `MALFORMED_BASE58_ENCODED_ADDRESS`.
* - `INVALID_`: Some input is invalid (other than because it was MALFORMED). E.g. `INVALID_NUMBER_OF_BYTES`.
* - `EXPECTED_`: Some input was different than expected, no need to specify the "GOT" part unless necessary. E.g. `EXPECTED_DECODED_ACCOUNT`.
* - `_CANNOT_`: Some operation cannot be performed or some input cannot be used due to some condition. E.g. `CANNOT_DECODE_EMPTY_BYTE_ARRAY` or `PDA_CANNOT_END_WITH_PDA_MARKER`.
* - `_MUST_BE_`: Some condition must be true. E.g. `NONCE_TRANSACTION_FIRST_INSTRUCTION_MUST_BE_ADVANCE_NONCE`.
* - `_FAILED_TO_`: Tried to perform some operation and failed. E.g. `FAILED_TO_DECODE_ACCOUNT`.
* - `_NOT_FOUND`: Some operation lead to not finding something. E.g. `ACCOUNT_NOT_FOUND`.
* - `_OUT_OF_RANGE`: Some value is out of range. E.g. `ENUM_DISCRIMINATOR_OUT_OF_RANGE`.
* - `_EXCEEDED`: Some limit was exceeded. E.g. `PDA_MAX_SEED_LENGTH_EXCEEDED`.
* - `_MISMATCH`: Some elements do not match. E.g. `ENCODER_DECODER_FIXED_SIZE_MISMATCH`.
* - `_MISSING`: Some required input is missing. E.g. `TRANSACTION_FEE_PAYER_MISSING`.
* - `_UNIMPLEMENTED`: Some required component is not available in the environment. E.g. `SUBTLE_CRYPTO_VERIFY_FUNCTION_UNIMPLEMENTED`.
*/ // Registry-related errors.
// Reserve error codes in the range [3834000-3834999].
const $530d27d1911236a2$export$52bc1fe1597469c4 = 3834000;
const $530d27d1911236a2$export$2d71e59415bfcd93 = 3834001;
const $530d27d1911236a2$export$6aef8b8f5962a16 = 4001000;
const $530d27d1911236a2$export$4a71b6cd17f698 = 6160000;
const $530d27d1911236a2$export$37ca37218d933bd9 = 6160001;
const $530d27d1911236a2$export$82cec0501ccee60d = 6160002;
const $07e15bc1b3e9ee4c$export$7349a4bcf219522a = {
[(0, $530d27d1911236a2$export$4a71b6cd17f698)]: 'The wallet account $address does not support the chain `$chain`',
[(0, $530d27d1911236a2$export$37ca37218d933bd9)]: 'The wallet account $address does not support the `$featureName` feature',
[(0, $530d27d1911236a2$export$82cec0501ccee60d)]: "The wallet '$walletName' does not support the `$featureName` feature",
[(0, $530d27d1911236a2$export$2d71e59415bfcd93)]: "No account with address $address could be found in the '$walletName' wallet",
[(0, $530d27d1911236a2$export$52bc1fe1597469c4)]: "No underlying Wallet Standard wallet could be found for this handle. This can happen if the wallet associated with the handle has been unregistered.",
[(0, $530d27d1911236a2$export$6aef8b8f5962a16)]: 'The user rejected the request'
};
const $d3e987deabbb48c3$var$START_INDEX = 'i';
const $d3e987deabbb48c3$var$TYPE = 't';
function $d3e987deabbb48c3$export$19d2f6f104531a75(code, context = {}) {
const messageFormatString = (0, $07e15bc1b3e9ee4c$export$7349a4bcf219522a)[code];
if (messageFormatString.length === 0) return '';
let state;
function commitStateUpTo(endIndex) {
if (state[$d3e987deabbb48c3$var$TYPE] === 2) {
const variableName = messageFormatString.slice(state[$d3e987deabbb48c3$var$START_INDEX] + 1, endIndex);
fragments.push(variableName in context ? `${context[variableName]}` : `$${variableName}`);
} else if (state[$d3e987deabbb48c3$var$TYPE] === 1) fragments.push(messageFormatString.slice(state[$d3e987deabbb48c3$var$START_INDEX], endIndex));
}
const fragments = [];
messageFormatString.split('').forEach((char, ii)=>{
if (ii === 0) {
state = {
[$d3e987deabbb48c3$var$START_INDEX]: 0,
[$d3e987deabbb48c3$var$TYPE]: messageFormatString[0] === '\\' ? 0 : messageFormatString[0] === '$' ? 2 : 1
};
return;
}
let nextState;
switch(state[$d3e987deabbb48c3$var$TYPE]){
case 0:
nextState = {
[$d3e987deabbb48c3$var$START_INDEX]: ii,
[$d3e987deabbb48c3$var$TYPE]: 1
};
break;
case 1:
if (char === '\\') nextState = {
[$d3e987deabbb48c3$var$START_INDEX]: ii,
[$d3e987deabbb48c3$var$TYPE]: 0
};
else if (char === '$') nextState = {
[$d3e987deabbb48c3$var$START_INDEX]: ii,
[$d3e987deabbb48c3$var$TYPE]: 2
};
break;
case 2:
if (char === '\\') nextState = {
[$d3e987deabbb48c3$var$START_INDEX]: ii,
[$d3e987deabbb48c3$var$TYPE]: 0
};
else if (char === '$') nextState = {
[$d3e987deabbb48c3$var$START_INDEX]: ii,
[$d3e987deabbb48c3$var$TYPE]: 2
};
else if (!char.match(/\w/)) nextState = {
[$d3e987deabbb48c3$var$START_INDEX]: ii,
[$d3e987deabbb48c3$var$TYPE]: 1
};
break;
}
if (nextState) {
if (state !== nextState) commitStateUpTo(ii);
state = nextState;
}
});
commitStateUpTo();
return fragments.join('');
}
function $d3e987deabbb48c3$export$82f46aa4e6535a45(code, context = {}) {
if (process.env.NODE_ENV !== 'production') return $d3e987deabbb48c3$export$19d2f6f104531a75(code, context);
else {
let decodingAdviceMessage = `Wallet Standard error #${code}; Decode this error by running \`npx @wallet-standard/errors decode -- ${code}`;
if (Object.keys(context).length) /**
* DANGER: Be sure that the shell command is escaped in such a way that makes it
* impossible for someone to craft malicious context values that would result in
* an exploit against anyone who bindly copy/pastes it into their terminal.
*/ decodingAdviceMessage += ` '${(0, $a9fe8b2a0a510d92$export$718674e070bbe277)(context)}'`;
return `${decodingAdviceMessage}\``;
}
}
const $a177a3a21b521781$var$program = new (0, $3Sr93$Command)();
$a177a3a21b521781$var$program.name('@wallet-standard/errors').description('Decode Wallet Standard JavaScript errors thrown in production').version((0, $a2eff9e01820a9b9$exports.version));
$a177a3a21b521781$var$program.command('decode').description('Decode a `WalletStandardErrorCode` to a human-readable message').argument('<code>', 'numeric error code to decode', (rawCode)=>{
const code = parseInt(rawCode, 10);
if (isNaN(code) || `${code}` !== rawCode) throw new (0, $3Sr93$InvalidArgumentError)('It must be an integer');
if (!(code in (0, $07e15bc1b3e9ee4c$export$7349a4bcf219522a))) throw new (0, $3Sr93$InvalidArgumentError)('There exists no error with that code');
return code;
}).argument('[encodedContext]', 'encoded context to interpolate into the error message', (encodedContext)=>{
try {
return (0, $a9fe8b2a0a510d92$export$5cdc53290040c8ea)(encodedContext);
} catch (e) {
throw new (0, $3Sr93$InvalidArgumentError)('Encoded context malformed');
}
}).action((code, context)=>{
const message = (0, $d3e987deabbb48c3$export$19d2f6f104531a75)(code, context);
console.log(`
${(0, $3Sr93$chalk).bold((0, $3Sr93$chalk).rgb(154, 71, 255)('[') + (0, $3Sr93$chalk).rgb(144, 108, 244)('D') + (0, $3Sr93$chalk).rgb(134, 135, 233)('e') + (0, $3Sr93$chalk).rgb(122, 158, 221)('c') + (0, $3Sr93$chalk).rgb(110, 178, 209)('o') + (0, $3Sr93$chalk).rgb(95, 195, 196)('d') + (0, $3Sr93$chalk).rgb(79, 212, 181)('e') + (0, $3Sr93$chalk).rgb(57, 227, 166)('d') + (0, $3Sr93$chalk).rgb(19, 241, 149)(']')) + (0, $3Sr93$chalk).rgb(19, 241, 149)(' Wallet Standard error code #' + code)}
- ${message}`);
if (context) console.log(`
${(0, $3Sr93$chalk).yellowBright((0, $3Sr93$chalk).bold('[Context]'))}
${JSON.stringify(context, null, 4).split('\n').join('\n ')}`);
});
function $a177a3a21b521781$export$889ea624f2cb2c57(argv) {
$a177a3a21b521781$var$program.parse(argv);
}
export {$a177a3a21b521781$export$889ea624f2cb2c57 as run};

38
node_modules/@wallet-standard/errors/lib/esm/codes.js generated vendored Normal file
View File

@@ -0,0 +1,38 @@
/**
* To add a new error, follow the instructions at
* https://github.com/wallet-standard/wallet-standard/tree/master/packages/core/errors/#adding-a-new-error
*
* WARNING:
* - Don't remove error codes
* - Don't change or reorder error codes.
*
* Good naming conventions:
* - Prefixing common errors — e.g. under the same package — can be a good way to namespace them. E.g. All codec-related errors start with `WALLET_STANDARD_ERROR__ACCOUNT__`.
* - Use consistent names — e.g. choose `PDA` or `PROGRAM_DERIVED_ADDRESS` and stick with it. Ensure your names are consistent with existing error codes. The decision might have been made for you.
* - Recommended prefixes and suffixes:
* - `MALFORMED_`: Some input was not constructed properly. E.g. `MALFORMED_BASE58_ENCODED_ADDRESS`.
* - `INVALID_`: Some input is invalid (other than because it was MALFORMED). E.g. `INVALID_NUMBER_OF_BYTES`.
* - `EXPECTED_`: Some input was different than expected, no need to specify the "GOT" part unless necessary. E.g. `EXPECTED_DECODED_ACCOUNT`.
* - `_CANNOT_`: Some operation cannot be performed or some input cannot be used due to some condition. E.g. `CANNOT_DECODE_EMPTY_BYTE_ARRAY` or `PDA_CANNOT_END_WITH_PDA_MARKER`.
* - `_MUST_BE_`: Some condition must be true. E.g. `NONCE_TRANSACTION_FIRST_INSTRUCTION_MUST_BE_ADVANCE_NONCE`.
* - `_FAILED_TO_`: Tried to perform some operation and failed. E.g. `FAILED_TO_DECODE_ACCOUNT`.
* - `_NOT_FOUND`: Some operation lead to not finding something. E.g. `ACCOUNT_NOT_FOUND`.
* - `_OUT_OF_RANGE`: Some value is out of range. E.g. `ENUM_DISCRIMINATOR_OUT_OF_RANGE`.
* - `_EXCEEDED`: Some limit was exceeded. E.g. `PDA_MAX_SEED_LENGTH_EXCEEDED`.
* - `_MISMATCH`: Some elements do not match. E.g. `ENCODER_DECODER_FIXED_SIZE_MISMATCH`.
* - `_MISSING`: Some required input is missing. E.g. `TRANSACTION_FEE_PAYER_MISSING`.
* - `_UNIMPLEMENTED`: Some required component is not available in the environment. E.g. `SUBTLE_CRYPTO_VERIFY_FUNCTION_UNIMPLEMENTED`.
*/
// Registry-related errors.
// Reserve error codes in the range [3834000-3834999].
export const WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND = 3834000;
export const WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND = 3834001;
// User-related errors.
// Reserve error codes in the range [4001000-4001999].
export const WALLET_STANDARD_ERROR__USER__REQUEST_REJECTED = 4001000;
// Feature-related errors.
// Reserve error codes in the range [6160000-6160999].
export const WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED = 6160000;
export const WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED = 6160001;
export const WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED = 6160002;
//# sourceMappingURL=codes.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"codes.js","sourceRoot":"","sources":["../../src/codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,2BAA2B;AAC3B,sDAAsD;AACtD,MAAM,CAAC,MAAM,iDAAiD,GAAG,OAAgB,CAAC;AAClF,MAAM,CAAC,MAAM,yDAAyD,GAAG,OAAgB,CAAC;AAE1F,uBAAuB;AACvB,sDAAsD;AACtD,MAAM,CAAC,MAAM,6CAA6C,GAAG,OAAgB,CAAC;AAE9E,0BAA0B;AAC1B,sDAAsD;AACtD,MAAM,CAAC,MAAM,iEAAiE,GAAG,OAAgB,CAAC;AAClG,MAAM,CAAC,MAAM,qEAAqE,GAAG,OAAgB,CAAC;AACtG,MAAM,CAAC,MAAM,6DAA6D,GAAG,OAAgB,CAAC"}

View File

@@ -0,0 +1,28 @@
export function decodeEncodedContext(encodedContext) {
const decodedUrlString = atob(encodedContext);
return Object.fromEntries(new URLSearchParams(decodedUrlString).entries());
}
function encodeValue(value) {
if (Array.isArray(value)) {
const commaSeparatedValues = value.map(encodeValue).join('%2C%20' /* ", " */);
return '%5B' /* "[" */ + commaSeparatedValues + /* "]" */ '%5D';
}
else if (typeof value === 'bigint') {
return `${value}n`;
}
else {
return encodeURIComponent(String(value != null && Object.getPrototypeOf(value) === null
? // Plain objects with no prototype don't have a `toString` method.
// Convert them before stringifying them.
{ ...value }
: value));
}
}
function encodeObjectContextEntry([key, value]) {
return `${key}=${encodeValue(value)}`;
}
export function encodeContextObject(context) {
const searchParamsString = Object.entries(context).map(encodeObjectContextEntry).join('&');
return btoa(searchParamsString);
}
//# sourceMappingURL=context.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/context.ts"],"names":[],"mappings":"AA6CA,MAAM,UAAU,oBAAoB,CAAC,cAAsB;IACvD,MAAM,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC;IAC9C,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,eAAe,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,oBAAoB,GAAG,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC9E,OAAO,KAAK,CAAC,SAAS,GAAG,oBAAoB,GAAG,SAAS,CAAC,KAAK,CAAC;IACpE,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACnC,OAAO,GAAG,KAAK,GAAG,CAAC;IACvB,CAAC;SAAM,CAAC;QACJ,OAAO,kBAAkB,CACrB,MAAM,CACF,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,IAAI;YAClD,CAAC,CAAC,kEAAkE;gBAClE,yCAAyC;gBACzC,EAAE,GAAI,KAAgB,EAAE;YAC1B,CAAC,CAAC,KAAK,CACd,CACJ,CAAC;IACN,CAAC;AACL,CAAC;AAED,SAAS,wBAAwB,CAAC,CAAC,GAAG,EAAE,KAAK,CAAoB;IAC7D,OAAO,GAAG,GAAG,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAe;IAC/C,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3F,OAAO,IAAI,CAAC,kBAAkB,CAAC,CAAC;AACpC,CAAC"}

37
node_modules/@wallet-standard/errors/lib/esm/error.js generated vendored Normal file
View File

@@ -0,0 +1,37 @@
import { getErrorMessage } from './message-formatter.js';
export function isWalletStandardError(e, code) {
const isWalletStandardError = e instanceof Error && e.name === 'WalletStandardError';
if (isWalletStandardError) {
if (code !== undefined) {
return e.context.__code === code;
}
return true;
}
return false;
}
export class WalletStandardError extends Error {
constructor(...[code, contextAndErrorOptions]) {
let context;
let errorOptions;
if (contextAndErrorOptions) {
// If the `ErrorOptions` type ever changes, update this code.
const { cause, ...contextRest } = contextAndErrorOptions;
if (cause) {
errorOptions = { cause };
}
if (Object.keys(contextRest).length > 0) {
context = contextRest;
}
}
const message = getErrorMessage(code, context);
super(message, errorOptions);
this.context = {
__code: code,
...context,
};
// This is necessary so that `isWalletStandardError()` can identify a `WalletStandardError`
// without having to import the class for use in an `instanceof` check.
this.name = 'WalletStandardError';
}
}
//# sourceMappingURL=error.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/error.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,UAAU,qBAAqB,CACjC,CAAU,EACV,IAAiB;IAEjB,MAAM,qBAAqB,GAAG,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,IAAI,KAAK,qBAAqB,CAAC;IACrF,IAAI,qBAAqB,EAAE,CAAC;QACxB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACrB,OAAQ,CAAqC,CAAC,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC;QAC1E,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAUD,MAAM,OAAO,mBAA0F,SAAQ,KAAK;IAEhH,YACI,GAAG,CAAC,IAAI,EAAE,sBAAsB,CAKzB;QAEP,IAAI,OAA2D,CAAC;QAChE,IAAI,YAAsC,CAAC;QAC3C,IAAI,sBAAsB,EAAE,CAAC;YACzB,6DAA6D;YAC7D,MAAM,EAAE,KAAK,EAAE,GAAG,WAAW,EAAE,GAAG,sBAAsB,CAAC;YACzD,IAAI,KAAK,EAAE,CAAC;gBACR,YAAY,GAAG,EAAE,KAAK,EAAE,CAAC;YAC7B,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtC,OAAO,GAAG,WAAqD,CAAC;YACpE,CAAC;QACL,CAAC;QACD,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC/C,KAAK,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG;YACX,MAAM,EAAE,IAAI;YACZ,GAAG,OAAO;SACkC,CAAC;QACjD,2FAA2F;QAC3F,uEAAuE;QACvE,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACtC,CAAC;CACJ"}

View File

@@ -0,0 +1,4 @@
export * from './codes.js';
export * from './error.js';
export * from './stack-trace.js';
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}

View File

@@ -0,0 +1,91 @@
import { encodeContextObject } from './context.js';
import { WalletStandardErrorMessages } from './messages.js';
var StateType;
(function (StateType) {
StateType[StateType["EscapeSequence"] = 0] = "EscapeSequence";
StateType[StateType["Text"] = 1] = "Text";
StateType[StateType["Variable"] = 2] = "Variable";
})(StateType || (StateType = {}));
const START_INDEX = 'i';
const TYPE = 't';
export function getHumanReadableErrorMessage(code, context = {}) {
const messageFormatString = WalletStandardErrorMessages[code];
if (messageFormatString.length === 0) {
return '';
}
let state;
function commitStateUpTo(endIndex) {
if (state[TYPE] === StateType.Variable) {
const variableName = messageFormatString.slice(state[START_INDEX] + 1, endIndex);
fragments.push(variableName in context ? `${context[variableName]}` : `$${variableName}`);
}
else if (state[TYPE] === StateType.Text) {
fragments.push(messageFormatString.slice(state[START_INDEX], endIndex));
}
}
const fragments = [];
messageFormatString.split('').forEach((char, ii) => {
if (ii === 0) {
state = {
[START_INDEX]: 0,
[TYPE]: messageFormatString[0] === '\\'
? StateType.EscapeSequence
: messageFormatString[0] === '$'
? StateType.Variable
: StateType.Text,
};
return;
}
let nextState;
switch (state[TYPE]) {
case StateType.EscapeSequence:
nextState = { [START_INDEX]: ii, [TYPE]: StateType.Text };
break;
case StateType.Text:
if (char === '\\') {
nextState = { [START_INDEX]: ii, [TYPE]: StateType.EscapeSequence };
}
else if (char === '$') {
nextState = { [START_INDEX]: ii, [TYPE]: StateType.Variable };
}
break;
case StateType.Variable:
if (char === '\\') {
nextState = { [START_INDEX]: ii, [TYPE]: StateType.EscapeSequence };
}
else if (char === '$') {
nextState = { [START_INDEX]: ii, [TYPE]: StateType.Variable };
}
else if (!char.match(/\w/)) {
nextState = { [START_INDEX]: ii, [TYPE]: StateType.Text };
}
break;
}
if (nextState) {
if (state !== nextState) {
commitStateUpTo(ii);
}
state = nextState;
}
});
commitStateUpTo();
return fragments.join('');
}
export function getErrorMessage(code, context = {}) {
if (process.env.NODE_ENV !== 'production') {
return getHumanReadableErrorMessage(code, context);
}
else {
let decodingAdviceMessage = `Wallet Standard error #${code}; Decode this error by running \`npx @wallet-standard/errors decode -- ${code}`;
if (Object.keys(context).length) {
/**
* DANGER: Be sure that the shell command is escaped in such a way that makes it
* impossible for someone to craft malicious context values that would result in
* an exploit against anyone who bindly copy/pastes it into their terminal.
*/
decodingAdviceMessage += ` '${encodeContextObject(context)}'`;
}
return `${decodingAdviceMessage}\``;
}
}
//# sourceMappingURL=message-formatter.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"message-formatter.js","sourceRoot":"","sources":["../../src/message-formatter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAE5D,IAAW,SAIV;AAJD,WAAW,SAAS;IAChB,6DAAc,CAAA;IACd,yCAAI,CAAA;IACJ,iDAAQ,CAAA;AACZ,CAAC,EAJU,SAAS,KAAT,SAAS,QAInB;AAKD,MAAM,WAAW,GAAG,GAAG,CAAC;AACxB,MAAM,IAAI,GAAG,GAAG,CAAC;AAEjB,MAAM,UAAU,4BAA4B,CACxC,IAAgB,EAChB,UAAkB,EAAE;IAEpB,MAAM,mBAAmB,GAAG,2BAA2B,CAAC,IAAI,CAAC,CAAC;IAC9D,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,CAAC;IACd,CAAC;IACD,IAAI,KAAY,CAAC;IACjB,SAAS,eAAe,CAAC,QAAiB;QACtC,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,QAAQ,EAAE,CAAC;YACrC,MAAM,YAAY,GAAG,mBAAmB,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;YACjF,SAAS,CAAC,IAAI,CACV,YAAY,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAoC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,YAAY,EAAE,CACpG,CAAC;QACN,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YACxC,SAAS,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC5E,CAAC;IACL,CAAC;IACD,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE;QAC/C,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;YACX,KAAK,GAAG;gBACJ,CAAC,WAAW,CAAC,EAAE,CAAC;gBAChB,CAAC,IAAI,CAAC,EACF,mBAAmB,CAAC,CAAC,CAAC,KAAK,IAAI;oBAC3B,CAAC,CAAC,SAAS,CAAC,cAAc;oBAC1B,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,KAAK,GAAG;wBAC9B,CAAC,CAAC,SAAS,CAAC,QAAQ;wBACpB,CAAC,CAAC,SAAS,CAAC,IAAI;aAC7B,CAAC;YACF,OAAO;QACX,CAAC;QACD,IAAI,SAAS,CAAC;QACd,QAAQ,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAClB,KAAK,SAAS,CAAC,cAAc;gBACzB,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC;gBAC1D,MAAM;YACV,KAAK,SAAS,CAAC,IAAI;gBACf,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBAChB,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,cAAc,EAAE,CAAC;gBACxE,CAAC;qBAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;oBACtB,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC;gBAClE,CAAC;gBACD,MAAM;YACV,KAAK,SAAS,CAAC,QAAQ;gBACnB,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBAChB,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,cAAc,EAAE,CAAC;gBACxE,CAAC;qBAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;oBACtB,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC;gBAClE,CAAC;qBAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC3B,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC;gBAC9D,CAAC;gBACD,MAAM;QACd,CAAC;QACD,IAAI,SAAS,EAAE,CAAC;YACZ,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACtB,eAAe,CAAC,EAAE,CAAC,CAAC;YACxB,CAAC;YACD,KAAK,GAAG,SAAS,CAAC;QACtB,CAAC;IACL,CAAC,CAAC,CAAC;IACH,eAAe,EAAE,CAAC;IAClB,OAAO,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,eAAe,CAC3B,IAAgB,EAChB,UAAkB,EAAE;IAEpB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QACxC,OAAO,4BAA4B,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC;SAAM,CAAC;QACJ,IAAI,qBAAqB,GAAG,0BAA0B,IAAI,0EAA0E,IAAI,EAAE,CAAC;QAC3I,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;YAC9B;;;;eAIG;YACH,qBAAqB,IAAI,KAAK,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC;QAClE,CAAC;QACD,OAAO,GAAG,qBAAqB,IAAI,CAAC;IACxC,CAAC;AACL,CAAC"}

View File

@@ -0,0 +1,18 @@
import { WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED, WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED, WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED, WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND, WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND, WALLET_STANDARD_ERROR__USER__REQUEST_REJECTED, } from './codes.js';
/**
* To add a new error, follow the instructions at
* https://github.com/wallet-standard/wallet-standard/tree/master/packages/core/errors#adding-a-new-error
*
* WARNING:
* - Don't change the meaning of an error message.
*/
export const WalletStandardErrorMessages = {
[WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED]: 'The wallet account $address does not support the chain `$chain`',
[WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED]: 'The wallet account $address does not support the `$featureName` feature',
[WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED]: "The wallet '$walletName' does not support the `$featureName` feature",
[WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND]: "No account with address $address could be found in the '$walletName' wallet",
[WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND]: 'No underlying Wallet Standard wallet could be found for this handle. This can happen if ' +
'the wallet associated with the handle has been unregistered.',
[WALLET_STANDARD_ERROR__USER__REQUEST_REJECTED]: 'The user rejected the request',
};
//# sourceMappingURL=messages.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/messages.ts"],"names":[],"mappings":"AACA,OAAO,EACH,iEAAiE,EACjE,qEAAqE,EACrE,6DAA6D,EAC7D,yDAAyD,EACzD,iDAAiD,EACjD,6CAA6C,GAChD,MAAM,YAAY,CAAC;AAEpB;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAInC;IACD,CAAC,iEAAiE,CAAC,EAC/D,iEAAiE;IACrE,CAAC,qEAAqE,CAAC,EACnE,yEAAyE;IAC7E,CAAC,6DAA6D,CAAC,EAC3D,sEAAsE;IAC1E,CAAC,yDAAyD,CAAC,EACvD,6EAA6E;IACjF,CAAC,iDAAiD,CAAC,EAC/C,0FAA0F;QAC1F,8DAA8D;IAClE,CAAC,6CAA6C,CAAC,EAAE,+BAA+B;CACnF,CAAC"}

View File

@@ -0,0 +1,6 @@
export function safeCaptureStackTrace(...args) {
if ('captureStackTrace' in Error && typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(...args);
}
}
//# sourceMappingURL=stack-trace.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stack-trace.js","sourceRoot":"","sources":["../../src/stack-trace.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,qBAAqB,CAAC,GAAG,IAAgD;IACrF,IAAI,mBAAmB,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,iBAAiB,KAAK,UAAU,EAAE,CAAC;QAChF,KAAK,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAC,CAAC;IACrC,CAAC;AACL,CAAC"}

View File

@@ -0,0 +1 @@
{"root":["../src/codes.ts","../src/context.ts","../src/error.ts","../src/index.ts","../src/message-formatter.ts","../src/messages.ts","../src/stack-trace.ts"],"version":"5.8.3"}

View File

@@ -0,0 +1 @@
{"root":["../src/codes.ts","../src/context.ts","../src/error.ts","../src/index.ts","../src/message-formatter.ts","../src/messages.ts","../src/stack-trace.ts"],"version":"5.8.3"}

View File

@@ -0,0 +1,49 @@
/**
* To add a new error, follow the instructions at
* https://github.com/wallet-standard/wallet-standard/tree/master/packages/core/errors/#adding-a-new-error
*
* WARNING:
* - Don't remove error codes
* - Don't change or reorder error codes.
*
* Good naming conventions:
* - Prefixing common errors — e.g. under the same package — can be a good way to namespace them. E.g. All codec-related errors start with `WALLET_STANDARD_ERROR__ACCOUNT__`.
* - Use consistent names — e.g. choose `PDA` or `PROGRAM_DERIVED_ADDRESS` and stick with it. Ensure your names are consistent with existing error codes. The decision might have been made for you.
* - Recommended prefixes and suffixes:
* - `MALFORMED_`: Some input was not constructed properly. E.g. `MALFORMED_BASE58_ENCODED_ADDRESS`.
* - `INVALID_`: Some input is invalid (other than because it was MALFORMED). E.g. `INVALID_NUMBER_OF_BYTES`.
* - `EXPECTED_`: Some input was different than expected, no need to specify the "GOT" part unless necessary. E.g. `EXPECTED_DECODED_ACCOUNT`.
* - `_CANNOT_`: Some operation cannot be performed or some input cannot be used due to some condition. E.g. `CANNOT_DECODE_EMPTY_BYTE_ARRAY` or `PDA_CANNOT_END_WITH_PDA_MARKER`.
* - `_MUST_BE_`: Some condition must be true. E.g. `NONCE_TRANSACTION_FIRST_INSTRUCTION_MUST_BE_ADVANCE_NONCE`.
* - `_FAILED_TO_`: Tried to perform some operation and failed. E.g. `FAILED_TO_DECODE_ACCOUNT`.
* - `_NOT_FOUND`: Some operation lead to not finding something. E.g. `ACCOUNT_NOT_FOUND`.
* - `_OUT_OF_RANGE`: Some value is out of range. E.g. `ENUM_DISCRIMINATOR_OUT_OF_RANGE`.
* - `_EXCEEDED`: Some limit was exceeded. E.g. `PDA_MAX_SEED_LENGTH_EXCEEDED`.
* - `_MISMATCH`: Some elements do not match. E.g. `ENCODER_DECODER_FIXED_SIZE_MISMATCH`.
* - `_MISSING`: Some required input is missing. E.g. `TRANSACTION_FEE_PAYER_MISSING`.
* - `_UNIMPLEMENTED`: Some required component is not available in the environment. E.g. `SUBTLE_CRYPTO_VERIFY_FUNCTION_UNIMPLEMENTED`.
*/
export declare const WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND: 3834000;
export declare const WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND: 3834001;
export declare const WALLET_STANDARD_ERROR__USER__REQUEST_REJECTED: 4001000;
export declare const WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED: 6160000;
export declare const WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED: 6160001;
export declare const WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED: 6160002;
/**
* A union of every Wallet Standard error code
*
* You might be wondering why this is not a TypeScript enum or const enum.
*
* One of the goals of this library is to enable people to use some or none of it without having to
* bundle all of it.
*
* If we made the set of error codes an enum then anyone who imported it (even if to only use a
* single error code) would be forced to bundle every code and its label.
*
* Const enums appear to solve this problem by letting the compiler inline only the codes that are
* actually used. Unfortunately exporting ambient (const) enums from a library like
* `@wallet-standard/errors` is not safe, for a variety of reasons covered here:
* https://stackoverflow.com/a/28818850
*/
export type WalletStandardErrorCode = typeof WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED | typeof WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED | typeof WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED | typeof WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND | typeof WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND | typeof WALLET_STANDARD_ERROR__USER__REQUEST_REJECTED;
//# sourceMappingURL=codes.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"codes.d.ts","sourceRoot":"","sources":["../../src/codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,eAAO,MAAM,iDAAiD,EAAG,OAAgB,CAAC;AAClF,eAAO,MAAM,yDAAyD,EAAG,OAAgB,CAAC;AAI1F,eAAO,MAAM,6CAA6C,EAAG,OAAgB,CAAC;AAI9E,eAAO,MAAM,iEAAiE,EAAG,OAAgB,CAAC;AAClG,eAAO,MAAM,qEAAqE,EAAG,OAAgB,CAAC;AACtG,eAAO,MAAM,6DAA6D,EAAG,OAAgB,CAAC;AAE9F;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,uBAAuB,GAC7B,OAAO,iEAAiE,GACxE,OAAO,qEAAqE,GAC5E,OAAO,6DAA6D,GACpE,OAAO,yDAAyD,GAChE,OAAO,iDAAiD,GACxD,OAAO,6CAA6C,CAAC"}

View File

@@ -0,0 +1,40 @@
import type { WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED, WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED, WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND, WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED, WalletStandardErrorCode } from './codes.js';
type DefaultUnspecifiedErrorContextToUndefined<T> = {
[P in WalletStandardErrorCode]: P extends keyof T ? T[P] : undefined;
};
/**
* To add a new error, follow the instructions at
* https://github.com/wallet-standard/wallet-standard/tree/master/packages/core/errors/#adding-a-new-error
*
* WARNING:
* - Don't change or remove members of an error's context.
*/
export type WalletStandardErrorContext = DefaultUnspecifiedErrorContextToUndefined<{
[WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED]: {
address: string;
chain: string;
featureName: string;
supportedChains: string[];
supportedFeatures: string[];
};
[WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED]: {
address: string;
featureName: string;
supportedChains: string[];
supportedFeatures: string[];
};
[WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED]: {
featureName: string;
supportedFeatures: string[];
supportedChains: string[];
walletName: string;
};
[WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND]: {
address: string;
walletName: string;
};
}>;
export declare function decodeEncodedContext(encodedContext: string): object;
export declare function encodeContextObject(context: object): string;
export {};
//# sourceMappingURL=context.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,iEAAiE,EACjE,qEAAqE,EACrE,yDAAyD,EACzD,6DAA6D,EAC7D,uBAAuB,EAC1B,MAAM,YAAY,CAAC;AAEpB,KAAK,yCAAyC,CAAC,CAAC,IAAI;KAC/C,CAAC,IAAI,uBAAuB,GAAG,CAAC,SAAS,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS;CACvE,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,0BAA0B,GAAG,yCAAyC,CAAC;IAC/E,CAAC,iEAAiE,CAAC,EAAE;QACjE,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAC;KAC/B,CAAC;IACF,CAAC,qEAAqE,CAAC,EAAE;QACrE,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAC;KAC/B,CAAC;IACF,CAAC,6DAA6D,CAAC,EAAE;QAC7D,WAAW,EAAE,MAAM,CAAC;QACpB,iBAAiB,EAAE,MAAM,EAAE,CAAC;QAC5B,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,UAAU,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,CAAC,yDAAyD,CAAC,EAAE;QACzD,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;KACtB,CAAC;CACL,CAAC,CAAC;AAEH,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAGnE;AAyBD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG3D"}

View File

@@ -0,0 +1,17 @@
import type { WalletStandardErrorCode } from './codes.js';
import type { WalletStandardErrorContext } from './context.js';
export declare function isWalletStandardError<TErrorCode extends WalletStandardErrorCode>(e: unknown, code?: TErrorCode): e is WalletStandardError<TErrorCode>;
type WalletStandardErrorCodedContext = Readonly<{
[P in WalletStandardErrorCode]: (WalletStandardErrorContext[P] extends undefined ? object : WalletStandardErrorContext[P]) & {
__code: P;
};
}>;
export declare class WalletStandardError<TErrorCode extends WalletStandardErrorCode = WalletStandardErrorCode> extends Error {
readonly context: WalletStandardErrorCodedContext[TErrorCode];
constructor(...[code, contextAndErrorOptions]: WalletStandardErrorContext[TErrorCode] extends undefined ? [code: TErrorCode, errorOptions?: ErrorOptions | undefined] : [
code: TErrorCode,
contextAndErrorOptions: WalletStandardErrorContext[TErrorCode] & (ErrorOptions | undefined)
]);
}
export {};
//# sourceMappingURL=error.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAG/D,wBAAgB,qBAAqB,CAAC,UAAU,SAAS,uBAAuB,EAC5E,CAAC,EAAE,OAAO,EACV,IAAI,CAAC,EAAE,UAAU,GAClB,CAAC,IAAI,mBAAmB,CAAC,UAAU,CAAC,CAStC;AAED,KAAK,+BAA+B,GAAG,QAAQ,CAAC;KAC3C,CAAC,IAAI,uBAAuB,GAAG,CAAC,0BAA0B,CAAC,CAAC,CAAC,SAAS,SAAS,GAC1E,MAAM,GACN,0BAA0B,CAAC,CAAC,CAAC,CAAC,GAAG;QACnC,MAAM,EAAE,CAAC,CAAC;KACb;CACJ,CAAC,CAAC;AAEH,qBAAa,mBAAmB,CAAC,UAAU,SAAS,uBAAuB,GAAG,uBAAuB,CAAE,SAAQ,KAAK;IAChH,QAAQ,CAAC,OAAO,EAAE,+BAA+B,CAAC,UAAU,CAAC,CAAC;gBAE1D,GAAG,CAAC,IAAI,EAAE,sBAAsB,CAAC,EAAE,0BAA0B,CAAC,UAAU,CAAC,SAAS,SAAS,GACrF,CAAC,IAAI,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC,GAC3D;QACI,IAAI,EAAE,UAAU;QAChB,sBAAsB,EAAE,0BAA0B,CAAC,UAAU,CAAC,GAAG,CAAC,YAAY,GAAG,SAAS,CAAC;KAC9F;CAwBd"}

View File

@@ -0,0 +1,4 @@
export * from './codes.js';
export * from './error.js';
export * from './stack-trace.js';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}

View File

@@ -0,0 +1,4 @@
import type { WalletStandardErrorCode } from './codes.js';
export declare function getHumanReadableErrorMessage<TErrorCode extends WalletStandardErrorCode>(code: TErrorCode, context?: object): string;
export declare function getErrorMessage<TErrorCode extends WalletStandardErrorCode>(code: TErrorCode, context?: object): string;
//# sourceMappingURL=message-formatter.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"message-formatter.d.ts","sourceRoot":"","sources":["../../src/message-formatter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAgB1D,wBAAgB,4BAA4B,CAAC,UAAU,SAAS,uBAAuB,EACnF,IAAI,EAAE,UAAU,EAChB,OAAO,GAAE,MAAW,GACrB,MAAM,CA6DR;AAED,wBAAgB,eAAe,CAAC,UAAU,SAAS,uBAAuB,EACtE,IAAI,EAAE,UAAU,EAChB,OAAO,GAAE,MAAW,GACrB,MAAM,CAeR"}

View File

@@ -0,0 +1,12 @@
import type { WalletStandardErrorCode } from './codes.js';
/**
* To add a new error, follow the instructions at
* https://github.com/wallet-standard/wallet-standard/tree/master/packages/core/errors#adding-a-new-error
*
* WARNING:
* - Don't change the meaning of an error message.
*/
export declare const WalletStandardErrorMessages: Readonly<{
[P in WalletStandardErrorCode]: string;
}>;
//# sourceMappingURL=messages.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAU1D;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,EAAE,QAAQ,CAAC;KAG9C,CAAC,IAAI,uBAAuB,GAAG,MAAM;CACzC,CAaA,CAAC"}

View File

@@ -0,0 +1,2 @@
export declare function safeCaptureStackTrace(...args: Parameters<typeof Error.captureStackTrace>): void;
//# sourceMappingURL=stack-trace.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stack-trace.d.ts","sourceRoot":"","sources":["../../src/stack-trace.ts"],"names":[],"mappings":"AAAA,wBAAgB,qBAAqB,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAI/F"}

View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,83 @@
{
"name": "chalk",
"version": "5.6.2",
"description": "Terminal string styling done right",
"license": "MIT",
"repository": "chalk/chalk",
"funding": "https://github.com/chalk/chalk?sponsor=1",
"type": "module",
"main": "./source/index.js",
"exports": "./source/index.js",
"imports": {
"#ansi-styles": "./source/vendor/ansi-styles/index.js",
"#supports-color": {
"node": "./source/vendor/supports-color/index.js",
"default": "./source/vendor/supports-color/browser.js"
}
},
"types": "./source/index.d.ts",
"sideEffects": false,
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
"scripts": {
"test": "xo && c8 ava && tsd",
"bench": "matcha benchmark.js"
},
"files": [
"source",
"!source/index.test-d.ts"
],
"keywords": [
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"string",
"ansi",
"style",
"styles",
"tty",
"formatting",
"rgb",
"256",
"shell",
"xterm",
"log",
"logging",
"command-line",
"text"
],
"devDependencies": {
"@types/node": "^16.11.10",
"ava": "^3.15.0",
"c8": "^7.10.0",
"color-convert": "^2.0.1",
"execa": "^6.0.0",
"log-update": "^5.0.0",
"matcha": "^0.7.0",
"tsd": "^0.19.0",
"xo": "^0.57.0",
"yoctodelay": "^2.0.0"
},
"xo": {
"rules": {
"unicorn/prefer-string-slice": "off",
"@typescript-eslint/consistent-type-imports": "off",
"@typescript-eslint/consistent-type-exports": "off",
"@typescript-eslint/consistent-type-definitions": "off",
"unicorn/expiring-todo-comments": "off"
}
},
"c8": {
"reporter": [
"text",
"lcov"
],
"exclude": [
"source/vendor"
]
}
}

View File

@@ -0,0 +1,297 @@
<h1 align="center">
<br>
<br>
<img width="320" src="media/logo.svg" alt="Chalk">
<br>
<br>
<br>
</h1>
> Terminal string styling done right
[![Coverage Status](https://codecov.io/gh/chalk/chalk/branch/main/graph/badge.svg)](https://codecov.io/gh/chalk/chalk)
[![npm dependents](https://badgen.net/npm/dependents/chalk)](https://www.npmjs.com/package/chalk?activeTab=dependents)
[![Downloads](https://badgen.net/npm/dt/chalk)](https://www.npmjs.com/package/chalk)
![](media/screenshot.png)
## Info
- [Why not switch to a smaller coloring package?](https://github.com/chalk/chalk?tab=readme-ov-file#why-not-switch-to-a-smaller-coloring-package)
- See [yoctocolors](https://github.com/sindresorhus/yoctocolors) for a smaller alternative
## Highlights
- Expressive API
- Highly performant
- No dependencies
- Ability to nest styles
- [256/Truecolor color support](#256-and-truecolor-color-support)
- Auto-detects color support
- Doesn't extend `String.prototype`
- Clean and focused
- Actively maintained
- [Used by ~115,000 packages](https://www.npmjs.com/browse/depended/chalk) as of July 4, 2024
## Install
```sh
npm install chalk
```
**IMPORTANT:** Chalk 5 is ESM. If you want to use Chalk with TypeScript or a build tool, you will probably want to use Chalk 4 for now. [Read more.](https://github.com/chalk/chalk/releases/tag/v5.0.0)
## Usage
```js
import chalk from 'chalk';
console.log(chalk.blue('Hello world!'));
```
Chalk comes with an easy to use composable API where you just chain and nest the styles you want.
```js
import chalk from 'chalk';
const log = console.log;
// Combine styled and normal strings
log(chalk.blue('Hello') + ' World' + chalk.red('!'));
// Compose multiple styles using the chainable API
log(chalk.blue.bgRed.bold('Hello world!'));
// Pass in multiple arguments
log(chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz'));
// Nest styles
log(chalk.red('Hello', chalk.underline.bgBlue('world') + '!'));
// Nest styles of the same type even (color, underline, background)
log(chalk.green(
'I am a green line ' +
chalk.blue.underline.bold('with a blue substring') +
' that becomes green again!'
));
// ES2015 template literal
log(`
CPU: ${chalk.red('90%')}
RAM: ${chalk.green('40%')}
DISK: ${chalk.yellow('70%')}
`);
// Use RGB colors in terminal emulators that support it.
log(chalk.rgb(123, 45, 67).underline('Underlined reddish color'));
log(chalk.hex('#DEADED').bold('Bold gray!'));
```
Easily define your own themes:
```js
import chalk from 'chalk';
const error = chalk.bold.red;
const warning = chalk.hex('#FFA500'); // Orange color
console.log(error('Error!'));
console.log(warning('Warning!'));
```
Take advantage of console.log [string substitution](https://nodejs.org/docs/latest/api/console.html#console_console_log_data_args):
```js
import chalk from 'chalk';
const name = 'Sindre';
console.log(chalk.green('Hello %s'), name);
//=> 'Hello Sindre'
```
## API
### chalk.`<style>[.<style>...](string, [string...])`
Example: `chalk.red.bold.underline('Hello', 'world');`
Chain [styles](#styles) and call the last one as a method with a string argument. Order doesn't matter, and later styles take precedent in case of a conflict. This simply means that `chalk.red.yellow.green` is equivalent to `chalk.green`.
Multiple arguments will be separated by space.
### chalk.level
Specifies the level of color support.
Color support is automatically detected, but you can override it by setting the `level` property. You should however only do this in your own code as it applies globally to all Chalk consumers.
If you need to change this in a reusable module, create a new instance:
```js
import {Chalk} from 'chalk';
const customChalk = new Chalk({level: 0});
```
| Level | Description |
| :---: | :--- |
| `0` | All colors disabled |
| `1` | Basic color support (16 colors) |
| `2` | 256 color support |
| `3` | Truecolor support (16 million colors) |
### supportsColor
Detect whether the terminal [supports color](https://github.com/chalk/supports-color). Used internally and handled for you, but exposed for convenience.
Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, use the environment variable `FORCE_COLOR=1` (level 1), `FORCE_COLOR=2` (level 2), or `FORCE_COLOR=3` (level 3) to forcefully enable color, or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
### chalkStderr and supportsColorStderr
`chalkStderr` contains a separate instance configured with color support detected for `stderr` stream instead of `stdout`. Override rules from `supportsColor` apply to this too. `supportsColorStderr` is exposed for convenience.
### modifierNames, foregroundColorNames, backgroundColorNames, and colorNames
All supported style strings are exposed as an array of strings for convenience. `colorNames` is the combination of `foregroundColorNames` and `backgroundColorNames`.
This can be useful if you wrap Chalk and need to validate input:
```js
import {modifierNames, foregroundColorNames} from 'chalk';
console.log(modifierNames.includes('bold'));
//=> true
console.log(foregroundColorNames.includes('pink'));
//=> false
```
## Styles
### Modifiers
- `reset` - Reset the current style.
- `bold` - Make the text bold.
- `dim` - Make the text have lower opacity.
- `italic` - Make the text italic. *(Not widely supported)*
- `underline` - Put a horizontal line below the text. *(Not widely supported)*
- `overline` - Put a horizontal line above the text. *(Not widely supported)*
- `inverse`- Invert background and foreground colors.
- `hidden` - Print the text but make it invisible.
- `strikethrough` - Puts a horizontal line through the center of the text. *(Not widely supported)*
- `visible`- Print the text only when Chalk has a color level above zero. Can be useful for things that are purely cosmetic.
### Colors
- `black`
- `red`
- `green`
- `yellow`
- `blue`
- `magenta`
- `cyan`
- `white`
- `blackBright` (alias: `gray`, `grey`)
- `redBright`
- `greenBright`
- `yellowBright`
- `blueBright`
- `magentaBright`
- `cyanBright`
- `whiteBright`
### Background colors
- `bgBlack`
- `bgRed`
- `bgGreen`
- `bgYellow`
- `bgBlue`
- `bgMagenta`
- `bgCyan`
- `bgWhite`
- `bgBlackBright` (alias: `bgGray`, `bgGrey`)
- `bgRedBright`
- `bgGreenBright`
- `bgYellowBright`
- `bgBlueBright`
- `bgMagentaBright`
- `bgCyanBright`
- `bgWhiteBright`
## 256 and Truecolor color support
Chalk supports 256 colors and [Truecolor](https://github.com/termstandard/colors) (16 million colors) on supported terminal apps.
Colors are downsampled from 16 million RGB values to an ANSI color format that is supported by the terminal emulator (or by specifying `{level: n}` as a Chalk option). For example, Chalk configured to run at level 1 (basic color support) will downsample an RGB value of #FF0000 (red) to 31 (ANSI escape for red).
Examples:
- `chalk.hex('#DEADED').underline('Hello, world!')`
- `chalk.rgb(15, 100, 204).inverse('Hello!')`
Background versions of these models are prefixed with `bg` and the first level of the module capitalized (e.g. `hex` for foreground colors and `bgHex` for background colors).
- `chalk.bgHex('#DEADED').underline('Hello, world!')`
- `chalk.bgRgb(15, 100, 204).inverse('Hello!')`
The following color models can be used:
- [`rgb`](https://en.wikipedia.org/wiki/RGB_color_model) - Example: `chalk.rgb(255, 136, 0).bold('Orange!')`
- [`hex`](https://en.wikipedia.org/wiki/Web_colors#Hex_triplet) - Example: `chalk.hex('#FF8800').bold('Orange!')`
- [`ansi256`](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) - Example: `chalk.bgAnsi256(194)('Honeydew, more or less')`
## Browser support
Since Chrome 69, ANSI escape codes are natively supported in the developer console.
## Windows
If you're on Windows, do yourself a favor and use [Windows Terminal](https://github.com/microsoft/terminal) instead of `cmd.exe`.
## FAQ
### Why not switch to a smaller coloring package?
Chalk may be larger, but there is a reason for that. It offers a more user-friendly API, well-documented types, supports millions of colors, and covers edge cases that smaller alternatives miss. Chalk is mature, reliable, and built to last.
But beyond the technical aspects, there's something more critical: trust and long-term maintenance. I have been active in open source for over a decade, and I'm committed to keeping Chalk maintained. Smaller packages might seem appealing now, but there's no guarantee they will be around for the long term, or that they won't become malicious over time.
Chalk is also likely already in your dependency tree (since 100K+ packages depend on it), so switching wont save space—in fact, it might increase it. npm deduplicates dependencies, so multiple Chalk instances turn into one, but adding another package alongside it will increase your overall size.
If the goal is to clean up the ecosystem, switching away from Chalk wont even make a dent. The real problem lies with packages that have very deep dependency trees (for example, those including a lot of polyfills). Chalk has no dependencies. It's better to focus on impactful changes rather than minor optimizations.
If absolute package size is important to you, I also maintain [yoctocolors](https://github.com/sindresorhus/yoctocolors), one of the smallest color packages out there.
*\- [Sindre](https://github.com/sindresorhus)*
### But the smaller coloring package has benchmarks showing it is faster
[Micro-benchmarks are flawed](https://sindresorhus.com/blog/micro-benchmark-fallacy) because they measure performance in unrealistic, isolated scenarios, often giving a distorted view of real-world performance. Don't believe marketing fluff. All the coloring packages are more than fast enough.
## Related
- [chalk-template](https://github.com/chalk/chalk-template) - [Tagged template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates) support for this module
- [chalk-cli](https://github.com/chalk/chalk-cli) - CLI for this module
- [ansi-styles](https://github.com/chalk/ansi-styles) - ANSI escape codes for styling strings in the terminal
- [supports-color](https://github.com/chalk/supports-color) - Detect whether a terminal supports color
- [strip-ansi](https://github.com/chalk/strip-ansi) - Strip ANSI escape codes
- [strip-ansi-stream](https://github.com/chalk/strip-ansi-stream) - Strip ANSI escape codes from a stream
- [has-ansi](https://github.com/chalk/has-ansi) - Check if a string has ANSI escape codes
- [ansi-regex](https://github.com/chalk/ansi-regex) - Regular expression for matching ANSI escape codes
- [wrap-ansi](https://github.com/chalk/wrap-ansi) - Wordwrap a string with ANSI escape codes
- [slice-ansi](https://github.com/chalk/slice-ansi) - Slice a string with ANSI escape codes
- [color-convert](https://github.com/qix-/color-convert) - Converts colors between different models
- [chalk-animation](https://github.com/bokub/chalk-animation) - Animate strings in the terminal
- [gradient-string](https://github.com/bokub/gradient-string) - Apply color gradients to strings
- [chalk-pipe](https://github.com/LitoMore/chalk-pipe) - Create chalk style schemes with simpler style strings
- [terminal-link](https://github.com/sindresorhus/terminal-link) - Create clickable links in the terminal
*(Not accepting additional entries)*
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)

View File

@@ -0,0 +1,325 @@
// TODO: Make it this when TS suports that.
// import {ModifierName, ForegroundColor, BackgroundColor, ColorName} from '#ansi-styles';
// import {ColorInfo, ColorSupportLevel} from '#supports-color';
import {
ModifierName,
ForegroundColorName,
BackgroundColorName,
ColorName,
} from './vendor/ansi-styles/index.js';
import {ColorInfo, ColorSupportLevel} from './vendor/supports-color/index.js';
export interface Options {
/**
Specify the color support for Chalk.
By default, color support is automatically detected based on the environment.
Levels:
- `0` - All colors disabled.
- `1` - Basic 16 colors support.
- `2` - ANSI 256 colors support.
- `3` - Truecolor 16 million colors support.
*/
readonly level?: ColorSupportLevel;
}
/**
Return a new Chalk instance.
*/
export const Chalk: new (options?: Options) => ChalkInstance; // eslint-disable-line @typescript-eslint/naming-convention
export interface ChalkInstance {
(...text: unknown[]): string;
/**
The color support for Chalk.
By default, color support is automatically detected based on the environment.
Levels:
- `0` - All colors disabled.
- `1` - Basic 16 colors support.
- `2` - ANSI 256 colors support.
- `3` - Truecolor 16 million colors support.
*/
level: ColorSupportLevel;
/**
Use RGB values to set text color.
@example
```
import chalk from 'chalk';
chalk.rgb(222, 173, 237);
```
*/
rgb: (red: number, green: number, blue: number) => this;
/**
Use HEX value to set text color.
@param color - Hexadecimal value representing the desired color.
@example
```
import chalk from 'chalk';
chalk.hex('#DEADED');
```
*/
hex: (color: string) => this;
/**
Use an [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set text color.
@example
```
import chalk from 'chalk';
chalk.ansi256(201);
```
*/
ansi256: (index: number) => this;
/**
Use RGB values to set background color.
@example
```
import chalk from 'chalk';
chalk.bgRgb(222, 173, 237);
```
*/
bgRgb: (red: number, green: number, blue: number) => this;
/**
Use HEX value to set background color.
@param color - Hexadecimal value representing the desired color.
@example
```
import chalk from 'chalk';
chalk.bgHex('#DEADED');
```
*/
bgHex: (color: string) => this;
/**
Use a [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set background color.
@example
```
import chalk from 'chalk';
chalk.bgAnsi256(201);
```
*/
bgAnsi256: (index: number) => this;
/**
Modifier: Reset the current style.
*/
readonly reset: this;
/**
Modifier: Make the text bold.
*/
readonly bold: this;
/**
Modifier: Make the text have lower opacity.
*/
readonly dim: this;
/**
Modifier: Make the text italic. *(Not widely supported)*
*/
readonly italic: this;
/**
Modifier: Put a horizontal line below the text. *(Not widely supported)*
*/
readonly underline: this;
/**
Modifier: Put a horizontal line above the text. *(Not widely supported)*
*/
readonly overline: this;
/**
Modifier: Invert background and foreground colors.
*/
readonly inverse: this;
/**
Modifier: Print the text but make it invisible.
*/
readonly hidden: this;
/**
Modifier: Puts a horizontal line through the center of the text. *(Not widely supported)*
*/
readonly strikethrough: this;
/**
Modifier: Print the text only when Chalk has a color level above zero.
Can be useful for things that are purely cosmetic.
*/
readonly visible: this;
readonly black: this;
readonly red: this;
readonly green: this;
readonly yellow: this;
readonly blue: this;
readonly magenta: this;
readonly cyan: this;
readonly white: this;
/*
Alias for `blackBright`.
*/
readonly gray: this;
/*
Alias for `blackBright`.
*/
readonly grey: this;
readonly blackBright: this;
readonly redBright: this;
readonly greenBright: this;
readonly yellowBright: this;
readonly blueBright: this;
readonly magentaBright: this;
readonly cyanBright: this;
readonly whiteBright: this;
readonly bgBlack: this;
readonly bgRed: this;
readonly bgGreen: this;
readonly bgYellow: this;
readonly bgBlue: this;
readonly bgMagenta: this;
readonly bgCyan: this;
readonly bgWhite: this;
/*
Alias for `bgBlackBright`.
*/
readonly bgGray: this;
/*
Alias for `bgBlackBright`.
*/
readonly bgGrey: this;
readonly bgBlackBright: this;
readonly bgRedBright: this;
readonly bgGreenBright: this;
readonly bgYellowBright: this;
readonly bgBlueBright: this;
readonly bgMagentaBright: this;
readonly bgCyanBright: this;
readonly bgWhiteBright: this;
}
/**
Main Chalk object that allows to chain styles together.
Call the last one as a method with a string argument.
Order doesn't matter, and later styles take precedent in case of a conflict.
This simply means that `chalk.red.yellow.green` is equivalent to `chalk.green`.
*/
declare const chalk: ChalkInstance;
export const supportsColor: ColorInfo;
export const chalkStderr: typeof chalk;
export const supportsColorStderr: typeof supportsColor;
export {
ModifierName, ForegroundColorName, BackgroundColorName, ColorName,
modifierNames, foregroundColorNames, backgroundColorNames, colorNames,
// } from '#ansi-styles';
} from './vendor/ansi-styles/index.js';
export {
ColorInfo,
ColorSupport,
ColorSupportLevel,
// } from '#supports-color';
} from './vendor/supports-color/index.js';
// TODO: Remove these aliases in the next major version
/**
@deprecated Use `ModifierName` instead.
Basic modifier names.
*/
export type Modifiers = ModifierName;
/**
@deprecated Use `ForegroundColorName` instead.
Basic foreground color names.
[More colors here.](https://github.com/chalk/chalk/blob/main/readme.md#256-and-truecolor-color-support)
*/
export type ForegroundColor = ForegroundColorName;
/**
@deprecated Use `BackgroundColorName` instead.
Basic background color names.
[More colors here.](https://github.com/chalk/chalk/blob/main/readme.md#256-and-truecolor-color-support)
*/
export type BackgroundColor = BackgroundColorName;
/**
@deprecated Use `ColorName` instead.
Basic color names. The combination of foreground and background color names.
[More colors here.](https://github.com/chalk/chalk/blob/main/readme.md#256-and-truecolor-color-support)
*/
export type Color = ColorName;
/**
@deprecated Use `modifierNames` instead.
Basic modifier names.
*/
export const modifiers: readonly Modifiers[];
/**
@deprecated Use `foregroundColorNames` instead.
Basic foreground color names.
*/
export const foregroundColors: readonly ForegroundColor[];
/**
@deprecated Use `backgroundColorNames` instead.
Basic background color names.
*/
export const backgroundColors: readonly BackgroundColor[];
/**
@deprecated Use `colorNames` instead.
Basic color names. The combination of foreground and background color names.
*/
export const colors: readonly Color[];
export default chalk;

View File

@@ -0,0 +1,225 @@
import ansiStyles from '#ansi-styles';
import supportsColor from '#supports-color';
import { // eslint-disable-line import/order
stringReplaceAll,
stringEncaseCRLFWithFirstIndex,
} from './utilities.js';
const {stdout: stdoutColor, stderr: stderrColor} = supportsColor;
const GENERATOR = Symbol('GENERATOR');
const STYLER = Symbol('STYLER');
const IS_EMPTY = Symbol('IS_EMPTY');
// `supportsColor.level` → `ansiStyles.color[name]` mapping
const levelMapping = [
'ansi',
'ansi',
'ansi256',
'ansi16m',
];
const styles = Object.create(null);
const applyOptions = (object, options = {}) => {
if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
throw new Error('The `level` option should be an integer from 0 to 3');
}
// Detect level if not set manually
const colorLevel = stdoutColor ? stdoutColor.level : 0;
object.level = options.level === undefined ? colorLevel : options.level;
};
export class Chalk {
constructor(options) {
// eslint-disable-next-line no-constructor-return
return chalkFactory(options);
}
}
const chalkFactory = options => {
const chalk = (...strings) => strings.join(' ');
applyOptions(chalk, options);
Object.setPrototypeOf(chalk, createChalk.prototype);
return chalk;
};
function createChalk(options) {
return chalkFactory(options);
}
Object.setPrototypeOf(createChalk.prototype, Function.prototype);
for (const [styleName, style] of Object.entries(ansiStyles)) {
styles[styleName] = {
get() {
const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
Object.defineProperty(this, styleName, {value: builder});
return builder;
},
};
}
styles.visible = {
get() {
const builder = createBuilder(this, this[STYLER], true);
Object.defineProperty(this, 'visible', {value: builder});
return builder;
},
};
const getModelAnsi = (model, level, type, ...arguments_) => {
if (model === 'rgb') {
if (level === 'ansi16m') {
return ansiStyles[type].ansi16m(...arguments_);
}
if (level === 'ansi256') {
return ansiStyles[type].ansi256(ansiStyles.rgbToAnsi256(...arguments_));
}
return ansiStyles[type].ansi(ansiStyles.rgbToAnsi(...arguments_));
}
if (model === 'hex') {
return getModelAnsi('rgb', level, type, ...ansiStyles.hexToRgb(...arguments_));
}
return ansiStyles[type][model](...arguments_);
};
const usedModels = ['rgb', 'hex', 'ansi256'];
for (const model of usedModels) {
styles[model] = {
get() {
const {level} = this;
return function (...arguments_) {
const styler = createStyler(getModelAnsi(model, levelMapping[level], 'color', ...arguments_), ansiStyles.color.close, this[STYLER]);
return createBuilder(this, styler, this[IS_EMPTY]);
};
},
};
const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);
styles[bgModel] = {
get() {
const {level} = this;
return function (...arguments_) {
const styler = createStyler(getModelAnsi(model, levelMapping[level], 'bgColor', ...arguments_), ansiStyles.bgColor.close, this[STYLER]);
return createBuilder(this, styler, this[IS_EMPTY]);
};
},
};
}
const proto = Object.defineProperties(() => {}, {
...styles,
level: {
enumerable: true,
get() {
return this[GENERATOR].level;
},
set(level) {
this[GENERATOR].level = level;
},
},
});
const createStyler = (open, close, parent) => {
let openAll;
let closeAll;
if (parent === undefined) {
openAll = open;
closeAll = close;
} else {
openAll = parent.openAll + open;
closeAll = close + parent.closeAll;
}
return {
open,
close,
openAll,
closeAll,
parent,
};
};
const createBuilder = (self, _styler, _isEmpty) => {
// Single argument is hot path, implicit coercion is faster than anything
// eslint-disable-next-line no-implicit-coercion
const builder = (...arguments_) => applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' '));
// We alter the prototype because we must return a function, but there is
// no way to create a function with a different prototype
Object.setPrototypeOf(builder, proto);
builder[GENERATOR] = self;
builder[STYLER] = _styler;
builder[IS_EMPTY] = _isEmpty;
return builder;
};
const applyStyle = (self, string) => {
if (self.level <= 0 || !string) {
return self[IS_EMPTY] ? '' : string;
}
let styler = self[STYLER];
if (styler === undefined) {
return string;
}
const {openAll, closeAll} = styler;
if (string.includes('\u001B')) {
while (styler !== undefined) {
// Replace any instances already present with a re-opening code
// otherwise only the part of the string until said closing code
// will be colored, and the rest will simply be 'plain'.
string = stringReplaceAll(string, styler.close, styler.open);
styler = styler.parent;
}
}
// We can move both next actions out of loop, because remaining actions in loop won't have
// any/visible effect on parts we add here. Close the styling before a linebreak and reopen
// after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92
const lfIndex = string.indexOf('\n');
if (lfIndex !== -1) {
string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
}
return openAll + string + closeAll;
};
Object.defineProperties(createChalk.prototype, styles);
const chalk = createChalk();
export const chalkStderr = createChalk({level: stderrColor ? stderrColor.level : 0});
export {
modifierNames,
foregroundColorNames,
backgroundColorNames,
colorNames,
// TODO: Remove these aliases in the next major version
modifierNames as modifiers,
foregroundColorNames as foregroundColors,
backgroundColorNames as backgroundColors,
colorNames as colors,
} from './vendor/ansi-styles/index.js';
export {
stdoutColor as supportsColor,
stderrColor as supportsColorStderr,
};
export default chalk;

View File

@@ -0,0 +1,33 @@
// TODO: When targeting Node.js 16, use `String.prototype.replaceAll`.
export function stringReplaceAll(string, substring, replacer) {
let index = string.indexOf(substring);
if (index === -1) {
return string;
}
const substringLength = substring.length;
let endIndex = 0;
let returnValue = '';
do {
returnValue += string.slice(endIndex, index) + substring + replacer;
endIndex = index + substringLength;
index = string.indexOf(substring, endIndex);
} while (index !== -1);
returnValue += string.slice(endIndex);
return returnValue;
}
export function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
let endIndex = 0;
let returnValue = '';
do {
const gotCR = string[index - 1] === '\r';
returnValue += string.slice(endIndex, (gotCR ? index - 1 : index)) + prefix + (gotCR ? '\r\n' : '\n') + postfix;
endIndex = index + 1;
index = string.indexOf('\n', endIndex);
} while (index !== -1);
returnValue += string.slice(endIndex);
return returnValue;
}

View File

@@ -0,0 +1,236 @@
export interface CSPair { // eslint-disable-line @typescript-eslint/naming-convention
/**
The ANSI terminal control sequence for starting this style.
*/
readonly open: string;
/**
The ANSI terminal control sequence for ending this style.
*/
readonly close: string;
}
export interface ColorBase {
/**
The ANSI terminal control sequence for ending this color.
*/
readonly close: string;
ansi(code: number): string;
ansi256(code: number): string;
ansi16m(red: number, green: number, blue: number): string;
}
export interface Modifier {
/**
Resets the current color chain.
*/
readonly reset: CSPair;
/**
Make text bold.
*/
readonly bold: CSPair;
/**
Emitting only a small amount of light.
*/
readonly dim: CSPair;
/**
Make text italic. (Not widely supported)
*/
readonly italic: CSPair;
/**
Make text underline. (Not widely supported)
*/
readonly underline: CSPair;
/**
Make text overline.
Supported on VTE-based terminals, the GNOME terminal, mintty, and Git Bash.
*/
readonly overline: CSPair;
/**
Inverse background and foreground colors.
*/
readonly inverse: CSPair;
/**
Prints the text, but makes it invisible.
*/
readonly hidden: CSPair;
/**
Puts a horizontal line through the center of the text. (Not widely supported)
*/
readonly strikethrough: CSPair;
}
export interface ForegroundColor {
readonly black: CSPair;
readonly red: CSPair;
readonly green: CSPair;
readonly yellow: CSPair;
readonly blue: CSPair;
readonly cyan: CSPair;
readonly magenta: CSPair;
readonly white: CSPair;
/**
Alias for `blackBright`.
*/
readonly gray: CSPair;
/**
Alias for `blackBright`.
*/
readonly grey: CSPair;
readonly blackBright: CSPair;
readonly redBright: CSPair;
readonly greenBright: CSPair;
readonly yellowBright: CSPair;
readonly blueBright: CSPair;
readonly cyanBright: CSPair;
readonly magentaBright: CSPair;
readonly whiteBright: CSPair;
}
export interface BackgroundColor {
readonly bgBlack: CSPair;
readonly bgRed: CSPair;
readonly bgGreen: CSPair;
readonly bgYellow: CSPair;
readonly bgBlue: CSPair;
readonly bgCyan: CSPair;
readonly bgMagenta: CSPair;
readonly bgWhite: CSPair;
/**
Alias for `bgBlackBright`.
*/
readonly bgGray: CSPair;
/**
Alias for `bgBlackBright`.
*/
readonly bgGrey: CSPair;
readonly bgBlackBright: CSPair;
readonly bgRedBright: CSPair;
readonly bgGreenBright: CSPair;
readonly bgYellowBright: CSPair;
readonly bgBlueBright: CSPair;
readonly bgCyanBright: CSPair;
readonly bgMagentaBright: CSPair;
readonly bgWhiteBright: CSPair;
}
export interface ConvertColor {
/**
Convert from the RGB color space to the ANSI 256 color space.
@param red - (`0...255`)
@param green - (`0...255`)
@param blue - (`0...255`)
*/
rgbToAnsi256(red: number, green: number, blue: number): number;
/**
Convert from the RGB HEX color space to the RGB color space.
@param hex - A hexadecimal string containing RGB data.
*/
hexToRgb(hex: string): [red: number, green: number, blue: number];
/**
Convert from the RGB HEX color space to the ANSI 256 color space.
@param hex - A hexadecimal string containing RGB data.
*/
hexToAnsi256(hex: string): number;
/**
Convert from the ANSI 256 color space to the ANSI 16 color space.
@param code - A number representing the ANSI 256 color.
*/
ansi256ToAnsi(code: number): number;
/**
Convert from the RGB color space to the ANSI 16 color space.
@param red - (`0...255`)
@param green - (`0...255`)
@param blue - (`0...255`)
*/
rgbToAnsi(red: number, green: number, blue: number): number;
/**
Convert from the RGB HEX color space to the ANSI 16 color space.
@param hex - A hexadecimal string containing RGB data.
*/
hexToAnsi(hex: string): number;
}
/**
Basic modifier names.
*/
export type ModifierName = keyof Modifier;
/**
Basic foreground color names.
[More colors here.](https://github.com/chalk/chalk/blob/main/readme.md#256-and-truecolor-color-support)
*/
export type ForegroundColorName = keyof ForegroundColor;
/**
Basic background color names.
[More colors here.](https://github.com/chalk/chalk/blob/main/readme.md#256-and-truecolor-color-support)
*/
export type BackgroundColorName = keyof BackgroundColor;
/**
Basic color names. The combination of foreground and background color names.
[More colors here.](https://github.com/chalk/chalk/blob/main/readme.md#256-and-truecolor-color-support)
*/
export type ColorName = ForegroundColorName | BackgroundColorName;
/**
Basic modifier names.
*/
export const modifierNames: readonly ModifierName[];
/**
Basic foreground color names.
*/
export const foregroundColorNames: readonly ForegroundColorName[];
/**
Basic background color names.
*/
export const backgroundColorNames: readonly BackgroundColorName[];
/*
Basic color names. The combination of foreground and background color names.
*/
export const colorNames: readonly ColorName[];
declare const ansiStyles: {
readonly modifier: Modifier;
readonly color: ColorBase & ForegroundColor;
readonly bgColor: ColorBase & BackgroundColor;
readonly codes: ReadonlyMap<number, number>;
} & ForegroundColor & BackgroundColor & Modifier & ConvertColor;
export default ansiStyles;

View File

@@ -0,0 +1,223 @@
const ANSI_BACKGROUND_OFFSET = 10;
const wrapAnsi16 = (offset = 0) => code => `\u001B[${code + offset}m`;
const wrapAnsi256 = (offset = 0) => code => `\u001B[${38 + offset};5;${code}m`;
const wrapAnsi16m = (offset = 0) => (red, green, blue) => `\u001B[${38 + offset};2;${red};${green};${blue}m`;
const styles = {
modifier: {
reset: [0, 0],
// 21 isn't widely supported and 22 does the same thing
bold: [1, 22],
dim: [2, 22],
italic: [3, 23],
underline: [4, 24],
overline: [53, 55],
inverse: [7, 27],
hidden: [8, 28],
strikethrough: [9, 29],
},
color: {
black: [30, 39],
red: [31, 39],
green: [32, 39],
yellow: [33, 39],
blue: [34, 39],
magenta: [35, 39],
cyan: [36, 39],
white: [37, 39],
// Bright color
blackBright: [90, 39],
gray: [90, 39], // Alias of `blackBright`
grey: [90, 39], // Alias of `blackBright`
redBright: [91, 39],
greenBright: [92, 39],
yellowBright: [93, 39],
blueBright: [94, 39],
magentaBright: [95, 39],
cyanBright: [96, 39],
whiteBright: [97, 39],
},
bgColor: {
bgBlack: [40, 49],
bgRed: [41, 49],
bgGreen: [42, 49],
bgYellow: [43, 49],
bgBlue: [44, 49],
bgMagenta: [45, 49],
bgCyan: [46, 49],
bgWhite: [47, 49],
// Bright color
bgBlackBright: [100, 49],
bgGray: [100, 49], // Alias of `bgBlackBright`
bgGrey: [100, 49], // Alias of `bgBlackBright`
bgRedBright: [101, 49],
bgGreenBright: [102, 49],
bgYellowBright: [103, 49],
bgBlueBright: [104, 49],
bgMagentaBright: [105, 49],
bgCyanBright: [106, 49],
bgWhiteBright: [107, 49],
},
};
export const modifierNames = Object.keys(styles.modifier);
export const foregroundColorNames = Object.keys(styles.color);
export const backgroundColorNames = Object.keys(styles.bgColor);
export const colorNames = [...foregroundColorNames, ...backgroundColorNames];
function assembleStyles() {
const codes = new Map();
for (const [groupName, group] of Object.entries(styles)) {
for (const [styleName, style] of Object.entries(group)) {
styles[styleName] = {
open: `\u001B[${style[0]}m`,
close: `\u001B[${style[1]}m`,
};
group[styleName] = styles[styleName];
codes.set(style[0], style[1]);
}
Object.defineProperty(styles, groupName, {
value: group,
enumerable: false,
});
}
Object.defineProperty(styles, 'codes', {
value: codes,
enumerable: false,
});
styles.color.close = '\u001B[39m';
styles.bgColor.close = '\u001B[49m';
styles.color.ansi = wrapAnsi16();
styles.color.ansi256 = wrapAnsi256();
styles.color.ansi16m = wrapAnsi16m();
styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
// From https://github.com/Qix-/color-convert/blob/3f0e0d4e92e235796ccb17f6e85c72094a651f49/conversions.js
Object.defineProperties(styles, {
rgbToAnsi256: {
value(red, green, blue) {
// We use the extended greyscale palette here, with the exception of
// black and white. normal palette only has 4 greyscale shades.
if (red === green && green === blue) {
if (red < 8) {
return 16;
}
if (red > 248) {
return 231;
}
return Math.round(((red - 8) / 247) * 24) + 232;
}
return 16
+ (36 * Math.round(red / 255 * 5))
+ (6 * Math.round(green / 255 * 5))
+ Math.round(blue / 255 * 5);
},
enumerable: false,
},
hexToRgb: {
value(hex) {
const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
if (!matches) {
return [0, 0, 0];
}
let [colorString] = matches;
if (colorString.length === 3) {
colorString = [...colorString].map(character => character + character).join('');
}
const integer = Number.parseInt(colorString, 16);
return [
/* eslint-disable no-bitwise */
(integer >> 16) & 0xFF,
(integer >> 8) & 0xFF,
integer & 0xFF,
/* eslint-enable no-bitwise */
];
},
enumerable: false,
},
hexToAnsi256: {
value: hex => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
enumerable: false,
},
ansi256ToAnsi: {
value(code) {
if (code < 8) {
return 30 + code;
}
if (code < 16) {
return 90 + (code - 8);
}
let red;
let green;
let blue;
if (code >= 232) {
red = (((code - 232) * 10) + 8) / 255;
green = red;
blue = red;
} else {
code -= 16;
const remainder = code % 36;
red = Math.floor(code / 36) / 5;
green = Math.floor(remainder / 6) / 5;
blue = (remainder % 6) / 5;
}
const value = Math.max(red, green, blue) * 2;
if (value === 0) {
return 30;
}
// eslint-disable-next-line no-bitwise
let result = 30 + ((Math.round(blue) << 2) | (Math.round(green) << 1) | Math.round(red));
if (value === 2) {
result += 60;
}
return result;
},
enumerable: false,
},
rgbToAnsi: {
value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
enumerable: false,
},
hexToAnsi: {
value: hex => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
enumerable: false,
},
});
return styles;
}
const ansiStyles = assembleStyles();
export default ansiStyles;

View File

@@ -0,0 +1 @@
export {default} from './index.js';

View File

@@ -0,0 +1,34 @@
/* eslint-env browser */
const level = (() => {
if (!('navigator' in globalThis)) {
return 0;
}
if (globalThis.navigator.userAgentData) {
const brand = navigator.userAgentData.brands.find(({brand}) => brand === 'Chromium');
if (brand && brand.version > 93) {
return 3;
}
}
if (/\b(Chrome|Chromium)\//.test(globalThis.navigator.userAgent)) {
return 1;
}
return 0;
})();
const colorSupport = level !== 0 && {
level,
hasBasic: true,
has256: level >= 2,
has16m: level >= 3,
};
const supportsColor = {
stdout: colorSupport,
stderr: colorSupport,
};
export default supportsColor;

View File

@@ -0,0 +1,55 @@
import type {WriteStream} from 'node:tty';
export type Options = {
/**
Whether `process.argv` should be sniffed for `--color` and `--no-color` flags.
@default true
*/
readonly sniffFlags?: boolean;
};
/**
Levels:
- `0` - All colors disabled.
- `1` - Basic 16 colors support.
- `2` - ANSI 256 colors support.
- `3` - Truecolor 16 million colors support.
*/
export type ColorSupportLevel = 0 | 1 | 2 | 3;
/**
Detect whether the terminal supports color.
*/
export type ColorSupport = {
/**
The color level.
*/
level: ColorSupportLevel;
/**
Whether basic 16 colors are supported.
*/
hasBasic: boolean;
/**
Whether ANSI 256 colors are supported.
*/
has256: boolean;
/**
Whether Truecolor 16 million colors are supported.
*/
has16m: boolean;
};
export type ColorInfo = ColorSupport | false;
export function createSupportsColor(stream?: WriteStream, options?: Options): ColorInfo;
declare const supportsColor: {
stdout: ColorInfo;
stderr: ColorInfo;
};
export default supportsColor;

View File

@@ -0,0 +1,190 @@
import process from 'node:process';
import os from 'node:os';
import tty from 'node:tty';
// From: https://github.com/sindresorhus/has-flag/blob/main/index.js
/// function hasFlag(flag, argv = globalThis.Deno?.args ?? process.argv) {
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process.argv) {
const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');
const position = argv.indexOf(prefix + flag);
const terminatorPosition = argv.indexOf('--');
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
}
const {env} = process;
let flagForceColor;
if (
hasFlag('no-color')
|| hasFlag('no-colors')
|| hasFlag('color=false')
|| hasFlag('color=never')
) {
flagForceColor = 0;
} else if (
hasFlag('color')
|| hasFlag('colors')
|| hasFlag('color=true')
|| hasFlag('color=always')
) {
flagForceColor = 1;
}
function envForceColor() {
if ('FORCE_COLOR' in env) {
if (env.FORCE_COLOR === 'true') {
return 1;
}
if (env.FORCE_COLOR === 'false') {
return 0;
}
return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
}
}
function translateLevel(level) {
if (level === 0) {
return false;
}
return {
level,
hasBasic: true,
has256: level >= 2,
has16m: level >= 3,
};
}
function _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) {
const noFlagForceColor = envForceColor();
if (noFlagForceColor !== undefined) {
flagForceColor = noFlagForceColor;
}
const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
if (forceColor === 0) {
return 0;
}
if (sniffFlags) {
if (hasFlag('color=16m')
|| hasFlag('color=full')
|| hasFlag('color=truecolor')) {
return 3;
}
if (hasFlag('color=256')) {
return 2;
}
}
// Check for Azure DevOps pipelines.
// Has to be above the `!streamIsTTY` check.
if ('TF_BUILD' in env && 'AGENT_NAME' in env) {
return 1;
}
if (haveStream && !streamIsTTY && forceColor === undefined) {
return 0;
}
const min = forceColor || 0;
if (env.TERM === 'dumb') {
return min;
}
if (process.platform === 'win32') {
// Windows 10 build 10586 is the first Windows release that supports 256 colors.
// Windows 10 build 14931 is the first release that supports 16m/TrueColor.
const osRelease = os.release().split('.');
if (
Number(osRelease[0]) >= 10
&& Number(osRelease[2]) >= 10_586
) {
return Number(osRelease[2]) >= 14_931 ? 3 : 2;
}
return 1;
}
if ('CI' in env) {
if (['GITHUB_ACTIONS', 'GITEA_ACTIONS', 'CIRCLECI'].some(key => key in env)) {
return 3;
}
if (['TRAVIS', 'APPVEYOR', 'GITLAB_CI', 'BUILDKITE', 'DRONE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
return 1;
}
return min;
}
if ('TEAMCITY_VERSION' in env) {
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
}
if (env.COLORTERM === 'truecolor') {
return 3;
}
if (env.TERM === 'xterm-kitty') {
return 3;
}
if (env.TERM === 'xterm-ghostty') {
return 3;
}
if (env.TERM === 'wezterm') {
return 3;
}
if ('TERM_PROGRAM' in env) {
const version = Number.parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
switch (env.TERM_PROGRAM) {
case 'iTerm.app': {
return version >= 3 ? 3 : 2;
}
case 'Apple_Terminal': {
return 2;
}
// No default
}
}
if (/-256(color)?$/i.test(env.TERM)) {
return 2;
}
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
return 1;
}
if ('COLORTERM' in env) {
return 1;
}
return min;
}
export function createSupportsColor(stream, options = {}) {
const level = _supportsColor(stream, {
streamIsTTY: stream && stream.isTTY,
...options,
});
return translateLevel(level);
}
const supportsColor = {
stdout: createSupportsColor({isTTY: tty.isatty(1)}),
stderr: createSupportsColor({isTTY: tty.isatty(2)}),
};
export default supportsColor;

View File

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
import commander from './index.js';
// wrapper to provide named exports for ESM.
export const {
program,
createCommand,
createArgument,
createOption,
CommanderError,
InvalidArgumentError,
InvalidOptionArgumentError, // deprecated old name
Command,
Argument,
Option,
Help,
} = commander;

View File

@@ -0,0 +1,24 @@
const { Argument } = require('./lib/argument.js');
const { Command } = require('./lib/command.js');
const { CommanderError, InvalidArgumentError } = require('./lib/error.js');
const { Help } = require('./lib/help.js');
const { Option } = require('./lib/option.js');
exports.program = new Command();
exports.createCommand = (name) => new Command(name);
exports.createOption = (flags, description) => new Option(flags, description);
exports.createArgument = (name, description) => new Argument(name, description);
/**
* Expose classes
*/
exports.Command = Command;
exports.Option = Option;
exports.Argument = Argument;
exports.Help = Help;
exports.CommanderError = CommanderError;
exports.InvalidArgumentError = InvalidArgumentError;
exports.InvalidOptionArgumentError = InvalidArgumentError; // Deprecated

View File

@@ -0,0 +1,149 @@
const { InvalidArgumentError } = require('./error.js');
class Argument {
/**
* Initialize a new command argument with the given name and description.
* The default is that the argument is required, and you can explicitly
* indicate this with <> around the name. Put [] around the name for an optional argument.
*
* @param {string} name
* @param {string} [description]
*/
constructor(name, description) {
this.description = description || '';
this.variadic = false;
this.parseArg = undefined;
this.defaultValue = undefined;
this.defaultValueDescription = undefined;
this.argChoices = undefined;
switch (name[0]) {
case '<': // e.g. <required>
this.required = true;
this._name = name.slice(1, -1);
break;
case '[': // e.g. [optional]
this.required = false;
this._name = name.slice(1, -1);
break;
default:
this.required = true;
this._name = name;
break;
}
if (this._name.length > 3 && this._name.slice(-3) === '...') {
this.variadic = true;
this._name = this._name.slice(0, -3);
}
}
/**
* Return argument name.
*
* @return {string}
*/
name() {
return this._name;
}
/**
* @package
*/
_concatValue(value, previous) {
if (previous === this.defaultValue || !Array.isArray(previous)) {
return [value];
}
return previous.concat(value);
}
/**
* Set the default value, and optionally supply the description to be displayed in the help.
*
* @param {*} value
* @param {string} [description]
* @return {Argument}
*/
default(value, description) {
this.defaultValue = value;
this.defaultValueDescription = description;
return this;
}
/**
* Set the custom handler for processing CLI command arguments into argument values.
*
* @param {Function} [fn]
* @return {Argument}
*/
argParser(fn) {
this.parseArg = fn;
return this;
}
/**
* Only allow argument value to be one of choices.
*
* @param {string[]} values
* @return {Argument}
*/
choices(values) {
this.argChoices = values.slice();
this.parseArg = (arg, previous) => {
if (!this.argChoices.includes(arg)) {
throw new InvalidArgumentError(
`Allowed choices are ${this.argChoices.join(', ')}.`,
);
}
if (this.variadic) {
return this._concatValue(arg, previous);
}
return arg;
};
return this;
}
/**
* Make argument required.
*
* @returns {Argument}
*/
argRequired() {
this.required = true;
return this;
}
/**
* Make argument optional.
*
* @returns {Argument}
*/
argOptional() {
this.required = false;
return this;
}
}
/**
* Takes an argument and returns its human readable equivalent for help usage.
*
* @param {Argument} arg
* @return {string}
* @private
*/
function humanReadableArgName(arg) {
const nameOutput = arg.name() + (arg.variadic === true ? '...' : '');
return arg.required ? '<' + nameOutput + '>' : '[' + nameOutput + ']';
}
exports.Argument = Argument;
exports.humanReadableArgName = humanReadableArgName;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
/**
* CommanderError class
*/
class CommanderError extends Error {
/**
* Constructs the CommanderError class
* @param {number} exitCode suggested exit code which could be used with process.exit
* @param {string} code an id string representing the error
* @param {string} message human-readable description of the error
*/
constructor(exitCode, code, message) {
super(message);
// properly capture stack trace in Node.js
Error.captureStackTrace(this, this.constructor);
this.name = this.constructor.name;
this.code = code;
this.exitCode = exitCode;
this.nestedError = undefined;
}
}
/**
* InvalidArgumentError class
*/
class InvalidArgumentError extends CommanderError {
/**
* Constructs the InvalidArgumentError class
* @param {string} [message] explanation of why argument is invalid
*/
constructor(message) {
super(1, 'commander.invalidArgument', message);
// properly capture stack trace in Node.js
Error.captureStackTrace(this, this.constructor);
this.name = this.constructor.name;
}
}
exports.CommanderError = CommanderError;
exports.InvalidArgumentError = InvalidArgumentError;

View File

@@ -0,0 +1,709 @@
const { humanReadableArgName } = require('./argument.js');
/**
* TypeScript import types for JSDoc, used by Visual Studio Code IntelliSense and `npm run typescript-checkJS`
* https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#import-types
* @typedef { import("./argument.js").Argument } Argument
* @typedef { import("./command.js").Command } Command
* @typedef { import("./option.js").Option } Option
*/
// Although this is a class, methods are static in style to allow override using subclass or just functions.
class Help {
constructor() {
this.helpWidth = undefined;
this.minWidthToWrap = 40;
this.sortSubcommands = false;
this.sortOptions = false;
this.showGlobalOptions = false;
}
/**
* prepareContext is called by Commander after applying overrides from `Command.configureHelp()`
* and just before calling `formatHelp()`.
*
* Commander just uses the helpWidth and the rest is provided for optional use by more complex subclasses.
*
* @param {{ error?: boolean, helpWidth?: number, outputHasColors?: boolean }} contextOptions
*/
prepareContext(contextOptions) {
this.helpWidth = this.helpWidth ?? contextOptions.helpWidth ?? 80;
}
/**
* Get an array of the visible subcommands. Includes a placeholder for the implicit help command, if there is one.
*
* @param {Command} cmd
* @returns {Command[]}
*/
visibleCommands(cmd) {
const visibleCommands = cmd.commands.filter((cmd) => !cmd._hidden);
const helpCommand = cmd._getHelpCommand();
if (helpCommand && !helpCommand._hidden) {
visibleCommands.push(helpCommand);
}
if (this.sortSubcommands) {
visibleCommands.sort((a, b) => {
// @ts-ignore: because overloaded return type
return a.name().localeCompare(b.name());
});
}
return visibleCommands;
}
/**
* Compare options for sort.
*
* @param {Option} a
* @param {Option} b
* @returns {number}
*/
compareOptions(a, b) {
const getSortKey = (option) => {
// WYSIWYG for order displayed in help. Short used for comparison if present. No special handling for negated.
return option.short
? option.short.replace(/^-/, '')
: option.long.replace(/^--/, '');
};
return getSortKey(a).localeCompare(getSortKey(b));
}
/**
* Get an array of the visible options. Includes a placeholder for the implicit help option, if there is one.
*
* @param {Command} cmd
* @returns {Option[]}
*/
visibleOptions(cmd) {
const visibleOptions = cmd.options.filter((option) => !option.hidden);
// Built-in help option.
const helpOption = cmd._getHelpOption();
if (helpOption && !helpOption.hidden) {
// Automatically hide conflicting flags. Bit dubious but a historical behaviour that is convenient for single-command programs.
const removeShort = helpOption.short && cmd._findOption(helpOption.short);
const removeLong = helpOption.long && cmd._findOption(helpOption.long);
if (!removeShort && !removeLong) {
visibleOptions.push(helpOption); // no changes needed
} else if (helpOption.long && !removeLong) {
visibleOptions.push(
cmd.createOption(helpOption.long, helpOption.description),
);
} else if (helpOption.short && !removeShort) {
visibleOptions.push(
cmd.createOption(helpOption.short, helpOption.description),
);
}
}
if (this.sortOptions) {
visibleOptions.sort(this.compareOptions);
}
return visibleOptions;
}
/**
* Get an array of the visible global options. (Not including help.)
*
* @param {Command} cmd
* @returns {Option[]}
*/
visibleGlobalOptions(cmd) {
if (!this.showGlobalOptions) return [];
const globalOptions = [];
for (
let ancestorCmd = cmd.parent;
ancestorCmd;
ancestorCmd = ancestorCmd.parent
) {
const visibleOptions = ancestorCmd.options.filter(
(option) => !option.hidden,
);
globalOptions.push(...visibleOptions);
}
if (this.sortOptions) {
globalOptions.sort(this.compareOptions);
}
return globalOptions;
}
/**
* Get an array of the arguments if any have a description.
*
* @param {Command} cmd
* @returns {Argument[]}
*/
visibleArguments(cmd) {
// Side effect! Apply the legacy descriptions before the arguments are displayed.
if (cmd._argsDescription) {
cmd.registeredArguments.forEach((argument) => {
argument.description =
argument.description || cmd._argsDescription[argument.name()] || '';
});
}
// If there are any arguments with a description then return all the arguments.
if (cmd.registeredArguments.find((argument) => argument.description)) {
return cmd.registeredArguments;
}
return [];
}
/**
* Get the command term to show in the list of subcommands.
*
* @param {Command} cmd
* @returns {string}
*/
subcommandTerm(cmd) {
// Legacy. Ignores custom usage string, and nested commands.
const args = cmd.registeredArguments
.map((arg) => humanReadableArgName(arg))
.join(' ');
return (
cmd._name +
(cmd._aliases[0] ? '|' + cmd._aliases[0] : '') +
(cmd.options.length ? ' [options]' : '') + // simplistic check for non-help option
(args ? ' ' + args : '')
);
}
/**
* Get the option term to show in the list of options.
*
* @param {Option} option
* @returns {string}
*/
optionTerm(option) {
return option.flags;
}
/**
* Get the argument term to show in the list of arguments.
*
* @param {Argument} argument
* @returns {string}
*/
argumentTerm(argument) {
return argument.name();
}
/**
* Get the longest command term length.
*
* @param {Command} cmd
* @param {Help} helper
* @returns {number}
*/
longestSubcommandTermLength(cmd, helper) {
return helper.visibleCommands(cmd).reduce((max, command) => {
return Math.max(
max,
this.displayWidth(
helper.styleSubcommandTerm(helper.subcommandTerm(command)),
),
);
}, 0);
}
/**
* Get the longest option term length.
*
* @param {Command} cmd
* @param {Help} helper
* @returns {number}
*/
longestOptionTermLength(cmd, helper) {
return helper.visibleOptions(cmd).reduce((max, option) => {
return Math.max(
max,
this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option))),
);
}, 0);
}
/**
* Get the longest global option term length.
*
* @param {Command} cmd
* @param {Help} helper
* @returns {number}
*/
longestGlobalOptionTermLength(cmd, helper) {
return helper.visibleGlobalOptions(cmd).reduce((max, option) => {
return Math.max(
max,
this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option))),
);
}, 0);
}
/**
* Get the longest argument term length.
*
* @param {Command} cmd
* @param {Help} helper
* @returns {number}
*/
longestArgumentTermLength(cmd, helper) {
return helper.visibleArguments(cmd).reduce((max, argument) => {
return Math.max(
max,
this.displayWidth(
helper.styleArgumentTerm(helper.argumentTerm(argument)),
),
);
}, 0);
}
/**
* Get the command usage to be displayed at the top of the built-in help.
*
* @param {Command} cmd
* @returns {string}
*/
commandUsage(cmd) {
// Usage
let cmdName = cmd._name;
if (cmd._aliases[0]) {
cmdName = cmdName + '|' + cmd._aliases[0];
}
let ancestorCmdNames = '';
for (
let ancestorCmd = cmd.parent;
ancestorCmd;
ancestorCmd = ancestorCmd.parent
) {
ancestorCmdNames = ancestorCmd.name() + ' ' + ancestorCmdNames;
}
return ancestorCmdNames + cmdName + ' ' + cmd.usage();
}
/**
* Get the description for the command.
*
* @param {Command} cmd
* @returns {string}
*/
commandDescription(cmd) {
// @ts-ignore: because overloaded return type
return cmd.description();
}
/**
* Get the subcommand summary to show in the list of subcommands.
* (Fallback to description for backwards compatibility.)
*
* @param {Command} cmd
* @returns {string}
*/
subcommandDescription(cmd) {
// @ts-ignore: because overloaded return type
return cmd.summary() || cmd.description();
}
/**
* Get the option description to show in the list of options.
*
* @param {Option} option
* @return {string}
*/
optionDescription(option) {
const extraInfo = [];
if (option.argChoices) {
extraInfo.push(
// use stringify to match the display of the default value
`choices: ${option.argChoices.map((choice) => JSON.stringify(choice)).join(', ')}`,
);
}
if (option.defaultValue !== undefined) {
// default for boolean and negated more for programmer than end user,
// but show true/false for boolean option as may be for hand-rolled env or config processing.
const showDefault =
option.required ||
option.optional ||
(option.isBoolean() && typeof option.defaultValue === 'boolean');
if (showDefault) {
extraInfo.push(
`default: ${option.defaultValueDescription || JSON.stringify(option.defaultValue)}`,
);
}
}
// preset for boolean and negated are more for programmer than end user
if (option.presetArg !== undefined && option.optional) {
extraInfo.push(`preset: ${JSON.stringify(option.presetArg)}`);
}
if (option.envVar !== undefined) {
extraInfo.push(`env: ${option.envVar}`);
}
if (extraInfo.length > 0) {
return `${option.description} (${extraInfo.join(', ')})`;
}
return option.description;
}
/**
* Get the argument description to show in the list of arguments.
*
* @param {Argument} argument
* @return {string}
*/
argumentDescription(argument) {
const extraInfo = [];
if (argument.argChoices) {
extraInfo.push(
// use stringify to match the display of the default value
`choices: ${argument.argChoices.map((choice) => JSON.stringify(choice)).join(', ')}`,
);
}
if (argument.defaultValue !== undefined) {
extraInfo.push(
`default: ${argument.defaultValueDescription || JSON.stringify(argument.defaultValue)}`,
);
}
if (extraInfo.length > 0) {
const extraDescription = `(${extraInfo.join(', ')})`;
if (argument.description) {
return `${argument.description} ${extraDescription}`;
}
return extraDescription;
}
return argument.description;
}
/**
* Generate the built-in help text.
*
* @param {Command} cmd
* @param {Help} helper
* @returns {string}
*/
formatHelp(cmd, helper) {
const termWidth = helper.padWidth(cmd, helper);
const helpWidth = helper.helpWidth ?? 80; // in case prepareContext() was not called
function callFormatItem(term, description) {
return helper.formatItem(term, termWidth, description, helper);
}
// Usage
let output = [
`${helper.styleTitle('Usage:')} ${helper.styleUsage(helper.commandUsage(cmd))}`,
'',
];
// Description
const commandDescription = helper.commandDescription(cmd);
if (commandDescription.length > 0) {
output = output.concat([
helper.boxWrap(
helper.styleCommandDescription(commandDescription),
helpWidth,
),
'',
]);
}
// Arguments
const argumentList = helper.visibleArguments(cmd).map((argument) => {
return callFormatItem(
helper.styleArgumentTerm(helper.argumentTerm(argument)),
helper.styleArgumentDescription(helper.argumentDescription(argument)),
);
});
if (argumentList.length > 0) {
output = output.concat([
helper.styleTitle('Arguments:'),
...argumentList,
'',
]);
}
// Options
const optionList = helper.visibleOptions(cmd).map((option) => {
return callFormatItem(
helper.styleOptionTerm(helper.optionTerm(option)),
helper.styleOptionDescription(helper.optionDescription(option)),
);
});
if (optionList.length > 0) {
output = output.concat([
helper.styleTitle('Options:'),
...optionList,
'',
]);
}
if (helper.showGlobalOptions) {
const globalOptionList = helper
.visibleGlobalOptions(cmd)
.map((option) => {
return callFormatItem(
helper.styleOptionTerm(helper.optionTerm(option)),
helper.styleOptionDescription(helper.optionDescription(option)),
);
});
if (globalOptionList.length > 0) {
output = output.concat([
helper.styleTitle('Global Options:'),
...globalOptionList,
'',
]);
}
}
// Commands
const commandList = helper.visibleCommands(cmd).map((cmd) => {
return callFormatItem(
helper.styleSubcommandTerm(helper.subcommandTerm(cmd)),
helper.styleSubcommandDescription(helper.subcommandDescription(cmd)),
);
});
if (commandList.length > 0) {
output = output.concat([
helper.styleTitle('Commands:'),
...commandList,
'',
]);
}
return output.join('\n');
}
/**
* Return display width of string, ignoring ANSI escape sequences. Used in padding and wrapping calculations.
*
* @param {string} str
* @returns {number}
*/
displayWidth(str) {
return stripColor(str).length;
}
/**
* Style the title for displaying in the help. Called with 'Usage:', 'Options:', etc.
*
* @param {string} str
* @returns {string}
*/
styleTitle(str) {
return str;
}
styleUsage(str) {
// Usage has lots of parts the user might like to color separately! Assume default usage string which is formed like:
// command subcommand [options] [command] <foo> [bar]
return str
.split(' ')
.map((word) => {
if (word === '[options]') return this.styleOptionText(word);
if (word === '[command]') return this.styleSubcommandText(word);
if (word[0] === '[' || word[0] === '<')
return this.styleArgumentText(word);
return this.styleCommandText(word); // Restrict to initial words?
})
.join(' ');
}
styleCommandDescription(str) {
return this.styleDescriptionText(str);
}
styleOptionDescription(str) {
return this.styleDescriptionText(str);
}
styleSubcommandDescription(str) {
return this.styleDescriptionText(str);
}
styleArgumentDescription(str) {
return this.styleDescriptionText(str);
}
styleDescriptionText(str) {
return str;
}
styleOptionTerm(str) {
return this.styleOptionText(str);
}
styleSubcommandTerm(str) {
// This is very like usage with lots of parts! Assume default string which is formed like:
// subcommand [options] <foo> [bar]
return str
.split(' ')
.map((word) => {
if (word === '[options]') return this.styleOptionText(word);
if (word[0] === '[' || word[0] === '<')
return this.styleArgumentText(word);
return this.styleSubcommandText(word); // Restrict to initial words?
})
.join(' ');
}
styleArgumentTerm(str) {
return this.styleArgumentText(str);
}
styleOptionText(str) {
return str;
}
styleArgumentText(str) {
return str;
}
styleSubcommandText(str) {
return str;
}
styleCommandText(str) {
return str;
}
/**
* Calculate the pad width from the maximum term length.
*
* @param {Command} cmd
* @param {Help} helper
* @returns {number}
*/
padWidth(cmd, helper) {
return Math.max(
helper.longestOptionTermLength(cmd, helper),
helper.longestGlobalOptionTermLength(cmd, helper),
helper.longestSubcommandTermLength(cmd, helper),
helper.longestArgumentTermLength(cmd, helper),
);
}
/**
* Detect manually wrapped and indented strings by checking for line break followed by whitespace.
*
* @param {string} str
* @returns {boolean}
*/
preformatted(str) {
return /\n[^\S\r\n]/.test(str);
}
/**
* Format the "item", which consists of a term and description. Pad the term and wrap the description, indenting the following lines.
*
* So "TTT", 5, "DDD DDDD DD DDD" might be formatted for this.helpWidth=17 like so:
* TTT DDD DDDD
* DD DDD
*
* @param {string} term
* @param {number} termWidth
* @param {string} description
* @param {Help} helper
* @returns {string}
*/
formatItem(term, termWidth, description, helper) {
const itemIndent = 2;
const itemIndentStr = ' '.repeat(itemIndent);
if (!description) return itemIndentStr + term;
// Pad the term out to a consistent width, so descriptions are aligned.
const paddedTerm = term.padEnd(
termWidth + term.length - helper.displayWidth(term),
);
// Format the description.
const spacerWidth = 2; // between term and description
const helpWidth = this.helpWidth ?? 80; // in case prepareContext() was not called
const remainingWidth = helpWidth - termWidth - spacerWidth - itemIndent;
let formattedDescription;
if (
remainingWidth < this.minWidthToWrap ||
helper.preformatted(description)
) {
formattedDescription = description;
} else {
const wrappedDescription = helper.boxWrap(description, remainingWidth);
formattedDescription = wrappedDescription.replace(
/\n/g,
'\n' + ' '.repeat(termWidth + spacerWidth),
);
}
// Construct and overall indent.
return (
itemIndentStr +
paddedTerm +
' '.repeat(spacerWidth) +
formattedDescription.replace(/\n/g, `\n${itemIndentStr}`)
);
}
/**
* Wrap a string at whitespace, preserving existing line breaks.
* Wrapping is skipped if the width is less than `minWidthToWrap`.
*
* @param {string} str
* @param {number} width
* @returns {string}
*/
boxWrap(str, width) {
if (width < this.minWidthToWrap) return str;
const rawLines = str.split(/\r\n|\n/);
// split up text by whitespace
const chunkPattern = /[\s]*[^\s]+/g;
const wrappedLines = [];
rawLines.forEach((line) => {
const chunks = line.match(chunkPattern);
if (chunks === null) {
wrappedLines.push('');
return;
}
let sumChunks = [chunks.shift()];
let sumWidth = this.displayWidth(sumChunks[0]);
chunks.forEach((chunk) => {
const visibleWidth = this.displayWidth(chunk);
// Accumulate chunks while they fit into width.
if (sumWidth + visibleWidth <= width) {
sumChunks.push(chunk);
sumWidth += visibleWidth;
return;
}
wrappedLines.push(sumChunks.join(''));
const nextChunk = chunk.trimStart(); // trim space at line break
sumChunks = [nextChunk];
sumWidth = this.displayWidth(nextChunk);
});
wrappedLines.push(sumChunks.join(''));
});
return wrappedLines.join('\n');
}
}
/**
* Strip style ANSI escape sequences from the string. In particular, SGR (Select Graphic Rendition) codes.
*
* @param {string} str
* @returns {string}
* @package
*/
function stripColor(str) {
// eslint-disable-next-line no-control-regex
const sgrPattern = /\x1b\[\d*(;\d*)*m/g;
return str.replace(sgrPattern, '');
}
exports.Help = Help;
exports.stripColor = stripColor;

View File

@@ -0,0 +1,367 @@
const { InvalidArgumentError } = require('./error.js');
class Option {
/**
* Initialize a new `Option` with the given `flags` and `description`.
*
* @param {string} flags
* @param {string} [description]
*/
constructor(flags, description) {
this.flags = flags;
this.description = description || '';
this.required = flags.includes('<'); // A value must be supplied when the option is specified.
this.optional = flags.includes('['); // A value is optional when the option is specified.
// variadic test ignores <value,...> et al which might be used to describe custom splitting of single argument
this.variadic = /\w\.\.\.[>\]]$/.test(flags); // The option can take multiple values.
this.mandatory = false; // The option must have a value after parsing, which usually means it must be specified on command line.
const optionFlags = splitOptionFlags(flags);
this.short = optionFlags.shortFlag; // May be a short flag, undefined, or even a long flag (if option has two long flags).
this.long = optionFlags.longFlag;
this.negate = false;
if (this.long) {
this.negate = this.long.startsWith('--no-');
}
this.defaultValue = undefined;
this.defaultValueDescription = undefined;
this.presetArg = undefined;
this.envVar = undefined;
this.parseArg = undefined;
this.hidden = false;
this.argChoices = undefined;
this.conflictsWith = [];
this.implied = undefined;
}
/**
* Set the default value, and optionally supply the description to be displayed in the help.
*
* @param {*} value
* @param {string} [description]
* @return {Option}
*/
default(value, description) {
this.defaultValue = value;
this.defaultValueDescription = description;
return this;
}
/**
* Preset to use when option used without option-argument, especially optional but also boolean and negated.
* The custom processing (parseArg) is called.
*
* @example
* new Option('--color').default('GREYSCALE').preset('RGB');
* new Option('--donate [amount]').preset('20').argParser(parseFloat);
*
* @param {*} arg
* @return {Option}
*/
preset(arg) {
this.presetArg = arg;
return this;
}
/**
* Add option name(s) that conflict with this option.
* An error will be displayed if conflicting options are found during parsing.
*
* @example
* new Option('--rgb').conflicts('cmyk');
* new Option('--js').conflicts(['ts', 'jsx']);
*
* @param {(string | string[])} names
* @return {Option}
*/
conflicts(names) {
this.conflictsWith = this.conflictsWith.concat(names);
return this;
}
/**
* Specify implied option values for when this option is set and the implied options are not.
*
* The custom processing (parseArg) is not called on the implied values.
*
* @example
* program
* .addOption(new Option('--log', 'write logging information to file'))
* .addOption(new Option('--trace', 'log extra details').implies({ log: 'trace.txt' }));
*
* @param {object} impliedOptionValues
* @return {Option}
*/
implies(impliedOptionValues) {
let newImplied = impliedOptionValues;
if (typeof impliedOptionValues === 'string') {
// string is not documented, but easy mistake and we can do what user probably intended.
newImplied = { [impliedOptionValues]: true };
}
this.implied = Object.assign(this.implied || {}, newImplied);
return this;
}
/**
* Set environment variable to check for option value.
*
* An environment variable is only used if when processed the current option value is
* undefined, or the source of the current value is 'default' or 'config' or 'env'.
*
* @param {string} name
* @return {Option}
*/
env(name) {
this.envVar = name;
return this;
}
/**
* Set the custom handler for processing CLI option arguments into option values.
*
* @param {Function} [fn]
* @return {Option}
*/
argParser(fn) {
this.parseArg = fn;
return this;
}
/**
* Whether the option is mandatory and must have a value after parsing.
*
* @param {boolean} [mandatory=true]
* @return {Option}
*/
makeOptionMandatory(mandatory = true) {
this.mandatory = !!mandatory;
return this;
}
/**
* Hide option in help.
*
* @param {boolean} [hide=true]
* @return {Option}
*/
hideHelp(hide = true) {
this.hidden = !!hide;
return this;
}
/**
* @package
*/
_concatValue(value, previous) {
if (previous === this.defaultValue || !Array.isArray(previous)) {
return [value];
}
return previous.concat(value);
}
/**
* Only allow option value to be one of choices.
*
* @param {string[]} values
* @return {Option}
*/
choices(values) {
this.argChoices = values.slice();
this.parseArg = (arg, previous) => {
if (!this.argChoices.includes(arg)) {
throw new InvalidArgumentError(
`Allowed choices are ${this.argChoices.join(', ')}.`,
);
}
if (this.variadic) {
return this._concatValue(arg, previous);
}
return arg;
};
return this;
}
/**
* Return option name.
*
* @return {string}
*/
name() {
if (this.long) {
return this.long.replace(/^--/, '');
}
return this.short.replace(/^-/, '');
}
/**
* Return option name, in a camelcase format that can be used
* as an object attribute key.
*
* @return {string}
*/
attributeName() {
if (this.negate) {
return camelcase(this.name().replace(/^no-/, ''));
}
return camelcase(this.name());
}
/**
* Check if `arg` matches the short or long flag.
*
* @param {string} arg
* @return {boolean}
* @package
*/
is(arg) {
return this.short === arg || this.long === arg;
}
/**
* Return whether a boolean option.
*
* Options are one of boolean, negated, required argument, or optional argument.
*
* @return {boolean}
* @package
*/
isBoolean() {
return !this.required && !this.optional && !this.negate;
}
}
/**
* This class is to make it easier to work with dual options, without changing the existing
* implementation. We support separate dual options for separate positive and negative options,
* like `--build` and `--no-build`, which share a single option value. This works nicely for some
* use cases, but is tricky for others where we want separate behaviours despite
* the single shared option value.
*/
class DualOptions {
/**
* @param {Option[]} options
*/
constructor(options) {
this.positiveOptions = new Map();
this.negativeOptions = new Map();
this.dualOptions = new Set();
options.forEach((option) => {
if (option.negate) {
this.negativeOptions.set(option.attributeName(), option);
} else {
this.positiveOptions.set(option.attributeName(), option);
}
});
this.negativeOptions.forEach((value, key) => {
if (this.positiveOptions.has(key)) {
this.dualOptions.add(key);
}
});
}
/**
* Did the value come from the option, and not from possible matching dual option?
*
* @param {*} value
* @param {Option} option
* @returns {boolean}
*/
valueFromOption(value, option) {
const optionKey = option.attributeName();
if (!this.dualOptions.has(optionKey)) return true;
// Use the value to deduce if (probably) came from the option.
const preset = this.negativeOptions.get(optionKey).presetArg;
const negativeValue = preset !== undefined ? preset : false;
return option.negate === (negativeValue === value);
}
}
/**
* Convert string from kebab-case to camelCase.
*
* @param {string} str
* @return {string}
* @private
*/
function camelcase(str) {
return str.split('-').reduce((str, word) => {
return str + word[0].toUpperCase() + word.slice(1);
});
}
/**
* Split the short and long flag out of something like '-m,--mixed <value>'
*
* @private
*/
function splitOptionFlags(flags) {
let shortFlag;
let longFlag;
// short flag, single dash and single character
const shortFlagExp = /^-[^-]$/;
// long flag, double dash and at least one character
const longFlagExp = /^--[^-]/;
const flagParts = flags.split(/[ |,]+/).concat('guard');
// Normal is short and/or long.
if (shortFlagExp.test(flagParts[0])) shortFlag = flagParts.shift();
if (longFlagExp.test(flagParts[0])) longFlag = flagParts.shift();
// Long then short. Rarely used but fine.
if (!shortFlag && shortFlagExp.test(flagParts[0]))
shortFlag = flagParts.shift();
// Allow two long flags, like '--ws, --workspace'
// This is the supported way to have a shortish option flag.
if (!shortFlag && longFlagExp.test(flagParts[0])) {
shortFlag = longFlag;
longFlag = flagParts.shift();
}
// Check for unprocessed flag. Fail noisily rather than silently ignore.
if (flagParts[0].startsWith('-')) {
const unsupportedFlag = flagParts[0];
const baseError = `option creation failed due to '${unsupportedFlag}' in option flags '${flags}'`;
if (/^-[^-][^-]/.test(unsupportedFlag))
throw new Error(
`${baseError}
- a short flag is a single dash and a single character
- either use a single dash and a single character (for a short flag)
- or use a double dash for a long option (and can have two, like '--ws, --workspace')`,
);
if (shortFlagExp.test(unsupportedFlag))
throw new Error(`${baseError}
- too many short flags`);
if (longFlagExp.test(unsupportedFlag))
throw new Error(`${baseError}
- too many long flags`);
throw new Error(`${baseError}
- unrecognised flag format`);
}
if (shortFlag === undefined && longFlag === undefined)
throw new Error(
`option creation failed due to no flags found in '${flags}'.`,
);
return { shortFlag, longFlag };
}
exports.Option = Option;
exports.DualOptions = DualOptions;

View File

@@ -0,0 +1,101 @@
const maxDistance = 3;
function editDistance(a, b) {
// https://en.wikipedia.org/wiki/DamerauLevenshtein_distance
// Calculating optimal string alignment distance, no substring is edited more than once.
// (Simple implementation.)
// Quick early exit, return worst case.
if (Math.abs(a.length - b.length) > maxDistance)
return Math.max(a.length, b.length);
// distance between prefix substrings of a and b
const d = [];
// pure deletions turn a into empty string
for (let i = 0; i <= a.length; i++) {
d[i] = [i];
}
// pure insertions turn empty string into b
for (let j = 0; j <= b.length; j++) {
d[0][j] = j;
}
// fill matrix
for (let j = 1; j <= b.length; j++) {
for (let i = 1; i <= a.length; i++) {
let cost = 1;
if (a[i - 1] === b[j - 1]) {
cost = 0;
} else {
cost = 1;
}
d[i][j] = Math.min(
d[i - 1][j] + 1, // deletion
d[i][j - 1] + 1, // insertion
d[i - 1][j - 1] + cost, // substitution
);
// transposition
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + 1);
}
}
}
return d[a.length][b.length];
}
/**
* Find close matches, restricted to same number of edits.
*
* @param {string} word
* @param {string[]} candidates
* @returns {string}
*/
function suggestSimilar(word, candidates) {
if (!candidates || candidates.length === 0) return '';
// remove possible duplicates
candidates = Array.from(new Set(candidates));
const searchingOptions = word.startsWith('--');
if (searchingOptions) {
word = word.slice(2);
candidates = candidates.map((candidate) => candidate.slice(2));
}
let similar = [];
let bestDistance = maxDistance;
const minSimilarity = 0.4;
candidates.forEach((candidate) => {
if (candidate.length <= 1) return; // no one character guesses
const distance = editDistance(word, candidate);
const length = Math.max(word.length, candidate.length);
const similarity = (length - distance) / length;
if (similarity > minSimilarity) {
if (distance < bestDistance) {
// better edit distance, throw away previous worse matches
bestDistance = distance;
similar = [candidate];
} else if (distance === bestDistance) {
similar.push(candidate);
}
}
});
similar.sort((a, b) => a.localeCompare(b));
if (searchingOptions) {
similar = similar.map((candidate) => `--${candidate}`);
}
if (similar.length > 1) {
return `\n(Did you mean one of ${similar.join(', ')}?)`;
}
if (similar.length === 1) {
return `\n(Did you mean ${similar[0]}?)`;
}
return '';
}
exports.suggestSimilar = suggestSimilar;

View File

@@ -0,0 +1,16 @@
{
"versions": [
{
"version": "*",
"target": {
"node": "supported"
},
"response": {
"type": "time-permitting"
},
"backing": {
"npm-funding": true
}
}
]
}

View File

@@ -0,0 +1,82 @@
{
"name": "commander",
"version": "13.1.0",
"description": "the complete solution for node.js command-line programs",
"keywords": [
"commander",
"command",
"option",
"parser",
"cli",
"argument",
"args",
"argv"
],
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/tj/commander.js.git"
},
"scripts": {
"check": "npm run check:type && npm run check:lint && npm run check:format",
"check:format": "prettier --check .",
"check:lint": "eslint .",
"check:type": "npm run check:type:js && npm run check:type:ts",
"check:type:ts": "tsd && tsc -p tsconfig.ts.json",
"check:type:js": "tsc -p tsconfig.js.json",
"fix": "npm run fix:lint && npm run fix:format",
"fix:format": "prettier --write .",
"fix:lint": "eslint --fix .",
"test": "jest && npm run check:type:ts",
"test-all": "jest && npm run test-esm && npm run check",
"test-esm": "node ./tests/esm-imports-test.mjs"
},
"files": [
"index.js",
"lib/*.js",
"esm.mjs",
"typings/index.d.ts",
"typings/esm.d.mts",
"package-support.json"
],
"type": "commonjs",
"main": "./index.js",
"exports": {
".": {
"require": {
"types": "./typings/index.d.ts",
"default": "./index.js"
},
"import": {
"types": "./typings/esm.d.mts",
"default": "./esm.mjs"
},
"default": "./index.js"
},
"./esm.mjs": {
"types": "./typings/esm.d.mts",
"import": "./esm.mjs"
}
},
"devDependencies": {
"@eslint/js": "^9.4.0",
"@types/jest": "^29.2.4",
"@types/node": "^22.7.4",
"eslint": "^9.17.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-jest": "^28.3.0",
"globals": "^15.7.0",
"jest": "^29.3.1",
"prettier": "^3.2.5",
"ts-jest": "^29.0.3",
"tsd": "^0.31.0",
"typescript": "^5.0.4",
"typescript-eslint": "^8.12.2"
},
"types": "typings/index.d.ts",
"engines": {
"node": ">=18"
},
"support": true
}

View File

@@ -0,0 +1,3 @@
// Just reexport the types from cjs
// This is a bit indirect. There is not an index.js, but TypeScript will look for index.d.ts for types.
export * from './index.js';

File diff suppressed because it is too large Load Diff

53
node_modules/@wallet-standard/errors/package.json generated vendored Normal file
View File

@@ -0,0 +1,53 @@
{
"name": "@wallet-standard/errors",
"version": "0.1.1",
"author": "Solana Maintainers <maintainers@solana.foundation>",
"repository": "https://github.com/wallet-standard/wallet-standard",
"license": "Apache-2.0",
"publishConfig": {
"access": "public"
},
"files": [
"bin",
"lib",
"src",
"LICENSE"
],
"engines": {
"node": ">=16"
},
"type": "module",
"sideEffects": false,
"bin": "./bin/cli.mjs",
"main": "./lib/cjs/index.js",
"module": "./lib/esm/index.js",
"types": "./lib/types/index.d.ts",
"exports": {
"require": "./lib/cjs/index.js",
"import": "./lib/esm/index.js",
"types": "./lib/types/index.d.ts"
},
"targets": {
"bin": {
"context": "node",
"distDir": "lib/",
"isLibrary": true,
"optimize": false,
"sourceMap": false
}
},
"dependencies": {
"chalk": "^5.4.1",
"commander": "^13.1.0"
},
"devDependencies": {
"parcel": "^2.14.4",
"shx": "^0.4.0"
},
"scripts": {
"clean": "shx mkdir -p lib && shx rm -rf lib",
"build": "parcel build --target bin src/cli.ts",
"package": "shx mkdir -p lib/cjs && shx echo '{ \"type\": \"commonjs\" }' > lib/cjs/package.json",
"test": "jest -c ../../../node_modules/@wallet-standard/test-config/jest.config.ts --rootDir ."
}
}

View File

@@ -0,0 +1,88 @@
import { decodeEncodedContext, encodeContextObject } from '../context.js';
async function getTestContext() {
return {
a: BigInt(1),
b: '"bar"',
c: "'baz'",
d: '!=$&ymbo;s\\',
e: [1, ["'2a'", '"2b"', '2c'], 3],
f: Symbol('hi'),
g: { foo: 'bar' },
h: new URL('http://anza.xyz'),
i: ((await crypto.subtle.generateKey('Ed25519', false /* extractable */, ['sign', 'verify'])) as CryptoKeyPair)
.privateKey,
j: Object.create(null),
k: null,
l: undefined,
m: "'",
n: "\\'",
o: "\\\\'",
p: '🚀',
q: 'حب',
r: 'प्यार',
s: '爱',
} as const;
}
const EXPECTED_URL_ENCODED_CONTEXT =
'a=1n&' +
'b=%22bar%22&' +
"c='baz'&" +
'd=!%3D%24%26ymbo%3Bs%5C&' +
"e=%5B1%2C%20%5B'2a'%2C%20%222b%22%2C%202c%5D%2C%203%5D&" +
'f=Symbol(hi)&' +
'g=%5Bobject%20Object%5D&' +
'h=http%3A%2F%2Fanza.xyz%2F&' +
'i=%5Bobject%20CryptoKey%5D&' +
'j=%5Bobject%20Object%5D&' +
'k=null&' +
'l=undefined&' +
"m='&" +
"n=%5C'&" +
"o=%5C%5C'&" +
'p=%F0%9F%9A%80&' +
'q=%D8%AD%D8%A8&' +
'r=%E0%A4%AA%E0%A5%8D%E0%A4%AF%E0%A4%BE%E0%A4%B0&' +
's=%E7%88%B1';
describe('decodeEncodedContext', () => {
it('produces the expected context object from a URL-encoded search string', () => {
const encodedContext = btoa(EXPECTED_URL_ENCODED_CONTEXT);
expect(decodeEncodedContext(encodedContext)).toStrictEqual({
a: '1n',
b: '"bar"',
c: "'baz'",
d: '!=$&ymbo;s\\',
e: '[1, [\'2a\', "2b", 2c], 3]',
f: 'Symbol(hi)',
g: '[object Object]',
h: 'http://anza.xyz/',
i: '[object CryptoKey]',
j: '[object Object]',
k: 'null',
l: 'undefined',
m: "'",
n: "\\'",
o: "\\\\'",
p: '🚀',
q: 'حب',
r: 'प्यार',
s: '爱',
});
});
});
describe('encodeContextObject', () => {
let context: object;
beforeEach(async () => {
context = await getTestContext();
});
it('produces a string with no single quotes in it', () => {
const encodedContext = encodeContextObject(context);
expect(encodedContext).not.toContain("'");
});
it('produces encoded context that base64 decodes to the expected URL-encoded search string', () => {
const encodedContext = encodeContextObject(context);
expect(atob(encodedContext)).toBe(EXPECTED_URL_ENCODED_CONTEXT);
});
});

View File

@@ -0,0 +1,122 @@
import { isWalletStandardError, WalletStandardError } from '../error.js';
import { getErrorMessage } from '../message-formatter.js';
jest.mock('../message-formatter');
describe('WalletStandardError', () => {
describe('given an error with context', () => {
let errorWithContext: WalletStandardError;
beforeEach(() => {
errorWithContext = new WalletStandardError(
// @ts-expect-error Mock error codes don't conform to `WalletStandardErrorCode`
123,
{ foo: 'bar' }
);
});
it('exposes its error code', () => {
expect(errorWithContext.context).toHaveProperty('__code', 123);
});
it('exposes its context', () => {
expect(errorWithContext.context).toHaveProperty('foo', 'bar');
});
it('exposes no cause', () => {
expect(errorWithContext.cause).toBeUndefined();
});
it('calls the message formatter with the code and context', () => {
expect(getErrorMessage).toHaveBeenCalledWith(123, { foo: 'bar' });
});
});
describe('given an error with no context', () => {
beforeEach(() => {
new WalletStandardError(
// @ts-expect-error Mock error codes don't conform to `WalletStandardErrorCode`
123,
undefined
);
});
it('calls the message formatter with undefined context', () => {
expect(getErrorMessage).toHaveBeenCalledWith(123, undefined);
});
});
describe('given an error with a cause', () => {
let errorWithCause: WalletStandardError;
let cause: unknown;
beforeEach(() => {
cause = {};
errorWithCause = new WalletStandardError(
// @ts-expect-error Mock error codes don't conform to `WalletStandardErrorCode`
123,
{ cause }
);
});
it('exposes its cause', () => {
expect(errorWithCause.cause).toBe(cause);
});
});
describe.each(['cause'])('given an error with only the `%s` property from `ErrorOptions` present', (propName) => {
let errorOptionValue: unknown;
let errorWithOption: WalletStandardError;
beforeEach(() => {
errorOptionValue = Symbol();
errorWithOption = new WalletStandardError(
// @ts-expect-error Mock error codes don't conform to `WalletStandardErrorCode`
123,
{ [propName]: errorOptionValue }
);
});
it('omits the error option from its context', () => {
expect(errorWithOption.context).not.toHaveProperty(propName);
});
it('calls the message formatter with the error option omitted', () => {
expect(getErrorMessage).toHaveBeenCalledWith(
123,
expect.not.objectContaining({ [propName]: errorOptionValue })
);
});
});
it('sets its message to the output of the message formatter', async () => {
expect.assertions(1);
jest.mocked(getErrorMessage).mockReturnValue('o no');
await jest.isolateModulesAsync(async () => {
const WalletStandardErrorModule =
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
await import('../error');
// @ts-expect-error Mock error codes don't conform to `WalletStandardErrorCode`
const error456 = new WalletStandardErrorModule.WalletStandardError(456);
expect(error456).toHaveProperty('message', 'o no');
});
});
});
describe('isWalletStandardError()', () => {
let error123: WalletStandardError;
beforeEach(() => {
// @ts-expect-error Mock error codes don't conform to `WalletStandardErrorCode`
error123 = new WalletStandardError(123);
});
it('returns `true` for an instance of `WalletStandardError`', () => {
expect(isWalletStandardError(error123)).toBe(true);
});
it('returns `false` for an instance of `Error`', () => {
expect(isWalletStandardError(new Error('bad thing'))).toBe(false);
});
it('returns `true` when the error code matches', () => {
expect(
isWalletStandardError(
error123,
// @ts-expect-error Mock error codes don't conform to `WalletStandardErrorCode`
123
)
).toBe(true);
});
it('returns `false` when the error code does not match', () => {
expect(
isWalletStandardError(
error123,
// @ts-expect-error Mock error codes don't conform to `WalletStandardErrorCode`
456
)
).toBe(false);
});
});

View File

@@ -0,0 +1,188 @@
import type { WalletStandardErrorCode } from '../codes.js';
import { encodeContextObject } from '../context.js';
import { getErrorMessage } from '../message-formatter.js';
import * as MessagesModule from '../messages.js';
jest.mock('../context');
jest.mock('../messages', () => ({
get WalletStandardErrorMessages() {
return {};
},
__esModule: true,
}));
describe('getErrorMessage', () => {
describe('in production mode', () => {
let originalEnv = process.env;
beforeEach(() => {
originalEnv = process.env;
process.env = { ...originalEnv, NODE_ENV: 'production' };
});
afterEach(() => {
process.env = originalEnv; // Reset to the original env
});
it('renders advice on where to decode a context-less error', () => {
const message = getErrorMessage(
// @ts-expect-error Mock error codes don't conform to `WalletStandardErrorCode`
123
);
expect(message).toBe(
'Wallet Standard error #123; Decode this error by running `npx @wallet-standard/errors decode -- 123`'
);
});
it('does not call the context encoder when the error has no context', () => {
getErrorMessage(
// @ts-expect-error Mock error codes don't conform to `WalletStandardErrorCode`
123
);
expect(encodeContextObject).not.toHaveBeenCalled();
});
it('does not call the context encoder when the error context has no keys', () => {
const context = {};
getErrorMessage(
// @ts-expect-error Mock error codes don't conform to `WalletStandardErrorCode`
123,
context
);
expect(encodeContextObject).not.toHaveBeenCalled();
});
it('calls the context encoder with the context', () => {
const context = { foo: 'bar' };
getErrorMessage(
// @ts-expect-error Mock error codes don't conform to `WalletStandardErrorCode`
123,
context
);
expect(encodeContextObject).toHaveBeenCalledWith(context);
});
it('renders advice on where to decode an error with encoded context', () => {
jest.mocked(encodeContextObject).mockReturnValue('ENCODED_CONTEXT');
const context = { foo: 'bar' };
const message = getErrorMessage(123 as WalletStandardErrorCode, context);
expect(message).toBe(
"Wallet Standard error #123; Decode this error by running `npx @wallet-standard/errors decode -- 123 'ENCODED_CONTEXT'`"
);
});
it('renders no encoded context in the decoding advice when the context has no keys', () => {
jest.mocked(encodeContextObject).mockReturnValue('ENCODED_CONTEXT');
const context = {};
const message = getErrorMessage(123 as WalletStandardErrorCode, context);
expect(message).toBe(
'Wallet Standard error #123; Decode this error by running `npx @wallet-standard/errors decode -- 123`'
);
});
});
describe('in dev mode', () => {
let originalEnv = process.env;
beforeEach(() => {
originalEnv = process.env;
process.env = { ...originalEnv, NODE_ENV: 'development' };
});
afterEach(() => {
process.env = originalEnv; // Reset to the original env
});
it('renders static error messages', () => {
const messagesSpy = jest.spyOn(MessagesModule, 'WalletStandardErrorMessages', 'get');
messagesSpy.mockReturnValue({
// @ts-expect-error Mock error config doesn't conform to exported config.
123: 'static error message',
});
const message = getErrorMessage(
// @ts-expect-error Mock error config doesn't conform to exported config.
123
);
expect(message).toBe('static error message');
});
it.each([
{
expected: "Something awful happened: 'bar'. How awful!",
input: "Something $severity happened: '$foo'. How $severity!",
},
// Literal backslashes, escaped dollar signs
{
expected: 'How \\awful\\ is the $severity?',
input: 'How \\\\$severity\\\\ is the \\$severity?',
},
// Variable at beginning of sequence
{ expected: 'awful times!', input: '$severity times!' },
// Variable at end of sequence
{ expected: "Isn't it awful?", input: "Isn't it $severity?" },
// Variable in middle of text sequence
{ expected: '~awful~', input: '~$severity~' },
// Variable interpolation with no value in the lookup
{ expected: 'Is $thing a sandwich?', input: 'Is $thing a sandwich?' },
// Variable that has, as a substring, some other value in the lookup
{ expected: '$fool', input: '$fool' },
// Trick for butting a variable up against regular text
{ expected: 'barl', input: '$foo\\l' },
// Escaped variable marker
{ expected: "It's the $severity, ya hear?", input: "It's the \\$severity, ya hear?" },
// Single dollar sign
{ expected: ' $ ', input: ' $ ' },
// Single dollar sign at start
{ expected: '$ ', input: '$ ' },
// Single dollar sign at end
{ expected: ' $', input: ' $' },
// Double dollar sign with legitimate variable name
{ expected: ' $bar ', input: ' $$foo ' },
// Double dollar sign with legitimate variable name at start
{ expected: '$bar ', input: '$$foo ' },
// Double dollar sign with legitimate variable name at end
{ expected: ' $bar', input: ' $$foo' },
// Single escape sequence
{ expected: ' ', input: ' \\ ' },
// Single escape sequence at start
{ expected: ' ', input: '\\ ' },
// Single escape sequence at end
{ expected: ' ', input: ' \\' },
// Double escape sequence
{ expected: ' \\ ', input: ' \\\\ ' },
// Double escape sequence at start
{ expected: '\\ ', input: '\\\\ ' },
// Double escape sequence at end
{ expected: ' \\', input: ' \\\\' },
// Just text
{ expected: 'Some unencumbered text.', input: 'Some unencumbered text.' },
// Empty string
{ expected: '', input: '' },
])('interpolates variables into the error message format string `"$input"`', ({ input, expected }) => {
const messagesSpy = jest.spyOn(MessagesModule, 'WalletStandardErrorMessages', 'get');
messagesSpy.mockReturnValue({
// @ts-expect-error Mock error config doesn't conform to exported config.
123: input,
});
const message = getErrorMessage(
// @ts-expect-error Mock error context doesn't conform to exported context.
123,
{ foo: 'bar', severity: 'awful' }
);
expect(message).toBe(expected);
});
it('interpolates a Uint8Array variable into a error message format string', () => {
const messagesSpy = jest.spyOn(MessagesModule, 'WalletStandardErrorMessages', 'get');
messagesSpy.mockReturnValue({
// @ts-expect-error Mock error config doesn't conform to exported config.
123: 'Here is some data: $data',
});
const message = getErrorMessage(
// @ts-expect-error Mock error context doesn't conform to exported context.
123,
{ data: new Uint8Array([1, 2, 3, 4]) }
);
expect(message).toBe('Here is some data: 1,2,3,4');
});
it('interpolates an undefined variable into a error message format string', () => {
const messagesSpy = jest.spyOn(MessagesModule, 'WalletStandardErrorMessages', 'get');
messagesSpy.mockReturnValue({
// @ts-expect-error Mock error config doesn't conform to exported config.
123: 'Here is a variable: $variable',
});
const message = getErrorMessage(
// @ts-expect-error Mock error context doesn't conform to exported context.
123,
{ variable: undefined }
);
expect(message).toBe('Here is a variable: undefined');
});
});
});

View File

@@ -0,0 +1,59 @@
import * as WalletStandardErrorCodeModule from '../codes.js';
import type { WalletStandardErrorCode } from '../codes.js';
import type { WalletStandardErrorContext } from '../context.js';
import { isWalletStandardError, WalletStandardError } from '../error.js';
const { WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND, WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND } =
WalletStandardErrorCodeModule;
// If this line raises a type error, you might have forgotten to add a new error to the
// `WalletStandardErrorCode` union in `src/codes.ts`.
Object.values(WalletStandardErrorCodeModule) satisfies WalletStandardErrorCode[];
const walletAccountNotFoundError = new WalletStandardError(WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND, {
address: 'abc',
walletName: 'Mock Wallet',
});
{
const code = walletAccountNotFoundError.context.__code;
code satisfies typeof WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND;
// @ts-expect-error Wrong error code.
code satisfies typeof WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND;
}
walletAccountNotFoundError.context satisfies WalletStandardErrorContext[typeof WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND];
// @ts-expect-error Non existent context property.
walletAccountNotFoundError.context.chains;
new WalletStandardError(WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND);
// @ts-expect-error Missing context property (`address` and `walletName`)
new WalletStandardError(WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND);
const unknownError = null as unknown as WalletStandardError;
if (unknownError.context.__code === WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND) {
unknownError.context satisfies WalletStandardErrorContext[typeof WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND];
// @ts-expect-error Context belongs to another error code
unknownError.context satisfies WalletStandardErrorContext[typeof WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND];
}
const e = null as unknown;
if (isWalletStandardError(e)) {
e.context satisfies Readonly<{ __code: WalletStandardErrorCode }>;
}
if (isWalletStandardError(e, WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND)) {
e.context satisfies WalletStandardErrorContext[typeof WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND];
// @ts-expect-error Context belongs to another error code
e.context satisfies WalletStandardErrorContext[typeof WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND];
}
// `WalletStandardErrorContext` must not contain any keys reserved by `ErrorOptions` (eg. `cause`)
null as unknown as WalletStandardErrorContext satisfies {
[Code in keyof WalletStandardErrorContext]: WalletStandardErrorContext[Code] extends undefined
? undefined
: {
[PP in keyof WalletStandardErrorContext[Code]]: PP extends keyof ErrorOptions
? never
: WalletStandardErrorContext[Code][PP];
};
};

63
node_modules/@wallet-standard/errors/src/cli.ts generated vendored Normal file
View File

@@ -0,0 +1,63 @@
import chalk from 'chalk';
import { Command, InvalidArgumentError } from 'commander';
import { version } from '../package.json';
import type { WalletStandardErrorCode } from './codes.js';
import { decodeEncodedContext } from './context.js';
import { getHumanReadableErrorMessage } from './message-formatter.js';
import { WalletStandardErrorMessages } from './messages.js';
const program = new Command();
program
.name('@wallet-standard/errors')
.description('Decode Wallet Standard JavaScript errors thrown in production')
.version(version);
program
.command('decode')
.description('Decode a `WalletStandardErrorCode` to a human-readable message')
.argument('<code>', 'numeric error code to decode', (rawCode) => {
const code = parseInt(rawCode, 10);
if (isNaN(code) || `${code}` !== rawCode) {
throw new InvalidArgumentError('It must be an integer');
}
if (!(code in WalletStandardErrorMessages)) {
throw new InvalidArgumentError('There exists no error with that code');
}
return code;
})
.argument('[encodedContext]', 'encoded context to interpolate into the error message', (encodedContext) => {
try {
return decodeEncodedContext(encodedContext);
} catch (e) {
throw new InvalidArgumentError('Encoded context malformed');
}
})
.action((code: number, context) => {
const message = getHumanReadableErrorMessage(code as WalletStandardErrorCode, context);
console.log(`
${
chalk.bold(
chalk.rgb(154, 71, 255)('[') +
chalk.rgb(144, 108, 244)('D') +
chalk.rgb(134, 135, 233)('e') +
chalk.rgb(122, 158, 221)('c') +
chalk.rgb(110, 178, 209)('o') +
chalk.rgb(95, 195, 196)('d') +
chalk.rgb(79, 212, 181)('e') +
chalk.rgb(57, 227, 166)('d') +
chalk.rgb(19, 241, 149)(']')
) + chalk.rgb(19, 241, 149)(' Wallet Standard error code #' + code)
}
- ${message}`);
if (context) {
console.log(`
${chalk.yellowBright(chalk.bold('[Context]'))}
${JSON.stringify(context, null, 4).split('\n').join('\n ')}`);
}
});
export function run(argv: readonly string[]) {
program.parse(argv);
}

64
node_modules/@wallet-standard/errors/src/codes.ts generated vendored Normal file
View File

@@ -0,0 +1,64 @@
/**
* To add a new error, follow the instructions at
* https://github.com/wallet-standard/wallet-standard/tree/master/packages/core/errors/#adding-a-new-error
*
* WARNING:
* - Don't remove error codes
* - Don't change or reorder error codes.
*
* Good naming conventions:
* - Prefixing common errors — e.g. under the same package — can be a good way to namespace them. E.g. All codec-related errors start with `WALLET_STANDARD_ERROR__ACCOUNT__`.
* - Use consistent names — e.g. choose `PDA` or `PROGRAM_DERIVED_ADDRESS` and stick with it. Ensure your names are consistent with existing error codes. The decision might have been made for you.
* - Recommended prefixes and suffixes:
* - `MALFORMED_`: Some input was not constructed properly. E.g. `MALFORMED_BASE58_ENCODED_ADDRESS`.
* - `INVALID_`: Some input is invalid (other than because it was MALFORMED). E.g. `INVALID_NUMBER_OF_BYTES`.
* - `EXPECTED_`: Some input was different than expected, no need to specify the "GOT" part unless necessary. E.g. `EXPECTED_DECODED_ACCOUNT`.
* - `_CANNOT_`: Some operation cannot be performed or some input cannot be used due to some condition. E.g. `CANNOT_DECODE_EMPTY_BYTE_ARRAY` or `PDA_CANNOT_END_WITH_PDA_MARKER`.
* - `_MUST_BE_`: Some condition must be true. E.g. `NONCE_TRANSACTION_FIRST_INSTRUCTION_MUST_BE_ADVANCE_NONCE`.
* - `_FAILED_TO_`: Tried to perform some operation and failed. E.g. `FAILED_TO_DECODE_ACCOUNT`.
* - `_NOT_FOUND`: Some operation lead to not finding something. E.g. `ACCOUNT_NOT_FOUND`.
* - `_OUT_OF_RANGE`: Some value is out of range. E.g. `ENUM_DISCRIMINATOR_OUT_OF_RANGE`.
* - `_EXCEEDED`: Some limit was exceeded. E.g. `PDA_MAX_SEED_LENGTH_EXCEEDED`.
* - `_MISMATCH`: Some elements do not match. E.g. `ENCODER_DECODER_FIXED_SIZE_MISMATCH`.
* - `_MISSING`: Some required input is missing. E.g. `TRANSACTION_FEE_PAYER_MISSING`.
* - `_UNIMPLEMENTED`: Some required component is not available in the environment. E.g. `SUBTLE_CRYPTO_VERIFY_FUNCTION_UNIMPLEMENTED`.
*/
// Registry-related errors.
// Reserve error codes in the range [3834000-3834999].
export const WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND = 3834000 as const;
export const WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND = 3834001 as const;
// User-related errors.
// Reserve error codes in the range [4001000-4001999].
export const WALLET_STANDARD_ERROR__USER__REQUEST_REJECTED = 4001000 as const;
// Feature-related errors.
// Reserve error codes in the range [6160000-6160999].
export const WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED = 6160000 as const;
export const WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED = 6160001 as const;
export const WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED = 6160002 as const;
/**
* A union of every Wallet Standard error code
*
* You might be wondering why this is not a TypeScript enum or const enum.
*
* One of the goals of this library is to enable people to use some or none of it without having to
* bundle all of it.
*
* If we made the set of error codes an enum then anyone who imported it (even if to only use a
* single error code) would be forced to bundle every code and its label.
*
* Const enums appear to solve this problem by letting the compiler inline only the codes that are
* actually used. Unfortunately exporting ambient (const) enums from a library like
* `@wallet-standard/errors` is not safe, for a variety of reasons covered here:
* https://stackoverflow.com/a/28818850
*/
export type WalletStandardErrorCode =
| typeof WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED
| typeof WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED
| typeof WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED
| typeof WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND
| typeof WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND
| typeof WALLET_STANDARD_ERROR__USER__REQUEST_REJECTED;

77
node_modules/@wallet-standard/errors/src/context.ts generated vendored Normal file
View File

@@ -0,0 +1,77 @@
import type {
WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED,
WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED,
WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND,
WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED,
WalletStandardErrorCode,
} from './codes.js';
type DefaultUnspecifiedErrorContextToUndefined<T> = {
[P in WalletStandardErrorCode]: P extends keyof T ? T[P] : undefined;
};
/**
* To add a new error, follow the instructions at
* https://github.com/wallet-standard/wallet-standard/tree/master/packages/core/errors/#adding-a-new-error
*
* WARNING:
* - Don't change or remove members of an error's context.
*/
export type WalletStandardErrorContext = DefaultUnspecifiedErrorContextToUndefined<{
[WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED]: {
address: string;
chain: string;
featureName: string;
supportedChains: string[];
supportedFeatures: string[];
};
[WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED]: {
address: string;
featureName: string;
supportedChains: string[];
supportedFeatures: string[];
};
[WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED]: {
featureName: string;
supportedFeatures: string[];
supportedChains: string[];
walletName: string;
};
[WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND]: {
address: string;
walletName: string;
};
}>;
export function decodeEncodedContext(encodedContext: string): object {
const decodedUrlString = atob(encodedContext);
return Object.fromEntries(new URLSearchParams(decodedUrlString).entries());
}
function encodeValue(value: unknown): string {
if (Array.isArray(value)) {
const commaSeparatedValues = value.map(encodeValue).join('%2C%20' /* ", " */);
return '%5B' /* "[" */ + commaSeparatedValues + /* "]" */ '%5D';
} else if (typeof value === 'bigint') {
return `${value}n`;
} else {
return encodeURIComponent(
String(
value != null && Object.getPrototypeOf(value) === null
? // Plain objects with no prototype don't have a `toString` method.
// Convert them before stringifying them.
{ ...(value as object) }
: value
)
);
}
}
function encodeObjectContextEntry([key, value]: [string, unknown]): `${typeof key}=${string}` {
return `${key}=${encodeValue(value)}`;
}
export function encodeContextObject(context: object): string {
const searchParamsString = Object.entries(context).map(encodeObjectContextEntry).join('&');
return btoa(searchParamsString);
}

59
node_modules/@wallet-standard/errors/src/error.ts generated vendored Normal file
View File

@@ -0,0 +1,59 @@
import type { WalletStandardErrorCode } from './codes.js';
import type { WalletStandardErrorContext } from './context.js';
import { getErrorMessage } from './message-formatter.js';
export function isWalletStandardError<TErrorCode extends WalletStandardErrorCode>(
e: unknown,
code?: TErrorCode
): e is WalletStandardError<TErrorCode> {
const isWalletStandardError = e instanceof Error && e.name === 'WalletStandardError';
if (isWalletStandardError) {
if (code !== undefined) {
return (e as WalletStandardError<TErrorCode>).context.__code === code;
}
return true;
}
return false;
}
type WalletStandardErrorCodedContext = Readonly<{
[P in WalletStandardErrorCode]: (WalletStandardErrorContext[P] extends undefined
? object
: WalletStandardErrorContext[P]) & {
__code: P;
};
}>;
export class WalletStandardError<TErrorCode extends WalletStandardErrorCode = WalletStandardErrorCode> extends Error {
readonly context: WalletStandardErrorCodedContext[TErrorCode];
constructor(
...[code, contextAndErrorOptions]: WalletStandardErrorContext[TErrorCode] extends undefined
? [code: TErrorCode, errorOptions?: ErrorOptions | undefined]
: [
code: TErrorCode,
contextAndErrorOptions: WalletStandardErrorContext[TErrorCode] & (ErrorOptions | undefined),
]
) {
let context: WalletStandardErrorContext[TErrorCode] | undefined;
let errorOptions: ErrorOptions | undefined;
if (contextAndErrorOptions) {
// If the `ErrorOptions` type ever changes, update this code.
const { cause, ...contextRest } = contextAndErrorOptions;
if (cause) {
errorOptions = { cause };
}
if (Object.keys(contextRest).length > 0) {
context = contextRest as WalletStandardErrorContext[TErrorCode];
}
}
const message = getErrorMessage(code, context);
super(message, errorOptions);
this.context = {
__code: code,
...context,
} as WalletStandardErrorCodedContext[TErrorCode];
// This is necessary so that `isWalletStandardError()` can identify a `WalletStandardError`
// without having to import the class for use in an `instanceof` check.
this.name = 'WalletStandardError';
}
}

3
node_modules/@wallet-standard/errors/src/index.ts generated vendored Normal file
View File

@@ -0,0 +1,3 @@
export * from './codes.js';
export * from './error.js';
export * from './stack-trace.js';

View File

@@ -0,0 +1,101 @@
import type { WalletStandardErrorCode } from './codes.js';
import { encodeContextObject } from './context.js';
import { WalletStandardErrorMessages } from './messages.js';
const enum StateType {
EscapeSequence,
Text,
Variable,
}
type State = Readonly<{
[START_INDEX]: number;
[TYPE]: StateType;
}>;
const START_INDEX = 'i';
const TYPE = 't';
export function getHumanReadableErrorMessage<TErrorCode extends WalletStandardErrorCode>(
code: TErrorCode,
context: object = {}
): string {
const messageFormatString = WalletStandardErrorMessages[code];
if (messageFormatString.length === 0) {
return '';
}
let state: State;
function commitStateUpTo(endIndex?: number) {
if (state[TYPE] === StateType.Variable) {
const variableName = messageFormatString.slice(state[START_INDEX] + 1, endIndex);
fragments.push(
variableName in context ? `${context[variableName as keyof typeof context]}` : `$${variableName}`
);
} else if (state[TYPE] === StateType.Text) {
fragments.push(messageFormatString.slice(state[START_INDEX], endIndex));
}
}
const fragments: string[] = [];
messageFormatString.split('').forEach((char, ii) => {
if (ii === 0) {
state = {
[START_INDEX]: 0,
[TYPE]:
messageFormatString[0] === '\\'
? StateType.EscapeSequence
: messageFormatString[0] === '$'
? StateType.Variable
: StateType.Text,
};
return;
}
let nextState;
switch (state[TYPE]) {
case StateType.EscapeSequence:
nextState = { [START_INDEX]: ii, [TYPE]: StateType.Text };
break;
case StateType.Text:
if (char === '\\') {
nextState = { [START_INDEX]: ii, [TYPE]: StateType.EscapeSequence };
} else if (char === '$') {
nextState = { [START_INDEX]: ii, [TYPE]: StateType.Variable };
}
break;
case StateType.Variable:
if (char === '\\') {
nextState = { [START_INDEX]: ii, [TYPE]: StateType.EscapeSequence };
} else if (char === '$') {
nextState = { [START_INDEX]: ii, [TYPE]: StateType.Variable };
} else if (!char.match(/\w/)) {
nextState = { [START_INDEX]: ii, [TYPE]: StateType.Text };
}
break;
}
if (nextState) {
if (state !== nextState) {
commitStateUpTo(ii);
}
state = nextState;
}
});
commitStateUpTo();
return fragments.join('');
}
export function getErrorMessage<TErrorCode extends WalletStandardErrorCode>(
code: TErrorCode,
context: object = {}
): string {
if (process.env.NODE_ENV !== 'production') {
return getHumanReadableErrorMessage(code, context);
} else {
let decodingAdviceMessage = `Wallet Standard error #${code}; Decode this error by running \`npx @wallet-standard/errors decode -- ${code}`;
if (Object.keys(context).length) {
/**
* DANGER: Be sure that the shell command is escaped in such a way that makes it
* impossible for someone to craft malicious context values that would result in
* an exploit against anyone who bindly copy/pastes it into their terminal.
*/
decodingAdviceMessage += ` '${encodeContextObject(context)}'`;
}
return `${decodingAdviceMessage}\``;
}
}

35
node_modules/@wallet-standard/errors/src/messages.ts generated vendored Normal file
View File

@@ -0,0 +1,35 @@
import type { WalletStandardErrorCode } from './codes.js';
import {
WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED,
WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED,
WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED,
WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND,
WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND,
WALLET_STANDARD_ERROR__USER__REQUEST_REJECTED,
} from './codes.js';
/**
* To add a new error, follow the instructions at
* https://github.com/wallet-standard/wallet-standard/tree/master/packages/core/errors#adding-a-new-error
*
* WARNING:
* - Don't change the meaning of an error message.
*/
export const WalletStandardErrorMessages: Readonly<{
// This type makes this data structure exhaustive with respect to `WalletStandardErrorCode`.
// TypeScript will fail to build this project if add an error code without a message.
[P in WalletStandardErrorCode]: string;
}> = {
[WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_CHAIN_UNSUPPORTED]:
'The wallet account $address does not support the chain `$chain`',
[WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED]:
'The wallet account $address does not support the `$featureName` feature',
[WALLET_STANDARD_ERROR__FEATURES__WALLET_FEATURE_UNIMPLEMENTED]:
"The wallet '$walletName' does not support the `$featureName` feature",
[WALLET_STANDARD_ERROR__REGISTRY__WALLET_ACCOUNT_NOT_FOUND]:
"No account with address $address could be found in the '$walletName' wallet",
[WALLET_STANDARD_ERROR__REGISTRY__WALLET_NOT_FOUND]:
'No underlying Wallet Standard wallet could be found for this handle. This can happen if ' +
'the wallet associated with the handle has been unregistered.',
[WALLET_STANDARD_ERROR__USER__REQUEST_REJECTED]: 'The user rejected the request',
};

View File

@@ -0,0 +1,5 @@
export function safeCaptureStackTrace(...args: Parameters<typeof Error.captureStackTrace>): void {
if ('captureStackTrace' in Error && typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(...args);
}
}