diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index c00d197c..5be23322 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -59,7 +59,7 @@
-
+
@@ -67,7 +67,7 @@
-
+
@@ -89,7 +89,7 @@
-
+
@@ -98,7 +98,7 @@
-
+
diff --git a/package.json b/package.json
index 239ea597..f4ad9c4f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "powership",
- "version": "3.2.20",
+ "version": "3.2.23",
"private": true,
"scripts": {
"pack": "run-s pack:*",
@@ -45,7 +45,7 @@
"runmate": "latest",
"typedoc-plugin-markdown": "3.14.0",
"typescript": "4.8.2",
- "bun-safe": "1.0.5",
+ "bun-safe": "1.0.7",
"semver": "7.5.2",
"typedoc": "0.23.24",
"zx": "7.2.3"
diff --git a/packages/accounts/package.json b/packages/accounts/package.json
index 87748c19..7217aa3a 100644
--- a/packages/accounts/package.json
+++ b/packages/accounts/package.json
@@ -1,6 +1,6 @@
{
"name": "@powership/accounts",
- "version": "3.2.22",
+ "version": "3.2.23",
"description": "Powership accounts",
"type": "module",
"main": "./out/index.cjs",
diff --git a/packages/babel-plugins/package.json b/packages/babel-plugins/package.json
index 3135a744..22c4bbad 100644
--- a/packages/babel-plugins/package.json
+++ b/packages/babel-plugins/package.json
@@ -1,6 +1,6 @@
{
"name": "@powership/babel-plugins",
- "version": "3.2.22",
+ "version": "3.2.23",
"main": "./out/index.js",
"sideEffects": false,
"typings": "./out/index.d.ts",
diff --git a/packages/boilerplate/package.json b/packages/boilerplate/package.json
index aa4e58c0..9a8ed932 100644
--- a/packages/boilerplate/package.json
+++ b/packages/boilerplate/package.json
@@ -1,6 +1,6 @@
{
"name": "@powership/boilerplate",
- "version": "3.2.22",
+ "version": "3.2.23",
"author": "antoniopresto ",
"sideEffects": false,
"type": "module",
@@ -34,6 +34,7 @@
"out/*",
"tsconfig/*",
"eslintrc.cjs",
+ "babel-config.cjs",
"README.md"
]
}
diff --git a/packages/deepstate/package.json b/packages/deepstate/package.json
index 690b076d..082eca23 100644
--- a/packages/deepstate/package.json
+++ b/packages/deepstate/package.json
@@ -1,6 +1,6 @@
{
"name": "@powership/deepstate",
- "version": "3.2.22",
+ "version": "3.2.23",
"main": "out/index.cjs",
"module": "out/module/index.mjs",
"sideEffects": false,
diff --git a/packages/entity/package.json b/packages/entity/package.json
index f02078b8..09090c9d 100644
--- a/packages/entity/package.json
+++ b/packages/entity/package.json
@@ -1,6 +1,6 @@
{
"name": "@powership/entity",
- "version": "3.2.22",
+ "version": "3.2.23",
"type": "module",
"main": "./out/index.cjs",
"module": "./out/module/index.mjs",
diff --git a/packages/helpers/package.json b/packages/helpers/package.json
index b7f5e0b2..4d3798f8 100644
--- a/packages/helpers/package.json
+++ b/packages/helpers/package.json
@@ -1,6 +1,6 @@
{
"name": "@powership/helpers",
- "version": "3.2.22",
+ "version": "3.2.23",
"type": "module",
"main": "./out/index.cjs",
"module": "./out/module/index.mjs",
diff --git a/packages/logstorm/package.json b/packages/logstorm/package.json
index 5fa401fe..e412d458 100644
--- a/packages/logstorm/package.json
+++ b/packages/logstorm/package.json
@@ -1,6 +1,6 @@
{
"name": "logstorm",
- "version": "3.2.22",
+ "version": "3.2.23",
"typings": "out",
"author": "antoniopresto ",
"type": "module",
@@ -39,7 +39,8 @@
"description": "run command in each package",
"keywords": [],
"dependencies": {
- "plugin-hooks": "2.0.0"
+ "plugin-hooks": "2.0.0",
+ "@powership/utils": "workspace:*"
},
"devDependencies": {
"@powership/boilerplate": "workspace:*",
diff --git a/packages/mongo/package.json b/packages/mongo/package.json
index ee26b512..8d7a1b0a 100644
--- a/packages/mongo/package.json
+++ b/packages/mongo/package.json
@@ -1,6 +1,6 @@
{
"name": "@powership/mongo",
- "version": "3.2.22",
+ "version": "3.2.23",
"type": "module",
"main": "./out/index.cjs",
"module": "./out/module/index.mjs",
diff --git a/packages/plugin-engine/package.json b/packages/plugin-engine/package.json
index 05901d87..8ba85994 100644
--- a/packages/plugin-engine/package.json
+++ b/packages/plugin-engine/package.json
@@ -1,6 +1,6 @@
{
"name": "plugin-engine",
- "version": "3.2.22",
+ "version": "3.2.23",
"type": "module",
"main": "./out/index.cjs",
"module": "./out/module/index.mjs",
diff --git a/packages/powership/package.json b/packages/powership/package.json
index 7f15d43c..463ee1af 100644
--- a/packages/powership/package.json
+++ b/packages/powership/package.json
@@ -1,6 +1,6 @@
{
"name": "powership",
- "version": "3.2.22",
+ "version": "3.2.23",
"author": "antoniopresto ",
"type": "module",
"main": "./out/index.cjs",
diff --git a/packages/runmate/package.json b/packages/runmate/package.json
index 04280bdd..5aaf2c6c 100644
--- a/packages/runmate/package.json
+++ b/packages/runmate/package.json
@@ -1,6 +1,6 @@
{
"name": "runmate",
- "version": "3.2.22",
+ "version": "3.2.23",
"typings": "out",
"author": "antoniopresto ",
"license": "MIT",
diff --git a/packages/runmate/src/__tests__/findWorkspacePackages.spec.ts b/packages/runmate/src/__tests__/findWorkspacePackages.spec.ts
index 1b91dc2a..259cbc3a 100644
--- a/packages/runmate/src/__tests__/findWorkspacePackages.spec.ts
+++ b/packages/runmate/src/__tests__/findWorkspacePackages.spec.ts
@@ -7,14 +7,20 @@ describe('findWorkspacePackages', () => {
cwd: nodePath.resolve(__dirname),
});
+ expect(sut).toEqual([]);
+ });
+
+ test('catch top package', () => {
+ const sut = findWorkspacePackages({
+ cwd: nodePath.resolve(__dirname, '../../'),
+ });
+
expect(sut).toEqual([
{
- found: [],
- pattern: 'apps/*',
- },
- {
- found: [],
- pattern: 'packages/*',
+ path: expect.stringMatching(/\/packages\/runmate\/package.json$/),
+ json: expect.objectContaining({ name: 'runmate' }),
+ relative: './',
+ pattern: './',
},
]);
});
diff --git a/packages/runmate/src/commands/main.ts b/packages/runmate/src/commands/main.ts
index 342b8458..427f087d 100644
--- a/packages/runmate/src/commands/main.ts
+++ b/packages/runmate/src/commands/main.ts
@@ -11,6 +11,11 @@ export function main(program: Command) {
'Run command in each package in ./packages folder or in `--cwd` option folder'
)
.option('-d, --cwd ', 'Source directory or glob pattern')
+ .option(
+ '--include-root ',
+ 'Include root project in execution',
+ 'true'
+ )
.option(
'-c, --chunk-size ',
'Chunk size of parallel executions',
@@ -33,6 +38,7 @@ export function main(program: Command) {
.action(async function run(
commands: string[],
options?: {
+ includeRoot?: unknown;
cwd?: string;
chunkSize: string;
failFast: boolean;
@@ -42,7 +48,7 @@ export function main(program: Command) {
packageNameCommand: boolean;
}
): Promise {
- const {
+ let {
//
cwd: src,
chunkSize = 1,
@@ -51,6 +57,7 @@ export function main(program: Command) {
packages,
packageNameCommand,
from,
+ includeRoot,
} = options || {};
const ignoreList = ignore?.split(/, ?/);
@@ -60,6 +67,17 @@ export function main(program: Command) {
const runner = await packageRunner({
cwd: src,
failFast,
+ includeRoot: (() => {
+ if (typeof includeRoot === 'boolean') return includeRoot;
+
+ if (typeof includeRoot !== 'string') {
+ throw new Error(
+ `includeRoot received invalid value: ${includeRoot} `
+ );
+ }
+
+ return includeRoot === 'true';
+ })(),
});
if (packageNameCommand !== false) {
diff --git a/packages/runmate/src/commands/set-json-value.ts b/packages/runmate/src/commands/set-json-value.ts
index 5eb4f63a..cae8291d 100644
--- a/packages/runmate/src/commands/set-json-value.ts
+++ b/packages/runmate/src/commands/set-json-value.ts
@@ -1,4 +1,5 @@
-import { chalk, jsonParse, nodePath, setByPath } from '@powership/utils';
+import { jsonParse, setByPath } from '@powership/utils';
+import { chalk, nodePath } from '@powership/utils/out/node-utils';
import { Command } from 'commander';
import { writePackageJSON } from '../handleJSON';
diff --git a/packages/runmate/src/findWorkspacePackages.ts b/packages/runmate/src/findWorkspacePackages.ts
index ae1d15ad..7e2599a6 100644
--- a/packages/runmate/src/findWorkspacePackages.ts
+++ b/packages/runmate/src/findWorkspacePackages.ts
@@ -1,15 +1,16 @@
import nodePath from 'path';
-import * as path from 'path';
import process from 'process';
import fs from 'fs-extra';
import * as glob from 'glob';
import { PackageJson } from './ICommons';
+import { readPackageJSON } from './handleJSON';
export type FindWorkspacePackagesInit = {
cwd?: string;
globCache?: any;
+ includeRoot?: boolean;
};
export type WorkspacePackagesFoundResult = ReturnType<
@@ -17,38 +18,51 @@ export type WorkspacePackagesFoundResult = ReturnType<
>;
export function findWorkspacePackages(init?: FindWorkspacePackagesInit) {
- const { cwd: rootDir = process.cwd(), globCache } = init || {};
+ const {
+ cwd: rootDir = process.cwd(),
+ globCache,
+ includeRoot = true,
+ } = init || {};
const pnpmWorkspaces = listPnpmWorkspaces(rootDir);
const packageJsonWorkspaces = listPackageJSONWorkspaces(rootDir);
- const foundPatterns = pnpmWorkspaces?.length
+ let foundPatterns = pnpmWorkspaces?.length
? pnpmWorkspaces
: packageJsonWorkspaces?.length
? packageJsonWorkspaces
: null;
if (!foundPatterns) {
- throw new Error('No workspaces config found.');
+ console.warn('⚠️ No workspaces config found.');
+ foundPatterns = [];
}
- return foundPatterns.flatMap((pattern) => {
- const found = glob.sync(nodePath.join(pattern, 'package.json'), {
- cwd: rootDir,
- absolute: true,
- cache: globCache,
- ignore: ['**/node_modules/**'],
- });
+ if (includeRoot) {
+ foundPatterns.unshift('./');
+ }
- return {
- found,
- pattern,
- };
+ return foundPatterns.flatMap((pattern) => {
+ return glob
+ .sync(nodePath.join(pattern, 'package.json'), {
+ cwd: rootDir,
+ absolute: true,
+ cache: globCache,
+ ignore: ['**/node_modules/**'],
+ })
+ .flatMap((path) => {
+ return {
+ pattern,
+ path: path,
+ json: readPackageJSON(path),
+ relative: nodePath.relative(rootDir, nodePath.dirname(path)) || `./`,
+ };
+ });
});
}
function listPnpmWorkspaces(rootDir: string) {
- const pnpmWorkspacePath = path.join(rootDir, 'pnpm-workspace.yaml');
+ const pnpmWorkspacePath = nodePath.join(rootDir, 'pnpm-workspace.yaml');
if (fs.existsSync(pnpmWorkspacePath)) {
const workspaceFileContent = fs.readFileSync(pnpmWorkspacePath, 'utf-8');
@@ -72,7 +86,7 @@ function listPnpmWorkspaces(rootDir: string) {
}
function listPackageJSONWorkspaces(rootDir: string) {
- const packageJsonPath = path.join(rootDir, 'package.json');
+ const packageJsonPath = nodePath.join(rootDir, 'package.json');
if (fs.existsSync(packageJsonPath)) {
const packageJson = fs.readJSONSync(packageJsonPath) as PackageJson;
diff --git a/packages/runmate/src/packageRunner.ts b/packages/runmate/src/packageRunner.ts
index 7824f526..920f9882 100644
--- a/packages/runmate/src/packageRunner.ts
+++ b/packages/runmate/src/packageRunner.ts
@@ -2,6 +2,7 @@ import nodePath from 'path';
import { inspect } from 'util';
import { chunk } from 'lodash';
+import { logstorm } from 'logstorm';
import { DepTree, PackageItem } from './depTree';
import { findWorkspacePackages } from './findWorkspacePackages';
@@ -69,6 +70,7 @@ export interface PackageRunnerOptions {
cwd?: string;
cache?: boolean | Record;
failFast?: boolean;
+ includeRoot?: boolean;
}
export interface PackageRunOptions {
@@ -103,6 +105,7 @@ export async function packageRunner(
cwd = process.cwd(),
cache: cacheOption = true,
failFast: failFastRoot = true,
+ includeRoot,
} = options;
const cache = (() => {
@@ -112,11 +115,24 @@ export async function packageRunner(
return undefined;
})();
- const files = findWorkspacePackages({ globCache: cache, cwd }).flatMap(
- (el) => el.found
- );
+ const files = findWorkspacePackages({ globCache: cache, cwd, includeRoot });
+
+ (() => {
+ // force log
+ const level = logstorm.level;
+ const prefix = logstorm.prefix;
+ logstorm.level = 'info';
+ logstorm.prefix = false;
+ logstorm.info(
+ `Running command in:\n${(() => {
+ return files.map((el) => ` ‣ ${el.relative}`).join('\n');
+ })()}`
+ );
+ logstorm.level = level;
+ logstorm.prefix = prefix;
+ })();
- const utils = files.map((file) => getPackageRunnerUtils(file));
+ const utils = files.map((file) => getPackageRunnerUtils(file.path));
const packages = reduceObject(utils, (item) => ({ [item.name]: item }));
const depTree = new DepTree(utils.map((el) => el.json)).find();
diff --git a/packages/schema/package.json b/packages/schema/package.json
index 2b454c21..51bd0b27 100644
--- a/packages/schema/package.json
+++ b/packages/schema/package.json
@@ -1,6 +1,6 @@
{
"name": "@powership/schema",
- "version": "3.2.22",
+ "version": "3.2.23",
"type": "module",
"main": "./out/index.cjs",
"module": "./out/module/index.mjs",
diff --git a/packages/server/package.json b/packages/server/package.json
index 1bf2143b..9c8f43c5 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -1,6 +1,6 @@
{
"name": "@powership/server",
- "version": "3.2.22",
+ "version": "3.2.23",
"type": "module",
"main": "./out/index.cjs",
"module": "./out/module/index.mjs",
diff --git a/packages/transporter/package.json b/packages/transporter/package.json
index c65512de..08963b9c 100644
--- a/packages/transporter/package.json
+++ b/packages/transporter/package.json
@@ -1,6 +1,6 @@
{
"name": "@powership/transporter",
- "version": "3.2.22",
+ "version": "3.2.23",
"type": "module",
"main": "./out/index.cjs",
"module": "./out/module/index.mjs",
diff --git a/packages/utils/package.json b/packages/utils/package.json
index 209b501b..b5bc7661 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@powership/utils",
- "version": "3.2.22",
+ "version": "3.2.23",
"typings": "out",
"author": "antoniopresto ",
"license": "MIT",
@@ -15,7 +15,11 @@
"import": "./out/module/index.mjs",
"require": "./out/index.cjs"
},
- "./node-utils": "./out/module/node-utils"
+ "./out/node-utils": {
+ "types": "./out/node-utils.d.ts",
+ "import": "./out/module/node-utils.mjs",
+ "require": "./out/node-utils.cjs"
+ }
},
"browser": {
"out/module/index.mjs": "./out/browser/module/index.mjs",
@@ -40,9 +44,19 @@
"description": "powership utils and helper functions",
"keywords": [],
"dependencies": {
+ "@types/dateformat": "5.0.2",
+ "@types/fs-extra": "9.0.13",
+ "@types/lodash": "4.14.191",
+ "@types/lodash-es": "4.17.12",
+ "@types/semver": "7.5.8",
"aggio": "0.2.0",
"awesome-phonenumber": "6.2.0",
"big.js": "6.2.1",
+ "bun-safe": "1.0.7",
+ "bun-types": "1.0.29",
+ "chalk": "4.1.2",
+ "commander": "10.0.0",
+ "dateformat": "5.0.3",
"dayjs": "1.11.6",
"deep-diff": "1.0.2",
"deep-object-diff": "1.1.9",
@@ -50,9 +64,7 @@
"fast-copy": "3.0.0",
"fast-deep-equal": "3.1.3",
"fs-extra": "10.1.0",
- "chalk": "4.1.2",
- "bun-safe": "1.0.5",
- "bun-types": "1.0.29",
+ "glob": "10.3.10",
"graphql": "16.6.0",
"graphql-parse-resolve-info": "4.13.0",
"hoper": "1.0.8",
@@ -65,29 +77,22 @@
"object-hash": "3.0.0",
"plugin-hooks": "2.0.0",
"prettier": "2.8.8",
+ "qs": "6.11.2",
+ "semver": "7.6.0",
"slugify": "1.6.5",
"ts-toolbelt": "9.6.0",
+ "tsx": "4.7.1",
"ulid": "2.3.0",
- "qs": "6.11.2",
- "url-pattern": "1.0.3",
- "commander": "10.0.0",
- "glob": "10.3.10",
- "semver": "7.6.0",
- "@types/semver": "7.5.8",
- "@types/lodash": "4.14.191",
- "@types/lodash-es": "4.17.12",
- "@types/fs-extra": "9.0.13",
- "tsx": "4.7.1"
+ "url-pattern": "1.0.3"
},
"devDependencies": {
- "@powership/boilerplate": "workspace:*",
"@babel/cli": "7.19.3",
"@babel/plugin-transform-typescript": "7.19.3",
"@babel/preset-env": "7.19.3",
"@babel/preset-typescript": "7.18.6",
"@powership/babel-plugins": "workspace:*",
+ "@powership/boilerplate": "workspace:*",
"@types/big.js": "6.1.6",
- "@types/qs": "6.9.10",
"@types/deep-diff": "^1.0.2",
"@types/ejson": "2.2.0",
"@types/jest": "29.5.3",
@@ -95,6 +100,7 @@
"@types/node": "16.18.3",
"@types/object-hash": "2.2.1",
"@types/prettier": "2.7.1",
+ "@types/qs": "6.9.10",
"@typescript-eslint/eslint-plugin": "5.39.0",
"@typescript-eslint/parser": "5.39.0",
"babel-preset-minify": "0.5.2",
diff --git a/packages/utils/src/dateFormat.ts b/packages/utils/src/dateFormat.ts
new file mode 100644
index 00000000..0f2cb2ab
--- /dev/null
+++ b/packages/utils/src/dateFormat.ts
@@ -0,0 +1,414 @@
+/*
+ * Date Format 1.2.3
+ * (c) 2007-2009 Steven Levithan
+ * MIT license
+ *
+ * Includes enhancements by Scott Trenda
+ * and Kris Kowal
+ *
+ * Accepts a date, a mask, or a date and a mask.
+ * Returns a formatted version of the given date.
+ * The date defaults to the current date/time.
+ * The mask defaults to masks.default.
+ */
+
+/**
+ * @param date Defaults to the current date/time.
+ * @param mask Defaults to `masks.default`.
+ * @param utc
+ * @param gmt
+ * @returns A formatted version of the given date.
+ */
+export function dateFormat(
+ date?: Date | string | number,
+ mask?: string,
+ utc?: boolean,
+ gmt?: boolean
+): string;
+export function dateFormat(mask?: string, utc?: boolean, gmt?: boolean): string;
+export function dateFormat(...args: any[]) {
+ let [date, mask, utc, gmt] = args;
+
+ // You can't provide utc if you skip other args (use the 'UTC:' mask prefix)
+ if (arguments.length === 1 && typeof date === 'string' && !/\d/.test(date)) {
+ mask = date;
+ date = undefined;
+ }
+
+ date = date || date === 0 ? date : new Date();
+
+ if (!(date instanceof Date)) {
+ date = new Date(date);
+ }
+
+ if (isNaN(date)) {
+ throw TypeError('Invalid date');
+ }
+
+ mask = String(masks[mask] || mask || masks['default']);
+
+ // Allow setting the utc/gmt argument via the mask
+ const maskSlice = mask.slice(0, 4);
+ if (maskSlice === 'UTC:' || maskSlice === 'GMT:') {
+ mask = mask.slice(4);
+ utc = true;
+ if (maskSlice === 'GMT:') {
+ gmt = true;
+ }
+ }
+
+ const _ = () => (utc ? 'getUTC' : 'get');
+ const d = () => date[_() + 'Date']();
+ const D = () => date[_() + 'Day']();
+ const m = () => date[_() + 'Month']();
+ const y = () => date[_() + 'FullYear']();
+ const H = () => date[_() + 'Hours']();
+ const M = () => date[_() + 'Minutes']();
+ const s = () => date[_() + 'Seconds']();
+ const L = () => date[_() + 'Milliseconds']();
+ const o = () => (utc ? 0 : date.getTimezoneOffset());
+ const W = () => getWeek(date);
+ const N = () => getDayOfWeek(date);
+
+ const flags = {
+ d: () => d(),
+ dd: () => pad(d()),
+ ddd: () => i18n.dayNames[D()],
+ DDD: () =>
+ getDayName({
+ y: y(),
+ m: m(),
+ d: d(),
+ _: _(),
+ dayName: i18n.dayNames[D()],
+ short: true,
+ }),
+ dddd: () => i18n.dayNames[D() + 7],
+ DDDD: () =>
+ getDayName({
+ y: y(),
+ m: m(),
+ d: d(),
+ _: _(),
+ dayName: i18n.dayNames[D() + 7],
+ }),
+ m: () => m() + 1,
+ mm: () => pad(m() + 1),
+ mmm: () => i18n.monthNames[m()],
+ mmmm: () => i18n.monthNames[m() + 12],
+ yy: () => String(y()).slice(2),
+ yyyy: () => pad(y(), 4),
+ h: () => H() % 12 || 12,
+ hh: () => pad(H() % 12 || 12),
+ H: () => H(),
+ HH: () => pad(H()),
+ M: () => M(),
+ MM: () => pad(M()),
+ s: () => s(),
+ ss: () => pad(s()),
+ l: () => pad(L(), 3),
+ L: () => pad(Math.floor(L() / 10)),
+ t: () => (H() < 12 ? i18n.timeNames[0] : i18n.timeNames[1]),
+ tt: () => (H() < 12 ? i18n.timeNames[2] : i18n.timeNames[3]),
+ T: () => (H() < 12 ? i18n.timeNames[4] : i18n.timeNames[5]),
+ TT: () => (H() < 12 ? i18n.timeNames[6] : i18n.timeNames[7]),
+ Z: () => (gmt ? 'GMT' : utc ? 'UTC' : formatTimezone(date)),
+ o: () =>
+ (o() > 0 ? '-' : '+') +
+ pad(Math.floor(Math.abs(o()) / 60) * 100 + (Math.abs(o()) % 60), 4),
+ p: () =>
+ (o() > 0 ? '-' : '+') +
+ pad(Math.floor(Math.abs(o()) / 60), 2) +
+ ':' +
+ pad(Math.floor(Math.abs(o()) % 60), 2),
+ S: () =>
+ ['th', 'st', 'nd', 'rd'][
+ // @ts-ignore
+ d() % 10 > 3 ? 0 : (((d() % 100) - (d() % 10) != 10) * d()) % 10
+ ],
+ W: () => W(),
+ WW: () => pad(W()),
+ N: () => N(),
+ };
+
+ return mask.replace(token, (match) => {
+ if (match in flags) {
+ return flags[match]();
+ }
+ return match.slice(1, match.length - 1);
+ });
+}
+
+// /**
+// * Get proper timezone abbreviation or timezone offset.
+// *
+// * This will fall back to `GMT+xxxx` if it does not recognize the
+// * timezone within the `timezone` RegEx above. Currently only common
+// * American and Australian timezone abbreviations are supported.
+// */
+
+export interface DateFormatMasks {
+ /**
+ * @default "ddd mmm dd yyyy HH:MM:ss"
+ */
+ default: string;
+ /**
+ * @default "m/d/yy"
+ */
+ shortDate: string;
+ /**
+ * @default "mm/dd/yyyy"
+ */
+ paddedShortDate: string;
+ /**
+ * @default "mmm d, yyyy"
+ */
+ mediumDate: string;
+ /**
+ * @default "mmmm d, yyyy"
+ */
+ longDate: string;
+ /**
+ * @default "dddd, mmmm d, yyyy"
+ */
+ fullDate: string;
+ /**
+ * @default "h:MM TT"
+ */
+ shortTime: string;
+ /**
+ * @default "h:MM:ss TT"
+ */
+ mediumTime: string;
+ /**
+ * @default "h:MM:ss TT Z"
+ */
+ longTime: string;
+ /**
+ * @default "yyyy-mm-dd"
+ */
+ isoDate: string;
+ /**
+ * @default "HH:MM:ss"
+ */
+ isoTime: string;
+ /**
+ * @default "yyyy-mm-dd'T'HH:MM:sso"
+ */
+ isoDateTime: string;
+ /**
+ * @default "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
+ */
+ isoUtcDateTime: string;
+ /**
+ * @default "ddd, dd mmm yyyy HH:MM:ss Z"
+ */
+ expiresHeaderFormat: string;
+ [key: string]: string;
+}
+
+export interface DateFormatI18n {
+ dayNames: string[];
+ monthNames: string[];
+ timeNames: string[];
+}
+
+// Regexes and supporting functions are cached through closure
+const token =
+ /d{1,4}|D{3,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|W{1,2}|[LlopSZN]|"[^"]*"|'[^']*'/g;
+const timezone =
+ /\b(?:[A-Z]{1,3}[A-Z][TC])(?:[-+]\d{4})?|((?:Australian )?(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time)\b/g;
+const timezoneClip = /[^-+\dA-Z]/g;
+
+export let masks: DateFormatMasks = {
+ default: 'ddd mmm dd yyyy HH:MM:ss',
+ shortDate: 'm/d/yy',
+ paddedShortDate: 'mm/dd/yyyy',
+ mediumDate: 'mmm d, yyyy',
+ longDate: 'mmmm d, yyyy',
+ fullDate: 'dddd, mmmm d, yyyy',
+ shortTime: 'h:MM TT',
+ mediumTime: 'h:MM:ss TT',
+ longTime: 'h:MM:ss TT Z',
+ isoDate: 'yyyy-mm-dd',
+ isoTime: 'HH:MM:ss',
+ isoDateTime: "yyyy-mm-dd'T'HH:MM:sso",
+ isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'",
+ expiresHeaderFormat: 'ddd, dd mmm yyyy HH:MM:ss Z',
+};
+
+/**
+ * Internationalization strings
+ *
+ * @example
+ * import { i18n } from 'dateformat';
+ *
+ * i18n.dayNames = [
+ * 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat',
+ * 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'
+ * ];
+ * i18n.monthNames = [
+ * 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',
+ * 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'
+ * ];
+ * i18n.timeNames = [
+ * 'a', 'p', 'am', 'pm', 'A', 'P', 'AM', 'PM'
+ * ];
+ **/
+
+export let i18n: DateFormatI18n = {
+ dayNames: [
+ 'Sun',
+ 'Mon',
+ 'Tue',
+ 'Wed',
+ 'Thu',
+ 'Fri',
+ 'Sat',
+ 'Sunday',
+ 'Monday',
+ 'Tuesday',
+ 'Wednesday',
+ 'Thursday',
+ 'Friday',
+ 'Saturday',
+ ],
+ monthNames: [
+ 'Jan',
+ 'Feb',
+ 'Mar',
+ 'Apr',
+ 'May',
+ 'Jun',
+ 'Jul',
+ 'Aug',
+ 'Sep',
+ 'Oct',
+ 'Nov',
+ 'Dec',
+ 'January',
+ 'February',
+ 'March',
+ 'April',
+ 'May',
+ 'June',
+ 'July',
+ 'August',
+ 'September',
+ 'October',
+ 'November',
+ 'December',
+ ],
+ timeNames: ['a', 'p', 'am', 'pm', 'A', 'P', 'AM', 'PM'],
+};
+
+const pad = (val, len = 2) => String(val).padStart(len, '0');
+
+/**
+ * Get day name
+ * Yesterday, Today, Tomorrow if the date lies within, else fallback to Monday - Sunday
+ * @param {Object}
+ * @return {String}
+ */
+const getDayName = ({ y, m, d, _, dayName, short = false }) => {
+ const today = new Date();
+ const yesterday = new Date();
+ yesterday.setDate(yesterday[_ + 'Date']() - 1);
+ const tomorrow = new Date();
+ tomorrow.setDate(tomorrow[_ + 'Date']() + 1);
+ const today_d = () => today[_ + 'Date']();
+ const today_m = () => today[_ + 'Month']();
+ const today_y = () => today[_ + 'FullYear']();
+ const yesterday_d = () => yesterday[_ + 'Date']();
+ const yesterday_m = () => yesterday[_ + 'Month']();
+ const yesterday_y = () => yesterday[_ + 'FullYear']();
+ const tomorrow_d = () => tomorrow[_ + 'Date']();
+ const tomorrow_m = () => tomorrow[_ + 'Month']();
+ const tomorrow_y = () => tomorrow[_ + 'FullYear']();
+
+ if (today_y() === y && today_m() === m && today_d() === d) {
+ return short ? 'Tdy' : 'Today';
+ } else if (
+ yesterday_y() === y &&
+ yesterday_m() === m &&
+ yesterday_d() === d
+ ) {
+ return short ? 'Ysd' : 'Yesterday';
+ } else if (tomorrow_y() === y && tomorrow_m() === m && tomorrow_d() === d) {
+ return short ? 'Tmw' : 'Tomorrow';
+ }
+ return dayName;
+};
+
+/**
+ * Get the ISO 8601 week number
+ * Based on comments from
+ * http://techblog.procurios.nl/k/n618/news/view/33796/14863/Calculate-ISO-8601-week-and-year-in-javascript.html
+ *
+ * @param {Date} `date`
+ * @return {Number}
+ */
+const getWeek = (date: Date): number => {
+ // Remove time components of date
+ const targetThursday = new Date(
+ date.getFullYear(),
+ date.getMonth(),
+ date.getDate()
+ );
+
+ // Change date to Thursday same week
+ targetThursday.setDate(
+ targetThursday.getDate() - ((targetThursday.getDay() + 6) % 7) + 3
+ );
+
+ // Take January 4th as it is always in week 1 (see ISO 8601)
+ const firstThursday = new Date(targetThursday.getFullYear(), 0, 4);
+
+ // Change date to Thursday same week
+ firstThursday.setDate(
+ firstThursday.getDate() - ((firstThursday.getDay() + 6) % 7) + 3
+ );
+
+ // Check if daylight-saving-time-switch occurred and correct for it
+ const ds =
+ targetThursday.getTimezoneOffset() - firstThursday.getTimezoneOffset();
+ targetThursday.setHours(targetThursday.getHours() - ds);
+
+ // Number of weeks between target Thursday and first Thursday
+ // @ts-ignore
+ const weekDiff = (targetThursday - firstThursday) / (86400000 * 7);
+ return 1 + Math.floor(weekDiff);
+};
+
+/**
+ * Get ISO-8601 numeric representation of the day of week
+ * 1 (for Monday) through 7 (for Sunday)
+ *
+ * @param {Date} `date`
+ * @return {Number}
+ */
+const getDayOfWeek = (date) => {
+ let dow = date.getDay();
+ if (dow === 0) {
+ dow = 7;
+ }
+ return dow;
+};
+
+/**
+ * Get proper timezone abbreviation or timezone offset.
+ *
+ * This will fall back to `GMT+xxxx` if it does not recognize the
+ * timezone within the `timezone` RegEx above. Currently only common
+ * American and Australian timezone abbreviations are supported.
+ *
+ * @param {String | Date} date
+ * @return {String}
+ */
+export const formatTimezone = (date) => {
+ // @ts-ignore
+ return (String(date).match(timezone) || [''])
+ .pop()
+ .replace(timezoneClip, '')
+ .replace(/GMT\+0000/g, 'UTC');
+};
diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts
index c1315f53..436d966a 100644
--- a/packages/utils/src/index.ts
+++ b/packages/utils/src/index.ts
@@ -80,13 +80,11 @@ export * from './state/miniState';
export * from './ReactLike';
export * from './jsonClone';
export * from './tryCatch';
+export * from './dateFormat';
// @only-server
export * from './logLevels';
-// @only-server
-export * from './node-utils';
-
// @only-server
export * from './nodeLogger';
// @only-server
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f2a07412..42f1b974 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -30,8 +30,8 @@ importers:
specifier: 4.15.2
version: 4.15.2(eslint@7.20.0)(typescript@4.8.2)
bun-safe:
- specifier: 1.0.5
- version: 1.0.5
+ specifier: 1.0.7
+ version: 1.0.7
bun-types:
specifier: 1.0.26
version: 1.0.26
@@ -669,6 +669,9 @@ importers:
packages/logstorm:
dependencies:
+ '@powership/utils':
+ specifier: workspace:*
+ version: link:../utils
plugin-hooks:
specifier: 2.0.0
version: 2.0.0
@@ -1586,6 +1589,9 @@ importers:
packages/utils:
dependencies:
+ '@types/dateformat':
+ specifier: 5.0.2
+ version: 5.0.2
'@types/fs-extra':
specifier: 9.0.13
version: 9.0.13
@@ -1608,8 +1614,8 @@ importers:
specifier: 6.2.1
version: 6.2.1
bun-safe:
- specifier: 1.0.5
- version: 1.0.5
+ specifier: 1.0.7
+ version: 1.0.7
bun-types:
specifier: 1.0.29
version: 1.0.29
@@ -1619,6 +1625,9 @@ importers:
commander:
specifier: 10.0.0
version: 10.0.0
+ dateformat:
+ specifier: 5.0.3
+ version: 5.0.3
dayjs:
specifier: 1.11.6
version: 1.11.6
@@ -4794,6 +4803,10 @@ packages:
resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==}
dev: true
+ /@types/dateformat@5.0.2:
+ resolution: {integrity: sha512-M95hNBMa/hnwErH+a+VOD/sYgTmo15OTYTM2Hr52/e0OdOuY+Crag+kd3/ioZrhg0WGbl9Sm3hR7UU+MH6rfOw==}
+ dev: false
+
/@types/deep-diff@1.0.5:
resolution: {integrity: sha512-PQyNSy1YMZU1hgZA5tTYfHPpUAo9Dorn1PZho2/budQLfqLu3JIP37JAavnwYpR1S2yFZTXa3hxaE4ifGW5jaA==}
dev: true
@@ -6035,8 +6048,8 @@ packages:
ieee754: 1.2.1
dev: true
- /bun-safe@1.0.5:
- resolution: {integrity: sha512-4Kuyxb/v1RAw9PU739WlKtFzvKH8EAFIFYqI6fRPc0z95nIGp/30O60aFIOb6DcOVw1lm+Q9M42Kf8OLmH0kbA==}
+ /bun-safe@1.0.7:
+ resolution: {integrity: sha512-vKAtLM2NlBfLGqe8H54SxRP8Obz/yZNiFBLZmE4s/iz2lqgocHe9ok5UXIp8M8+VXmClVOccEk4XGW479dHyGg==}
hasBin: true
dependencies:
bun-types: 1.0.29
@@ -6309,6 +6322,11 @@ packages:
resolution: {integrity: sha512-qTcEYLen3r7ojZNgVUaRggOI+KM7jrKxXeSHhogh/TWxYMeONEMqY+hmkobiYQozsGIyg9OYVzO4ZIfoB4I0pQ==}
dev: false
+ /dateformat@5.0.3:
+ resolution: {integrity: sha512-Kvr6HmPXUMerlLcLF+Pwq3K7apHpYmGDVqrxcDasBg86UcKeTSNWbEzU8bwdXnxnR44FtMhJAxI4Bov6Y/KUfA==}
+ engines: {node: '>=12.20'}
+ dev: false
+
/dayjs@1.11.6:
resolution: {integrity: sha512-zZbY5giJAinCG+7AGaw0wIhNZ6J8AhWuSXKvuc1KAyMiRsvGQWqh4L+MomvhdAYjN+lqvVCMq1I41e3YHvXkyQ==}
dev: false