Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Downloads and tests #34

Merged
merged 1 commit into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
.output
/build
/dist
/test/output

# OS
.DS_Store
Expand Down
19 changes: 13 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ The library is designed to be compatible with both module systems, so you can ch
- `getEndpoint(network?: number | string, countriesList?: string | Array<string>): { [key: string]: Array<string> }` — Get an object of SMS endpoints (phone numbers) per country.
- `sms(number?: boolean | string | number | Array<string>, message?: string, network?: number | string, encodeMessage?: boolean, platform?: string): string` — Create an SMS URI based on the provided parameters.
- `mms(number?: boolean | string | number | Array<string>, message?: string, network?: number | string, encodeMessage?: boolean, platform?: string): string` — Create an MMS URI based on the provided parameters.
- `downloadMessage(hex: string | string[], optionalFilename?: string): Promise<string>` — Download a file with the encoded content as `.txms.txt` file in your working directory. You can provide one hex transaction or an array of transactions (`.batch` will be prepended to suffix if batch is chosen and optional name not defined).
- `downloadMessage(hex: string | string[], optionalFilename?: string, optionalPath?: string): Promise<string>` — Download a file with the encoded content as `.txms.txt` file in your working directory. You can provide one hex transaction or an array of transactions (`.batch` will be prepended to suffix if batch is chosen and optional name not defined).

Note: The `downloadMessage` function is asynchronous and returns a Promise. You can use the `await` keyword to wait for the Promise to resolve. The function will download a file with the encoded content as a `(.batch).txms.txt` file in your working directory. You can optionally provide a filename as the second parameter. It is designed to be used in Node.js environments as well as Browser. It is not designed to download high amount of files. if you prefer to do your own download flow, you can use the `encode` function and save the result to a file.

Expand All @@ -160,6 +160,7 @@ Note: The `downloadMessage` function is asynchronous and returns a Promise. You
- `encodeMessage` (default: `true`) = whether to encode the message before using `encodeURIComponent`.
- `platform` = the platform to use for the SMS URI. Currently supported: `ios`, `global`. Default: `global`. `ios` uses the `&body=`, while `global` uses the `?` for `?body=` parameter.
- `optionalFilename` = the optional filename for the downloaded file suffixed with `.txms.txt`. Filename is slugified.
- `optionalPath` = the optional path for the downloaded file. If not provided, the file will be saved in the working directory.

## CLI

Expand All @@ -172,17 +173,23 @@ npm i -g txms.js
### Getting started

```bash
txms {type} {value} {value1}
txms {type}={value}
```

- type: `version` (`v`), `encode` (`e`), `decode` (`d`), `getendpoint` (`g`), `sms`, `mms`, `download` (`dl`)
- value: 1st parameter for the type
- value1: 2nd parameter for the type
Types:

- `--version` (`-v`) - Get the version of the library.
- `--encode` (`-e`) - Encode the HEX transaction.
- `--decode` (`-d`) - Decode the UTF-16BE transaction.
- `--getendpoint` (`-g`) - Get the SMS/MMS endpoint for the network and country.
- `--sms` - Create an SMS URI based on the provided parameters.
- `--mms` - Create an MMS URI based on the provided parameters.
- `--download` (`-dl`) - Boolean value to download a file with the encoded content as `.txms.txt` file in your working directory.

### Piping

```bash
echo {value} | txms {type} {value1}
echo {value} | txms {type}={value1}
```

## Extending Aliases and Countries
Expand Down
200 changes: 157 additions & 43 deletions bin/txms
Original file line number Diff line number Diff line change
@@ -1,14 +1,122 @@
#!/usr/bin/env node

import { mkdirSync, readFileSync, existsSync } from 'fs';
import { fileURLToPath } from 'url';
import path from 'path';
import txms from '../dist/index.js';

if (process.stdin.isTTY) {
const typ = process.argv[2];
const value = process.argv[3];
const value1 = process.argv[4];
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Helper function to parse command-line arguments with key-value pairs
function parseArgs(argv) {
const args = {
kind: null, // The type of operation to perform
value: null, // This will hold the hex data for encode/decode
output: null, // For download output directory
filename: null, // For download filename
countryCodes: null, // For getEndpoint
phoneNumbers: null, // For SMS/MMS phone numbers
download: false, // Flag to indicate download
};

argv.forEach((arg) => {
if (arg.startsWith('--')) {
const [key, value] = arg.split('=');
switch (key) {
case '--version':
args.kind = 'version';
break;
case '--encode':
args.kind = 'encode';
args.value = value;
break;
case '--decode':
args.kind = 'decode';
args.value = value;
break;
case '--getendpoint':
args.kind = 'getendpoint';
args.value = value; // Network type for getEndpoint
break;
case '--sms':
args.kind = 'sms';
args.phoneNumbers = value; // Comma-separated phone numbers
break;
case '--mms':
args.kind = 'mms';
args.phoneNumbers = value; // Comma-separated phone numbers
break;
case '--download':
args.download = true;
break;
case '--output':
args.output = value;
break;
case '--filename':
args.filename = value;
break;
case '--countries':
args.countryCodes = value.split(','); // Comma-separated country codes
break;
default:
break;
}
} else if (arg.startsWith('-')) {
const [key, value] = arg.split('=');
switch (key) {
case '-v':
args.kind = 'version';
break;
case '-e':
args.kind = 'encode';
args.value = value;
break;
case '-d':
args.kind = 'decode';
args.value = value;
break;
case '-g':
args.kind = 'getendpoint';
args.value = value;
break;
case '-s':
args.kind = 'sms';
args.phoneNumbers = value;
break;
case '-m':
args.kind = 'mms';
args.phoneNumbers = value;
break;
case '-o':
args.output = value;
break;
case '-f':
args.filename = value;
break;
case '-c':
args.countryCodes = value.split(',');
break;
default:
break;
}
} else {
if (!args.value) {
args.value = arg;
}
}
});
return args;
}

run(typ, value, value1);
// Parse the arguments
const args = parseArgs(process.argv.slice(2));

if (process.stdin.isTTY) {
// If the script is run with a TTY, process the command-line arguments
run(args.kind, args.value, args.output, args.countryCodes, args.phoneNumbers, args.download, args.filename);
} else {
// If data is being piped into the script, capture it
let content = '';
process.stdin.setEncoding('utf8');
process.stdin.on('data', (buf) => {
Expand All @@ -17,59 +125,65 @@ if (process.stdin.isTTY) {
process.stdin.on('end', () => {
content = content.trim();

let value = content;
let typ = process.argv[2];
let value1 = process.argv[3];

if (!content) {
value = process.argv[2];
typ = process.argv[3];
value1 = process.argv[4];
run(args.kind, args.value, args.output, args.countryCodes, args.phoneNumbers, args.download, args.filename);
} else {
run(args.kind, content, args.output, args.countryCodes, args.phoneNumbers, args.download, args.filename);
}

run(typ, value, value1);
});
}

function run(typ, value, value1) {
if (!value) {
process.stderr.write('value is required\n');
async function run(kind, value, output, countryCodes, phoneNumbers, download, filename) {
if (!value && kind !== 'version') {
process.stderr.write('Value is required\n');
process.exit(1);
}

try {
if (typ === 'version' || typ === 'v') {
const packageJsonPath = join(__dirname, '../package.json');
if (download && output && !existsSync(output)) {
mkdirSync(output, { recursive: true });
}

if (kind === 'version' || kind === 'v') {
const packageJsonPath = path.join(__dirname, '../package.json');
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
const version = packageJson.version;
process.stdout.write(`TxMS version: ${version}\n`);
} else if (typ === 'encode' || typ === 'e') {
const encoded = txms.encode(value);
process.stdout.write(`${encoded}\n`);
} else if (typ === 'decode' || typ === 'd') {
process.stdout.write(version);
process.exit(0);
} else if (kind === 'encode' || kind === 'e') {
if (download) {
const filenm = await txms.downloadMessage(value, filename ? filename : undefined, output);
process.stdout.write(`TxMS file was downloaded as "${filenm}".\n`);
} else {
const encoded = txms.encode(value);
process.stdout.write(encoded);
}
process.exit(0);
} else if (kind === 'decode' || kind === 'd') {
const decoded = txms.decode(value);
process.stdout.write(`${decoded}\n`);
} else if (typ === 'getendpoint' || typ === 'g') {
const endpoint = txms.getEndpoint(value, value1);
process.stdout.write(`${JSON.stringify(endpoint, null, 2)}\n`);
} else if (typ === 'sms') {
const sms = txms.sms(true, value);
process.stdout.write(`${sms}\n`);
} else if (typ === 'mms') {
const mms = txms.mms(true, value);
process.stdout.write(`${mms}\n`);
} else if (typ === 'download' || typ === 'dl') {
txms.downloadMessage(value, value1).then((filename) => {
process.stdout.write(`TxMS file was downloaded as "${filename}" in your working directory.\n`);
process.exit(0);
}).catch((err) => {
process.stderr.write(`${err.message}\n`);
process.exit(1);
});
process.stdout.write(decoded);
process.exit(0);
} else if (kind === 'getendpoint' || kind === 'g') {
const endpoint = txms.getEndpoint(value, countryCodes);
let endpointString = Object.keys(endpoint).map(key => {
const numbers = endpoint[key].join(',');
return `${key}:${numbers}`;
}).join(';');
process.stdout.write(endpointString);
process.exit(0);
} else if (kind === 'sms') {
const message = txms.encode(value);
const sms = txms.sms(phoneNumbers ? phoneNumbers.split(',') : true, message);
process.stdout.write(sms);
process.exit(0);
} else if (kind === 'mms') {
const message = txms.encode(value);
const mms = txms.mms(phoneNumbers ? phoneNumbers.split(',') : true, message);
process.stdout.write(mms);
process.exit(0);
} else {
throw new Error('Invalid type specified.');
}
process.exit(0);
} catch (err) {
process.stderr.write(`${err.message}\n`);
process.exit(1);
Expand Down
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "txms.js",
"version": "1.2.7",
"version": "1.2.8",
"description": "Transaction messaging service protocol",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand All @@ -12,7 +12,7 @@
"build": "tsc -p ./tsconfig.json",
"test": "npm run unit",
"preunit": "npm run build",
"unit": "tape test/*.js",
"unit": "node --test",
"lint": "eslint 'src/**/*.{js,ts}' --fix"
},
"engines": {
Expand Down Expand Up @@ -46,11 +46,11 @@
"author": "@bchainhub",
"license": "CORE",
"devDependencies": {
"@types/node": "^22.3.0",
"@typescript-eslint/eslint-plugin": "^8.1.0",
"@typescript-eslint/parser": "^8.1.0",
"eslint": "^9.9.0",
"tape": "^5.8.1",
"@types/node": "^22.5.1",
"@typescript-eslint/eslint-plugin": "^8.3.0",
"@typescript-eslint/parser": "^8.3.0",
"eslint": "^9.9.1",
"jsdom": "^25.0.0",
"typescript": "^5.5.4"
}
}
Loading