diff --git a/.eslintignore b/.eslintignore index 473e3ac..d3decb7 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ node_modules coverage -CHANGELOG.md \ No newline at end of file +CHANGELOG.md +*.d.ts \ No newline at end of file diff --git a/API.md b/API.md index ee883b4..9e817fc 100644 --- a/API.md +++ b/API.md @@ -29,11 +29,11 @@ A class for encoding and decoding base 10 integers to a custom alphanumeric base ### Parameters -- `configOptions` **[object][21]?** Optional object defining initial settings for the class (optional, default `{}`) +- `configOptions` **[object][21]?** Optional object defining initial settings for the class (optional, default `{allowLowerCaseDictionary:false,dictionary:'ABCDEFGHIJKLMNOPQRSTUVWXYZ'}`) - - `configOptions.allowLowerCaseDictionary` **[boolean][22]?** Whether or not to allow lower case letters in the dictionary - - `configOptions.dictionary` **[string][23]?** Starting dictionary to use. Must contain only letters or numbers. Characters cannot be repeated. - If `allowLowerCaseDictionary = true`, then lower case letters are not considered the same as upper case. (e.g. 'ABCabc' has 6 unique characters.) + - `configOptions.allowLowerCaseDictionary` **[boolean][22]** Whether or not to allow lower case letters in the dictionary (optional, default `false`) + - `configOptions.dictionary` **[string][23]** Starting dictionary to use. Must contain only letters or numbers. Characters cannot be repeated. + If `allowLowerCaseDictionary = true`, then lower case letters are not considered the same as upper case. (e.g. 'ABCabc' has 6 unique characters.) (optional, default `'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`) ### Examples @@ -240,6 +240,10 @@ console.log(encoder.deconstruct('')) // undefined Returns **[Array][27]<[number][25]>** An array of numbers. Characters not present in the dictionary are treated as letters and return `undefined` for that array value. Passing an empty string (`''`), `null`, or `undefined` will return `undefined` for the whole function. +## + +Type: [string][23] + [1]: #alphanumericencoder [2]: #parameters [3]: #examples diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..ce83a64 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,25 @@ +// Manually generated from https://www.typescriptlang.org/play + +export class AlphanumericEncoder { + constructor(configOptions?: { + allowLowerCaseDictionary: boolean | undefined + dictionary: string | undefined + }) + private _defaultDictionary + private _dictionaryInUse + private _allowLowerCaseDictionary + + set allowLowerCaseDictionary(arg: boolean) + get allowLowerCaseDictionary(): boolean + + set dictionary(arg: string) + get dictionary(): string + + resetDefaultDictionary(): void + + encode(integerToEncode: number): string + + decode(stringToDecode: string): number + + deconstruct(stringToDeconstruct: string | number): number[] +} diff --git a/index.js b/index.js index 9369547..6a5e56a 100644 --- a/index.js +++ b/index.js @@ -1,10 +1,8 @@ -// @ts-check - /** * A class for encoding and decoding base 10 integers to a custom alphanumeric base representation. * @param {object} [configOptions] Optional object defining initial settings for the class - * @param {boolean} [configOptions.allowLowerCaseDictionary] Whether or not to allow lower case letters in the dictionary - * @param {string} [configOptions.dictionary] Starting dictionary to use. Must contain only letters or numbers. Characters cannot be repeated. + * @param {boolean} [configOptions.allowLowerCaseDictionary=false] Whether or not to allow lower case letters in the dictionary + * @param {string} [configOptions.dictionary='ABCDEFGHIJKLMNOPQRSTUVWXYZ'] Starting dictionary to use. Must contain only letters or numbers. Characters cannot be repeated. * If `allowLowerCaseDictionary = true`, then lower case letters are not considered the same as upper case. (e.g. 'ABCabc' has 6 unique characters.) * @example * // Import into a project @@ -26,7 +24,12 @@ * const encoder = new AlphanumericEncoder(configOptions) */ class AlphanumericEncoder { - constructor(configOptions = {}) { + constructor( + configOptions = { + allowLowerCaseDictionary: false, + dictionary: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + } + ) { /** * @private * @type {string} Internal value used to initialize and reset the dictionary @@ -209,8 +212,15 @@ class AlphanumericEncoder { ) } + /** + * Takes a letter between 0 and max letter length and returns the corresponding letter + * + * @private + * @param {number} num The index to search for + * @param {string} dictionary The dictionary used to search + * @returns {string} The letter corresponding to this number index + */ function numToLetter(num, dictionary) { - // Takes a letter between 0 and max letter length and returns the corresponding letter if (num === 0) { return undefined } @@ -330,12 +340,17 @@ class AlphanumericEncoder { } const safeString = String(stringToDeconstruct) // Force argument to string to process number arguments and prevent slice from throwing an error + /** + * @private + * @type {number[]} Array of numbers after splitting a string. + * Elements include (in order) the number or decoded number from a letter. + */ const deconstructedArray = [] let character = '' let componentPart = safeString.slice(0, 1) // Initialize with the first character (which has been guranteed present by above guard functions) // A helper function to push the final component into the array that gets returned. Numbers get added as is, strings get decoded. - const addDecodedElement = (componentString) => { + const addDecodedElement = (/** @type {string} */ componentString) => { if (componentString.match(/[0-9]/)) { deconstructedArray.push(Number.parseInt(componentString, 10)) // Numbers } else { diff --git a/index.test.js b/index.test.js index 59f488d..bce7325 100644 --- a/index.test.js +++ b/index.test.js @@ -1,8 +1,9 @@ -// @ts-check - const AlphanumericEncoder = require('./index') -let encoder = new AlphanumericEncoder() +let encoder = new AlphanumericEncoder({ + allowLowerCaseDictionary: false, + dictionary: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +}) const numberToEncodedLetters = [ [1, 'A'], @@ -67,7 +68,6 @@ describe('Allow Lower Case Dictionaries', () => { test.each([true, 1, [123], { value: 1 }])( 'allowLowerCaseDictionary with truthy value %p', (truthyTestValue) => { - // @ts-ignore encoder.allowLowerCaseDictionary = truthyTestValue expect(encoder.allowLowerCaseDictionary).toBeTruthy() } @@ -86,7 +86,6 @@ describe('Allow Lower Case Dictionaries', () => { test.each([false, 0, null, undefined])( 'allowLowerCaseDictionary with falsy value %p', (truthyTestValue) => { - // @ts-ignore encoder.allowLowerCaseDictionary = truthyTestValue expect(encoder.allowLowerCaseDictionary).toBeFalsy() } @@ -317,7 +316,7 @@ describe('Test Decoding', () => { test('Expect decoding strings to integers greater than Number.MAX_SAFE_INTEGER throws an error', () => { expect(() => { - encoder.decode('BKTXHSOGHKKF') + encoder.decode('BKTXHSOGHKKF') // BKTXHSOGHKKE is what max safe integer encodes to under default dictionary }).toThrow(/maximum safe integer/) }) diff --git a/package.json b/package.json index 31ead9d..1ffd8c3 100644 --- a/package.json +++ b/package.json @@ -24,12 +24,13 @@ "package-lock.json" ], "main": "index.js", + "types": "index.d.ts", "repository": { "type": "git", "url": "https://github.com/M-Scott-Lassiter/Alphanumeric-Encoder.git" }, "scripts": { - "build": "npm run lint && npm run test && npm run docs && npm run tableofcontents && npm run format", + "build": "npm run lint && npm run test && npm run docs && npm run tableofcontents && npm run format && echo \"Build process complete.\" && exit 0", "cz": "cz", "docs": "documentation build index.js --format md --output API.md", "format": "npx prettier . --write", diff --git a/release.config.js b/release.config.js deleted file mode 100644 index 31a9168..0000000 --- a/release.config.js +++ /dev/null @@ -1,67 +0,0 @@ -module.exports = { - branches: ['main', 'next'], - plugins: [ - [ - '@semantic-release/commit-analyzer', - { - preset: 'angular', - releaseRules: [{ scope: 'api', release: 'patch' }] - } - ], - [ - '@semantic-release/release-notes-generator', - { - preset: 'conventionalcommits', - presetConfig: { - types: [ - { - type: 'build', - section: ':building_construction: Build Changes', - hidden: false - }, - { type: 'ci', hidden: true }, - { type: 'docs', hidden: true }, - { type: 'feat', section: ':gift: Feature Changes', hidden: false }, - { type: 'fix', section: ':lady_beetle: Bug Fixes', hidden: false }, - { - type: 'perf', - section: ':fast_forward: Performance Improvements', - hidden: false - }, - { type: 'refactor', hidden: true }, - { type: 'test', section: ':dart: Test Changes', hidden: false } - ] - }, - writerOpts: { - commitsSort: ['subject', 'scope'] - } - } - ], - [ - '@semantic-release/changelog', - { - changelogFile: 'CHANGELOG.md' - } - ], - '@semantic-release/npm', - ['@semantic-release/github'], - [ - '@semantic-release/git', - { - assets: [ - 'index.js', - 'README.md', - 'API.md', - 'CHANGELOG.md', - 'CONTRIBUTING.md', - 'LICENSE', - 'package.json', - 'package-lock.json' - ], - // eslint-disable-next-line no-template-curly-in-string - message: 'docs: ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}' // These variables are used in the CD script by semantic-release - } - ] - ], - preset: 'angular' -}