Compare commits

..

70 Commits

Author SHA1 Message Date
24b3458888 10.0.8 2023-06-23 16:44:45 +02:00
cffa47ac3d fix(core): update 2023-06-23 16:44:44 +02:00
9dadf3f78f 10.0.7 2023-01-09 15:34:06 +01:00
b35a671fe9 fix(core): update 2023-01-09 15:34:05 +01:00
0ca38c109e 10.0.6 2023-01-09 15:32:37 +01:00
4e2321e1ee fix(core): update 2023-01-09 15:32:37 +01:00
a640ab3d7b 10.0.5 2022-09-05 00:21:43 +02:00
37d6d56287 fix(core): update 2022-09-05 00:21:42 +02:00
443a026502 10.0.4 2022-07-24 23:11:41 +02:00
9644c5b7e3 fix(core): update 2022-07-24 23:11:41 +02:00
25faa8c697 10.0.3 2022-07-24 23:04:52 +02:00
982387aaa3 fix(core): update 2022-07-24 23:04:51 +02:00
4a11f50efe 10.0.2 2022-06-09 19:27:00 +02:00
0ddec29392 fix(core): update 2022-06-09 19:26:59 +02:00
df484d54e8 10.0.1 2022-06-07 15:50:48 +02:00
f637c20241 fix(core): update 2022-06-07 15:50:47 +02:00
ed0c1a9181 10.0.0 2022-06-07 15:43:28 +02:00
0e22999f69 BREAKING CHANGE(core): switch to esm 2022-06-07 15:43:28 +02:00
38f001ab23 9.0.7 2022-06-07 15:11:22 +02:00
d1429c5a41 fix(core): update 2022-06-07 15:11:21 +02:00
403a0f4fae 9.0.6 2022-03-11 09:46:54 +01:00
91ade8a4d4 fix(updated repo structure): update 2022-03-11 09:46:54 +01:00
1a571bba90 9.0.5 2021-12-22 19:08:54 +01:00
bcb66b2ccf fix(core): update 2021-12-22 19:08:53 +01:00
0000984e4b 9.0.4 2021-12-20 15:11:22 +01:00
b391e54083 fix(core): update 2021-12-20 15:11:21 +01:00
b32c06aef2 9.0.3 2021-12-03 00:24:10 +01:00
27f60f6719 fix(core): update 2021-12-03 00:24:10 +01:00
b2482ab8a5 9.0.2 2021-12-01 10:47:29 +01:00
9c614bd2f3 fix(core): update 2021-12-01 10:47:29 +01:00
b12de7aed4 9.0.1 2021-12-01 01:19:50 +01:00
d6eb54d21c fix(absolute pathing): add functions for easily getting absolute paths 2021-12-01 01:19:49 +01:00
6646f173c6 9.0.0 2021-12-01 01:14:07 +01:00
f20657ff71 BREAKING CHANGE(relative pathing): improved relative pathing 2021-12-01 01:14:07 +01:00
7f3f2da702 8.0.11 2021-11-30 16:34:36 +01:00
1e60ab375b fix(core): update 2021-11-30 16:34:35 +01:00
98fa607c43 8.0.10 2021-04-26 08:24:36 +00:00
12b1672e58 fix(core): update 2021-04-26 08:24:36 +00:00
9fca2c3aa4 8.0.9 2021-04-07 09:48:54 +00:00
5b7d822cfc fix(core): update 2021-04-07 09:48:54 +00:00
ce57478e39 8.0.8 2020-10-11 15:34:24 +00:00
292c2699ea fix(core): update 2020-10-11 15:34:24 +00:00
afb7fa8e89 8.0.7 2020-10-09 15:15:48 +00:00
e2c3005a08 fix(core): update 2020-10-09 15:15:47 +00:00
53e595a023 8.0.6 2020-10-06 00:57:48 +00:00
93702dca78 fix(core): update 2020-10-06 00:57:47 +00:00
0a95ae6284 8.0.5 2020-10-05 16:20:58 +00:00
de09f85c34 fix(core): update 2020-10-05 16:20:57 +00:00
b9fefc7c95 8.0.4 2020-10-02 14:34:10 +00:00
76eae15f7d fix(core): update 2020-10-02 14:34:09 +00:00
2e457f6011 8.0.3 2020-10-02 14:13:34 +00:00
e83c63fd2a fix(core): update 2020-10-02 14:13:34 +00:00
c01006e365 8.0.2 2020-10-02 13:29:40 +00:00
a7adec8275 fix(core): update 2020-10-02 13:29:40 +00:00
2eddbf5751 8.0.1 2020-10-02 13:26:54 +00:00
eca3e141d2 fix(core): update 2020-10-02 13:26:53 +00:00
701b77eff5 8.0.0 2020-08-10 20:58:23 +00:00
e3c46cdd2c BREAKING CHANGE(Smartfile class): switch to a Buffer only approach 2020-08-10 20:58:22 +00:00
7204607c8a 7.0.12 2020-04-13 17:48:25 +00:00
039c6f7fc6 fix(core): update 2020-04-13 17:48:25 +00:00
b42595fccc 7.0.11 2020-03-15 19:08:42 +00:00
2d9a65d11c fix(core): update 2020-03-15 19:08:41 +00:00
b3ce66167e 7.0.10 2020-03-15 18:58:46 +00:00
c7f800fc88 fix(core): update 2020-03-15 18:58:46 +00:00
d8f4b011b7 7.0.9 2020-03-04 16:31:14 +00:00
b4add67f37 fix(core): update 2020-03-04 16:31:13 +00:00
f86f053bd5 7.0.8 2020-02-07 21:00:54 +00:00
a78ca67b43 fix(core): update 2020-02-07 21:00:54 +00:00
b1bedd0f54 7.0.7 2020-02-07 21:00:05 +00:00
ec58f7ac55 fix(core): update 2020-02-07 21:00:04 +00:00
32 changed files with 5121 additions and 2256 deletions

View File

@ -0,0 +1,104 @@
name: CI Pipeline
on: push
env:
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci
jobs:
security:
runs-on: ubuntu-latest
continue-on-error: true
container:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
steps:
- uses: actions/checkout@v3
- name: Install pnpm and npmci
run: |
pnpm install -g pnpm
pnpm install -g @shipzone/npmci
- name: Run npm prepare
run: npmci npm prepare
- name: Audit production dependencies
run: |
npmci command npm config set registry https://registry.npmjs.org
npmci command pnpm audit --audit-level=high --prod
- name: Audit development dependencies
run: |
npmci command npm config set registry https://registry.npmjs.org
npmci command pnpm audit --audit-level=high --dev
test:
needs: security
runs-on: ubuntu-latest
container:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
steps:
- uses: actions/checkout@v3
- name: Test stable
run: |
npmci node install stable
npmci npm install
npmci npm test
- name: Test build
run: |
npmci node install stable
npmci npm install
npmci npm build
release:
needs: test
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
container:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
steps:
- uses: actions/checkout@v3
- name: Release
run: |
npmci node install stable
npmci npm publish
metadata:
needs: test
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
container:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
continue-on-error: true
steps:
- uses: actions/checkout@v3
- name: Code quality
run: |
npmci command npm install -g typescript
npmci npm prepare
npmci npm install
- name: Trigger
run: npmci trigger
- name: Build docs and upload artifacts
run: |
npmci node install stable
npmci npm install
npmci command npm run buildDocs
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: public
path: public
retention-days: 7

4
.gitignore vendored
View File

@ -15,8 +15,6 @@ node_modules/
# builds # builds
dist/ dist/
dist_web/ dist_*/
dist_serve/
dist_ts_web/
# custom # custom

View File

@ -4,35 +4,46 @@ image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
cache: cache:
paths: paths:
- .npmci_cache/ - .npmci_cache/
key: "$CI_BUILD_STAGE" key: '$CI_BUILD_STAGE'
stages: stages:
- security - security
- test - test
- release - release
- metadata - metadata
before_script:
- pnpm install -g pnpm
- pnpm install -g @shipzone/npmci
- npmci npm prepare
# ==================== # ====================
# security stage # security stage
# ==================== # ====================
mirror: # ====================
# security stage
# ====================
auditProductionDependencies:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
stage: security stage: security
script: script:
- npmci git mirror - npmci command npm config set registry https://registry.npmjs.org
- npmci command pnpm audit --audit-level=high --prod
tags: tags:
- lossless
- docker - docker
- notpriv allow_failure: true
snyk: auditDevDependencies:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
stage: security stage: security
script: script:
- npmci npm prepare - npmci command npm config set registry https://registry.npmjs.org
- npmci command npm install -g snyk - npmci command pnpm audit --audit-level=high --dev
- npmci command npm install --ignore-scripts
- npmci command snyk test
tags: tags:
- lossless
- docker - docker
- notpriv allow_failure: true
# ==================== # ====================
# test stage # test stage
@ -41,26 +52,22 @@ snyk:
testStable: testStable:
stage: test stage: test
script: script:
- npmci npm prepare
- npmci node install stable - npmci node install stable
- npmci npm install - npmci npm install
- npmci npm test - npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/ coverage: /\d+.?\d+?\%\s*coverage/
tags: tags:
- docker - docker
- priv
testBuild: testBuild:
stage: test stage: test
script: script:
- npmci npm prepare
- npmci node install stable - npmci node install stable
- npmci npm install - npmci npm install
- npmci command npm run build - npmci npm build
coverage: /\d+.?\d+?\%\s*coverage/ coverage: /\d+.?\d+?\%\s*coverage/
tags: tags:
- docker - docker
- notpriv
release: release:
stage: release stage: release
@ -70,6 +77,7 @@ release:
only: only:
- tags - tags
tags: tags:
- lossless
- docker - docker
- notpriv - notpriv
@ -79,12 +87,14 @@ release:
codequality: codequality:
stage: metadata stage: metadata
allow_failure: true allow_failure: true
only:
- tags
script: script:
- npmci command npm install -g tslint typescript - npmci command npm install -g typescript
- npmci npm prepare - npmci npm prepare
- npmci npm install - npmci npm install
- npmci command "tslint -c tslint.json ./ts/**/*.ts"
tags: tags:
- lossless
- docker - docker
- priv - priv
@ -95,20 +105,18 @@ trigger:
only: only:
- tags - tags
tags: tags:
- lossless
- docker - docker
- notpriv - notpriv
pages: pages:
image: hosttoday/ht-docker-dbase:npmci
services:
- docker:stable-dind
stage: metadata stage: metadata
script: script:
- npmci command npm install -g @gitzone/tsdoc - npmci node install stable
- npmci npm prepare
- npmci npm install - npmci npm install
- npmci command tsdoc - npmci command npm run buildDocs
tags: tags:
- lossless
- docker - docker
- notpriv - notpriv
only: only:

4
.snyk
View File

@ -1,4 +0,0 @@
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
version: v1.13.1
ignore: {}
patch: {}

11
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "npm test",
"name": "Run npm test",
"request": "launch",
"type": "node-terminal"
}
]
}

26
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,26 @@
{
"json.schemas": [
{
"fileMatch": ["/npmextra.json"],
"schema": {
"type": "object",
"properties": {
"npmci": {
"type": "object",
"description": "settings for npmci"
},
"gitzone": {
"type": "object",
"description": "settings for gitzone",
"properties": {
"projectType": {
"type": "string",
"enum": ["website", "element", "service", "npm", "wcc"]
}
}
}
}
}
}
]
}

View File

@ -1,40 +0,0 @@
# @pushrocks/smartfile
smart ways to work with files in nodejs
## Availabililty and Links
* [npmjs.org (npm package)](https://www.npmjs.com/package/@pushrocks/smartfile)
* [gitlab.com (source)](https://gitlab.com/pushrocks/smartfile)
* [github.com (source mirror)](https://github.com/pushrocks/smartfile)
* [docs (typedoc)](https://pushrocks.gitlab.io/smartfile/)
## Status for master
[![build status](https://gitlab.com/pushrocks/smartfile/badges/master/build.svg)](https://gitlab.com/pushrocks/smartfile/commits/master)
[![coverage report](https://gitlab.com/pushrocks/smartfile/badges/master/coverage.svg)](https://gitlab.com/pushrocks/smartfile/commits/master)
[![npm downloads per month](https://img.shields.io/npm/dm/@pushrocks/smartfile.svg)](https://www.npmjs.com/package/@pushrocks/smartfile)
[![Known Vulnerabilities](https://snyk.io/test/npm/@pushrocks/smartfile/badge.svg)](https://snyk.io/test/npm/@pushrocks/smartfile)
[![TypeScript](https://img.shields.io/badge/TypeScript->=%203.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
[![node](https://img.shields.io/badge/node->=%2010.x.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-prettier-ff69b4.svg)](https://prettier.io/)
## Usage
smartfile is an approach of being one tool to handle files in diverse environments.
### Smartfile Sections
smartfile thinks in sections:
| section | description |
| ----------- | ---------------------------------------------------------------------------- |
| fs | (object) gets data from fs to somewhere |
| memory | gets data from memory to somewhere |
| remote | gets data from remote locations to somewhere |
| interpreter | (object) handles yaml and json |
| smartfile | (class) a virtual representation of a file, alternative to vinyl file format |
For further information read the linked docs at the top of this readme.
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
[![repo-footer](https://lossless.gitlab.io/publicrelations/repofooter.svg)](https://maintainedby.lossless.com)

View File

View File

@ -1,19 +1,16 @@
{ {
"npmts": {
"mode": "default",
"coverageTreshold": 70
},
"npmdocker": {}, "npmdocker": {},
"npmci": { "npmci": {
"npmGlobalTools": [], "npmGlobalTools": [],
"npmAccessLevel": "public" "npmAccessLevel": "public"
}, },
"gitzone": { "gitzone": {
"projectType": "npm",
"module": { "module": {
"githost": "gitlab.com", "githost": "gitlab.com",
"gitscope": "pushrocks", "gitscope": "pushrocks",
"gitrepo": "smartfile", "gitrepo": "smartfile",
"shortDescription": "smart ways to work with files in nodejs", "description": "smart ways to work with files in nodejs",
"npmPackagename": "@pushrocks/smartfile", "npmPackagename": "@pushrocks/smartfile",
"license": "MIT" "license": "MIT"
} }

1887
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,15 @@
{ {
"name": "@pushrocks/smartfile", "name": "@pushrocks/smartfile",
"private": false, "private": false,
"version": "7.0.6", "version": "10.0.8",
"description": "offers smart ways to work with files in nodejs", "description": "offers smart ways to work with files in nodejs",
"main": "dist/index.js", "main": "dist_ts/index.js",
"typings": "dist/index.d.ts", "typings": "dist_ts/index.d.ts",
"type": "module",
"scripts": { "scripts": {
"test": "(tstest test/)", "test": "(tstest test/)",
"reinstall": "(rm -r node_modules && npm install)", "build": "(tsbuild --web --allowimplicitany)",
"release": "(git pull origin master && npm version patch && git push origin master && git checkout release && git merge master && git push origin release && git checkout master)", "buildDocs": "tsdoc"
"update": "(git checkout master && git pull origin master && npm install)",
"upgrade": "(npm run update) && (ncu upgradeAll && npm install)",
"build": "(tsbuild)"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -21,41 +19,51 @@
"filesystem", "filesystem",
"json" "json"
], ],
"author": "Smart Coordination GmbH <office@push.rocks> (https://push.rocks)", "author": "Lossless GmbH <hello@lossless.com> (https://lossless.com)",
"license": "MIT", "license": "MIT",
"bugs": { "bugs": {
"url": "https://gitlab.com/pushrocks/smartfile/issues" "url": "https://gitlab.com/pushrocks/smartfile/issues"
}, },
"homepage": "https://gitlab.com/pushrocks/smartfile", "homepage": "https://gitlab.com/pushrocks/smartfile",
"dependencies": { "dependencies": {
"@pushrocks/smarthash": "^2.0.6", "@pushrocks/lik": "^6.0.0",
"@pushrocks/smartpath": "^4.0.1", "@pushrocks/smartdelay": "^2.0.13",
"@pushrocks/smartpromise": "^3.0.5", "@pushrocks/smartfile-interfaces": "^1.0.7",
"@pushrocks/smartrequest": "^1.1.27", "@pushrocks/smarthash": "^3.0.1",
"@types/fs-extra": "^8.0.0", "@pushrocks/smartjson": "^5.0.5",
"fs-extra": "^8.1.0", "@pushrocks/smartmime": "^1.0.5",
"glob": "^7.1.4", "@pushrocks/smartpath": "^5.0.5",
"js-yaml": "^3.13.1" "@pushrocks/smartpromise": "^3.1.6",
"@pushrocks/smartrequest": "^2.0.11",
"@pushrocks/smartstream": "^2.0.3",
"@pushrocks/streamfunction": "^4.0.4",
"@types/fs-extra": "^11.0.0",
"@types/glob": "^8.0.0",
"@types/js-yaml": "^4.0.5",
"fs-extra": "^11.1.0",
"glob": "^8.0.3",
"js-yaml": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@gitzone/tsbuild": "^2.1.17", "@gitzone/tsbuild": "^2.1.65",
"@gitzone/tsrun": "^1.2.8", "@gitzone/tsrun": "^1.2.39",
"@gitzone/tstest": "^1.0.24", "@gitzone/tstest": "^1.0.74",
"@pushrocks/tapbundle": "^3.0.13", "@pushrocks/tapbundle": "^5.0.4",
"@types/node": "^12.7.8", "@types/node": "^18.11.18"
"gulp-function": "^2.2.14",
"tslint": "^5.20.0",
"tslint-config-prettier": "^1.18.0"
}, },
"files": [ "files": [
"ts/*", "ts/**/*",
"ts_web/*", "ts_web/**/*",
"dist/*", "dist/**/*",
"dist_web/*", "dist_*/**/*",
"dist_ts_web/*", "dist_ts/**/*",
"assets/*", "dist_ts_web/**/*",
"assets/**/*",
"cli.js", "cli.js",
"npmextra.json", "npmextra.json",
"readme.md" "readme.md"
],
"browserslist": [
"last 1 chrome versions"
] ]
} }

4396
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

49
readme.md Normal file
View File

@ -0,0 +1,49 @@
# @pushrocks/smartfile
smart ways to work with files in nodejs
## Availabililty and Links
* [npmjs.org (npm package)](https://www.npmjs.com/package/@pushrocks/smartfile)
* [gitlab.com (source)](https://gitlab.com/pushrocks/smartfile)
* [github.com (source mirror)](https://github.com/pushrocks/smartfile)
* [docs (typedoc)](https://pushrocks.gitlab.io/smartfile/)
## Status for master
Status Category | Status Badge
-- | --
GitLab Pipelines | [![pipeline status](https://gitlab.com/pushrocks/smartfile/badges/master/pipeline.svg)](https://lossless.cloud)
GitLab Pipline Test Coverage | [![coverage report](https://gitlab.com/pushrocks/smartfile/badges/master/coverage.svg)](https://lossless.cloud)
npm | [![npm downloads per month](https://badgen.net/npm/dy/@pushrocks/smartfile)](https://lossless.cloud)
Snyk | [![Known Vulnerabilities](https://badgen.net/snyk/pushrocks/smartfile)](https://lossless.cloud)
TypeScript Support | [![TypeScript](https://badgen.net/badge/TypeScript/>=%203.x/blue?icon=typescript)](https://lossless.cloud)
node Support | [![node](https://img.shields.io/badge/node->=%2010.x.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
Code Style | [![Code Style](https://badgen.net/badge/style/prettier/purple)](https://lossless.cloud)
PackagePhobia (total standalone install weight) | [![PackagePhobia](https://badgen.net/packagephobia/install/@pushrocks/smartfile)](https://lossless.cloud)
PackagePhobia (package size on registry) | [![PackagePhobia](https://badgen.net/packagephobia/publish/@pushrocks/smartfile)](https://lossless.cloud)
BundlePhobia (total size when bundled) | [![BundlePhobia](https://badgen.net/bundlephobia/minzip/@pushrocks/smartfile)](https://lossless.cloud)
## Usage
smartfile is an approach of being one tool to handle files in diverse environments.
### Smartfile Sections
smartfile thinks in sections:
| section | description |
| ----------- | ---------------------------------------------------------------------------- |
| fs | (object) gets data from fs to somewhere |
| memory | gets data from memory to somewhere |
| remote | gets data from remote locations to somewhere |
| interpreter | (object) handles yaml and json |
| smartfile | (class) a virtual representation of a file, alternative to vinyl file format |
## Contribution
We are always happy for code contributions. If you are not the code contributing type that is ok. Still, maintaining Open Source repositories takes considerable time and thought. If you like the quality of what we do and our modules are useful to you we would appreciate a little monthly contribution: You can [contribute one time](https://lossless.link/contribute-onetime) or [contribute monthly](https://lossless.link/contribute). :)
For further information read the linked docs at the top of this readme.
## Legal
> MIT licensed | **&copy;** [Task Venture Capital GmbH](https://task.vc)
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)

View File

@ -1,5 +1,5 @@
import * as smartfile from '../ts/index'; import * as smartfile from '../ts/index.js';
import path = require('path'); import * as path from 'path';
import { expect, tap } from '@pushrocks/tapbundle'; import { expect, tap } from '@pushrocks/tapbundle';
@ -8,64 +8,64 @@ import { expect, tap } from '@pushrocks/tapbundle';
// --------------------------- // ---------------------------
tap.test('.fs.fileExistsSync -> should return an accurate boolean', async () => { tap.test('.fs.fileExistsSync -> should return an accurate boolean', async () => {
expect(smartfile.fs.fileExistsSync('./test/testassets/mytest.json')).to.be.true; // tslint:disable-next-line: no-unused-expression
expect(smartfile.fs.fileExistsSync('./test/testassets/notthere.json')).be.false; expect(smartfile.fs.fileExistsSync('./test/testassets/mytest.json')).toBeTrue();
// tslint:disable-next-line: no-unused-expression
expect(smartfile.fs.fileExistsSync('./test/testassets/notthere.json')).toBeFalse();
}); });
tap.test('.fs.fileExists -> should resolve or reject a promise', async () => { tap.test('.fs.fileExists -> should resolve or reject a promise', async () => {
expect(smartfile.fs.fileExists('./test/testassets/mytest.json')).to.be.instanceof(Promise); expect(smartfile.fs.fileExists('./test/testassets/mytest.json')).toBeInstanceOf(Promise);
await smartfile.fs.fileExists('./test/testassets/mytest.json'); await smartfile.fs.fileExists('./test/testassets/mytest.json');
await smartfile.fs.fileExists('./test/testassets/notthere.json').catch(err => { await smartfile.fs.fileExists('./test/testassets/notthere.json').catch((err) => {
return expect(err.message).to.equal( return expect(err.message).toEqual(
"ENOENT: no such file or directory, access './test/testassets/notthere.json'" "ENOENT: no such file or directory, access './test/testassets/notthere.json'"
); );
}); });
}); });
tap.test('.fs.listFoldersSync() -> should get the file type from a string', async () => { tap.test('.fs.listFoldersSync() -> should get the file type from a string', async () => {
expect(smartfile.fs.listFoldersSync('./test/testassets/')).to.include('testfolder'); expect(smartfile.fs.listFoldersSync('./test/testassets/')).toContain('testfolder');
expect(smartfile.fs.listFoldersSync('./test/testassets/')).to.not.include('notExistentFolder'); expect(smartfile.fs.listFoldersSync('./test/testassets/')).not.toContain('notExistentFolder');
}); });
tap.test('.fs.listFolders() -> should get the file type from a string', async () => { tap.test('.fs.listFolders() -> should get the file type from a string', async () => {
let folderArrayArg = await smartfile.fs.listFolders('./test/testassets/'); const folderArrayArg = await smartfile.fs.listFolders('./test/testassets/');
expect(folderArrayArg).to.include('testfolder'); expect(folderArrayArg).toContain('testfolder');
expect(folderArrayArg).to.not.include('notExistentFolder'); expect(folderArrayArg).not.toContain('notExistentFolder');
}); });
tap.test('.fs.listFilesSync() -> should get the file type from a string', async () => { tap.test('.fs.listFilesSync() -> should get the file type from a string', async () => {
expect(smartfile.fs.listFilesSync('./test/testassets/')).to.include('mytest.json'); expect(smartfile.fs.listFilesSync('./test/testassets/')).toContain('mytest.json');
expect(smartfile.fs.listFilesSync('./test/testassets/')).to.not.include('notExistentFile'); expect(smartfile.fs.listFilesSync('./test/testassets/')).not.toContain('notExistentFile');
expect(smartfile.fs.listFilesSync('./test/testassets/', /mytest\.json/)).to.include( expect(smartfile.fs.listFilesSync('./test/testassets/', /mytest\.json/)).toContain('mytest.json');
'mytest.json' expect(smartfile.fs.listFilesSync('./test/testassets/', /mytests.json/)).not.toContain(
);
expect(smartfile.fs.listFilesSync('./test/testassets/', /mytests.json/)).to.not.include(
'mytest.json' 'mytest.json'
); );
}); });
tap.test('.fs.listFiles() -> should get the file type from a string', async () => { tap.test('.fs.listFiles() -> should get the file type from a string', async () => {
let folderArrayArg = await smartfile.fs.listFiles('./test/testassets/'); const folderArrayArg = await smartfile.fs.listFiles('./test/testassets/');
expect(folderArrayArg).to.include('mytest.json'); expect(folderArrayArg).toContain('mytest.json');
expect(folderArrayArg).to.not.include('notExistentFile'); expect(folderArrayArg).not.toContain('notExistentFile');
}); });
tap.test('.fs.listFileTree() -> should get a file tree', async () => { tap.test('.fs.listFileTree() -> should get a file tree', async () => {
let folderArrayArg = await smartfile.fs.listFileTree( const folderArrayArg = await smartfile.fs.listFileTree(
path.resolve('./test/testassets/'), path.resolve('./test/testassets/'),
'**/*.txt' '**/*.txt'
); );
expect(folderArrayArg).to.include('testfolder/testfile1.txt'); expect(folderArrayArg).toContain('testfolder/testfile1.txt');
expect(folderArrayArg).to.not.include('mytest.json'); expect(folderArrayArg).not.toContain('mytest.json');
}); });
tap.test('.fs.fileTreeToObject -> should read a file tree into an Object', async () => { tap.test('.fs.fileTreeToObject -> should read a file tree into an Object', async () => {
let fileArrayArg = await smartfile.fs.fileTreeToObject( const fileArrayArg = await smartfile.fs.fileTreeToObject(
path.resolve('./test/testassets/'), path.resolve('./test/testassets/'),
'**/*.txt' '**/*.txt'
); );
expect(fileArrayArg[0]).to.be.instanceof(smartfile.Smartfile); expect(fileArrayArg[0]).toBeInstanceOf(smartfile.Smartfile);
expect(fileArrayArg[0].contents.toString()).to.equal(fileArrayArg[0].contentBuffer.toString()); expect(fileArrayArg[0].contents.toString()).toEqual(fileArrayArg[0].contentBuffer.toString());
}); });
tap.test('.fs.copy() -> should copy a directory', async () => { tap.test('.fs.copy() -> should copy a directory', async () => {
@ -91,49 +91,47 @@ tap.test('.fs.remove -> should remove single files', async () => {
tap.test('.fs.removeSync -> should remove single files synchronouly', async () => { tap.test('.fs.removeSync -> should remove single files synchronouly', async () => {
smartfile.fs.removeSync('./test/testassets/temp/testfile1.txt'); smartfile.fs.removeSync('./test/testassets/temp/testfile1.txt');
expect(smartfile.fs.fileExistsSync('./test/testassets/temp/testfile1.txt')).to.be.false; expect(smartfile.fs.fileExistsSync('./test/testassets/temp/testfile1.txt')).toBeFalse();
}); });
tap.test('.fs.removeMany -> should remove and array of files', async () => { tap.test('.fs.removeMany -> should remove and array of files', async () => {
smartfile.fs smartfile.fs
.removeMany(['./test/testassets/temp/testfile1.txt', './test/testassets/temp/testfile2.txt']) .removeMany(['./test/testassets/temp/testfile1.txt', './test/testassets/temp/testfile2.txt'])
.then(() => { .then(() => {
expect(smartfile.fs.fileExistsSync('./test/testassets/temp/testfile1.txt')).to.be.false; expect(smartfile.fs.fileExistsSync('./test/testassets/temp/testfile1.txt')).toBeFalse();
expect(smartfile.fs.fileExistsSync('./test/testassets/temp/testfile2.txt')).to.be.false; expect(smartfile.fs.fileExistsSync('./test/testassets/temp/testfile2.txt')).toBeFalse();
}); });
}); });
tap.test('.fs.removeManySync -> should remove and array of single files synchronouly', async () => { tap.test('.fs.removeManySync -> should remove and array of single files synchronouly', async () => {
smartfile.fs.removeManySync([ smartfile.fs.removeManySync([
'./test/testassets/temp/testfile1.txt', './test/testassets/temp/testfile1.txt',
'./test/testassets/temp/testfile2.txt' './test/testassets/temp/testfile2.txt',
]); ]);
expect(smartfile.fs.fileExistsSync('./test/testassets/temp/testfile1.txt')).to.be.false; expect(smartfile.fs.fileExistsSync('./test/testassets/temp/testfile1.txt')).toBeFalse();
expect(smartfile.fs.fileExistsSync('./test/testassets/temp/testfile2.txt')).to.be.false; expect(smartfile.fs.fileExistsSync('./test/testassets/temp/testfile2.txt')).toBeFalse();
}); });
tap.test('.fs.toObjectSync() -> should read an ' + '.yaml' + ' file to an object', async () => { tap.test('.fs.toObjectSync() -> should read an .yaml file to an object', async () => {
let testData = smartfile.fs.toObjectSync('./test/testassets/mytest.yaml'); const testData = smartfile.fs.toObjectSync('./test/testassets/mytest.yaml');
expect(testData).to.include({ key1: 'this works' }); expect(testData.key1).toEqual('this works');
expect(testData).to.include({ key2: 'this works too' }); expect(testData.key2).toEqual('this works too');
}); });
tap.test( tap.test(
'.fs.toObjectSync() -> should state unknown file type for unknown file types', '.fs.toObjectSync() -> should state unknown file type for unknown file types',
async () => { async () => {
let testData = smartfile.fs.toObjectSync('./test/testassets/mytest.txt'); const testData = smartfile.fs.toObjectSync('./test/testassets/mytest.txt');
} }
); );
tap.test('.fs.toObjectSync() -> should read an ' + '.json' + ' file to an object', async () => { tap.test('.fs.toObjectSync() -> should read an .json file to an object', async () => {
let testData = smartfile.fs.toObjectSync('./test/testassets/mytest.json'); const testData = smartfile.fs.toObjectSync('./test/testassets/mytest.json');
expect(testData).to.include({ key1: 'this works' }); expect(testData.key1).toEqual('this works');
expect(testData).to.include({ key2: 'this works too' }); expect(testData.key2).toEqual('this works too');
}); });
tap.test('.fs.toStringSync() -> should read a file to a string', async () => { tap.test('.fs.toStringSync() -> should read a file to a string', async () => {
expect(smartfile.fs.toStringSync('./test/testassets/mytest.txt')).to.equal( expect(smartfile.fs.toStringSync('./test/testassets/mytest.txt')).toEqual('Some TestString &&%$');
'Some TestString &&%$'
);
}); });
// --------------------------- // ---------------------------
@ -141,7 +139,7 @@ tap.test('.fs.toStringSync() -> should read a file to a string', async () => {
// --------------------------- // ---------------------------
tap.test('.interpreter.filetype() -> should get the file type from a string', async () => { tap.test('.interpreter.filetype() -> should get the file type from a string', async () => {
expect(smartfile.interpreter.filetype('./somefolder/data.json')).equal('json'); expect(smartfile.interpreter.filetype('./somefolder/data.json')).toEqual('json');
}); });
// --------------------------- // ---------------------------
@ -149,7 +147,7 @@ tap.test('.interpreter.filetype() -> should get the file type from a string', as
// --------------------------- // ---------------------------
tap.test('.memory.toFs() -> should write a file to disk and return a promise', async () => { tap.test('.memory.toFs() -> should write a file to disk and return a promise', async () => {
let localString = 'myString'; const localString = 'myString';
await smartfile.memory.toFs( await smartfile.memory.toFs(
localString, localString,
path.join(process.cwd(), './test/testassets/temp/testMemToFs.txt') path.join(process.cwd(), './test/testassets/temp/testMemToFs.txt')
@ -159,7 +157,7 @@ tap.test('.memory.toFs() -> should write a file to disk and return a promise', a
tap.test( tap.test(
'.memory.toFsSync() -> should write a file to disk and return true if successfull', '.memory.toFsSync() -> should write a file to disk and return true if successfull',
async () => { async () => {
let localString = 'myString'; const localString = 'myString';
smartfile.memory.toFsSync( smartfile.memory.toFsSync(
localString, localString,
path.join(process.cwd(), './test/testassets/temp/testMemToFsSync.txt') path.join(process.cwd(), './test/testassets/temp/testMemToFsSync.txt')
@ -167,48 +165,33 @@ tap.test(
} }
); );
tap.test('.remote.toString() -> should load a remote file to a variable', async () => {
const responseString = await smartfile.remote.toString(
'https://raw.githubusercontent.com/pushrocks/smartfile/master/test/testassets/mytest.txt'
);
expect(responseString).to.equal('Some TestString &&%$');
});
tap.test('.remote.toString() -> should reject a Promise when the link is false', async tools => {
await smartfile.remote.toString('https://push.rocks/doesnotexist.txt').catch(err => {
return expect(err.message).to.equal(
'could not get remote file from https://push.rocks/doesnotexist.txt'
);
});
});
// --------------------------- // ---------------------------
// smartfile.Smartfile // smartfile.Smartfile
// --------------------------- // ---------------------------
tap.test('.Smartfile -> should produce vinyl compatible files', async () => { tap.test('.Smartfile -> should produce vinyl compatible files', async () => {
let smartfileArray = await smartfile.fs.fileTreeToObject( const smartfileArray = await smartfile.fs.fileTreeToObject(
process.cwd(), process.cwd(),
'./test/testassets/testfolder/**/*' './test/testassets/testfolder/**/*'
); );
let localSmartfile = smartfileArray[0]; const localSmartfile = smartfileArray[0];
expect(localSmartfile).to.be.instanceof(smartfile.Smartfile); expect(localSmartfile).toBeInstanceOf(smartfile.Smartfile);
expect(localSmartfile.contents).to.be.instanceof(Buffer); expect(localSmartfile.contents).toBeInstanceOf(Buffer);
// tslint:disable-next-line:no-unused-expression // tslint:disable-next-line:no-unused-expression
expect(localSmartfile.isBuffer()).to.be.true; expect(localSmartfile.isBuffer()).toBeTrue();
// tslint:disable-next-line:no-unused-expression // tslint:disable-next-line:no-unused-expression
expect(localSmartfile.isDirectory()).to.be.false; expect(localSmartfile.isDirectory()).toBeFalse();
// tslint:disable-next-line:no-unused-expression // tslint:disable-next-line:no-unused-expression
expect(localSmartfile.isNull()).to.be.false; expect(localSmartfile.isNull()).toBeFalse();
}); });
tap.test('should output a smartfile array to disk', async () => { tap.test('should output a smartfile array to disk', async () => {
let smartfileArray = await smartfile.fs.fileTreeToObject('./test/testassets/testfolder/', '*'); const smartfileArray = await smartfile.fs.fileTreeToObject('./test/testassets/testfolder/', '*');
for (let smartfile of smartfileArray) { for (const smartfileInstance of smartfileArray) {
console.log(smartfile.relative); console.log(smartfileInstance.relative);
console.log(smartfile.path); console.log(smartfileInstance.path);
console.log(smartfile.base); console.log(smartfileInstance.base);
console.log(smartfile.parsedPath); console.log(smartfileInstance.parsedPath);
} }
await smartfile.memory.smartfileArrayToFs( await smartfile.memory.smartfileArrayToFs(
smartfileArray, smartfileArray,
@ -216,4 +199,26 @@ tap.test('should output a smartfile array to disk', async () => {
); );
}); });
tap.test('should create, store and retrieve valid smartfiles', async () => {
const fileString = 'hi there';
const filePath = './test/testassets/utf8.txt';
const smartfileInstance = await smartfile.Smartfile.fromString(filePath, fileString, 'utf8');
smartfileInstance.write();
const smartfileInstance2 = await smartfile.Smartfile.fromFilePath(filePath);
const retrievedString = smartfileInstance.contents.toString();
expect(retrievedString).toEqual(fileString);
});
tap.test('should get a hash', async () => {
const fileString = 'hi there';
const filePath = './test/testassets/utf8.txt';
const smartfileInstance = await smartfile.Smartfile.fromString(filePath, fileString, 'utf8');
const hash = await smartfileInstance.getHash();
console.log(hash);
});
tap.test('should wait for file to be ready', async () => {
await smartfile.fs.waitForFileToBeReady('./test/testassets/mytest.json');
});
tap.start(); tap.start();

View File

@ -0,0 +1,15 @@
import { tap, expect } from '@pushrocks/tapbundle';
import * as smartfile from '../ts/index.js';
tap.test('should create a virtualdirectory', async () => {
const virtualDir = await smartfile.VirtualDirectory.fromFsDirPath('./test/testassets/testfolder');
expect(virtualDir.smartfileArray.length).toEqual(4);
});
tap.test('should write to a directory', async () => {
const virtualDir = await smartfile.VirtualDirectory.fromFsDirPath('./test/testassets/testfolder');
virtualDir.saveToDisk('./test/testassets/test');
});
tap.start();

View File

@ -0,0 +1 @@
okidoks

View File

@ -0,0 +1 @@
hi

View File

View File

1
test/testassets/utf8.txt Normal file
View File

@ -0,0 +1 @@
hi there

8
ts/00_commitinfo_data.ts Normal file
View File

@ -0,0 +1,8 @@
/**
* autocreated commitinfo by @pushrocks/commitinfo
*/
export const commitinfo = {
name: '@pushrocks/smartfile',
version: '10.0.8',
description: 'offers smart ways to work with files in nodejs'
}

View File

@ -1,12 +1,13 @@
import * as plugins from './smartfile.plugins'; import * as plugins from './smartfile.plugins.js';
import * as SmartfileFs from './smartfile.fs'; import * as fsMod from './smartfile.fs.js';
import * as SmartfileInterpreter from './smartfile.interpreter'; import * as fsStreamMod from './smartfile.fsstream.js';
import * as SmartfileMemory from './smartfile.memory'; import * as interpreterMod from './smartfile.interpreter.js';
import * as SmartfileRemote from './smartfile.remote'; import * as memoryMod from './smartfile.memory.js';
export { Smartfile } from './smartfile.classes.smartfile'; export * from './smartfile.classes.smartfile.js';
export * from './smartfile.classes.virtualdirectory.js';
export let fs = SmartfileFs; export const fs = fsMod;
export let interpreter = SmartfileInterpreter; export const fsStream = fsStreamMod;
export let memory = SmartfileMemory; export const interpreter = interpreterMod;
export let remote = SmartfileRemote; export const memory = memoryMod;

View File

@ -1,19 +1,18 @@
import * as plugins from './smartfile.plugins'; import * as plugins from './smartfile.plugins.js';
import * as fs from './smartfile.fs'; import * as fs from './smartfile.fs.js';
import * as memory from './smartfile.memory'; import * as memory from './smartfile.memory.js';
export interface ISmartfileConstructorOptions { export interface ISmartfileConstructorOptions {
path?: string; path: string;
contentString?: string; contentBuffer: Buffer;
contentBuffer?: Buffer; base: string;
base?: string;
} }
/** /**
* class Smartfile * class Smartfile
* -> is vinyl file compatible * -> is vinyl file compatible
*/ */
export class Smartfile { export class Smartfile extends plugins.smartjson.Smartjson {
// ====== // ======
// STATIC // STATIC
// ====== // ======
@ -22,44 +21,91 @@ export class Smartfile {
* creates a Smartfile from a filePath * creates a Smartfile from a filePath
* @param filePath * @param filePath
*/ */
public static async fromFilePath(filePath: string) { public static async fromFilePath(filePath: string, baseArg: string = process.cwd()) {
filePath = plugins.path.resolve(filePath); filePath = plugins.path.resolve(filePath);
const fileString = fs.toStringSync(filePath); const fileBuffer = fs.toBufferSync(filePath);
const smartfile = new Smartfile({ const smartfile = new Smartfile({
path: filePath, contentBuffer: fileBuffer,
contentString: fileString base: baseArg,
path: plugins.path.relative(baseArg, filePath),
}); });
return smartfile; return smartfile;
} }
public static async fromBuffer(
filePath: string,
contentBufferArg: Buffer,
baseArg: string = process.cwd()
) {
const smartfile = new Smartfile({
contentBuffer: contentBufferArg,
base: baseArg,
path: plugins.path.relative(baseArg, filePath),
});
return smartfile;
}
public static async fromString(
filePath: string,
contentStringArg: string,
encodingArg: 'utf8' | 'binary',
baseArg = process.cwd()
) {
const smartfile = new Smartfile({
contentBuffer: Buffer.from(contentStringArg, encodingArg),
base: baseArg,
path: plugins.path.relative(baseArg, filePath),
});
return smartfile;
}
public static async fromFoldedJson(foldedJsonArg: string) {
return new Smartfile(plugins.smartjson.parse(foldedJsonArg));
}
// ======== // ========
// INSTANCE // INSTANCE
// ======== // ========
/** /**
* the full path of the file on disk * the relative path of the file
*/ */
path: string; @plugins.smartjson.foldDec()
public path: string;
/** /**
* * a parsed path
*/ */
parsedPath: plugins.path.ParsedPath; public get parsedPath(): plugins.path.ParsedPath {
return plugins.path.parse(this.path);
}
public get absolutePath() {
return plugins.path.join(this.base, this.path);
}
public get absoluteParsedPath() {
return plugins.path.parse(this.absolutePath);
}
/** /**
* the content of the file as Buffer * the content of the file as Buffer
*/ */
contentBuffer: Buffer; @plugins.smartjson.foldDec()
public contentBuffer: Buffer;
/** /**
* The current working directory of the file * The current working directory of the file
* Note:this is similar to gulp and different from native node path base * Note:this is similar to gulp and different from native node path base
*/ */
base: string; @plugins.smartjson.foldDec()
public base: string;
/** /**
* sync the file with disk * sync the file with disk
*/ */
sync: boolean; @plugins.smartjson.foldDec()
public sync: boolean;
/** /**
* the constructor of Smartfile * the constructor of Smartfile
@ -67,15 +113,13 @@ export class Smartfile {
*/ */
constructor(optionsArg: ISmartfileConstructorOptions) { constructor(optionsArg: ISmartfileConstructorOptions) {
super();
if (optionsArg.contentBuffer) { if (optionsArg.contentBuffer) {
this.contentBuffer = optionsArg.contentBuffer; this.contentBuffer = optionsArg.contentBuffer;
} else if (optionsArg.contentString) {
this.setContentsFromString(optionsArg.contentString);
} else { } else {
console.log('created empty Smartfile?'); console.log('created empty Smartfile?');
} }
this.path = optionsArg.path; this.path = optionsArg.path;
this.parsedPath = plugins.path.parse(this.path);
this.base = optionsArg.base; this.base = optionsArg.base;
} }
@ -83,24 +127,56 @@ export class Smartfile {
* set contents from string * set contents from string
* @param contentString * @param contentString
*/ */
setContentsFromString(contentString: string) { public setContentsFromString(contentString: string, encodingArg: 'utf8' | 'binary' = 'utf8') {
this.contents = new Buffer(contentString); this.contents = new Buffer(contentString, encodingArg);
} }
/** /**
* write file to disk * write file to disk at its original location
* Behaviours: * Behaviours:
* - no argument write to exactly where the file was picked up * - no argument write to exactly where the file was picked up
*/ */
async write(pathArg?: string) { public async write() {
const stringToWrite = this.contentBuffer.toString(); await memory.toFs(this.contentBuffer, plugins.path.join(this.base, this.path));
await memory.toFs(stringToWrite, this.path); }
/**
* writes the file to path given as argument
* note: if the path is not absolute, takes process.cwd() as base
* @param filePathArg
*/
public async writeToDiskAtPath(filePathArg: string) {
if (!plugins.path.isAbsolute(filePathArg)) {
filePathArg = plugins.path.join(process.cwd(), filePathArg);
}
await memory.toFs(this.contentBuffer, filePathArg);
}
/**
* writes the file to a directory combined with the relative path portion
* @param dirPathArg
* @returns
*/
public async writeToDir(dirPathArg: string) {
dirPathArg = plugins.smartpath.transform.toAbsolute(dirPathArg) as string;
const filePath = plugins.path.join(dirPathArg, this.path);
await memory.toFs(this.contentBuffer, filePath);
return filePath;
} }
/** /**
* read file from disk * read file from disk
*/ */
async read() {} public async read() {
this.contentBuffer = await fs.toBuffer(plugins.path.join(this.base, this.path));
}
/**
* deletes the file from disk at its original location
*/
public async delete() {
await fs.remove(plugins.path.join(this.base, this.path));
}
// ----------------------------------------------- // -----------------------------------------------
// vinyl compatibility // vinyl compatibility
@ -118,21 +194,21 @@ export class Smartfile {
/** /**
* vinyl-compatibility * vinyl-compatibility
*/ */
get cwd() { public get cwd() {
return process.cwd(); return process.cwd();
} }
/** /**
* return relative path of file * return relative path of file
*/ */
get relative(): string { public get relative(): string {
return plugins.path.relative(this.base, this.path); return this.path;
} }
/** /**
* return truw when the file has content * return truw when the file has content
*/ */
isNull(): boolean { public isNull(): boolean {
if (!this.contentBuffer) { if (!this.contentBuffer) {
return true; return true;
} }
@ -142,28 +218,48 @@ export class Smartfile {
/** /**
* return true if contents are Buffer * return true if contents are Buffer
*/ */
isBuffer(): boolean { public isBuffer(): boolean {
if (this.contents instanceof Buffer) { if (this.contents instanceof Buffer) {
return true; return true;
} }
return false; return false;
} }
isDirectory() { public isDirectory() {
return false; return false;
} }
isStream() { public isStream() {
return false; return false;
} }
isSymbolic() { public isSymbolic() {
return false; return false;
} }
public async getHash(typeArg: 'path' | 'content' | 'all' = 'all') {
const pathHash = await plugins.smarthash.sha256FromString(this.path);
const contentHash = await plugins.smarthash.sha256FromBuffer(this.contentBuffer);
const combinedHash = await plugins.smarthash.sha256FromString(pathHash + contentHash);
switch (typeArg) {
case 'path':
return pathHash;
case 'content':
return contentHash;
case 'all':
default:
return combinedHash;
}
}
// update things // update things
updateFileName(fileNameArg: string) { public updateFileName(fileNameArg: string) {
let oldFileName = this.parsedPath.base; const oldFileName = this.parsedPath.base;
this.path = this.path.replace(new RegExp(oldFileName + '$'), fileNameArg); this.path = this.path.replace(new RegExp(oldFileName + '$'), fileNameArg);
} }
public async editContentAsString(editFuncArg: (fileStringArg: string) => Promise<string>) {
const newFileString = await editFuncArg(this.contentBuffer.toString());
this.contentBuffer = Buffer.from(newFileString);
}
} }

View File

@ -0,0 +1,61 @@
import { Smartfile } from './smartfile.classes.smartfile.js';
import * as plugins from './smartfile.plugins.js';
import * as fs from './smartfile.fs.js';
/**
* a virtual directory exposes a fs api
*/
export class VirtualDirectory {
// STATIC
public static async fromFsDirPath(pathArg: string): Promise<VirtualDirectory> {
const newVirtualDir = new VirtualDirectory();
newVirtualDir.addSmartfiles(await fs.fileTreeToObject(pathArg, '**/*'));
return newVirtualDir;
}
public static async fromVirtualDirTransferableObject(
virtualDirTransferableObjectArg: plugins.smartfileInterfaces.VirtualDirTransferableObject
): Promise<VirtualDirectory> {
const newVirtualDir = new VirtualDirectory();
for (const fileArg of virtualDirTransferableObjectArg.files) {
newVirtualDir.addSmartfiles([Smartfile.enfoldFromJson(fileArg) as Smartfile]);
}
return newVirtualDir;
}
// INSTANCE
public smartfileArray: Smartfile[] = [];
constructor() {}
public addSmartfiles(smartfileArrayArg: Smartfile[]) {
this.smartfileArray = this.smartfileArray.concat(smartfileArrayArg);
}
public async getFileByPath(pathArg: string) {
for (const smartfile of this.smartfileArray) {
if (smartfile.path === pathArg) {
return smartfile;
}
}
}
public async toVirtualDirTransferableObject(): Promise<plugins.smartfileInterfaces.VirtualDirTransferableObject> {
return {
files: this.smartfileArray.map((smartfileArg) => smartfileArg.foldToJson()),
};
}
public async saveToDisk(dirArg: string) {
console.log(`writing VirtualDirectory with ${this.smartfileArray.length} to directory:
--> ${dirArg}`);
for (const smartfileArg of this.smartfileArray) {
const filePath = await smartfileArg.writeToDir(dirArg);
console.log(`wrote ${smartfileArg.relative} to
--> ${filePath}`);
}
}
// TODO implement root shifting to get subdirectories as new virtual directories
// TODO implement root shifting to combine VirtualDirecotries in a parent virtual directory
}

View File

@ -1,9 +1,9 @@
import plugins = require('./smartfile.plugins'); import * as plugins from './smartfile.plugins.js';
import SmartfileInterpreter = require('./smartfile.interpreter'); import * as interpreter from './smartfile.interpreter.js';
import { Smartfile } from './smartfile.classes.smartfile'; import { Smartfile } from './smartfile.classes.smartfile.js';
import * as memory from './smartfile.memory'; import * as memory from './smartfile.memory.js';
/*=============================================================== /*===============================================================
============================ Checks ============================= ============================ Checks =============================
===============================================================*/ ===============================================================*/
@ -31,7 +31,7 @@ export const fileExistsSync = (filePath): boolean => {
*/ */
export const fileExists = async (filePath): Promise<boolean> => { export const fileExists = async (filePath): Promise<boolean> => {
const done = plugins.smartpromise.defer<boolean>(); const done = plugins.smartpromise.defer<boolean>();
plugins.fs.access(filePath, 4, err => { plugins.fs.access(filePath, 4, (err) => {
err ? done.resolve(false) : done.resolve(true); err ? done.resolve(false) : done.resolve(true);
}); });
return done.promise; return done.promise;
@ -64,7 +64,7 @@ export const isFile = (pathArg): boolean => {
*/ */
export const copy = async (fromArg: string, toArg: string): Promise<boolean> => { export const copy = async (fromArg: string, toArg: string): Promise<boolean> => {
const done = plugins.smartpromise.defer<boolean>(); const done = plugins.smartpromise.defer<boolean>();
plugins.fsExtra.copy(fromArg, toArg, {}, err => { plugins.fsExtra.copy(fromArg, toArg, {}, (err) => {
if (err) { if (err) {
throw new Error(`Could not copy from ${fromArg} to ${toArg}: ${err}`); throw new Error(`Could not copy from ${fromArg} to ${toArg}: ${err}`);
} }
@ -186,25 +186,35 @@ export const removeManySync = (filePathArrayArg: string[]): void => {
export const toObjectSync = (filePathArg, fileTypeArg?) => { export const toObjectSync = (filePathArg, fileTypeArg?) => {
const fileString = plugins.fsExtra.readFileSync(filePathArg, 'utf8'); const fileString = plugins.fsExtra.readFileSync(filePathArg, 'utf8');
let fileType; let fileType;
fileTypeArg ? (fileType = fileTypeArg) : (fileType = SmartfileInterpreter.filetype(filePathArg)); fileTypeArg ? (fileType = fileTypeArg) : (fileType = interpreter.filetype(filePathArg));
return SmartfileInterpreter.objectFile(fileString, fileType); return interpreter.objectFile(fileString, fileType);
}; };
/** /**
* reads a file content to a String * reads a file content to a String
* @param filePath
* @returns {string|Buffer|any}
*/ */
export const toStringSync = (filePath: string): string => { export const toStringSync = (filePath: string): string => {
const fileString: string = plugins.fsExtra.readFileSync(filePath, 'utf8'); const encoding = plugins.smartmime.getEncoding(filePath);
let fileString: string | Buffer = plugins.fsExtra.readFileSync(filePath, encoding);
if (Buffer.isBuffer(fileString)) {
fileString = fileString.toString('binary');
}
return fileString; return fileString;
}; };
export const toBuffer = async (filePath: string): Promise<Buffer> => {
return plugins.fsExtra.readFile(filePath);
};
export const toBufferSync = (filePath: string): Buffer => {
return plugins.fsExtra.readFileSync(filePath);
};
export const fileTreeToHash = async (dirPathArg: string, miniMatchFilter: string) => { export const fileTreeToHash = async (dirPathArg: string, miniMatchFilter: string) => {
const fileTreeObject = await fileTreeToObject(dirPathArg, miniMatchFilter); const fileTreeObject = await fileTreeToObject(dirPathArg, miniMatchFilter);
let combinedString = ''; let combinedString = '';
for (const smartfile of fileTreeObject) { for (const smartfile of fileTreeObject) {
combinedString += smartfile.contentBuffer.toString(); combinedString += await smartfile.getHash();
} }
const hash = await plugins.smarthash.sha256FromString(combinedString); const hash = await plugins.smarthash.sha256FromString(combinedString);
return hash; return hash;
@ -221,7 +231,7 @@ export const fileTreeToObject = async (dirPathArg: string, miniMatchFilter: stri
if (plugins.path.isAbsolute(miniMatchFilter)) { if (plugins.path.isAbsolute(miniMatchFilter)) {
dirPath = '/'; dirPath = '/';
} else { } else {
dirPath = dirPathArg; dirPath = plugins.smartpath.transform.toAbsolute(dirPathArg) as string;
} }
const fileTree = await listFileTree(dirPath, miniMatchFilter); const fileTree = await listFileTree(dirPath, miniMatchFilter);
@ -241,7 +251,7 @@ export const fileTreeToObject = async (dirPathArg: string, miniMatchFilter: stri
new Smartfile({ new Smartfile({
contentBuffer: Buffer.from(fileContentString), contentBuffer: Buffer.from(fileContentString),
base: dirPath, base: dirPath,
path: filePath path: filePath,
}) })
); );
} }
@ -261,11 +271,11 @@ export const listFolders = async (pathArg: string, regexFilter?: RegExp): Promis
* @returns an array with the folder names as strings * @returns an array with the folder names as strings
*/ */
export const listFoldersSync = (pathArg: string, regexFilter?: RegExp): string[] => { export const listFoldersSync = (pathArg: string, regexFilter?: RegExp): string[] => {
let folderArray = plugins.fsExtra.readdirSync(pathArg).filter(file => { let folderArray = plugins.fsExtra.readdirSync(pathArg).filter((file) => {
return plugins.fsExtra.statSync(plugins.path.join(pathArg, file)).isDirectory(); return plugins.fsExtra.statSync(plugins.path.join(pathArg, file)).isDirectory();
}); });
if (regexFilter) { if (regexFilter) {
folderArray = folderArray.filter(fileItem => { folderArray = folderArray.filter((fileItem) => {
return regexFilter.test(fileItem); return regexFilter.test(fileItem);
}); });
} }
@ -285,11 +295,11 @@ export const listFiles = async (pathArg: string, regexFilter?: RegExp): Promise<
* @returns an array with the folder names as strings * @returns an array with the folder names as strings
*/ */
export const listFilesSync = (pathArg: string, regexFilter?: RegExp): string[] => { export const listFilesSync = (pathArg: string, regexFilter?: RegExp): string[] => {
let fileArray = plugins.fsExtra.readdirSync(pathArg).filter(file => { let fileArray = plugins.fsExtra.readdirSync(pathArg).filter((file) => {
return plugins.fsExtra.statSync(plugins.path.join(pathArg, file)).isFile(); return plugins.fsExtra.statSync(plugins.path.join(pathArg, file)).isFile();
}); });
if (regexFilter) { if (regexFilter) {
fileArray = fileArray.filter(fileItem => { fileArray = fileArray.filter((fileItem) => {
return regexFilter.test(fileItem); return regexFilter.test(fileItem);
}); });
} }
@ -310,11 +320,11 @@ export const listAllItems = async (pathArg: string, regexFilter?: RegExp): Promi
* @executes SYNC * @executes SYNC
*/ */
export const listAllItemsSync = (pathArg: string, regexFilter?: RegExp): string[] => { export const listAllItemsSync = (pathArg: string, regexFilter?: RegExp): string[] => {
let allItmesArray = plugins.fsExtra.readdirSync(pathArg).filter(file => { let allItmesArray = plugins.fsExtra.readdirSync(pathArg).filter((file) => {
return plugins.fsExtra.statSync(plugins.path.join(pathArg, file)).isFile(); return plugins.fsExtra.statSync(plugins.path.join(pathArg, file)).isFile();
}); });
if (regexFilter) { if (regexFilter) {
allItmesArray = allItmesArray.filter(fileItem => { allItmesArray = allItmesArray.filter((fileItem) => {
return regexFilter.test(fileItem); return regexFilter.test(fileItem);
}); });
} }
@ -344,7 +354,7 @@ export const listFileTree = async (
const options = { const options = {
cwd: dirPath, cwd: dirPath,
nodir: true, nodir: true,
dot: true dot: true,
}; };
plugins.glob(miniMatchFilter, options, (err, files: string[]) => { plugins.glob(miniMatchFilter, options, (err, files: string[]) => {
if (err) { if (err) {
@ -356,10 +366,36 @@ export const listFileTree = async (
let fileList = await done.promise; let fileList = await done.promise;
if (absolutePathsBool) { if (absolutePathsBool) {
fileList = fileList.map(filePath => { fileList = fileList.map((filePath) => {
return plugins.path.resolve(plugins.path.join(dirPath, filePath)); return plugins.path.resolve(plugins.path.join(dirPath, filePath));
}); });
} }
return fileList; return fileList;
}; };
/**
* checks wether a file is ready for processing
*/
export const waitForFileToBeReady = async (filePathArg: string): Promise<void> => {
if (!plugins.path.isAbsolute(filePathArg)) {
filePathArg = plugins.path.resolve(filePathArg);
}
const limitedArray = new plugins.lik.LimitedArray<number>(3);
let fileReady = false;
while (!fileReady) {
const stats = await plugins.fsExtra.stat(filePathArg);
limitedArray.addOne(stats.size);
if (
limitedArray.array.length < 3 ||
!(
limitedArray.array[0] === limitedArray.array[1] &&
limitedArray.array[1] === limitedArray.array[2]
)
) {
await plugins.smartdelay.delayFor(5000);
} else {
fileReady = true;
}
}
};

14
ts/smartfile.fsstream.ts Normal file
View File

@ -0,0 +1,14 @@
/*
This file contains logic for streaming things from and to the filesystem
*/
import * as plugins from './smartfile.plugins.js';
export const createReadStream = (pathArg: string) => {
return plugins.fs.createReadStream(pathArg);
};
export const createWriteStream = (pathArg: string) => {
return plugins.fs.createWriteStream(pathArg);
};
export const streamDirectory = async (dirPathArg: string) => {};

View File

@ -1,4 +1,4 @@
import plugins = require('./smartfile.plugins'); import * as plugins from './smartfile.plugins.js';
export let filetype = (pathArg: string): string => { export let filetype = (pathArg: string): string => {
const extName = plugins.path.extname(pathArg); const extName = plugins.path.extname(pathArg);
@ -10,7 +10,7 @@ export let objectFile = (fileStringArg: string, fileTypeArg) => {
switch (fileTypeArg) { switch (fileTypeArg) {
case 'yml': case 'yml':
case 'yaml': case 'yaml':
return plugins.yaml.safeLoad(fileStringArg); return plugins.yaml.load(fileStringArg);
case 'json': case 'json':
return JSON.parse(fileStringArg); return JSON.parse(fileStringArg);
default: default:

View File

@ -1,8 +1,7 @@
import plugins = require('./smartfile.plugins'); import * as plugins from './smartfile.plugins.js';
import { Smartfile } from './smartfile.classes.smartfile'; import { Smartfile } from './smartfile.classes.smartfile.js';
import * as smartfileFs from './smartfile.fs'; import * as smartfileFs from './smartfile.fs.js';
import * as interpreter from './smartfile.interpreter.js';
import SmartfileInterpreter = require('./smartfile.interpreter');
/** /**
* converts file to Object * converts file to Object
@ -10,8 +9,8 @@ import SmartfileInterpreter = require('./smartfile.interpreter');
* @param fileTypeArg * @param fileTypeArg
* @returns {any|any} * @returns {any|any}
*/ */
export let toObject = function(fileStringArg: string, fileTypeArg: string) { export let toObject = (fileStringArg: string, fileTypeArg: string) => {
return SmartfileInterpreter.objectFile(fileStringArg, fileTypeArg); return interpreter.objectFile(fileStringArg, fileTypeArg);
}; };
export interface IToFsOptions { export interface IToFsOptions {
@ -25,11 +24,11 @@ export interface IToFsOptions {
* @param fileBaseArg * @param fileBaseArg
*/ */
export let toFs = async ( export let toFs = async (
fileContentArg: string | Smartfile, fileContentArg: string | Buffer | Smartfile,
filePathArg, filePathArg: string,
optionsArg: IToFsOptions = {} optionsArg: IToFsOptions = {}
) => { ) => {
let done = plugins.smartpromise.defer(); const done = plugins.smartpromise.defer();
// check args // check args
if (!fileContentArg || !filePathArg) { if (!fileContentArg || !filePathArg) {
@ -37,24 +36,27 @@ export let toFs = async (
} }
// prepare actual write action // prepare actual write action
let fileString: string; let fileContent: string | Buffer;
let fileEncoding: 'utf8' | 'binary' = 'utf8';
let filePath: string = filePathArg; let filePath: string = filePathArg;
// handle Smartfile // handle Smartfile
if (fileContentArg instanceof Smartfile) { if (fileContentArg instanceof Smartfile) {
let fileContentArg2: any = fileContentArg; fileContent = fileContentArg.contentBuffer;
fileString = fileContentArg.contentBuffer.toString();
// handle options // handle options
if (optionsArg.respectRelative) { if (optionsArg.respectRelative) {
filePath = plugins.path.join(filePath, fileContentArg.path); filePath = plugins.path.join(filePath, fileContentArg.path);
} }
} else if (Buffer.isBuffer(fileContentArg)) {
fileContent = fileContentArg;
fileEncoding = 'binary';
} else if (typeof fileContentArg === 'string') { } else if (typeof fileContentArg === 'string') {
fileString = fileContentArg; fileContent = fileContentArg;
} else { } else {
throw new Error('fileContent is neither string nor Smartfile'); throw new Error('fileContent is neither string nor Smartfile');
} }
await smartfileFs.ensureDir(plugins.path.parse(filePath).dir); await smartfileFs.ensureDir(plugins.path.parse(filePath).dir);
plugins.fsExtra.writeFile(filePath, fileString, { encoding: 'utf8' }, done.resolve); plugins.fsExtra.writeFile(filePath, fileContent, { encoding: fileEncoding }, done.resolve);
return await done.promise; return await done.promise;
}; };
@ -63,7 +65,7 @@ export let toFs = async (
* @param fileArg * @param fileArg
* @param filePathArg * @param filePathArg
*/ */
export let toFsSync = function(fileArg: string, filePathArg: string) { export const toFsSync = (fileArg: string, filePathArg: string) => {
// function checks to abort if needed // function checks to abort if needed
if (!fileArg || !filePathArg) { if (!fileArg || !filePathArg) {
throw new Error('expected a valid arguments'); throw new Error('expected a valid arguments');
@ -71,7 +73,7 @@ export let toFsSync = function(fileArg: string, filePathArg: string) {
// prepare actual write action // prepare actual write action
let fileString: string; let fileString: string;
let filePath: string = filePathArg; const filePath: string = filePathArg;
if (typeof fileArg !== 'string') { if (typeof fileArg !== 'string') {
throw new Error('fileArg is not of type String.'); throw new Error('fileArg is not of type String.');
@ -83,9 +85,9 @@ export let toFsSync = function(fileArg: string, filePathArg: string) {
export let smartfileArrayToFs = async (smartfileArrayArg: Smartfile[], dirArg: string) => { export let smartfileArrayToFs = async (smartfileArrayArg: Smartfile[], dirArg: string) => {
await smartfileFs.ensureDir(dirArg); await smartfileFs.ensureDir(dirArg);
for (let smartfile of smartfileArrayArg) { for (const smartfile of smartfileArrayArg) {
await toFs(smartfile, dirArg, { await toFs(smartfile, dirArg, {
respectRelative: true respectRelative: true,
}); });
} }
}; };

View File

@ -5,15 +5,32 @@ import * as path from 'path';
export { fs, path }; export { fs, path };
// @pushrocks scope // @pushrocks scope
import * as lik from '@pushrocks/lik';
import * as smartfileInterfaces from '@pushrocks/smartfile-interfaces';
import * as smartdelay from '@pushrocks/smartdelay';
import * as smarthash from '@pushrocks/smarthash'; import * as smarthash from '@pushrocks/smarthash';
import * as smartjson from '@pushrocks/smartjson';
import * as smartmime from '@pushrocks/smartmime';
import * as smartpath from '@pushrocks/smartpath'; import * as smartpath from '@pushrocks/smartpath';
import * as smartpromise from '@pushrocks/smartpromise'; import * as smartpromise from '@pushrocks/smartpromise';
import * as smartrequest from '@pushrocks/smartrequest'; import * as smartrequest from '@pushrocks/smartrequest';
import * as smartstream from '@pushrocks/smartstream';
export { smarthash, smartpath, smartpromise, smartrequest }; export {
lik,
smartfileInterfaces,
smartdelay,
smarthash,
smartjson,
smartmime,
smartpath,
smartpromise,
smartrequest,
smartstream,
};
// third party scope // third party scope
import * as fsExtra from 'fs-extra'; import fsExtra from 'fs-extra';
import glob from 'glob'; import glob from 'glob';
import yaml from 'js-yaml'; import yaml from 'js-yaml';

View File

@ -1,50 +0,0 @@
import plugins = require('./smartfile.plugins');
import SmartfileInterpreter = require('./smartfile.interpreter');
/* export let toFs = function (from: string, toPath: string) {
let done = plugins.q.defer()
let stream = plugins.smartrequest(from).pipe(plugins.fsExtra.createWriteStream(toPath))
stream.on('finish', function () {
done.resolve(toPath)
})
return done.promise
} */
/**
*
* @param fromArg
* @returns {any}
*/
export let toObject = function(fromArg: string) {
let done = plugins.smartpromise.defer();
plugins.smartrequest
.request(fromArg, {
method: 'get'
})
.then((res: any) => {
if (res.statusCode === 200) {
done.resolve(res.body);
} else {
console.log('could not get remote file from ' + fromArg);
done.reject(new Error('could not get remote file from ' + fromArg));
}
});
return done.promise;
};
/**
*
* @param fromArg
* @returns {any}
*/
export let toString = (fromArg: string) => {
let done = plugins.smartpromise.defer();
plugins.smartrequest.getBinary(fromArg).then((res: any) => {
if (res.statusCode === 200) {
done.resolve(res.body);
} else {
done.reject(new Error('could not get remote file from ' + fromArg));
}
});
return done.promise;
};

8
tsconfig.json Normal file
View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"experimentalDecorators": true,
"esModuleInterop": true,
"target": "ES2017",
"moduleResolution": "node"
}
}

View File

@ -1,17 +0,0 @@
{
"extends": ["tslint:latest", "tslint-config-prettier"],
"rules": {
"semicolon": [true, "always"],
"no-console": false,
"ordered-imports": false,
"object-literal-sort-keys": false,
"member-ordering": {
"options":{
"order": [
"static-method"
]
}
}
},
"defaultSeverity": "warning"
}