fix(core): update

This commit is contained in:
Philipp Kunz 2023-03-29 14:54:07 +02:00
commit 98be43fbb5
23 changed files with 5199 additions and 0 deletions

20
.gitignore vendored Normal file
View File

@ -0,0 +1,20 @@
.nogit/
# artifacts
coverage/
public/
pages/
# installs
node_modules/
# caches
.yarn/
.cache/
.rpt2_cache
# builds
dist/
dist_*/
# custom

128
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,128 @@
# gitzone ci_default
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
cache:
paths:
- .npmci_cache/
key: '$CI_BUILD_STAGE'
stages:
- security
- test
- release
- metadata
before_script:
- pnpm install -g pnpm
- pnpm install -g @shipzone/npmci
- npmci npm prepare
# ====================
# security stage
# ====================
# ====================
# security stage
# ====================
auditProductionDependencies:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
stage: security
script:
- npmci command npm config set registry https://registry.npmjs.org
- npmci command pnpm audit --audit-level=high --prod
tags:
- lossless
- docker
allow_failure: true
auditDevDependencies:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
stage: security
script:
- npmci command npm config set registry https://registry.npmjs.org
- npmci command pnpm audit --audit-level=high --dev
tags:
- lossless
- docker
allow_failure: true
# ====================
# test stage
# ====================
testStable:
stage: test
script:
- npmci node install stable
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
testBuild:
stage: test
script:
- npmci node install stable
- npmci npm install
- npmci npm build
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
release:
stage: release
script:
- npmci node install stable
- npmci npm publish
only:
- tags
tags:
- lossless
- docker
- notpriv
# ====================
# metadata stage
# ====================
codequality:
stage: metadata
allow_failure: true
only:
- tags
script:
- npmci command npm install -g typescript
- npmci npm prepare
- npmci npm install
tags:
- lossless
- docker
- priv
trigger:
stage: metadata
script:
- npmci trigger
only:
- tags
tags:
- lossless
- docker
- notpriv
pages:
stage: metadata
script:
- npmci node install stable
- npmci npm install
- npmci command npm run buildDocs
tags:
- lossless
- docker
- notpriv
only:
- tags
artifacts:
expire_in: 1 week
paths:
- public
allow_failure: true

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"]
}
}
}
}
}
}
]
}

21
license Normal file
View File

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

16
npmextra.json Normal file
View File

@ -0,0 +1,16 @@
{
"npmci": {
"npmAccessLevel": "public"
},
"gitzone": {
"projectType": "npm",
"module": {
"githost": "gitlab.com",
"gitscope": "pushrocks",
"gitrepo": "typedserver",
"description": "easy serving of static files",
"npmPackagename": "@apiglobal/typedserver",
"license": "MIT"
}
}
}

68
package.json Normal file
View File

@ -0,0 +1,68 @@
{
"name": "@apiglobal/typedserver",
"version": "2.0.33",
"description": "easy serving of static files",
"main": "dist_ts/index.js",
"typings": "dist_ts/index.d.ts",
"type": "module",
"scripts": {
"test": "npm run build && tstest test/",
"build": "tsbuild --web --allowimplicitany && tsbundle --from ./ts_web/index.ts --to ./dist_ts_web/bundle.js",
"buildDocs": "tsdoc"
},
"repository": {
"type": "git",
"url": "https://github.com/pushrocks/easyserve.git"
},
"keywords": [
"serve",
"browser-sync"
],
"author": "Lossless GmbH <office@lossless.com> (https://lossless.com)",
"license": "MIT",
"bugs": {
"url": "https://github.com/pushrocks/easyserve/issues"
},
"files": [
"ts/**/*",
"ts_web/**/*",
"dist/**/*",
"dist_*/**/*",
"dist_ts/**/*",
"dist_ts_web/**/*",
"assets/**/*",
"cli.js",
"npmextra.json",
"readme.md"
],
"homepage": "https://github.com/pushrocks/easyserve",
"dependencies": {
"@apiglobal/typedrequest": "^2.0.12",
"@apiglobal/typedrequest-interfaces": "^2.0.1",
"@apiglobal/typedsocket": "^2.0.22",
"@pushrocks/smartchok": "^1.0.23",
"@pushrocks/smartdelay": "^2.0.13",
"@pushrocks/smartexpress": "^4.0.34",
"@pushrocks/smartfile": "^10.0.7",
"@pushrocks/smartlog": "^3.0.1",
"@pushrocks/smartlog-destination-devtools": "^1.0.10",
"@pushrocks/smartopen": "^2.0.0",
"@pushrocks/smartpath": "^5.0.5",
"@pushrocks/smartpromise": "^3.1.7",
"@pushrocks/smartrx": "^3.0.0",
"@pushrocks/webstore": "^2.0.5",
"lit": "^2.7.0"
},
"devDependencies": {
"@gitzone/tsbuild": "^2.1.63",
"@gitzone/tsbundle": "^2.0.6",
"@gitzone/tsrun": "^1.2.39",
"@gitzone/tstest": "^1.0.72",
"@pushrocks/tapbundle": "^5.0.4",
"@types/node": "^18.15.11"
},
"private": false,
"browserslist": [
"last 1 chrome versions"
]
}

4298
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

49
readme.md Normal file
View File

@ -0,0 +1,49 @@
# @apiglobal/typedserver
easy serving of static files
## Availabililty and Links
* [npmjs.org (npm package)](https://www.npmjs.com/package/@apiglobal/typedserver)
* [gitlab.com (source)](https://gitlab.com/pushrocks/typedserver)
* [github.com (source mirror)](https://github.com/pushrocks/typedserver)
* [docs (typedoc)](https://pushrocks.gitlab.io/typedserver/)
## Status for master
Status Category | Status Badge
-- | --
GitLab Pipelines | [![pipeline status](https://gitlab.com/pushrocks/typedserver/badges/master/pipeline.svg)](https://lossless.cloud)
GitLab Pipline Test Coverage | [![coverage report](https://gitlab.com/pushrocks/typedserver/badges/master/coverage.svg)](https://lossless.cloud)
npm | [![npm downloads per month](https://badgen.net/npm/dy/@apiglobal/typedserver)](https://lossless.cloud)
Snyk | [![Known Vulnerabilities](https://badgen.net/snyk/pushrocks/typedserver)](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/@apiglobal/typedserver)](https://lossless.cloud)
PackagePhobia (package size on registry) | [![PackagePhobia](https://badgen.net/packagephobia/publish/@apiglobal/typedserver)](https://lossless.cloud)
BundlePhobia (total size when bundled) | [![BundlePhobia](https://badgen.net/bundlephobia/minzip/@apiglobal/typedserver)](https://lossless.cloud)
## Usage
Use TypeScript for best in class instellisense.
```javascript
import { TypedServer } from '@apiglobal/typedserver';
let myTypedserver = new TypedServer('/some/path/to/webroot', 8080);
myTypedserver.start().then(() => {
// this is executed when server is running guaranteed
myTypedserver.stop(); // .stop() will work even if not waiting for server to be fully started
});
myTypedserver.reload(); // reloads all connected browsers of this instance
```
## 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)

11
test/index.html Normal file
View File

@ -0,0 +1,11 @@
<head>
<title>An Awesome Test Page</title>
<style>
body {
color: #fff;
}
</style>
</head>
<body>
This is a test page!
</body>

30
test/test.ts Normal file
View File

@ -0,0 +1,30 @@
import { tap, expect } from '@pushrocks/tapbundle';
import * as smartpath from '@pushrocks/smartpath';
import { TypedServer } from '../ts/index.js';
let testTypedServer: TypedServer;
tap.test('should create a valid instance of TypedServer', async () => {
testTypedServer = new TypedServer({
injectReload: true,
port: 3000,
serveDir: smartpath.get.dirnameFromImportMetaUrl(import.meta.url),
watch: true,
});
expect(testTypedServer).toBeInstanceOf(TypedServer);
});
tap.test('should start to serve files', async (tools) => {
await testTypedServer.start();
await tools.delayFor(5000);
await testTypedServer.reload();
await tools.delayFor(5000);
await testTypedServer.reload();
});
tap.test('should stop to serve files ', async (tools) => {
await tools.delayFor(5000);
await testTypedServer.stop();
});
tap.start();

8
ts/00_commitinfo_data.ts Normal file
View File

@ -0,0 +1,8 @@
/**
* autocreated commitinfo by @pushrocks/commitinfo
*/
export const commitinfo = {
name: '@apiglobal/typedserver',
version: '2.0.34',
description: 'easy serving of static files'
}

1
ts/index.ts Normal file
View File

@ -0,0 +1 @@
export * from './typedserver.classes.typedserver.js';

12
ts/interfaces/index.ts Normal file
View File

@ -0,0 +1,12 @@
import * as typedrequestInterfaces from '@apiglobal/typedrequest-interfaces';
export interface IReq_PushLatestServerChangeTime extends typedrequestInterfaces.implementsTR<
typedrequestInterfaces.ITypedRequest,
IReq_PushLatestServerChangeTime
> {
method: 'pushLatestServerChangeTime',
request: {
time: number;
};
response: {}
}

View File

@ -0,0 +1,170 @@
import * as plugins from './typedserver.plugins.js';
import * as paths from './typedserver.paths.js';
import * as interfaces from './interfaces/index.js';
export interface IEasyServerConstructorOptions {
serveDir: string;
injectReload: boolean;
port?: number;
watch?: boolean;
}
export class TypedServer {
// static
// nothing here yet
// instance
public options: IEasyServerConstructorOptions;
public smartexpressInstance: plugins.smartexpress.Server;
public smartchokInstance: plugins.smartchok.Smartchok;
public serveDirHashSubject = new plugins.smartrx.rxjs.ReplaySubject<string>(1);
public serveHash: string = '000000';
public typedsocket: plugins.typedsocket.TypedSocket;
public typedrouter = new plugins.typedrequest.TypedRouter();
public lastReload: number = Date.now();
public ended = false;
constructor(optionsArg: IEasyServerConstructorOptions) {
const standardOptions: IEasyServerConstructorOptions = {
injectReload: true,
port: 3000,
serveDir: process.cwd(),
watch: true,
};
this.options = {
...standardOptions,
...optionsArg,
};
}
/**
* inits and starts the server
*/
public async start() {
// set the smartexpress instance
this.smartexpressInstance = new plugins.smartexpress.Server({
port: this.options.port,
forceSsl: false,
cors: true,
});
// add routes to the smartexpress instance
this.smartexpressInstance.addRoute(
'/typedserver/:request',
new plugins.smartexpress.Handler('ALL', async (req, res) => {
switch (req.params.request) {
case 'devtools':
res.setHeader('Content-Type', 'text/javascript');
res.status(200);
res.write(plugins.smartfile.fs.toStringSync(paths.bundlePath));
res.end();
break;
case 'reloadcheck':
console.log('got request for reloadcheck');
res.setHeader('Content-Type', 'text/plain');
res.status(200);
if (this.ended) {
res.write('end');
res.end();
return;
}
res.write(this.lastReload.toString());
res.end();
}
})
);
this.smartexpressInstance.addRoute(
'/*',
new plugins.smartexpress.HandlerStatic(this.options.serveDir, {
responseModifier: async (responseArg) => {
let fileString = responseArg.responseContent;
if (plugins.path.parse(responseArg.path).ext === '.html') {
const fileStringArray = fileString.split('<head>');
if (this.options.injectReload && fileStringArray.length === 2) {
fileStringArray[0] = `${fileStringArray[0]}<head>
<!-- injected by @apiglobal/typedserver start -->
<script async defer type="module" src="/typedserver/devtools"></script>
<script>
globalThis.typedserver = {
lastReload: '${this.lastReload}',
versionInfo: ${JSON.stringify({}, null, 2)},
}
</script>
<!-- injected by @apiglobal/typedserver stop -->
`;
fileString = fileStringArray.join('');
console.log('injected typedserver script.');
} else if (this.options.injectReload) {
console.log('Could not insert typedserver script');
}
}
const headers = responseArg.headers;
headers.appHash = this.serveHash;
headers['Cache-Control'] = 'no-cache, no-store, must-revalidate';
headers['Pragma'] = 'no-cache';
headers['Expires'] = '0';
return {
headers,
path: responseArg.path,
responseContent: fileString,
};
},
serveIndexHtmlDefault: true,
})
);
this.smartchokInstance = new plugins.smartchok.Smartchok([this.options.serveDir], {});
if (this.options.watch) {
await this.smartchokInstance.start();
(await this.smartchokInstance.getObservableFor('change')).subscribe(async () => {
await this.createServeDirHash();
this.reload();
});
}
await this.createServeDirHash();
// lets start the server
await this.smartexpressInstance.start();
console.log('open url in browser');
this.typedsocket = await plugins.typedsocket.TypedSocket.createServer(
this.typedrouter,
this.smartexpressInstance
);
// await plugins.smartopen.openUrl(`http://testing.git.zone:${this.options.port}`);
}
/**
* reloads the page
*/
public async reload() {
this.lastReload = Date.now();
for (const connectionArg of await this.typedsocket.findAllTargetConnections(async () => true)) {
const pushTime =
this.typedsocket.createTypedRequest<interfaces.IReq_PushLatestServerChangeTime>(
'pushLatestServerChangeTime',
connectionArg
);
pushTime.fire({
time: this.lastReload,
});
}
}
public async stop() {
this.ended = true;
await this.smartexpressInstance.stop();
await this.typedsocket.stop();
await this.smartchokInstance.stop();
}
public async createServeDirHash() {
const serveDirHash = await plugins.smartfile.fs.fileTreeToHash(this.options.serveDir, '**/*');
this.serveHash = serveDirHash;
console.log('Current ServeDir hash: ' + serveDirHash);
this.serveDirHashSubject.next(serveDirHash);
}
}

8
ts/typedserver.paths.ts Normal file
View File

@ -0,0 +1,8 @@
import * as plugins from './typedserver.plugins.js';
export const packageDir = plugins.path.join(
plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url),
'../'
);
export const bundlePath = plugins.path.join(packageDir, './dist_ts_web/bundle.js');

36
ts/typedserver.plugins.ts Normal file
View File

@ -0,0 +1,36 @@
// node native
import * as path from 'path';
export { path };
// @apiglobal scope
import * as typedrequest from '@apiglobal/typedrequest';
import * as typedrequestInterfaces from '@apiglobal/typedrequest-interfaces';
import * as typedsocket from '@apiglobal/typedsocket';
export {
typedrequest,
typedrequestInterfaces,
typedsocket,
}
// @pushrocks scope
import * as smartchok from '@pushrocks/smartchok';
import * as smartdelay from '@pushrocks/smartdelay';
import * as smartexpress from '@pushrocks/smartexpress';
import * as smartfile from '@pushrocks/smartfile';
import * as smartopen from '@pushrocks/smartopen';
import * as smartpath from '@pushrocks/smartpath';
import * as smartpromise from '@pushrocks/smartpromise';
import * as smartrx from '@pushrocks/smartrx';
export {
smartchok,
smartdelay,
smartexpress,
smartfile,
smartopen,
smartpath,
smartpromise,
smartrx,
};

View File

@ -0,0 +1,8 @@
/**
* autocreated commitinfo by @pushrocks/commitinfo
*/
export const commitinfo = {
name: '@apiglobal/typedserver',
version: '2.0.34',
description: 'easy serving of static files'
}

125
ts_web/index.ts Normal file
View File

@ -0,0 +1,125 @@
import * as plugins from './typedserver_web.plugins.js';
import * as interfaces from '../ts/interfaces/index.js';
import { logger } from './typedserver_web.logger.js';
logger.log('info', `TypedServer-Devtools initialized!`);
import { TypedserverInfoscreen } from './typedserver_web.infoscreen.js';
export class ReloadChecker {
public reloadJustified = false;
public backendConnectionLost = false;
public infoscreen = new TypedserverInfoscreen();
public store = new plugins.webstore.WebStore({
dbName: 'apiglobal__typedserver',
storeName: 'apiglobal__typedserver',
});
public storeKey = 'lastServerChange';
public typedsocket: plugins.typedsocket.TypedSocket;
public typedrouter = new plugins.typedrequest.TypedRouter();
constructor() {}
public async reload() {
// this looks a bit hacky, but apparently is the safest way to really reload stuff
window.location.reload();
}
/**
* starts the reload checker
*/
public async performHttpRequest() {
logger.log('info', 'performing http check...');
(await this.store.get(this.storeKey))
? null
: await this.store.set(this.storeKey, globalThis.typedserver.lastReload);
let response: Response;
try {
const controller = new AbortController();
plugins.smartdelay.delayFor(5000).then(() => {
controller.abort();
});
response = await fetch('/typedserver/reloadcheck', {
method: 'POST',
signal: controller.signal,
});
} catch (err: any) {}
if (response?.status !== 200) {
this.backendConnectionLost = true;
logger.log('warn', `got a status ${response?.status}.`);
this.infoscreen.setText(`backend connection lost... Status ${response?.status}`);
}
if (this.backendConnectionLost) {
this.backendConnectionLost = false;
this.infoscreen.setSuccess('regained connection to backend...');
}
return response;
}
public async checkReload(lastServerChange: number) {
let reloadJustified = false;
(await this.store.get(this.storeKey)) !== lastServerChange ? (reloadJustified = true) : null;
if (reloadJustified) {
this.store.set(this.storeKey, lastServerChange);
const reloadText = `about to reload ${
globalThis.globalSw ? '(purging the sw cache first...)' : ''
}`;
this.infoscreen.setText(reloadText);
if (globalThis.globalSw?.purgeCache) {
await globalThis.globalSw.purgeCache();
} else {
console.log('globalThis.globalSw not found...');
}
this.infoscreen.setText(`cleaned caches`);
await plugins.smartdelay.delayFor(200);
this.reload();
return;
} else {
if (this.infoscreen) {
this.infoscreen.hide();
}
return;
}
}
public async connectTypedsocket() {
if (!this.typedsocket) {
this.typedrouter.addTypedHandler<interfaces.IReq_PushLatestServerChangeTime>(
new plugins.typedrequest.TypedHandler('pushLatestServerChangeTime', async (dataArg) => {
this.checkReload(dataArg.time);
return {};
})
);
this.typedsocket = await plugins.typedsocket.TypedSocket.createClient(
this.typedrouter,
plugins.typedsocket.TypedSocket.useWindowLocationOriginUrl()
);
}
}
public started = false;
public async start() {
this.started = true;
logger.log('info', `starting ReloadChecker...`);
while (this.started) {
const response = await this.performHttpRequest();
if (response.status === 200) {
logger.log('info', `ReloadChecker reached backend!`);
await this.checkReload(parseInt(await response.text()));
await this.connectTypedsocket();
await plugins.smartdelay.delayFor(120000);
}
}
}
public async stop() {
this.started = false;
}
}
const reloadCheckInstance = new ReloadChecker();
reloadCheckInstance.start();

View File

@ -0,0 +1,109 @@
import {LitElement, html, css} from 'lit';
import { customElement, property } from 'lit/decorators.js';
import * as plugins from './typedserver_web.plugins.js';
declare global {
interface HTMLElementTagNameMap {
'typedserver-infoscreen': TypedserverInfoscreen;
}
}
@customElement('typedserver-infoscreen')
export class TypedserverInfoscreen extends LitElement {
//INSTANCE
@property()
private text = 'Hello';
@property()
private success = false;
public static styles = [
css`
* {
box-sizing: border-box;
}
:host {
}
.mainbox {
z-index: 1000;
position: fixed;
transition: all 0.3s;
display: block;
bottom: -50px;
right: 0px;
left: 0px;
height : 50px;
background: #222;
color: #CCC;
padding: 15px;
border-top: 1px solid #e4002b;
text-align: center;
font-family: 'Roboto', sans-serif;
color: #fff;
background: #111;
box-shadow: 0px -30px 30px rgba(0,0,0,1);
opacity: 0;
}
@media (prefers-color-scheme: light) {
.mainbox {
color: #333;
background: #eeeeee;
box-shadow: 0px 0px 5px rgba(0,0,0,0.3);
}
}
.show {
bottom: 0px;
opacity: 1;
}
.success {
background: green;
border-top: 1px solid green;
}
`
];
public setText(textArg: string) {
this.text = textArg;
this.show();
this.success = false;
}
public setSuccess(textArg: string) {
this.text = textArg;
this.show();
this.success = true;
}
private appended = false;
public show () {
this.appended = true;
document.body.append(this);
}
public hide() {
this.success = false;
this.text = '';
if (this.appended) {
document.body.removeChild(this);
}
}
public render () {
return html`
<div class="mainbox ${this.show ? 'show' : ''} ${this.success ? 'success': ''}">${this.text}</div>
`
}
public async firstUpdated(_changedProperties: Map<string | number | symbol, unknown>): Promise<void> {
super.firstUpdated(_changedProperties);
}
}

View File

@ -0,0 +1,15 @@
import * as plugins from './typedserver_web.plugins.js';
export const logger = new plugins.smartlog.Smartlog({
logContext: {
company: 'Some Company',
companyunit: 'Some CompanyUnit',
containerName: 'Some Containername',
environment: "local",
runtime: 'node',
zone: 'gitzone'
},
minimumLogLevel: 'silly'
});
logger.addLogDestination(new plugins.smartlogDestinationDevtools.SmartlogDestinationDevtools());

View File

@ -0,0 +1,21 @@
// @apiglobal scope
import * as typedrequest from '@apiglobal/typedrequest';
import * as typedsocket from '@apiglobal/typedsocket';
export {
typedrequest,
typedsocket,
}
// pushrocks scope
import * as smartdelay from '@pushrocks/smartdelay';
import * as smartlog from '@pushrocks/smartlog';
import * as smartlogDestinationDevtools from '@pushrocks/smartlog-destination-devtools';
import * as webstore from '@pushrocks/webstore';
export {
smartdelay,
smartlog,
smartlogDestinationDevtools,
webstore,
};

8
tsconfig.json Normal file
View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"experimentalDecorators": true,
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "nodenext"
}
}