mirror of
https://github.com/fluxscape/fluxscape.git
synced 2026-01-11 14:52:54 +01:00
Compare commits
3 Commits
feature/sa
...
feature/st
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41711c3934 | ||
|
|
5d8b2d5bba | ||
|
|
851dbc98d3 |
@@ -48,7 +48,7 @@ export async function execute(command: Command, event: MessageEvent) {
|
||||
|
||||
// Deploy to temp folder
|
||||
await compilation.deployToFolder(tempDir, {
|
||||
environment: command.cloudService ? new Environment(command.cloudService) : undefined
|
||||
environment: command.cloudService ? new Environment("", command.cloudService) : undefined
|
||||
});
|
||||
|
||||
// Upload to S3
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Environment, ExternalCloudService } from '@noodl-models/CloudServices/ExternalCloudService';
|
||||
import {
|
||||
CloudServiceEvent,
|
||||
CloudServiceEvents,
|
||||
CreateEnvironment,
|
||||
CreateEnvironmentRequest,
|
||||
Environment,
|
||||
ICloudBackendService,
|
||||
ICloudService,
|
||||
UpdateEnvironmentRequest
|
||||
@@ -12,6 +12,9 @@ import { ProjectModel } from '@noodl-models/projectmodel';
|
||||
import { getCloudServices } from '@noodl-models/projectmodel.editor';
|
||||
import { Model } from '@noodl-utils/model';
|
||||
|
||||
import { GlobalCloudService } from './providers/GlobalCloudService';
|
||||
import { ProjectCloudService } from './providers/ProjectCloudService';
|
||||
|
||||
export type CloudQueueItem = {
|
||||
frontendId: string;
|
||||
environmentId: string;
|
||||
@@ -20,7 +23,9 @@ export type CloudQueueItem = {
|
||||
class CloudBackendService implements ICloudBackendService {
|
||||
private _isLoading = false;
|
||||
private _collection?: Environment[];
|
||||
private _localExternal = new ExternalCloudService();
|
||||
|
||||
private _globalProvider = new GlobalCloudService();
|
||||
private _projectProvider = new ProjectCloudService();
|
||||
|
||||
get isLoading(): boolean {
|
||||
return this._isLoading;
|
||||
@@ -32,12 +37,14 @@ class CloudBackendService implements ICloudBackendService {
|
||||
|
||||
constructor(private readonly service: CloudService) {}
|
||||
|
||||
async fetch(): Promise<Environment[]> {
|
||||
async fetch(project: ProjectModel): Promise<Environment[]> {
|
||||
this._isLoading = true;
|
||||
try {
|
||||
// Fetch environments from local machine
|
||||
const localEnvironments = await this._localExternal.list();
|
||||
this._collection = localEnvironments.map((x) => new Environment(x));
|
||||
const projectResults = await this._projectProvider.list(project);
|
||||
this._collection = projectResults.map((x) => new Environment("project", x));
|
||||
|
||||
const globalResults = await this._globalProvider.list(project);
|
||||
this._collection = this._collection.concat(globalResults.map((x) => new Environment("global", x)));
|
||||
} finally {
|
||||
this._isLoading = false;
|
||||
this.service.notifyListeners(CloudServiceEvent.BackendUpdated);
|
||||
@@ -48,7 +55,7 @@ class CloudBackendService implements ICloudBackendService {
|
||||
async fromProject(project: ProjectModel): Promise<Environment> {
|
||||
const activeCloudServices = getCloudServices(project);
|
||||
if (!this._collection) {
|
||||
await this.fetch();
|
||||
await this.fetch(project);
|
||||
}
|
||||
|
||||
return this.items.find((b) => {
|
||||
@@ -56,16 +63,16 @@ class CloudBackendService implements ICloudBackendService {
|
||||
});
|
||||
}
|
||||
|
||||
async create(options: CreateEnvironmentRequest): Promise<CreateEnvironment> {
|
||||
return await this._localExternal.create(options);
|
||||
async create(project: ProjectModel, options: CreateEnvironmentRequest): Promise<CreateEnvironment> {
|
||||
return await this._projectProvider.create(project, options);
|
||||
}
|
||||
|
||||
async update(options: UpdateEnvironmentRequest): Promise<boolean> {
|
||||
return await this._localExternal.update(options);
|
||||
async update(project: ProjectModel, options: UpdateEnvironmentRequest): Promise<boolean> {
|
||||
return await this._projectProvider.update(project, options);
|
||||
}
|
||||
|
||||
async delete(id: string): Promise<boolean> {
|
||||
return await this._localExternal.delete(id);
|
||||
async delete(project: ProjectModel, id: string): Promise<boolean> {
|
||||
return await this._projectProvider.delete(project, id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,15 +102,11 @@ export class CloudService extends Model<CloudServiceEvent, CloudServiceEvents> i
|
||||
*/
|
||||
public async prefetch() {
|
||||
this.reset();
|
||||
await this.fetch();
|
||||
}
|
||||
|
||||
public async fetch() {
|
||||
await this.backend.fetch();
|
||||
await this.backend.fetch(ProjectModel.instance);
|
||||
}
|
||||
|
||||
public async getActiveEnvironment(project: ProjectModel): Promise<Environment> {
|
||||
await this.backend.fetch();
|
||||
await this.backend.fetch(project);
|
||||
return this.backend.fromProject(project);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
export * from './CloudService';
|
||||
export * from './type';
|
||||
export * from './ExternalCloudService';
|
||||
|
||||
@@ -1,25 +1,21 @@
|
||||
import { JSONStorage } from '@noodl/platform';
|
||||
|
||||
import { CreateEnvironment, CreateEnvironmentRequest, UpdateEnvironmentRequest } from '@noodl-models/CloudServices';
|
||||
import {
|
||||
CreateEnvironment,
|
||||
CreateEnvironmentRequest,
|
||||
EnvironmentDataFormat,
|
||||
ICloudServiceProvider,
|
||||
UpdateEnvironmentRequest
|
||||
} from '@noodl-models/CloudServices';
|
||||
import { ProjectModel } from '@noodl-models/projectmodel';
|
||||
|
||||
/** The data format is separated from our internal model. */
|
||||
export type EnvironmentDataFormat = {
|
||||
enabled: boolean;
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
masterKey: string;
|
||||
appId: string;
|
||||
endpoint: string;
|
||||
};
|
||||
|
||||
export class ExternalCloudService {
|
||||
async list(): Promise<EnvironmentDataFormat[]> {
|
||||
export class GlobalCloudService implements ICloudServiceProvider {
|
||||
async list(_project: ProjectModel): Promise<EnvironmentDataFormat[]> {
|
||||
const local = await JSONStorage.get('externalBrokers');
|
||||
return local.brokers || [];
|
||||
}
|
||||
|
||||
async create(options: CreateEnvironmentRequest): Promise<CreateEnvironment> {
|
||||
async create(_project: ProjectModel, options: CreateEnvironmentRequest): Promise<CreateEnvironment> {
|
||||
const id = `${options.url}-${options.appId}`;
|
||||
|
||||
const newBroker: EnvironmentDataFormat = {
|
||||
@@ -44,7 +40,7 @@ export class ExternalCloudService {
|
||||
};
|
||||
}
|
||||
|
||||
async update(options: UpdateEnvironmentRequest): Promise<boolean> {
|
||||
async update(_project: ProjectModel, options: UpdateEnvironmentRequest): Promise<boolean> {
|
||||
const local = await JSONStorage.get('externalBrokers');
|
||||
const brokers: EnvironmentDataFormat[] = local.brokers || [];
|
||||
|
||||
@@ -63,7 +59,7 @@ export class ExternalCloudService {
|
||||
return true;
|
||||
}
|
||||
|
||||
async delete(id: string): Promise<boolean> {
|
||||
async delete(_project: ProjectModel, id: string): Promise<boolean> {
|
||||
const local = await JSONStorage.get('externalBrokers');
|
||||
const brokers: EnvironmentDataFormat[] = local.brokers || [];
|
||||
|
||||
@@ -79,25 +75,3 @@ export class ExternalCloudService {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export class Environment {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
createdAt: string;
|
||||
masterKeyUpdatedAt: string;
|
||||
masterKey: string;
|
||||
appId: string;
|
||||
url: string;
|
||||
|
||||
constructor(item: EnvironmentDataFormat) {
|
||||
this.id = item.id;
|
||||
this.name = item.name;
|
||||
this.description = item.description;
|
||||
this.createdAt = '';
|
||||
this.masterKeyUpdatedAt = '';
|
||||
this.masterKey = item.masterKey;
|
||||
this.appId = item.appId;
|
||||
this.url = item.endpoint;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
import { filesystem } from '@noodl/platform';
|
||||
|
||||
import {
|
||||
CreateEnvironment,
|
||||
CreateEnvironmentRequest,
|
||||
EnvironmentDataFormat,
|
||||
ICloudServiceProvider,
|
||||
UpdateEnvironmentRequest
|
||||
} from '@noodl-models/CloudServices';
|
||||
import { ProjectModel } from '@noodl-models/projectmodel';
|
||||
|
||||
/**
|
||||
* Store the Cloud Service relative to the project folder.
|
||||
*/
|
||||
export class ProjectCloudService implements ICloudServiceProvider {
|
||||
private async load(project: ProjectModel) {
|
||||
const dirpath = filesystem.resolve(project._retainedProjectDirectory, ".noodl");
|
||||
const filepath = filesystem.resolve(dirpath, "cloudservices.json");
|
||||
if (!filesystem.exists(filepath)) {
|
||||
return []
|
||||
}
|
||||
|
||||
// TODO: Validate file content
|
||||
return filesystem.readJson(filepath);
|
||||
}
|
||||
|
||||
private async save(project: ProjectModel, items: EnvironmentDataFormat[]) {
|
||||
const dirpath = filesystem.resolve(project._retainedProjectDirectory, ".noodl");
|
||||
const filepath = filesystem.resolve(dirpath, "cloudservices.json");
|
||||
if (!filesystem.exists(filepath)) {
|
||||
await filesystem.makeDirectory(dirpath);
|
||||
}
|
||||
|
||||
await filesystem.writeJson(filepath, items);
|
||||
}
|
||||
|
||||
async list(project: ProjectModel): Promise<EnvironmentDataFormat[]> {
|
||||
if (!project || !project._retainedProjectDirectory) {
|
||||
return []
|
||||
}
|
||||
|
||||
return await this.load(project);
|
||||
}
|
||||
|
||||
async create(project: ProjectModel, options: CreateEnvironmentRequest): Promise<CreateEnvironment> {
|
||||
const id = `${options.url}-${options.appId}`;
|
||||
|
||||
const newBroker: EnvironmentDataFormat = {
|
||||
enabled: true,
|
||||
id,
|
||||
name: options.name,
|
||||
description: options.description,
|
||||
masterKey: options.masterKey,
|
||||
appId: options.appId,
|
||||
endpoint: options.url
|
||||
};
|
||||
|
||||
const current = await this.load(project);
|
||||
await this.save(project, [...current, newBroker]);
|
||||
|
||||
return {
|
||||
id: newBroker.id,
|
||||
appId: newBroker.appId,
|
||||
url: newBroker.endpoint,
|
||||
masterKey: newBroker.masterKey
|
||||
};
|
||||
}
|
||||
|
||||
async update(project: ProjectModel, options: UpdateEnvironmentRequest): Promise<boolean> {
|
||||
const current = await this.load(project);
|
||||
|
||||
// Find and update
|
||||
const broker = current.find((x) => x.id === options.id);
|
||||
if (!broker) return false;
|
||||
|
||||
if (typeof options.name !== undefined) broker.name = options.name;
|
||||
if (typeof options.description !== undefined) broker.description = options.description;
|
||||
if (typeof options.appId !== undefined) broker.appId = options.appId;
|
||||
if (typeof options.masterKey !== undefined) broker.masterKey = options.masterKey;
|
||||
if (typeof options.url !== undefined) broker.endpoint = options.url;
|
||||
|
||||
await this.save(project, current);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async delete(project: ProjectModel, id: string): Promise<boolean> {
|
||||
const current = await this.load(project);
|
||||
|
||||
// Find the environment
|
||||
const found = current.find((b) => b.id === id);
|
||||
if (found) {
|
||||
// Delete the environment
|
||||
current.splice(current.indexOf(found), 1);
|
||||
}
|
||||
|
||||
// Save the list
|
||||
await this.save(project, current);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import { Environment } from '@noodl-models/CloudServices';
|
||||
import { ProjectModel } from '@noodl-models/projectmodel';
|
||||
import { IModel } from '@noodl-utils/model';
|
||||
|
||||
@@ -30,11 +29,11 @@ export interface ICloudBackendService {
|
||||
get isLoading(): boolean;
|
||||
get items(): Environment[];
|
||||
|
||||
fetch(): Promise<Environment[]>;
|
||||
fetch(project: ProjectModel): Promise<Environment[]>;
|
||||
fromProject(project: ProjectModel): Promise<Environment> | undefined;
|
||||
create(options: CreateEnvironmentRequest): Promise<CreateEnvironment>;
|
||||
update(options: UpdateEnvironmentRequest): Promise<boolean>;
|
||||
delete(id: string): Promise<boolean>;
|
||||
create(project: ProjectModel, options: CreateEnvironmentRequest): Promise<CreateEnvironment>;
|
||||
update(project: ProjectModel, options: UpdateEnvironmentRequest): Promise<boolean>;
|
||||
delete(project: ProjectModel, id: string): Promise<boolean>;
|
||||
}
|
||||
|
||||
export enum CloudServiceEvent {
|
||||
@@ -55,3 +54,54 @@ export interface ICloudService extends IModel<CloudServiceEvent, CloudServiceEve
|
||||
|
||||
get backend(): ICloudBackendService;
|
||||
}
|
||||
|
||||
/** The data format is separated from our internal model. */
|
||||
export type EnvironmentDataFormat = {
|
||||
enabled: boolean;
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
masterKey: string;
|
||||
appId: string;
|
||||
endpoint: string;
|
||||
};
|
||||
|
||||
export class Environment {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
createdAt: string;
|
||||
masterKeyUpdatedAt: string;
|
||||
masterKey: string;
|
||||
appId: string;
|
||||
url: string;
|
||||
|
||||
provider: string;
|
||||
|
||||
get typeDisplayName() {
|
||||
switch (this.provider) {
|
||||
case "project": return "Self hosted";
|
||||
default: return "Global Self hosted"
|
||||
}
|
||||
}
|
||||
|
||||
constructor(provider: string, item: EnvironmentDataFormat) {
|
||||
this.provider = provider;
|
||||
|
||||
this.id = item.id;
|
||||
this.name = item.name;
|
||||
this.description = item.description;
|
||||
this.createdAt = '';
|
||||
this.masterKeyUpdatedAt = '';
|
||||
this.masterKey = item.masterKey;
|
||||
this.appId = item.appId;
|
||||
this.url = item.endpoint;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ICloudServiceProvider {
|
||||
list(project: ProjectModel | undefined): Promise<EnvironmentDataFormat[]>;
|
||||
create(project: ProjectModel | undefined, options: CreateEnvironmentRequest): Promise<CreateEnvironment>;
|
||||
update(project: ProjectModel | undefined, options: UpdateEnvironmentRequest): Promise<boolean>;
|
||||
delete(project: ProjectModel | undefined, id: string): Promise<boolean>;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { CloudService } from '@noodl-models/CloudServices';
|
||||
import { ProjectModel } from '@noodl-models/projectmodel';
|
||||
import SchemaModel from '@noodl-models/schemamodel';
|
||||
|
||||
class FormCollection {
|
||||
@@ -193,7 +194,7 @@ export default class CloudFormation {
|
||||
}) {
|
||||
// Create new cloud services if needed
|
||||
if (options.cloudServices.id === undefined) {
|
||||
CloudService.instance.backend.fetch().then((collection) => {
|
||||
CloudService.instance.backend.fetch(ProjectModel.instance).then((collection) => {
|
||||
// TODO(OS): Cloud formation Cloud Service
|
||||
// // Make sure we have a unique name for the cloud services
|
||||
// const orgName = options.cloudServices.name;
|
||||
|
||||
@@ -41,7 +41,7 @@ export default class SchemaHandler {
|
||||
return; // No project broker
|
||||
}
|
||||
|
||||
CloudService.instance.backend.fetch().then((collection) => {
|
||||
CloudService.instance.backend.fetch(ProjectModel.instance).then((collection) => {
|
||||
// Find by the Url / Endpoint and app id
|
||||
let environment = collection.find((b) => {
|
||||
return b.url === activeBroker.endpoint && b.appId === activeBroker.appId;
|
||||
|
||||
@@ -87,7 +87,7 @@ export function CloudServiceCard({
|
||||
<div className={css['MetaBar']}>
|
||||
<div className={classNames([css['TypeDisplay'], isEditorEnvironment && css['is-editor-environment']])}>
|
||||
<Icon icon={IconName.CloudCheck} size={IconSize.Small} UNSAFE_style={{ marginRight: 4 }} />
|
||||
{'Self hosted '}
|
||||
{environment.typeDisplayName + ' '}
|
||||
{errorMessage && <span className={css['ArchivedDisplay']}>({errorMessage})</span>}
|
||||
{isEditorEnvironment && <span className={css['UsedInEditorDisplay']}>(Used in editor)</span>}
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { CloudService, Environment } from '@noodl-models/CloudServices';
|
||||
import { ToastType } from '../../../ToastLayer/components/ToastCard';
|
||||
import { CloudServiceCard } from '../CloudServiceCard';
|
||||
import { useCloudServiceContext } from '../CloudServicePanel.context';
|
||||
import { ProjectModel } from '@noodl-models/projectmodel';
|
||||
|
||||
export interface CloudServiceCardItemProps {
|
||||
environment: Environment;
|
||||
@@ -20,7 +21,7 @@ export function CloudServiceCardItem({ environment, deleteEnvironment }: CloudSe
|
||||
async function onDelete() {
|
||||
await deleteEnvironment();
|
||||
await runActivity('Deleting cloud service...', async () => {
|
||||
const response: boolean = await CloudService.instance.backend.delete(environment.id);
|
||||
const response: boolean = await CloudService.instance.backend.delete(ProjectModel.instance, environment.id);
|
||||
return {
|
||||
type: ToastType.Success,
|
||||
message: 'Cloud service deleted'
|
||||
|
||||
@@ -12,6 +12,7 @@ import { Text, TextType } from '@noodl-core-ui/components/typography/Text';
|
||||
|
||||
import { ToastType } from '../../../ToastLayer/components/ToastCard';
|
||||
import { useCloudServiceContext } from '../CloudServicePanel.context';
|
||||
import { ProjectModel } from '@noodl-models/projectmodel';
|
||||
|
||||
function isValidParseUrl(url: string) {
|
||||
if (!url) return false;
|
||||
@@ -63,7 +64,7 @@ export function CloudServiceCreateModal({ isVisible, onClose }: CloudServiceCrea
|
||||
|
||||
async function onCreate() {
|
||||
await runActivity('Creating Cloud Service...', async () => {
|
||||
await cloudService.backend.create({
|
||||
await cloudService.backend.create(ProjectModel.instance, {
|
||||
name,
|
||||
description,
|
||||
masterKey: masterKey ? masterKey : undefined,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { FeedbackType } from '@noodl-constants/FeedbackType';
|
||||
import { CloudService, Environment } from '@noodl-models/CloudServices';
|
||||
@@ -12,6 +12,7 @@ import { HStack, VStack } from '@noodl-core-ui/components/layout/Stack';
|
||||
import { Text } from '@noodl-core-ui/components/typography/Text';
|
||||
|
||||
import { ToastLayer } from '../../../ToastLayer';
|
||||
import { ProjectModel } from '@noodl-models/projectmodel';
|
||||
|
||||
export interface CloudServiceModalProps {
|
||||
isVisible: boolean;
|
||||
@@ -60,7 +61,7 @@ function AsSelfHosted({
|
||||
}
|
||||
|
||||
CloudService.instance.backend
|
||||
.update({
|
||||
.update(ProjectModel.instance, {
|
||||
id: environment.id,
|
||||
name,
|
||||
description,
|
||||
@@ -70,7 +71,7 @@ function AsSelfHosted({
|
||||
})
|
||||
.then(() => {
|
||||
ToastLayer.showSuccess(`Updated Cloud Service`);
|
||||
CloudService.instance.backend.fetch();
|
||||
CloudService.instance.backend.fetch(ProjectModel.instance);
|
||||
})
|
||||
.catch(() => {
|
||||
ToastLayer.showError(`Failed to update Cloud Service`);
|
||||
|
||||
@@ -35,7 +35,7 @@ export function CloudServiceContextProvider({ children }) {
|
||||
const { hasActivity, runActivity } = useActivityQueue({
|
||||
onSuccess: async () => {
|
||||
// Always fetch all the backends after something have changed
|
||||
await cloudService.backend.fetch();
|
||||
await cloudService.backend.fetch(ProjectModel.instance);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user