fix(ci): Fix Docker images and npm registry URL in CI workflows
This commit is contained in:
parent
320b3ed9eb
commit
8f49f0cb4f
@ -6,8 +6,8 @@ on:
|
||||
- '**'
|
||||
|
||||
env:
|
||||
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
|
||||
IMAGE: code.foss.global/hosttoday/ht-docker-node:npmci
|
||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
|
||||
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
||||
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
||||
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
||||
@ -27,7 +27,7 @@ jobs:
|
||||
- name: Install pnpm and npmci
|
||||
run: |
|
||||
pnpm install -g pnpm
|
||||
pnpm install -g @shipzone/npmci
|
||||
pnpm install -g @ship.zone/npmci
|
||||
npmci npm prepare
|
||||
|
||||
- name: Audit production dependencies
|
||||
@ -54,7 +54,7 @@ jobs:
|
||||
- name: Prepare
|
||||
run: |
|
||||
pnpm install -g pnpm
|
||||
pnpm install -g @shipzone/npmci
|
||||
pnpm install -g @ship.zone/npmci
|
||||
npmci npm prepare
|
||||
|
||||
- name: Test stable
|
||||
|
@ -6,8 +6,8 @@ on:
|
||||
- '*'
|
||||
|
||||
env:
|
||||
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
|
||||
IMAGE: code.foss.global/hosttoday/ht-docker-node:npmci
|
||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
|
||||
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
||||
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
||||
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
||||
@ -27,7 +27,7 @@ jobs:
|
||||
- name: Prepare
|
||||
run: |
|
||||
pnpm install -g pnpm
|
||||
pnpm install -g @shipzone/npmci
|
||||
pnpm install -g @ship.zone/npmci
|
||||
npmci npm prepare
|
||||
|
||||
- name: Audit production dependencies
|
||||
@ -54,7 +54,7 @@ jobs:
|
||||
- name: Prepare
|
||||
run: |
|
||||
pnpm install -g pnpm
|
||||
pnpm install -g @shipzone/npmci
|
||||
pnpm install -g @ship.zone/npmci
|
||||
npmci npm prepare
|
||||
|
||||
- name: Test stable
|
||||
@ -74,7 +74,7 @@ jobs:
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: registry.gitlab.com/hosttoday/ht-docker-dbase:npmci
|
||||
image: code.foss.global/hosttoday/ht-docker-dbase:npmci
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@ -82,15 +82,15 @@ jobs:
|
||||
- name: Prepare
|
||||
run: |
|
||||
pnpm install -g pnpm
|
||||
pnpm install -g @shipzone/npmci
|
||||
pnpm install -g @ship.zone/npmci
|
||||
|
||||
- name: Release
|
||||
run: |
|
||||
npmci docker login
|
||||
npmci docker build
|
||||
npmci docker test
|
||||
# npmci docker push gitea.lossless.digital
|
||||
npmci docker push dockerregistry.lossless.digital
|
||||
# npmci docker push
|
||||
npmci docker push
|
||||
|
||||
metadata:
|
||||
needs: test
|
||||
|
@ -1,6 +1,6 @@
|
||||
# gitzone dockerfile_service
|
||||
## STAGE 1 // BUILD
|
||||
FROM registry.gitlab.com/hosttoday/ht-docker-node:npmci as node1
|
||||
FROM code.foss.global/hosttoday/ht-docker-node:npmci as node1
|
||||
COPY ./ /app
|
||||
WORKDIR /app
|
||||
ARG NPMCI_TOKEN_NPM2
|
||||
@ -12,7 +12,7 @@ RUN pnpm run build
|
||||
|
||||
# gitzone dockerfile_service
|
||||
## STAGE 2 // install production
|
||||
FROM registry.gitlab.com/hosttoday/ht-docker-node:npmci as node2
|
||||
FROM code.foss.global/hosttoday/ht-docker-node:npmci as node2
|
||||
WORKDIR /app
|
||||
COPY --from=node1 /app /app
|
||||
RUN rm -rf .pnpm-store
|
||||
@ -24,7 +24,7 @@ RUN rm -rf node_modules/ && pnpm install --prod
|
||||
|
||||
|
||||
## STAGE 3 // rebuild dependencies for alpine
|
||||
FROM registry.gitlab.com/hosttoday/ht-docker-node:alpinenpmci as node3
|
||||
FROM code.foss.global/hosttoday/ht-docker-node:alpinenpmci as node3
|
||||
WORKDIR /app
|
||||
COPY --from=node2 /app /app
|
||||
ARG NPMCI_TOKEN_NPM2
|
||||
@ -34,7 +34,7 @@ RUN pnpm config set store-dir .pnpm-store
|
||||
RUN pnpm rebuild -r
|
||||
|
||||
## STAGE 4 // the final production image with all dependencies in place
|
||||
FROM registry.gitlab.com/hosttoday/ht-docker-node:alpine as node4
|
||||
FROM code.foss.global/hosttoday/ht-docker-node:alpine as node4
|
||||
WORKDIR /app
|
||||
COPY --from=node3 /app /app
|
||||
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## 2024-10-27 - 1.2.4 - fix(ci)
|
||||
Fix Docker images and npm registry URL in CI workflows
|
||||
|
||||
- Updated Docker image registry URL from 'registry.gitlab.com' to 'code.foss.global'.
|
||||
- Fixed npmci package installation path from '@shipzone/npmci' to '@ship.zone/npmci'.
|
||||
|
||||
## 2024-10-23 - 1.2.3 - fix(cli)
|
||||
Set up CLI client definition and registry configuration
|
||||
|
||||
|
20
package.json
20
package.json
@ -18,19 +18,21 @@
|
||||
"start": "node cli.js",
|
||||
"startTs": "node cli.ts.js",
|
||||
"watch": "tswatch website",
|
||||
"publish": "tspublish"
|
||||
"publish": "tspublish",
|
||||
"buildDocs": "tsdoc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@git.zone/tsbuild": "^2.1.84",
|
||||
"@git.zone/tsbundle": "^2.0.15",
|
||||
"@git.zone/tspublish": "^1.3.0",
|
||||
"@git.zone/tsbuild": "^2.1.85",
|
||||
"@git.zone/tsbundle": "^2.1.0",
|
||||
"@git.zone/tspublish": "^1.4.0",
|
||||
"@git.zone/tstest": "^1.0.90",
|
||||
"@git.zone/tswatch": "^2.0.23",
|
||||
"@git.zone/tswatch": "^2.0.25",
|
||||
"@push.rocks/tapbundle": "^5.3.0",
|
||||
"@types/node": "^22.7.7"
|
||||
"@types/node": "^22.8.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@api.global/typedrequest": "3.1.10",
|
||||
"@api.global/typedrequest-interfaces": "^3.0.19",
|
||||
"@api.global/typedserver": "^3.0.51",
|
||||
"@api.global/typedsocket": "^3.0.1",
|
||||
"@apiclient.xyz/cloudflare": "^6.0.1",
|
||||
@ -40,7 +42,7 @@
|
||||
"@design.estate/dees-catalog": "^1.2.0",
|
||||
"@design.estate/dees-domtools": "^2.0.64",
|
||||
"@design.estate/dees-element": "^2.0.39",
|
||||
"@git.zone/tsrun": "^1.2.49",
|
||||
"@git.zone/tsrun": "^1.3.3",
|
||||
"@push.rocks/early": "^4.0.3",
|
||||
"@push.rocks/npmextra": "^5.0.23",
|
||||
"@push.rocks/projectinfo": "^5.0.1",
|
||||
@ -59,6 +61,7 @@
|
||||
"@push.rocks/smartjwt": "^2.2.1",
|
||||
"@push.rocks/smartlog": "^3.0.7",
|
||||
"@push.rocks/smartlog-destination-clickhouse": "^1.0.13",
|
||||
"@push.rocks/smartlog-interfaces": "^3.0.2",
|
||||
"@push.rocks/smartpath": "^5.0.18",
|
||||
"@push.rocks/smartpromise": "^4.0.4",
|
||||
"@push.rocks/smartrequest": "^2.0.22",
|
||||
@ -70,7 +73,6 @@
|
||||
"@push.rocks/smartunique": "^3.0.9",
|
||||
"@push.rocks/taskbuffer": "^3.0.2",
|
||||
"@push.rocks/webjwt": "^1.0.9",
|
||||
"@serve.zone/interfaces": "^1.1.2",
|
||||
"@tsclass/tsclass": "^4.1.2"
|
||||
},
|
||||
"files": [
|
||||
@ -125,4 +127,4 @@
|
||||
"security",
|
||||
"logging"
|
||||
]
|
||||
}
|
||||
}
|
1288
pnpm-lock.yaml
generated
1288
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@serve.zone/cloudly',
|
||||
version: '1.2.3',
|
||||
version: '1.2.4',
|
||||
description: 'A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and provide robust configuration and API integration.'
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import { MongodbConnector } from './connector.mongodb/connector.js';
|
||||
import { CloudlyCoreflowManager } from './manager.coreflow/coreflowmanager.js';
|
||||
import { ClusterManager } from './manager.cluster/classes.clustermanager.js';
|
||||
import { CloudlyTaskmanager } from './manager.task/taskmanager.js';
|
||||
import { CloudlySecretManager } from './manager.secret/classes.secretmanager.js'
|
||||
import { CloudlySecretManager } from './manager.secret/classes.secretmanager.js';
|
||||
import { CloudlyServerManager } from './manager.server/classes.servermanager.js';
|
||||
import { ExternalApiManager } from './manager.status/statusmanager.js';
|
||||
import { ImageManager } from './manager.image/classes.imagemanager.js';
|
||||
|
@ -9,50 +9,53 @@ import type { Cloudly } from './classes.cloudly.js';
|
||||
export class CloudlyConfig {
|
||||
public cloudlyRef: Cloudly;
|
||||
public appData: plugins.npmextra.AppData<plugins.servezoneInterfaces.data.ICloudlyConfig>;
|
||||
public data: plugins.servezoneInterfaces.data.ICloudlyConfig
|
||||
|
||||
public data: plugins.servezoneInterfaces.data.ICloudlyConfig;
|
||||
|
||||
constructor(cloudlyRefArg: Cloudly) {
|
||||
this.cloudlyRef = cloudlyRefArg;
|
||||
}
|
||||
|
||||
public async init() {
|
||||
this.appData = await plugins.npmextra.AppData.createAndInit<plugins.servezoneInterfaces.data.ICloudlyConfig>({
|
||||
envMapping: {
|
||||
cfToken: 'CF_TOKEN',
|
||||
environment: 'SERVEZONE_ENVIRONMENT' as 'production' | 'integration',
|
||||
letsEncryptEmail: 'hard:domains@lossless.org',
|
||||
hetznerToken: 'HETZNER_API_TOKEN',
|
||||
letsEncryptPrivateKey: null,
|
||||
publicUrl: 'SERVEZONE_URL',
|
||||
publicPort: 'SERVEZONE_PORT',
|
||||
mongoDescriptor: {
|
||||
mongoDbUrl: 'MONGODB_URL',
|
||||
mongoDbName: 'MONGODB_DATABASE',
|
||||
mongoDbUser: 'MONGODB_USER',
|
||||
mongoDbPass: 'MONGODB_PASSWORD',
|
||||
this.appData =
|
||||
await plugins.npmextra.AppData.createAndInit<plugins.servezoneInterfaces.data.ICloudlyConfig>(
|
||||
{
|
||||
envMapping: {
|
||||
cfToken: 'CF_TOKEN',
|
||||
environment: 'SERVEZONE_ENVIRONMENT' as 'production' | 'integration',
|
||||
letsEncryptEmail: 'hard:domains@lossless.org',
|
||||
hetznerToken: 'HETZNER_API_TOKEN',
|
||||
letsEncryptPrivateKey: null,
|
||||
publicUrl: 'SERVEZONE_URL',
|
||||
publicPort: 'SERVEZONE_PORT',
|
||||
mongoDescriptor: {
|
||||
mongoDbUrl: 'MONGODB_URL',
|
||||
mongoDbName: 'MONGODB_DATABASE',
|
||||
mongoDbUser: 'MONGODB_USER',
|
||||
mongoDbPass: 'MONGODB_PASSWORD',
|
||||
},
|
||||
s3Descriptor: {
|
||||
endpoint: 'S3_ENDPOINT',
|
||||
accessKey: 'S3_ACCESSKEY',
|
||||
accessSecret: 'S3_SECRETKEY',
|
||||
port: 'S3_PORT', // Note: This will remain as a string. Ensure to parse it to an integer where it's used.
|
||||
useSsl: true,
|
||||
},
|
||||
sslMode:
|
||||
'SERVEZONE_SSLMODE' as plugins.servezoneInterfaces.data.ICloudlyConfig['sslMode'],
|
||||
servezoneAdminaccount: 'SERVEZONE_ADMINACCOUNT',
|
||||
},
|
||||
requiredKeys: [
|
||||
'cfToken',
|
||||
'hetznerToken',
|
||||
'letsEncryptEmail',
|
||||
'publicUrl',
|
||||
'publicPort',
|
||||
'sslMode',
|
||||
'environment',
|
||||
'mongoDescriptor',
|
||||
],
|
||||
},
|
||||
s3Descriptor: {
|
||||
endpoint: 'S3_ENDPOINT',
|
||||
accessKey: 'S3_ACCESSKEY',
|
||||
accessSecret: 'S3_SECRETKEY',
|
||||
port: 'S3_PORT', // Note: This will remain as a string. Ensure to parse it to an integer where it's used.
|
||||
useSsl: true,
|
||||
},
|
||||
sslMode: 'SERVEZONE_SSLMODE' as plugins.servezoneInterfaces.data.ICloudlyConfig['sslMode'],
|
||||
servezoneAdminaccount: 'SERVEZONE_ADMINACCOUNT',
|
||||
},
|
||||
requiredKeys: [
|
||||
'cfToken',
|
||||
'hetznerToken',
|
||||
'letsEncryptEmail',
|
||||
'publicUrl',
|
||||
'publicPort',
|
||||
'sslMode',
|
||||
'environment',
|
||||
'mongoDescriptor',
|
||||
],
|
||||
});
|
||||
);
|
||||
|
||||
const kvStore = await this.appData.getKvStore();
|
||||
|
||||
|
@ -45,16 +45,16 @@ export class CloudlyServer {
|
||||
logger.log('info', `Using letsencrypt for ssl mode. Trying to obtain a certificate...`);
|
||||
logger.log('info', `This might take 10 minutes...`);
|
||||
sslCert = await this.cloudlyRef.letsencryptConnector.getCertificateForDomain(
|
||||
this.cloudlyRef.config.data.publicUrl
|
||||
this.cloudlyRef.config.data.publicUrl,
|
||||
);
|
||||
logger.log(
|
||||
'success',
|
||||
`Successfully obtained certificate for cloudly domain ${this.cloudlyRef.config.data.publicUrl}`
|
||||
`Successfully obtained certificate for cloudly domain ${this.cloudlyRef.config.data.publicUrl}`,
|
||||
);
|
||||
} else if (this.cloudlyRef.config.data.sslMode === 'external') {
|
||||
logger.log(
|
||||
'info',
|
||||
`Using external certificate for ssl mode, meaning cloudly is not in charge of ssl termination.`
|
||||
`Using external certificate for ssl mode, meaning cloudly is not in charge of ssl termination.`,
|
||||
);
|
||||
}
|
||||
|
||||
@ -95,7 +95,7 @@ export class CloudlyServer {
|
||||
this.typedServer.typedrouter.addTypedRouter(this.typedrouter);
|
||||
this.typedServer.server.addRoute(
|
||||
'/curlfresh/:scriptname',
|
||||
this.cloudlyRef.serverManager.curlfreshInstance.handler
|
||||
this.cloudlyRef.serverManager.curlfreshInstance.handler,
|
||||
);
|
||||
await this.typedServer.start();
|
||||
}
|
||||
|
@ -24,19 +24,19 @@ export class LetsencryptConnector {
|
||||
environment: this.cloudlyRef.config.data.environment,
|
||||
setChallenge: async (dnsChallenge) => {
|
||||
await this.cloudlyRef.cloudflareConnector.cloudflare.convenience.acmeSetDnsChallenge(
|
||||
dnsChallenge
|
||||
dnsChallenge,
|
||||
);
|
||||
},
|
||||
removeChallenge: async (dnsChallenge) => {
|
||||
await this.cloudlyRef.cloudflareConnector.cloudflare.convenience.acmeRemoveDnsChallenge(
|
||||
dnsChallenge
|
||||
dnsChallenge,
|
||||
);
|
||||
},
|
||||
mongoDescriptor: this.cloudlyRef.config.data.mongoDescriptor,
|
||||
});
|
||||
await this.smartacme.start().catch(err => {
|
||||
await this.smartacme.start().catch((err) => {
|
||||
console.error('error in init', err);
|
||||
console.log(`trying again in a few minutes`)
|
||||
console.log(`trying again in a few minutes`);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,9 @@ export class MongodbConnector {
|
||||
}
|
||||
|
||||
public async init() {
|
||||
this.smartdataDb = new plugins.smartdata.SmartdataDb(this.cloudlyRef.config.data.mongoDescriptor);
|
||||
this.smartdataDb = new plugins.smartdata.SmartdataDb(
|
||||
this.cloudlyRef.config.data.mongoDescriptor,
|
||||
);
|
||||
await this.smartdataDb.init();
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@ import { logger } from './logger.js';
|
||||
const cloudlyQenv = new plugins.qenv.Qenv(paths.packageDir, paths.nogitDir, true);
|
||||
early.stop();
|
||||
|
||||
|
||||
/**
|
||||
* starts the cloudly instance
|
||||
*/
|
||||
@ -17,7 +16,7 @@ const runCli = async () => {
|
||||
|
||||
logger.log(
|
||||
'info',
|
||||
`running in environment ${await cloudlyQenv.getEnvVarOnDemand('SERVEZONE_ENVIRONMENT')}`
|
||||
`running in environment ${await cloudlyQenv.getEnvVarOnDemand('SERVEZONE_ENVIRONMENT')}`,
|
||||
);
|
||||
|
||||
await cloudlyInstance.start();
|
||||
@ -27,4 +26,4 @@ const runCli = async () => {
|
||||
|
||||
export { runCli, Cloudly };
|
||||
type ICloudlyConfig = plugins.servezoneInterfaces.data.ICloudlyConfig;
|
||||
export { type ICloudlyConfig }
|
||||
export { type ICloudlyConfig };
|
||||
|
@ -9,8 +9,8 @@ export const logger = new plugins.smartlog.Smartlog({
|
||||
zone: null,
|
||||
companyunit: null,
|
||||
containerName: null,
|
||||
}
|
||||
},
|
||||
});
|
||||
logger.enableConsole({
|
||||
captureAll: false
|
||||
captureAll: false,
|
||||
});
|
||||
|
@ -5,7 +5,6 @@ import { logger } from '../logger.js';
|
||||
import { Authorization } from './classes.authorization.js';
|
||||
import { User } from './classes.user.js';
|
||||
|
||||
|
||||
export interface IJwtData {
|
||||
userId: string;
|
||||
status: 'loggedIn' | 'loggedOut';
|
||||
@ -13,7 +12,7 @@ export interface IJwtData {
|
||||
}
|
||||
|
||||
export class CloudlyAuthManager {
|
||||
cloudlyRef: Cloudly
|
||||
cloudlyRef: Cloudly;
|
||||
public get db() {
|
||||
return this.cloudlyRef.mongodbConnector.smartdataDb;
|
||||
}
|
||||
@ -38,7 +37,9 @@ export class CloudlyAuthManager {
|
||||
await this.smartjwtInstance.init();
|
||||
const kvStore = await this.cloudlyRef.config.appData.getKvStore();
|
||||
|
||||
const existingJwtKeys: plugins.tsclass.network.IJwtKeypair = (await kvStore.readKey('jwtKeypair')) as plugins.tsclass.network.IJwtKeypair;
|
||||
const existingJwtKeys: plugins.tsclass.network.IJwtKeypair = (await kvStore.readKey(
|
||||
'jwtKeypair',
|
||||
)) as plugins.tsclass.network.IJwtKeypair;
|
||||
|
||||
if (!existingJwtKeys) {
|
||||
await this.smartjwtInstance.createNewKeyPair();
|
||||
@ -76,40 +77,61 @@ export class CloudlyAuthManager {
|
||||
type: user.data.type,
|
||||
},
|
||||
};
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public async stop () {}
|
||||
public async stop() {}
|
||||
|
||||
public validIdentityGuard = new plugins.smartguard.Guard<{identity: plugins.servezoneInterfaces.data.IIdentity}>(async (dataArg) => {
|
||||
const jwt = dataArg.identity.jwt;
|
||||
const jwtData: IJwtData = await this.smartjwtInstance.verifyJWTAndGetData(jwt);
|
||||
const expired = jwtData.expiresAt < Date.now();
|
||||
plugins.smartexpect.expect(jwtData.status).setFailMessage('user not logged in').toEqual('loggedIn');
|
||||
plugins.smartexpect.expect(expired).setFailMessage(`jwt expired`).toBeFalse();
|
||||
plugins.smartexpect.expect(dataArg.identity.expiresAt).setFailMessage(`expiresAt >>identity valid until:${dataArg.identity.expiresAt}, but jwt says: ${jwtData.expiresAt}<< has been tampered with`).toEqual(jwtData.expiresAt);
|
||||
plugins.smartexpect.expect(dataArg.identity.userId).setFailMessage('userId has been tampered with').toEqual(jwtData.userId);
|
||||
if (expired) {
|
||||
throw new Error('identity is expired');
|
||||
}
|
||||
return true;
|
||||
}, {
|
||||
failedHint: 'identity is not valid.',
|
||||
name: 'validIdentityGuard',
|
||||
});
|
||||
public validIdentityGuard = new plugins.smartguard.Guard<{
|
||||
identity: plugins.servezoneInterfaces.data.IIdentity;
|
||||
}>(
|
||||
async (dataArg) => {
|
||||
const jwt = dataArg.identity.jwt;
|
||||
const jwtData: IJwtData = await this.smartjwtInstance.verifyJWTAndGetData(jwt);
|
||||
const expired = jwtData.expiresAt < Date.now();
|
||||
plugins.smartexpect
|
||||
.expect(jwtData.status)
|
||||
.setFailMessage('user not logged in')
|
||||
.toEqual('loggedIn');
|
||||
plugins.smartexpect.expect(expired).setFailMessage(`jwt expired`).toBeFalse();
|
||||
plugins.smartexpect
|
||||
.expect(dataArg.identity.expiresAt)
|
||||
.setFailMessage(
|
||||
`expiresAt >>identity valid until:${dataArg.identity.expiresAt}, but jwt says: ${jwtData.expiresAt}<< has been tampered with`,
|
||||
)
|
||||
.toEqual(jwtData.expiresAt);
|
||||
plugins.smartexpect
|
||||
.expect(dataArg.identity.userId)
|
||||
.setFailMessage('userId has been tampered with')
|
||||
.toEqual(jwtData.userId);
|
||||
if (expired) {
|
||||
throw new Error('identity is expired');
|
||||
}
|
||||
return true;
|
||||
},
|
||||
{
|
||||
failedHint: 'identity is not valid.',
|
||||
name: 'validIdentityGuard',
|
||||
},
|
||||
);
|
||||
|
||||
public adminIdentityGuard = new plugins.smartguard.Guard<{identity: plugins.servezoneInterfaces.data.IIdentity}>(async (dataArg) => {
|
||||
await plugins.smartguard.passGuardsOrReject(dataArg, [this.validIdentityGuard]);
|
||||
const jwt = dataArg.identity.jwt;
|
||||
const jwtData: IJwtData = await this.smartjwtInstance.verifyJWTAndGetData(jwt);
|
||||
const user = await this.CUser.getInstance({id: jwtData.userId});
|
||||
const isAdminBool = user.data.role === 'admin';
|
||||
console.log(`user is admin: ${isAdminBool}`);
|
||||
return isAdminBool;
|
||||
}, {
|
||||
failedHint: 'user is not admin.',
|
||||
name: 'adminIdentityGuard',
|
||||
})
|
||||
}
|
||||
public adminIdentityGuard = new plugins.smartguard.Guard<{
|
||||
identity: plugins.servezoneInterfaces.data.IIdentity;
|
||||
}>(
|
||||
async (dataArg) => {
|
||||
await plugins.smartguard.passGuardsOrReject(dataArg, [this.validIdentityGuard]);
|
||||
const jwt = dataArg.identity.jwt;
|
||||
const jwtData: IJwtData = await this.smartjwtInstance.verifyJWTAndGetData(jwt);
|
||||
const user = await this.CUser.getInstance({ id: jwtData.userId });
|
||||
const isAdminBool = user.data.role === 'admin';
|
||||
console.log(`user is admin: ${isAdminBool}`);
|
||||
return isAdminBool;
|
||||
},
|
||||
{
|
||||
failedHint: 'user is not admin.',
|
||||
name: 'adminIdentityGuard',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
@plugins.smartdata.managed()
|
||||
export class Authorization extends plugins.smartdata.SmartDataDbDoc<Authorization, Authorization> {
|
||||
|
||||
}
|
||||
export class Authorization extends plugins.smartdata.SmartDataDbDoc<Authorization, Authorization> {}
|
||||
|
@ -14,11 +14,13 @@ export class User extends plugins.smartdata.SmartDataDbDoc<
|
||||
user.data = {
|
||||
type: 'machine',
|
||||
username: userNameArg,
|
||||
tokens: [{
|
||||
token: 'machineUser',
|
||||
expiresAt: Date.now() + 3600 * 1000 * 24 * 365,
|
||||
assignedRoles: ['admin'],
|
||||
}],
|
||||
tokens: [
|
||||
{
|
||||
token: 'machineUser',
|
||||
expiresAt: Date.now() + 3600 * 1000 * 24 * 365,
|
||||
assignedRoles: ['admin'],
|
||||
},
|
||||
],
|
||||
role: 'api',
|
||||
};
|
||||
await user.save();
|
||||
|
@ -1,5 +1,3 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
export class Cert extends plugins.smartdata.SmartDataDbDoc<Cert, Cert> {
|
||||
|
||||
}
|
||||
export class Cert extends plugins.smartdata.SmartDataDbDoc<Cert, Cert> {}
|
||||
|
@ -11,4 +11,4 @@ export class CertManager {
|
||||
constructor(cloudly: Cloudly) {
|
||||
this.cloudlyRef = cloudly;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,11 +4,12 @@ import * as plugins from '../plugins.js';
|
||||
* cluster defines a swarmkit cluster
|
||||
*/
|
||||
@plugins.smartdata.managed()
|
||||
export class Cluster extends plugins.smartdata.SmartDataDbDoc<Cluster, plugins.servezoneInterfaces.data.ICluster> {
|
||||
export class Cluster extends plugins.smartdata.SmartDataDbDoc<
|
||||
Cluster,
|
||||
plugins.servezoneInterfaces.data.ICluster
|
||||
> {
|
||||
// STATIC
|
||||
public static async fromConfigObject(
|
||||
configObjectArg: plugins.servezoneInterfaces.data.ICluster
|
||||
) {
|
||||
public static async fromConfigObject(configObjectArg: plugins.servezoneInterfaces.data.ICluster) {
|
||||
const newCluster = new Cluster();
|
||||
Object.assign(newCluster, configObjectArg);
|
||||
return newCluster;
|
||||
|
@ -40,7 +40,7 @@ export class ClusterManager {
|
||||
return {
|
||||
clusterConfig: await cluster.createSavableObject(),
|
||||
};
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IRequest_GetAllClusters>(
|
||||
@ -49,10 +49,10 @@ export class ClusterManager {
|
||||
const clusters = await this.getAllClusters();
|
||||
return {
|
||||
clusters: await Promise.all(
|
||||
clusters.map((clusterArg) => clusterArg.createSavableObject())
|
||||
clusters.map((clusterArg) => clusterArg.createSavableObject()),
|
||||
),
|
||||
};
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
// delete cluster
|
||||
@ -63,7 +63,7 @@ export class ClusterManager {
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -18,17 +18,23 @@ export class CloudlyCoreflowManager {
|
||||
new plugins.typedrequest.TypedHandler('getIdentityByToken', async (requestData) => {
|
||||
const user = await this.cloudlyRef.authManager.CUser.getInstance({
|
||||
data: {
|
||||
tokens: [{
|
||||
token: requestData.token,
|
||||
}] // find the proper user here.
|
||||
} as any
|
||||
tokens: [
|
||||
{
|
||||
token: requestData.token,
|
||||
},
|
||||
], // find the proper user here.
|
||||
} as any,
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new plugins.typedrequest.TypedResponseError('The supplied token is not valid. No matching user found.');
|
||||
throw new plugins.typedrequest.TypedResponseError(
|
||||
'The supplied token is not valid. No matching user found.',
|
||||
);
|
||||
}
|
||||
if (user.data.type !== 'machine') {
|
||||
throw new plugins.typedrequest.TypedResponseError('The supplied token is not valid. The user is not a machine.');
|
||||
throw new plugins.typedrequest.TypedResponseError(
|
||||
'The supplied token is not valid. The user is not a machine.',
|
||||
);
|
||||
}
|
||||
let cluster: Cluster;
|
||||
if (user.data.role === 'cluster') {
|
||||
@ -42,18 +48,20 @@ export class CloudlyCoreflowManager {
|
||||
type: 'machine', // if someone authenticates by token, they are a machine, no matter what.
|
||||
userId: user.id,
|
||||
expiresAt: expiryTimestamp,
|
||||
...(cluster ? {
|
||||
clusterId: cluster.id,
|
||||
clusterName: cluster.data.name,
|
||||
} : {}),
|
||||
...(cluster
|
||||
? {
|
||||
clusterId: cluster.id,
|
||||
clusterName: cluster.data.name,
|
||||
}
|
||||
: {}),
|
||||
jwt: await this.cloudlyRef.authManager.smartjwtInstance.createJWT({
|
||||
status: 'loggedIn',
|
||||
userId: user.id,
|
||||
expiresAt: expiryTimestamp,
|
||||
})
|
||||
}),
|
||||
},
|
||||
};
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
// lets enable the getting of cluster configs
|
||||
@ -64,17 +72,14 @@ export class CloudlyCoreflowManager {
|
||||
const identity = dataArg.identity;
|
||||
console.log('trying to get clusterConfigSet');
|
||||
console.log(dataArg);
|
||||
const cluster =
|
||||
await this.cloudlyRef.clusterManager.getClusterBy_Identity(
|
||||
identity
|
||||
);
|
||||
const cluster = await this.cloudlyRef.clusterManager.getClusterBy_Identity(identity);
|
||||
console.log('got cluster config and sending it back to coreflow');
|
||||
return {
|
||||
configData: await cluster.createSavableObject(),
|
||||
deploymentDirectives: [],
|
||||
};
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// lets enable getting of certificates
|
||||
@ -84,14 +89,14 @@ export class CloudlyCoreflowManager {
|
||||
async (dataArg) => {
|
||||
console.log(`incoming API request for certificate ${dataArg.domainName}`);
|
||||
const cert = await this.cloudlyRef.letsencryptConnector.getCertificateForDomain(
|
||||
dataArg.domainName
|
||||
dataArg.domainName,
|
||||
);
|
||||
console.log(`got certificate ready for reponse ${dataArg.domainName}`);
|
||||
return {
|
||||
certificate: await cert.createSavableObject(),
|
||||
};
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,14 @@ import * as plugins from '../plugins.js';
|
||||
import type { ImageManager } from './classes.imagemanager.js';
|
||||
|
||||
@plugins.smartdata.managed()
|
||||
export class Image extends plugins.smartdata.SmartDataDbDoc<Image, plugins.servezoneInterfaces.data.IImage, ImageManager> {
|
||||
public static async create(imageDataArg: Partial<plugins.servezoneInterfaces.data.IImage['data']>) {
|
||||
export class Image extends plugins.smartdata.SmartDataDbDoc<
|
||||
Image,
|
||||
plugins.servezoneInterfaces.data.IImage,
|
||||
ImageManager
|
||||
> {
|
||||
public static async create(
|
||||
imageDataArg: Partial<plugins.servezoneInterfaces.data.IImage['data']>,
|
||||
) {
|
||||
const image = new Image();
|
||||
image.id = await this.getNewId();
|
||||
console.log(imageDataArg);
|
||||
@ -14,7 +20,7 @@ export class Image extends plugins.smartdata.SmartDataDbDoc<Image, plugins.serve
|
||||
versions: [],
|
||||
},
|
||||
});
|
||||
console.log((Image as any).saveableProperties)
|
||||
console.log((Image as any).saveableProperties);
|
||||
await image.save();
|
||||
return image;
|
||||
}
|
||||
@ -32,14 +38,10 @@ export class Image extends plugins.smartdata.SmartDataDbDoc<Image, plugins.serve
|
||||
* note: this is relative to the storage method defined by the imageManager
|
||||
*/
|
||||
public async getStoragePath(versionStringArg: string) {
|
||||
return `${this.data.name}:${versionStringArg}`.replace('/', '__')
|
||||
return `${this.data.name}:${versionStringArg}`.replace('/', '__');
|
||||
}
|
||||
|
||||
public async getWriteStream() {
|
||||
|
||||
}
|
||||
public async getWriteStream() {}
|
||||
|
||||
public async getReadStream() {
|
||||
|
||||
}
|
||||
}
|
||||
public async getReadStream() {}
|
||||
}
|
||||
|
@ -35,8 +35,8 @@ export class ImageManager {
|
||||
return {
|
||||
image: await image.createSavableObject(),
|
||||
};
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_GetImage>(
|
||||
@ -48,7 +48,7 @@ export class ImageManager {
|
||||
return {
|
||||
image: await image.createSavableObject(),
|
||||
};
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
this.typedrouter.addTypedHandler(
|
||||
@ -61,8 +61,8 @@ export class ImageManager {
|
||||
});
|
||||
await image.delete();
|
||||
return {};
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
this.typedrouter.addTypedHandler(
|
||||
@ -75,11 +75,11 @@ export class ImageManager {
|
||||
images: await Promise.all(
|
||||
images.map((image) => {
|
||||
return image.createSavableObject();
|
||||
})
|
||||
}),
|
||||
),
|
||||
};
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
this.typedrouter.addTypedHandler(
|
||||
@ -97,7 +97,7 @@ export class ImageManager {
|
||||
}
|
||||
const imageVersion = reqArg.versionString;
|
||||
console.log(
|
||||
`got request to push image version ${imageVersion} for image ${refImage.data.name}`
|
||||
`got request to push image version ${imageVersion} for image ${refImage.data.name}`,
|
||||
);
|
||||
const imagePushStream = reqArg.imageStream;
|
||||
(async () => {
|
||||
@ -111,13 +111,16 @@ export class ImageManager {
|
||||
},
|
||||
});
|
||||
imagePushStream.writeToWebstream(smartWebDuplex.writable);
|
||||
await this.dockerImageStore.storeImage(refImage.id, plugins.smartstream.SmartDuplex.fromWebReadableStream(smartWebDuplex.readable));
|
||||
await this.dockerImageStore.storeImage(
|
||||
refImage.id,
|
||||
plugins.smartstream.SmartDuplex.fromWebReadableStream(smartWebDuplex.readable),
|
||||
);
|
||||
})();
|
||||
return {
|
||||
allowed: true,
|
||||
};
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
this.typedrouter.addTypedHandler(
|
||||
@ -128,20 +131,20 @@ export class ImageManager {
|
||||
id: reqArg.imageId,
|
||||
});
|
||||
const imageVersion = image.data.versions.find(
|
||||
(version) => version.versionString === reqArg.versionString
|
||||
(version) => version.versionString === reqArg.versionString,
|
||||
);
|
||||
const readable = this.imageDir.fastGetStream(
|
||||
{
|
||||
path: await image.getStoragePath(reqArg.versionString),
|
||||
},
|
||||
'webstream'
|
||||
'webstream',
|
||||
);
|
||||
const imageVirtualStream = new plugins.typedrequest.VirtualStream();
|
||||
return {
|
||||
imageStream: imageVirtualStream,
|
||||
};
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -151,7 +154,7 @@ export class ImageManager {
|
||||
await this.cloudlyRef.config.appData.waitForAndGetKey('s3Descriptor');
|
||||
console.log(this.cloudlyRef.config.data.s3Descriptor);
|
||||
this.smartbucketInstance = new plugins.smartbucket.SmartBucket(
|
||||
this.cloudlyRef.config.data.s3Descriptor
|
||||
this.cloudlyRef.config.data.s3Descriptor,
|
||||
);
|
||||
const bucket = await this.smartbucketInstance.getBucketByName('cloudly-test');
|
||||
await bucket.fastPut({ path: 'images/00init', contents: 'init' });
|
||||
|
@ -12,4 +12,4 @@ export class LogManager {
|
||||
this.cloudlyRef = cloudlyRefArg;
|
||||
this.cloudlyRef.typedrouter.addTypedRouter(this.typedRouter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ export class SecretBundle extends plugins.smartdata.SmartDataDbDoc<
|
||||
secretGroups.push(
|
||||
await SecretGroup.getInstance({
|
||||
id: secretGroupId,
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
return secretGroups;
|
||||
|
@ -40,23 +40,23 @@ export class CloudlySecretManager {
|
||||
'adminGetConfigBundlesAndSecretGroups',
|
||||
async (dataArg, toolsArg) => {
|
||||
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], dataArg);
|
||||
dataArg.identity.jwt
|
||||
dataArg.identity.jwt;
|
||||
const secretBundles = await SecretBundle.getInstances({});
|
||||
const secretGroups = await SecretGroup.getInstances({});
|
||||
return {
|
||||
secretBundles: [
|
||||
...(await Promise.all(
|
||||
secretBundles.map((configBundle) => configBundle.createSavableObject())
|
||||
secretBundles.map((configBundle) => configBundle.createSavableObject()),
|
||||
)),
|
||||
],
|
||||
secretGroups: [
|
||||
...(await Promise.all(
|
||||
secretGroups.map((secretGroup) => secretGroup.createSavableObject())
|
||||
secretGroups.map((secretGroup) => secretGroup.createSavableObject()),
|
||||
)),
|
||||
],
|
||||
};
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_Admin_CreateConfigBundlesAndSecretGroups>(
|
||||
@ -72,8 +72,8 @@ export class CloudlySecretManager {
|
||||
return {
|
||||
ok: true,
|
||||
};
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
this.typedrouter.addTypedHandler(
|
||||
@ -96,8 +96,8 @@ export class CloudlySecretManager {
|
||||
return {
|
||||
ok: true,
|
||||
};
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// lets add typedrouter routes for accessing the configvailt from apps
|
||||
@ -116,19 +116,19 @@ export class CloudlySecretManager {
|
||||
},
|
||||
});
|
||||
const authorization = await wantedBundle.getAuthorizationFromAuthKey(
|
||||
dataArg.authorization
|
||||
dataArg.authorization,
|
||||
);
|
||||
return {
|
||||
envBundle: {
|
||||
configKeyValueObject: await wantedBundle.getKeyValueObjectForEnvironment(
|
||||
authorization.environment
|
||||
authorization.environment,
|
||||
),
|
||||
environment: authorization.environment,
|
||||
timeSensitive: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import type { CloudlyServerManager } from './classes.servermanager.js';
|
||||
export class CurlFresh {
|
||||
public optionsArg = {
|
||||
npmRegistry: 'https://registry.npmjs.org',
|
||||
}
|
||||
};
|
||||
public scripts = {
|
||||
'setup.sh': `#!/bin/bash
|
||||
|
||||
@ -50,7 +50,7 @@ bash -c "spark installdaemon"
|
||||
public handler = new plugins.typedserver.servertools.Handler('ALL', async (req, res) => {
|
||||
logger.log('info', 'curlfresh handler called. a server might be coming online soon :)');
|
||||
const scriptname = req.params.scriptname;
|
||||
switch(scriptname) {
|
||||
switch (scriptname) {
|
||||
case 'setup.sh':
|
||||
logger.log('info', 'sending setup.sh');
|
||||
res.type('application/x-sh');
|
||||
@ -66,22 +66,25 @@ bash -c "spark installdaemon"
|
||||
this.serverManagerRef = serverManagerRefArg;
|
||||
}
|
||||
public async getServerUserData(): Promise<string> {
|
||||
const sslMode = await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('sslMode');
|
||||
const sslMode =
|
||||
await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('sslMode');
|
||||
let protocol: 'http' | 'https';
|
||||
if (sslMode === 'none') {
|
||||
protocol = 'http';
|
||||
} else {
|
||||
protocol = 'https';
|
||||
}
|
||||
|
||||
const domain = await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('publicUrl');
|
||||
const port = await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('publicPort');
|
||||
|
||||
|
||||
const domain =
|
||||
await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('publicUrl');
|
||||
const port =
|
||||
await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('publicPort');
|
||||
|
||||
const serverUserData = `#cloud-config
|
||||
runcmd:
|
||||
- curl -o- ${protocol}://${domain}:${port}/curlfresh/setup.sh | sh
|
||||
`
|
||||
`;
|
||||
console.log(serverUserData);
|
||||
return serverUserData;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,13 @@ import * as plugins from '../plugins.js';
|
||||
* cluster defines a swarmkit cluster
|
||||
*/
|
||||
@plugins.smartdata.Manager()
|
||||
export class Server extends plugins.smartdata.SmartDataDbDoc<Server, plugins.servezoneInterfaces.data.IServer> {
|
||||
export class Server extends plugins.smartdata.SmartDataDbDoc<
|
||||
Server,
|
||||
plugins.servezoneInterfaces.data.IServer
|
||||
> {
|
||||
// STATIC
|
||||
public static async createFromHetznerServer(
|
||||
hetznerServerArg: plugins.hetznercloud.HetznerServer
|
||||
hetznerServerArg: plugins.hetznercloud.HetznerServer,
|
||||
) {
|
||||
const newServer = new Server();
|
||||
newServer.id = plugins.smartunique.shortId(8);
|
||||
@ -16,7 +19,7 @@ export class Server extends plugins.smartdata.SmartDataDbDoc<Server, plugins.ser
|
||||
requiredDebianPackages: [],
|
||||
sshKeys: [],
|
||||
type: 'hetzner',
|
||||
}
|
||||
};
|
||||
Object.assign(newServer, { data });
|
||||
await newServer.save();
|
||||
return newServer;
|
||||
|
@ -29,17 +29,19 @@ export class CloudlyServerManager {
|
||||
const serverId = requestData.serverId;
|
||||
const server = await this.CServer.getInstance({
|
||||
id: serverId,
|
||||
})
|
||||
});
|
||||
return {
|
||||
configData: await server.createSavableObject(),
|
||||
};
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public async start() {
|
||||
this.hetznerAccount = new plugins.hetznercloud.HetznerAccount(this.cloudlyRef.config.data.hetznerToken);
|
||||
this.hetznerAccount = new plugins.hetznercloud.HetznerAccount(
|
||||
this.cloudlyRef.config.data.hetznerToken,
|
||||
);
|
||||
}
|
||||
|
||||
public async stop() {}
|
||||
@ -66,16 +68,18 @@ export class CloudlyServerManager {
|
||||
clusterId: cluster.id,
|
||||
priority: '1',
|
||||
},
|
||||
userData: await this.curlfreshInstance.getServerUserData()
|
||||
userData: await this.curlfreshInstance.getServerUserData(),
|
||||
});
|
||||
const newServer = await Server.createFromHetznerServer(server);
|
||||
console.log(`cluster created new server for cluster ${cluster.id}`);
|
||||
} else {
|
||||
console.log(`cluster ${cluster.id} already has servers. Making sure that they actually exist in the real world...`);
|
||||
console.log(
|
||||
`cluster ${cluster.id} already has servers. Making sure that they actually exist in the real world...`,
|
||||
);
|
||||
// if there is a server, make sure that it exists
|
||||
for (const server of servers) {
|
||||
const hetznerServer = await this.hetznerAccount.getServersByLabel({
|
||||
'clusterId': cluster.id
|
||||
clusterId: cluster.id,
|
||||
});
|
||||
if (!hetznerServer) {
|
||||
console.log(`server ${server.id} does not exist in the real world. Creating it now...`);
|
||||
@ -86,7 +90,7 @@ export class CloudlyServerManager {
|
||||
labels: {
|
||||
clusterId: cluster.id,
|
||||
priority: '1',
|
||||
}
|
||||
},
|
||||
});
|
||||
const newServer = await Server.createFromHetznerServer(hetznerServer);
|
||||
}
|
||||
@ -99,7 +103,7 @@ export class CloudlyServerManager {
|
||||
const results = await this.CServer.getInstances({
|
||||
data: {
|
||||
assignedClusterId: clusterArg.id,
|
||||
}
|
||||
},
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
@ -1,13 +1,14 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import { ServiceManager } from './classes.servicemanager.js';
|
||||
|
||||
export class Service extends plugins.smartdata.SmartDataDbDoc<Service, plugins.servezoneInterfaces.data.IService, ServiceManager> {
|
||||
|
||||
export class Service extends plugins.smartdata.SmartDataDbDoc<
|
||||
Service,
|
||||
plugins.servezoneInterfaces.data.IService,
|
||||
ServiceManager
|
||||
> {
|
||||
@plugins.smartdata.svDb()
|
||||
public id: string;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
public data: plugins.servezoneInterfaces.data.IService['data'];
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { Service } from './classes.service.js';
|
||||
export class ServiceManager {
|
||||
public typedrouter = new plugins.typedrequest.TypedRouter();
|
||||
public cloudlyRef: Cloudly;
|
||||
|
||||
|
||||
get db() {
|
||||
return this.cloudlyRef.mongodbConnector.smartdataDb;
|
||||
}
|
||||
@ -15,4 +15,4 @@ export class ServiceManager {
|
||||
constructor(cloudlyRef: Cloudly) {
|
||||
this.cloudlyRef = cloudlyRef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ export class ExternalApiManager {
|
||||
return {
|
||||
networkNodes,
|
||||
};
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
import * as plugins from './plugins.js';
|
||||
|
||||
export const packageDir = plugins.path.join(plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url), '../');
|
||||
export const packageDir = plugins.path.join(
|
||||
plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url),
|
||||
'../',
|
||||
);
|
||||
export const nogitDir = plugins.path.join(packageDir, '.nogit/');
|
||||
export const dockerImageStoreDir = plugins.path.join(nogitDir, './dockerimagestore/');
|
||||
export const distServeDir = plugins.path.join(packageDir, './dist_serve');
|
||||
|
8
ts_interfaces/00_commitinfo_data.ts
Normal file
8
ts_interfaces/00_commitinfo_data.ts
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* autocreated commitinfo by @push.rocks/commitinfo
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@serve.zone/interfaces',
|
||||
version: '1.1.2',
|
||||
description: 'interfaces for working with containers'
|
||||
}
|
16
ts_interfaces/data/cloudlyconfig.ts
Normal file
16
ts_interfaces/data/cloudlyconfig.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
export interface ICloudlyConfig {
|
||||
cfToken?: string;
|
||||
hetznerToken?: string;
|
||||
environment?: 'production' | 'integration';
|
||||
letsEncryptEmail?: string;
|
||||
letsEncryptPrivateKey?: string;
|
||||
jwtKeypair?: plugins.tsclass.network.IJwtKeypair;
|
||||
mongoDescriptor?: plugins.tsclass.database.IMongoDescriptor;
|
||||
s3Descriptor?: plugins.tsclass.storage.IS3Descriptor;
|
||||
publicUrl?: string;
|
||||
publicPort?: string;
|
||||
sslMode?: 'none' | 'letsencrypt' | 'external';
|
||||
servezoneAdminaccount?: string;
|
||||
}
|
36
ts_interfaces/data/cluster.ts
Normal file
36
ts_interfaces/data/cluster.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import { type IDockerRegistryInfo } from '../data/docker.js';
|
||||
import type { IServer } from './server.js';
|
||||
|
||||
export interface ICluster {
|
||||
id: string;
|
||||
data: {
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* a cluster has a machine user that governs access rights.
|
||||
*/
|
||||
userId: string;
|
||||
|
||||
/**
|
||||
* how can the cluster reach cloudly
|
||||
*/
|
||||
cloudlyUrl?: string;
|
||||
|
||||
/**
|
||||
* what servers are expected to be part of the cluster
|
||||
*/
|
||||
servers: IServer[];
|
||||
|
||||
/**
|
||||
* ACME info. This is used to get SSL certificates.
|
||||
*/
|
||||
acmeInfo: {
|
||||
serverAddress: string;
|
||||
serverSecret: string;
|
||||
};
|
||||
|
||||
sshKeys: plugins.tsclass.network.ISshKey[];
|
||||
};
|
||||
}
|
1
ts_interfaces/data/config.ts
Normal file
1
ts_interfaces/data/config.ts
Normal file
@ -0,0 +1 @@
|
||||
export type TConfigType = 'server' | 'cluster' | 'coreflow' | 'service';
|
14
ts_interfaces/data/deployment.ts
Normal file
14
ts_interfaces/data/deployment.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
/**
|
||||
* results from a DeploymentDirective
|
||||
* tracks the status of a deployment
|
||||
*/
|
||||
export interface IDeployment {
|
||||
id: string;
|
||||
deploymentDirectiveId: string;
|
||||
affectedServiceIds: string[];
|
||||
usedImageId: string;
|
||||
deploymentLog: string[];
|
||||
status: 'scheduled' | 'running' | 'deployed' | 'failed';
|
||||
}
|
14
ts_interfaces/data/deploymentdirective.ts
Normal file
14
ts_interfaces/data/deploymentdirective.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import type { IServiceRessources } from "./docker.js";
|
||||
|
||||
/**
|
||||
* used for tellilng a cluster about a disired deployment
|
||||
* and specifies its configuration
|
||||
*/
|
||||
export interface IDeploymentDirective {
|
||||
id: string;
|
||||
name: string;
|
||||
imageClaim: string;
|
||||
ports: { hostPort: number; containerPort: number }[];
|
||||
environment: { [key: string]: string };
|
||||
resources?: IServiceRessources;
|
||||
}
|
15
ts_interfaces/data/docker.ts
Normal file
15
ts_interfaces/data/docker.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
export interface IDockerRegistryInfo {
|
||||
serveraddress: string;
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export interface IServiceRessources {
|
||||
cpuLimit?: number;
|
||||
cpuReservation?: number;
|
||||
memorySizeLimitMB?: number;
|
||||
memorySizeReservationMB?: number;
|
||||
volumeMounts?: plugins.tsclass.container.IVolumeMount[];
|
||||
}
|
6
ts_interfaces/data/env.ts
Normal file
6
ts_interfaces/data/env.ts
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
export interface IEnvBundle {
|
||||
environment: string;
|
||||
timeSensitive: boolean;
|
||||
configKeyValueObject: {[key: string]: string};
|
||||
}
|
11
ts_interfaces/data/event.ts
Normal file
11
ts_interfaces/data/event.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
export interface IEvent_Cloudly_ContainerVersionNotification
|
||||
extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedEvent<plugins.tsclass.container.IContainer>,
|
||||
IEvent_Cloudly_ContainerVersionNotification
|
||||
> {
|
||||
name: 'newContainerVersion';
|
||||
uniqueEventId: string;
|
||||
payload: plugins.tsclass.container.IContainer;
|
||||
}
|
15
ts_interfaces/data/image.ts
Normal file
15
ts_interfaces/data/image.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
export interface IImage {
|
||||
id: string;
|
||||
data: {
|
||||
name: string;
|
||||
description: string;
|
||||
versions: Array<{
|
||||
versionString: string;
|
||||
storagePath?: string;
|
||||
size: number;
|
||||
createdAt: number;
|
||||
}>;
|
||||
};
|
||||
}
|
17
ts_interfaces/data/index.ts
Normal file
17
ts_interfaces/data/index.ts
Normal file
@ -0,0 +1,17 @@
|
||||
export * from './cloudlyconfig.js';
|
||||
export * from './cluster.js';
|
||||
export * from './config.js';
|
||||
export * from './deployment.js';
|
||||
export * from './deploymentdirective.js';
|
||||
export * from './docker.js';
|
||||
export * from './env.js';
|
||||
export * from './event.js';
|
||||
export * from './image.js';
|
||||
export * from './secretbundle.js';
|
||||
export * from './secretgroup.js'
|
||||
export * from './server.js';
|
||||
export * from './service.js';
|
||||
export * from './status.js';
|
||||
export * from './traffic.js';
|
||||
export * from './user.js';
|
||||
export * from './version.js';
|
42
ts_interfaces/data/secretbundle.ts
Normal file
42
ts_interfaces/data/secretbundle.ts
Normal file
@ -0,0 +1,42 @@
|
||||
export interface ISecretBundle {
|
||||
id: string;
|
||||
data: {
|
||||
name: string;
|
||||
description: string;
|
||||
|
||||
/**
|
||||
* determines if the secret is a service or an external secret
|
||||
* if external secret additional checks are put in place to protect the secret
|
||||
*/
|
||||
type: 'service' | 'npmci' | 'gitzone' | 'external';
|
||||
|
||||
/**
|
||||
* You can add specific secret groups using this
|
||||
*/
|
||||
includedSecretGroupIds: string[];
|
||||
|
||||
/**
|
||||
* You can add specific tags using this
|
||||
*/
|
||||
includedTags: {
|
||||
key: string;
|
||||
value?: string;
|
||||
}[];
|
||||
|
||||
/**
|
||||
* add images
|
||||
*/
|
||||
includedImages: {
|
||||
imageId: string;
|
||||
permissions: ('read' | 'write')[];
|
||||
}[];
|
||||
|
||||
/**
|
||||
* authrozations select a specific environment of a config bundle
|
||||
*/
|
||||
authorizations: Array<{
|
||||
secretAccessKey: string;
|
||||
environment: string;
|
||||
}>;
|
||||
};
|
||||
}
|
54
ts_interfaces/data/secretgroup.ts
Normal file
54
ts_interfaces/data/secretgroup.ts
Normal file
@ -0,0 +1,54 @@
|
||||
export interface ISecretGroup {
|
||||
/**
|
||||
* the insatnce id. This should be a random id, except for default
|
||||
*/
|
||||
id: string;
|
||||
|
||||
data: {
|
||||
name: string;
|
||||
description: string;
|
||||
|
||||
/**
|
||||
* the key of the secretgroup like CI_RUNNER_TOKEN
|
||||
*/
|
||||
key: string;
|
||||
|
||||
/**
|
||||
* the priority of the secretgroup
|
||||
* will be used to determine which secretgroup will be used
|
||||
* when there are multiple secretgroups with the same key
|
||||
*/
|
||||
priority?: number;
|
||||
|
||||
/**
|
||||
* any tags that can be used to filter the secretgroup
|
||||
* can be used for putting secrets into projects
|
||||
*/
|
||||
tags: {
|
||||
key: string;
|
||||
value: string;
|
||||
}[];
|
||||
/**
|
||||
* the values for this secretGroup
|
||||
*/
|
||||
environments: {
|
||||
[key: string]: {
|
||||
value: string;
|
||||
|
||||
/**
|
||||
* can be used to update the value
|
||||
*/
|
||||
updateToken?: string;
|
||||
|
||||
/**
|
||||
* the linux timestamp of the last update
|
||||
*/
|
||||
lastUpdated: number;
|
||||
history: {
|
||||
timestamp: string;
|
||||
value: string;
|
||||
}[];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
36
ts_interfaces/data/server.ts
Normal file
36
ts_interfaces/data/server.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import { type IDockerRegistryInfo } from './docker.js';
|
||||
|
||||
export interface IServerMetrics {
|
||||
serverId: string;
|
||||
cpuUsageInPercent: number;
|
||||
memoryUsageinMB: number;
|
||||
memoryAvailableInMB: number;
|
||||
containerCount: number;
|
||||
containerMetrics: Array<{
|
||||
containerId: string;
|
||||
containerName: string;
|
||||
cpuUsageInPercent: number;
|
||||
memoryUsageInMB: number;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface IServer {
|
||||
id: string;
|
||||
data: {
|
||||
type: 'baremetal' | 'hetzner';
|
||||
|
||||
assignedClusterId: string;
|
||||
|
||||
/**
|
||||
* a list of debian packages to be installed
|
||||
*/
|
||||
requiredDebianPackages: string[];
|
||||
|
||||
/**
|
||||
* a list of SSH keys to deploy
|
||||
*/
|
||||
sshKeys: plugins.tsclass.network.ISshKey[];
|
||||
};
|
||||
}
|
26
ts_interfaces/data/service.ts
Normal file
26
ts_interfaces/data/service.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import type { IServiceRessources } from './docker.js';
|
||||
|
||||
export interface IService {
|
||||
id: string;
|
||||
data: {
|
||||
name: string;
|
||||
imageId: string;
|
||||
imageVersion: string;
|
||||
environment: { [key: string]: string };
|
||||
secretBundleId: string;
|
||||
scaleFactor: number;
|
||||
balancingStrategy: 'round-robin' | 'least-connections';
|
||||
ports: {
|
||||
web: number;
|
||||
custom?: { [domain: string]: string };
|
||||
};
|
||||
resources?: IServiceRessources;
|
||||
domains: {
|
||||
name: string;
|
||||
port?: number;
|
||||
protocol?: 'http' | 'https' | 'ssh';
|
||||
}[];
|
||||
deploymentIds: string[];
|
||||
deploymentDirectiveIds: string[];
|
||||
};
|
||||
}
|
20
ts_interfaces/data/status.ts
Normal file
20
ts_interfaces/data/status.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
export interface IClusterStatus {
|
||||
name: string;
|
||||
ip: string;
|
||||
nodesCount: number;
|
||||
containersUnderManagementCount: number;
|
||||
nodeStatusId: string;
|
||||
containerStatusArray: IContainerStatus[];
|
||||
}
|
||||
|
||||
export interface INodeStatus {
|
||||
nodeId: string;
|
||||
}
|
||||
|
||||
export interface IContainerStatus {
|
||||
serviceName: string;
|
||||
dockerImageUrl: string;
|
||||
dockerImageVersion: string;
|
||||
}
|
5
ts_interfaces/data/traffic.ts
Normal file
5
ts_interfaces/data/traffic.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
interface IReverseProxyConfig extends plugins.tsclass.network.IReverseProxyConfig {}
|
||||
|
||||
export { type IReverseProxyConfig };
|
30
ts_interfaces/data/user.ts
Normal file
30
ts_interfaces/data/user.ts
Normal file
@ -0,0 +1,30 @@
|
||||
export interface IToken {
|
||||
token: string;
|
||||
expiresAt: number;
|
||||
assignedRoles: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* an identity is assumed by authentication as a user
|
||||
* an identity is ephemeral and has to be renewed regularly
|
||||
*/
|
||||
export interface IIdentity {
|
||||
name: string;
|
||||
userId: string;
|
||||
type: 'machine' | 'human';
|
||||
role: 'admin' | 'user' | 'api' | 'cluster';
|
||||
expiresAt: number;
|
||||
/** the jwt token should contain above data for verification */
|
||||
jwt: string;
|
||||
}
|
||||
|
||||
export interface IUser {
|
||||
id: string;
|
||||
data: {
|
||||
type: 'machine' | 'human';
|
||||
role: 'admin' | 'user' | 'api' | 'cluster';
|
||||
username?: string;
|
||||
password?: string;
|
||||
tokens?: IToken[];
|
||||
}
|
||||
}
|
11
ts_interfaces/data/version.ts
Normal file
11
ts_interfaces/data/version.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export interface IContainerVersionData {
|
||||
/**
|
||||
* the docker image url
|
||||
* example: registry.gitlab.com/hosttoday/ht-docker-node:latest
|
||||
*/
|
||||
dockerImageUrl: string;
|
||||
/**
|
||||
* the docker image version. Note: This is different from docker tags that are often used for versions.
|
||||
*/
|
||||
dockerImageVersion: string;
|
||||
}
|
9
ts_interfaces/index.ts
Normal file
9
ts_interfaces/index.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import * as data from './data/index.js';
|
||||
import * as platformservice from './platformservice/index.js';
|
||||
import * as requests from './requests/index.js';
|
||||
|
||||
export {
|
||||
data,
|
||||
platformservice,
|
||||
requests
|
||||
}
|
1
ts_interfaces/platformservice/00readme.md
Normal file
1
ts_interfaces/platformservice/00readme.md
Normal file
@ -0,0 +1 @@
|
||||
The platform folder contains types that can be used for talking with the underlying platform by apps running on serve.zone.
|
23
ts_interfaces/platformservice/aibridge.ts
Normal file
23
ts_interfaces/platformservice/aibridge.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
export interface IChat {
|
||||
systemMessage: string;
|
||||
messages: {
|
||||
role: 'assistant' | 'user';
|
||||
content: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface IReq_Chat extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IReq_Chat
|
||||
> {
|
||||
method: 'chat',
|
||||
request: {
|
||||
chat: IChat;
|
||||
};
|
||||
response: {
|
||||
chat: IChat;
|
||||
latestMessage: string;
|
||||
}
|
||||
}
|
13
ts_interfaces/platformservice/index.ts
Normal file
13
ts_interfaces/platformservice/index.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import * as aibridge from './aibridge.js';
|
||||
import * as letter from './letter.js';
|
||||
import * as mta from './mta.js';
|
||||
import * as pushnotification from './pushnotification.js';
|
||||
import * as sms from './sms.js';
|
||||
|
||||
export {
|
||||
aibridge,
|
||||
letter,
|
||||
mta,
|
||||
pushnotification,
|
||||
sms,
|
||||
}
|
34
ts_interfaces/platformservice/letter.ts
Normal file
34
ts_interfaces/platformservice/letter.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
export interface IRequest_SendLetter extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_SendLetter
|
||||
> {
|
||||
method: 'sendLetter';
|
||||
request: {
|
||||
/**
|
||||
* will be used in logs
|
||||
*/
|
||||
description: string;
|
||||
/**
|
||||
* if you send any PDF / invoice that you have not made sure to be letterxpress compliant
|
||||
* we strongly recommend using a cover page
|
||||
*/
|
||||
needsCover: boolean;
|
||||
title?: string;
|
||||
from?: plugins.tsclass.business.IAddress;
|
||||
to?: plugins.tsclass.business.IAddress;
|
||||
coverBody?: string;
|
||||
service: ('Einschreiben')[];
|
||||
pdfAttachments?: Array<{
|
||||
name: string;
|
||||
binaryAttachmentString: string;
|
||||
}>
|
||||
};
|
||||
response: {
|
||||
/**
|
||||
* this process id allows status retrieval of the letter
|
||||
*/
|
||||
processId: string;
|
||||
};
|
||||
}
|
39
ts_interfaces/platformservice/mta.ts
Normal file
39
ts_interfaces/platformservice/mta.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
export type TTemplates = 'default' | 'linkaction' | 'notification';
|
||||
|
||||
export interface IRequest_SendEmail extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_SendEmail
|
||||
> {
|
||||
method: 'sendEmail';
|
||||
request: {
|
||||
title: string;
|
||||
from: string;
|
||||
to: string;
|
||||
body: string;
|
||||
attachments?: Array<{
|
||||
name: string;
|
||||
binaryAttachmentString: string;
|
||||
}>
|
||||
};
|
||||
response: {
|
||||
/**
|
||||
* the response id allows for handling of responses to that email
|
||||
*/
|
||||
responseId: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IRequestRegisterRecipient extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequestRegisterRecipient
|
||||
> {
|
||||
method: 'registerRecepient';
|
||||
request: {
|
||||
emailAddress: string;
|
||||
};
|
||||
response: {
|
||||
status: 'ok' | 'not ok';
|
||||
};
|
||||
}
|
16
ts_interfaces/platformservice/pushnotification.ts
Normal file
16
ts_interfaces/platformservice/pushnotification.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
export interface IRequest_SendPushNotification extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_SendPushNotification
|
||||
> {
|
||||
method: 'sendPushNotification';
|
||||
request: {
|
||||
deviceToken: string;
|
||||
message: string;
|
||||
}
|
||||
response: {
|
||||
ok: boolean;
|
||||
status: string;
|
||||
}
|
||||
}
|
33
ts_interfaces/platformservice/sms.ts
Normal file
33
ts_interfaces/platformservice/sms.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
export interface IRequest_SendSms
|
||||
extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_SendSms
|
||||
> {
|
||||
method: 'sendSms';
|
||||
request: {
|
||||
toNumber: number;
|
||||
fromName: string;
|
||||
messageText: string;
|
||||
};
|
||||
response: {
|
||||
status: 'ok' | 'not ok';
|
||||
}
|
||||
}
|
||||
|
||||
export interface IRequest_SendVerificationCode
|
||||
extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_SendVerificationCode
|
||||
> {
|
||||
method: 'sendVerificationCode';
|
||||
request: {
|
||||
toNumber: number;
|
||||
fromName: string;
|
||||
};
|
||||
response: {
|
||||
status: 'ok' | 'not ok';
|
||||
verificationCode: string;
|
||||
}
|
||||
}
|
20
ts_interfaces/plugins.ts
Normal file
20
ts_interfaces/plugins.ts
Normal file
@ -0,0 +1,20 @@
|
||||
// @apiglobal scope
|
||||
import * as typedrequestInterfaces from '@api.global/typedrequest-interfaces';
|
||||
|
||||
export {
|
||||
typedrequestInterfaces
|
||||
}
|
||||
|
||||
// @push.rocks scope
|
||||
import * as smartlogInterfaces from '@push.rocks/smartlog-interfaces';
|
||||
|
||||
export {
|
||||
smartlogInterfaces,
|
||||
}
|
||||
|
||||
// tsclass scope
|
||||
import * as tsclass from '@tsclass/tsclass';
|
||||
|
||||
export {
|
||||
tsclass
|
||||
}
|
18
ts_interfaces/requests/certificate.ts
Normal file
18
ts_interfaces/requests/certificate.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import * as userInterfaces from '../data/user.js';
|
||||
|
||||
export interface IRequest_Any_Cloudly_GetCertificateForDomain
|
||||
extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_Any_Cloudly_GetCertificateForDomain
|
||||
> {
|
||||
method: 'getCertificateForDomain';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
domainName: string;
|
||||
type: 'ssl';
|
||||
};
|
||||
response: {
|
||||
certificate: plugins.tsclass.network.ICert;
|
||||
};
|
||||
}
|
67
ts_interfaces/requests/cluster.ts
Normal file
67
ts_interfaces/requests/cluster.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import * as userInterfaces from '../data/user.js';
|
||||
import * as clusterInterfaces from '../data/cluster.js';
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
/**
|
||||
* get all clusters
|
||||
*/
|
||||
export interface IRequest_GetAllClusters extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_GetAllClusters
|
||||
> {
|
||||
method: 'getAllClusters';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
};
|
||||
response: {
|
||||
clusters: clusterInterfaces.ICluster[];
|
||||
};
|
||||
}
|
||||
|
||||
export interface IRequest_CreateCluster extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_CreateCluster
|
||||
> {
|
||||
method: 'createCluster';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
clusterName: string;
|
||||
};
|
||||
response: {
|
||||
clusterConfig: clusterInterfaces.ICluster;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* updates a cluster
|
||||
*/
|
||||
export interface IRequest_UpdateCluster extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_UpdateCluster
|
||||
> {
|
||||
method: 'updateCluster';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
clusterConfig: clusterInterfaces.ICluster;
|
||||
};
|
||||
response: {
|
||||
clusterConfig: clusterInterfaces.ICluster;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes a cluster
|
||||
*/
|
||||
export interface IRequest_DeleteCluster extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_DeleteCluster
|
||||
> {
|
||||
method: 'deleteCluster';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
clusterId: string;
|
||||
};
|
||||
response: {
|
||||
success: boolean;
|
||||
};
|
||||
}
|
49
ts_interfaces/requests/config.ts
Normal file
49
ts_interfaces/requests/config.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import * as clusterInterfaces from '../data/cluster.js';
|
||||
import * as serverInterfaces from '../data/server.js';
|
||||
import * as userInterfaces from '../data/user.js';
|
||||
import type { IService } from '../data/service.js';
|
||||
import type { IDeploymentDirective } from '../data/deploymentdirective.js';
|
||||
|
||||
export interface IRequest_Any_Cloudly_GetServerConfig
|
||||
extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_Any_Cloudly_GetServerConfig
|
||||
> {
|
||||
method: 'getServerConfig';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
serverId: string;
|
||||
};
|
||||
response: {
|
||||
configData: serverInterfaces.IServer;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IRequest_Any_Cloudly_GetClusterConfig
|
||||
extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_Any_Cloudly_GetClusterConfig
|
||||
> {
|
||||
method: 'getClusterConfig';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
};
|
||||
response: {
|
||||
configData: clusterInterfaces.ICluster;
|
||||
deploymentDirectives: IDeploymentDirective[];
|
||||
};
|
||||
}
|
||||
|
||||
export interface IRequest_Cloudly_Coreflow_PushClusterConfig
|
||||
extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_Cloudly_Coreflow_PushClusterConfig
|
||||
> {
|
||||
method: 'pushClusterConfig';
|
||||
request: {
|
||||
configData: clusterInterfaces.ICluster;
|
||||
deploymentDirectives: IDeploymentDirective[];
|
||||
};
|
||||
response: {};
|
||||
}
|
23
ts_interfaces/requests/identity.ts
Normal file
23
ts_interfaces/requests/identity.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import * as userInterfaces from '../data/user.js'
|
||||
|
||||
// ========
|
||||
// IDENTITY
|
||||
// ========
|
||||
|
||||
/**
|
||||
* get the identity that then will be used to get the config
|
||||
*/
|
||||
export interface IRequest_Any_Cloudly_CoreflowManager_GetIdentityByToken
|
||||
extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_Any_Cloudly_CoreflowManager_GetIdentityByToken
|
||||
> {
|
||||
method: 'getIdentityByToken';
|
||||
request: {
|
||||
token: string;
|
||||
};
|
||||
response: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
};
|
||||
}
|
94
ts_interfaces/requests/image.ts
Normal file
94
ts_interfaces/requests/image.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import * as userInterfaces from '../data/user.js';
|
||||
|
||||
import type { IImage } from '../data/index.js';
|
||||
|
||||
export interface IRequest_GetAllImages extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_GetAllImages
|
||||
> {
|
||||
method: 'getAllImages';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
};
|
||||
response: {
|
||||
images: IImage[];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a single image
|
||||
*/
|
||||
export interface IRequest_GetImage extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_GetImage
|
||||
> {
|
||||
method: 'getImage';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
imageId: string;
|
||||
};
|
||||
response: {
|
||||
image: IImage;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IRequest_CreateImage extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_CreateImage
|
||||
> {
|
||||
method: 'createImage';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
name: string;
|
||||
description: string;
|
||||
};
|
||||
response: {
|
||||
image: IImage;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
export interface IRequest_PushImageVersion extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_PushImageVersion
|
||||
> {
|
||||
method: 'pushImageVersion';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
imageId: string;
|
||||
versionString: string;
|
||||
imageStream: plugins.typedrequestInterfaces.IVirtualStream;
|
||||
};
|
||||
response: {
|
||||
allowed: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IRequest_PullImageVersion extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_PullImageVersion
|
||||
> {
|
||||
method: 'pullImageVersion';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
imageId: string;
|
||||
versionString: string;
|
||||
};
|
||||
response: {
|
||||
imageStream: plugins.typedrequestInterfaces.IVirtualStream;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IRequest_DeleteImage extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_DeleteImage
|
||||
> {
|
||||
method: 'deleteImage';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
imageId: string;
|
||||
};
|
||||
response: {
|
||||
};
|
||||
}
|
33
ts_interfaces/requests/index.ts
Normal file
33
ts_interfaces/requests/index.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import * as certificateRequests from './certificate.js';
|
||||
import * as clusterRequests from './cluster.js';
|
||||
import * as configRequests from './config.js';
|
||||
import * as identityRequests from './identity.js';
|
||||
import * as imageRequests from './image.js';
|
||||
import * as informRequests from './inform.js';
|
||||
import * as logRequests from './log.js';
|
||||
import * as networkRequests from './network.js';
|
||||
import * as routingRequests from './routing.js';
|
||||
import * as secretRequests from './secret.js';
|
||||
import * as serverRequests from './server.js';
|
||||
import * as statusRequests from './status.js';
|
||||
import * as versionRequests from './version.js';
|
||||
|
||||
export {
|
||||
certificateRequests as certificate,
|
||||
clusterRequests as cluster,
|
||||
configRequests as config,
|
||||
identityRequests as identity,
|
||||
imageRequests as image,
|
||||
informRequests as inform,
|
||||
logRequests as log,
|
||||
networkRequests as network,
|
||||
routingRequests as routing,
|
||||
secretRequests as secret,
|
||||
serverRequests as server,
|
||||
statusRequests as status,
|
||||
versionRequests as version,
|
||||
};
|
||||
|
||||
export * from './inform.js';
|
12
ts_interfaces/requests/inform.ts
Normal file
12
ts_interfaces/requests/inform.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
export interface IRequest_InformAboutNewContainerImage extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_InformAboutNewContainerImage
|
||||
> {
|
||||
method: 'servezonestandard_InformAboutNewContainerVersion';
|
||||
request: {
|
||||
containerImageInfo: plugins.tsclass.container.IContainer
|
||||
};
|
||||
response: {};
|
||||
}
|
13
ts_interfaces/requests/log.ts
Normal file
13
ts_interfaces/requests/log.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
export interface IRequest_Log extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_Log
|
||||
> {
|
||||
method: 'log';
|
||||
request: {
|
||||
authToken: string;
|
||||
logPackages: plugins.smartlogInterfaces.ILogPackage[];
|
||||
},
|
||||
response: {};
|
||||
}
|
9
ts_interfaces/requests/network.ts
Normal file
9
ts_interfaces/requests/network.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
export interface IRequest_Any_Cloudly_GetNetworkNodes {
|
||||
method: 'getNetworkNodes';
|
||||
request: {};
|
||||
response: {
|
||||
networkNodes: plugins.tsclass.network.INetworkNode[];
|
||||
};
|
||||
}
|
12
ts_interfaces/requests/routing.ts
Normal file
12
ts_interfaces/requests/routing.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { type IReverseProxyConfig } from '../data/traffic.js';
|
||||
|
||||
export interface IRequest_Coreflow_Coretraffic_RoutingUpdate {
|
||||
method: 'updateRouting';
|
||||
request: {
|
||||
reverseConfigs: IReverseProxyConfig[];
|
||||
};
|
||||
response: {
|
||||
status: 'ok' | 'error';
|
||||
errorText: string;
|
||||
};
|
||||
}
|
94
ts_interfaces/requests/secret.ts
Normal file
94
ts_interfaces/requests/secret.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import * as data from '../data/index.js';
|
||||
import * as userInterfaces from '../data/user.js';
|
||||
|
||||
export interface IReq_GetEnvBundle extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IReq_GetEnvBundle
|
||||
> {
|
||||
method: 'getEnvBundle';
|
||||
request: {
|
||||
authorization: string;
|
||||
/**
|
||||
* specify this if you want to get a warning, if the envBundle is for an unexpected environment
|
||||
*/
|
||||
environment?: string;
|
||||
};
|
||||
response: {
|
||||
envBundle: data.IEnvBundle;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IReq_Admin_LoginWithUsernameAndPassword extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IReq_Admin_LoginWithUsernameAndPassword
|
||||
> {
|
||||
method: 'adminLoginWithUsernameAndPassword';
|
||||
request: {
|
||||
username: string;
|
||||
password: string;
|
||||
};
|
||||
response: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IReq_Admin_GetConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IReq_Admin_GetConfigBundlesAndSecretGroups
|
||||
> {
|
||||
method: 'adminGetConfigBundlesAndSecretGroups';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
};
|
||||
response: {
|
||||
secretBundles: data.ISecretBundle[];
|
||||
secretGroups: data.ISecretGroup[];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
export interface IReq_Admin_CreateConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IReq_Admin_CreateConfigBundlesAndSecretGroups
|
||||
> {
|
||||
method: 'adminCreateConfigBundlesAndSecretGroups';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
secretBundles: data.ISecretBundle[];
|
||||
secretGroups: data.ISecretGroup[];
|
||||
};
|
||||
response: {
|
||||
ok: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IReq_Admin_UpdateConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IReq_Admin_UpdateConfigBundlesAndSecretGroups
|
||||
> {
|
||||
method: 'adminUpdateConfigBundlesAndSecretGroups';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
configBundles: data.ISecretBundle[];
|
||||
secretGroups: data.ISecretGroup[];
|
||||
};
|
||||
response: {
|
||||
ok: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IReq_Admin_DeleteConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IReq_Admin_DeleteConfigBundlesAndSecretGroups
|
||||
> {
|
||||
method: 'adminDeleteConfigBundlesAndSecretGroups';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
secretBundleIds: string[];
|
||||
secretGroupIds: string[];
|
||||
};
|
||||
response: {
|
||||
ok: boolean;
|
||||
};
|
||||
}
|
47
ts_interfaces/requests/server.ts
Normal file
47
ts_interfaces/requests/server.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import type { IServerMetrics } from '../data/server.js';
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
/**
|
||||
* This request can be used between any two players
|
||||
* Examples:
|
||||
* WebApp -> Cloudly (get metrics)
|
||||
* Cloudly -> Webapp (send metrics)
|
||||
* Cloudly -> Coreflow (get metrics)
|
||||
* Coreflow -> Cloudly (send metrics)
|
||||
*/
|
||||
export interface IRequest_Any_Cloudly_ServerStatus
|
||||
extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_Any_Cloudly_ServerStatus
|
||||
> {
|
||||
method: 'getOrSendServerMetrics',
|
||||
request: {
|
||||
getOrSend: 'get' | 'send';
|
||||
serverMetrics?: IServerMetrics;
|
||||
},
|
||||
response: {
|
||||
serverMetrics?: IServerMetrics;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* this request can be used between any two players
|
||||
* Examples:
|
||||
* WebApp -> Cloudly
|
||||
* Cloudly -> Coreflow
|
||||
* Cloudly -> HostingProvider
|
||||
*/
|
||||
export interface IRequest_TriggerServerAction
|
||||
extends plugins.typedrequestInterfaces.implementsTR<
|
||||
plugins.typedrequestInterfaces.ITypedRequest,
|
||||
IRequest_TriggerServerAction
|
||||
> {
|
||||
method: 'triggerServerAction';
|
||||
request: {
|
||||
actionName: 'reboot' | 'rebuild';
|
||||
payload: any;
|
||||
};
|
||||
response: {
|
||||
actionConfirmed: boolean;
|
||||
};
|
||||
}
|
12
ts_interfaces/requests/status.ts
Normal file
12
ts_interfaces/requests/status.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import * as userInterfaces from '../data/user.js';
|
||||
|
||||
/**
|
||||
* a status update dashboard
|
||||
*/
|
||||
export interface IRequest_Coreflow_Cloudly_CoreflowManagerStatusupdate {
|
||||
method: 'cloudlyStatus';
|
||||
request: {
|
||||
identity: userInterfaces.IIdentity;
|
||||
};
|
||||
response: {};
|
||||
}
|
8
ts_interfaces/requests/version.ts
Normal file
8
ts_interfaces/requests/version.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import * as versionInterfaces from '../data/version.js';
|
||||
|
||||
// Containers
|
||||
export interface IRequest_Any_Cloudly_VersionManager_InformCloudlyAboutNewContainerVersion {
|
||||
method: 'informCloudlyAboutNewContainerVersion';
|
||||
request: versionInterfaces.IContainerVersionData;
|
||||
response: {};
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
{
|
||||
"name": "@serve.zone/interfaces",
|
||||
"dependencies": [
|
||||
"@api.global/typedrequest-interfaces",
|
||||
"@push.rocks/smartlog-interfaces",
|
||||
"@tsclass/tsclass"
|
||||
],
|
||||
"registries": [
|
||||
|
@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@serve.zone/cloudly',
|
||||
version: '1.2.3',
|
||||
version: '1.2.4',
|
||||
description: 'A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and provide robust configuration and API integration.'
|
||||
}
|
||||
|
@ -6,9 +6,21 @@
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"esModuleInterop": true,
|
||||
"verbatimModuleSyntax": true
|
||||
"verbatimModuleSyntax": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@serve.zone/api": [
|
||||
"./ts_apiclient/index.ts"
|
||||
],
|
||||
"@serve.zone/cli": [
|
||||
"./ts_cliclient/index.ts"
|
||||
],
|
||||
"@serve.zone/interfaces": [
|
||||
"./ts_interfaces/index.ts"
|
||||
]
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
"dist_*/**/*.d.ts"
|
||||
]
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user