mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-31 04:23:40 +00:00
update sdk imports
This commit is contained in:
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"projects": {
|
|
||||||
"ui": {
|
|
||||||
"name": "ui",
|
|
||||||
"integrations": {},
|
|
||||||
"type": "angular",
|
|
||||||
"root": "projects/ui"
|
|
||||||
},
|
|
||||||
"install-wizard": {
|
|
||||||
"name": "install-wizard",
|
|
||||||
"integrations": {},
|
|
||||||
"type": "angular",
|
|
||||||
"root": "projects/install-wizard"
|
|
||||||
},
|
|
||||||
"setup-wizard": {
|
|
||||||
"name": "setup-wizard",
|
|
||||||
"integrations": {},
|
|
||||||
"type": "angular",
|
|
||||||
"root": "projects/setup-wizard"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"defaultProject": "ui"
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": null,
|
"name": null,
|
||||||
"ack-welcome": "0.3.4.4",
|
"ackWelcome": "0.3.4.4",
|
||||||
"marketplace": {
|
"marketplace": {
|
||||||
"selected-url": "https://registry.start9.com/",
|
"selectedUrl": "https://registry.start9.com/",
|
||||||
"known-hosts": {
|
"knownHosts": {
|
||||||
"https://registry.start9.com/": {},
|
"https://registry.start9.com/": {},
|
||||||
"https://community-registry.start9.com/": {}
|
"https://community-registry.start9.com/": {}
|
||||||
}
|
}
|
||||||
@@ -11,10 +11,10 @@
|
|||||||
"dev": {},
|
"dev": {},
|
||||||
"gaming": {
|
"gaming": {
|
||||||
"snake": {
|
"snake": {
|
||||||
"high-score": 0
|
"highScore": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ack-instructions": {},
|
"ackInstructions": {},
|
||||||
"theme": "Dark",
|
"theme": "Dark",
|
||||||
"widgets": []
|
"widgets": []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import {
|
|||||||
} from '@angular/core'
|
} from '@angular/core'
|
||||||
import { FormGroup, ReactiveFormsModule } from '@angular/forms'
|
import { FormGroup, ReactiveFormsModule } from '@angular/forms'
|
||||||
import { RouterModule } from '@angular/router'
|
import { RouterModule } from '@angular/router'
|
||||||
import { InputSpec } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
tuiMarkControlAsTouchedAndValidate,
|
tuiMarkControlAsTouchedAndValidate,
|
||||||
TuiValueChangesModule,
|
TuiValueChangesModule,
|
||||||
@@ -29,7 +30,7 @@ export interface ActionButton<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface FormContext<T> {
|
export interface FormContext<T> {
|
||||||
spec: InputSpec
|
spec: CT.InputSpec
|
||||||
buttons: ActionButton<T>[]
|
buttons: ActionButton<T>[]
|
||||||
value?: T
|
value?: T
|
||||||
patch?: Operation[]
|
patch?: Operation[]
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
import { T } from '@start9labs/start-sdk'
|
import { CB, CT, T } from '@start9labs/start-sdk'
|
||||||
import { Config } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/config'
|
|
||||||
import { Value } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/value'
|
|
||||||
import { InputSpec } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
|
||||||
import { TuiDialogOptions } from '@taiga-ui/core'
|
import { TuiDialogOptions } from '@taiga-ui/core'
|
||||||
import { TuiPromptData } from '@taiga-ui/kit'
|
import { TuiPromptData } from '@taiga-ui/kit'
|
||||||
import { NetworkInfo } from 'src/app/services/patch-db/data-model'
|
import { NetworkInfo } from 'src/app/services/patch-db/data-model'
|
||||||
@@ -20,7 +17,7 @@ export const REMOVE: Partial<TuiDialogOptions<TuiPromptData>> = {
|
|||||||
export function getClearnetSpec({
|
export function getClearnetSpec({
|
||||||
domains,
|
domains,
|
||||||
start9ToSubdomain,
|
start9ToSubdomain,
|
||||||
}: NetworkInfo): Promise<InputSpec> {
|
}: NetworkInfo): Promise<CT.InputSpec> {
|
||||||
const start9ToDomain = `${start9ToSubdomain?.value}.start9.to`
|
const start9ToDomain = `${start9ToSubdomain?.value}.start9.to`
|
||||||
const base = start9ToSubdomain ? { [start9ToDomain]: start9ToDomain } : {}
|
const base = start9ToSubdomain ? { [start9ToDomain]: start9ToDomain } : {}
|
||||||
|
|
||||||
@@ -32,13 +29,13 @@ export function getClearnetSpec({
|
|||||||
}, base)
|
}, base)
|
||||||
|
|
||||||
return configBuilderToSpec(
|
return configBuilderToSpec(
|
||||||
Config.of({
|
CB.Config.of({
|
||||||
domain: Value.select({
|
domain: CB.Value.select({
|
||||||
name: 'Domain',
|
name: 'Domain',
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
values,
|
values,
|
||||||
}),
|
}),
|
||||||
subdomain: Value.text({
|
subdomain: CB.Value.text({
|
||||||
name: 'Subdomain',
|
name: 'Subdomain',
|
||||||
required: false,
|
required: false,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
isEmptyObject,
|
isEmptyObject,
|
||||||
LoadingService,
|
LoadingService,
|
||||||
} from '@start9labs/shared'
|
} from '@start9labs/shared'
|
||||||
import { InputSpec } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { TuiButtonModule } from '@taiga-ui/experimental'
|
import { TuiButtonModule } from '@taiga-ui/experimental'
|
||||||
import {
|
import {
|
||||||
TuiDialogContext,
|
TuiDialogContext,
|
||||||
@@ -131,7 +131,7 @@ export class ServiceConfigModal {
|
|||||||
: 'Loading Config'
|
: 'Loading Config'
|
||||||
|
|
||||||
pkg?: PackageDataEntry
|
pkg?: PackageDataEntry
|
||||||
spec: InputSpec = {}
|
spec: CT.InputSpec = {}
|
||||||
patch: Operation[] = []
|
patch: Operation[] = []
|
||||||
buttons: ActionButton<any>[] = [
|
buttons: ActionButton<any>[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Pipe, PipeTransform } from '@angular/core'
|
import { Pipe, PipeTransform } from '@angular/core'
|
||||||
import { WithId } from '@start9labs/shared'
|
import { WithId } from '@start9labs/shared'
|
||||||
import { ActionMetadata } from '@start9labs/start-sdk/cjs/sdk/lib/types'
|
import { T } from '@start9labs/start-sdk'
|
||||||
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
|
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
|
||||||
|
|
||||||
@Pipe({
|
@Pipe({
|
||||||
@@ -10,12 +10,12 @@ import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
|
|||||||
export class GroupActionsPipe implements PipeTransform {
|
export class GroupActionsPipe implements PipeTransform {
|
||||||
transform(
|
transform(
|
||||||
actions: PackageDataEntry['actions'],
|
actions: PackageDataEntry['actions'],
|
||||||
): Array<Array<WithId<ActionMetadata>>> | null {
|
): Array<Array<WithId<T.ActionMetadata>>> | null {
|
||||||
if (!actions) return null
|
if (!actions) return null
|
||||||
|
|
||||||
const noGroup = 'noGroup'
|
const noGroup = 'noGroup'
|
||||||
const grouped = Object.entries(actions).reduce<
|
const grouped = Object.entries(actions).reduce<
|
||||||
Record<string, WithId<ActionMetadata>[]>
|
Record<string, WithId<T.ActionMetadata>[]>
|
||||||
>((groups, [id, action]) => {
|
>((groups, [id, action]) => {
|
||||||
const actionWithId = { id, ...action }
|
const actionWithId = { id, ...action }
|
||||||
const groupKey = action.group || noGroup
|
const groupKey = action.group || noGroup
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Pipe, PipeTransform } from '@angular/core'
|
import { Pipe, PipeTransform } from '@angular/core'
|
||||||
import { ServiceInterfaceWithHostInfo } from '@start9labs/start-sdk/cjs/sdk/lib/types'
|
import { T } from '@start9labs/start-sdk'
|
||||||
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
|
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
|
||||||
|
|
||||||
export interface ExtendedInterfaceInfo extends ServiceInterfaceWithHostInfo {
|
export interface ExtendedInterfaceInfo extends T.ServiceInterfaceWithHostInfo {
|
||||||
id: string
|
id: string
|
||||||
icon: string
|
icon: string
|
||||||
color: string
|
color: string
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import { ServiceActionComponent } from '../components/action.component'
|
|||||||
import { ServiceActionSuccessComponent } from '../components/action-success.component'
|
import { ServiceActionSuccessComponent } from '../components/action-success.component'
|
||||||
import { GroupActionsPipe } from '../pipes/group-actions.pipe'
|
import { GroupActionsPipe } from '../pipes/group-actions.pipe'
|
||||||
import { ToManifestPipe } from 'src/app/apps/portal/pipes/to-manifest'
|
import { ToManifestPipe } from 'src/app/apps/portal/pipes/to-manifest'
|
||||||
import { ActionMetadata } from '@start9labs/start-sdk/cjs/sdk/lib/types'
|
import { T } from '@start9labs/start-sdk'
|
||||||
import { getAllPackages, getManifest } from 'src/app/util/get-package-data'
|
import { getAllPackages, getManifest } from 'src/app/util/get-package-data'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -61,7 +61,12 @@ import { getAllPackages, getManifest } from 'src/app/util/get-package-data'
|
|||||||
`,
|
`,
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, ServiceActionComponent, GroupActionsPipe, ToManifestPipe],
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
ServiceActionComponent,
|
||||||
|
GroupActionsPipe,
|
||||||
|
ToManifestPipe,
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class ServiceActionsRoute {
|
export class ServiceActionsRoute {
|
||||||
private readonly id = getPkgId(inject(ActivatedRoute))
|
private readonly id = getPkgId(inject(ActivatedRoute))
|
||||||
@@ -87,7 +92,7 @@ export class ServiceActionsRoute {
|
|||||||
private readonly formDialog: FormDialogService,
|
private readonly formDialog: FormDialogService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async handleAction(action: WithId<ActionMetadata>) {
|
async handleAction(action: WithId<T.ActionMetadata>) {
|
||||||
if (action.disabled) {
|
if (action.disabled) {
|
||||||
this.dialogs
|
this.dialogs
|
||||||
.open(action.disabled, {
|
.open(action.disabled, {
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import { CommonModule } from '@angular/common'
|
import { CommonModule } from '@angular/common'
|
||||||
import { Component, inject, OnInit } from '@angular/core'
|
import { Component, inject, OnInit } from '@angular/core'
|
||||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||||
import {
|
import { CT } from '@start9labs/start-sdk'
|
||||||
unionSelectKey,
|
|
||||||
unionValueKey,
|
|
||||||
} from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
|
||||||
import { TuiNotificationModule } from '@taiga-ui/core'
|
import { TuiNotificationModule } from '@taiga-ui/core'
|
||||||
import { TuiButtonModule, TuiFadeModule } from '@taiga-ui/experimental'
|
import { TuiButtonModule, TuiFadeModule } from '@taiga-ui/experimental'
|
||||||
import { PolymorpheusComponent } from '@tinkoff/ng-polymorpheus'
|
import { PolymorpheusComponent } from '@tinkoff/ng-polymorpheus'
|
||||||
@@ -182,8 +179,8 @@ export class BackupsTargetsModal implements OnInit {
|
|||||||
text: 'Save',
|
text: 'Save',
|
||||||
handler: ({ type }: BackupConfig) =>
|
handler: ({ type }: BackupConfig) =>
|
||||||
this.add(
|
this.add(
|
||||||
type[unionSelectKey] === 'cifs' ? 'cifs' : 'cloud',
|
type[CT.unionSelectKey] === 'cifs' ? 'cifs' : 'cloud',
|
||||||
type[unionValueKey],
|
type[CT.unionValueKey],
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,19 +1,16 @@
|
|||||||
import {
|
import { CT } from '@start9labs/start-sdk'
|
||||||
unionSelectKey,
|
|
||||||
unionValueKey,
|
|
||||||
} from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
|
||||||
import { RR } from 'src/app/services/api/api.types'
|
import { RR } from 'src/app/services/api/api.types'
|
||||||
|
|
||||||
export type BackupConfig =
|
export type BackupConfig =
|
||||||
| {
|
| {
|
||||||
type: {
|
type: {
|
||||||
[unionSelectKey]: 'dropbox' | 'google-drive'
|
[CT.unionSelectKey]: 'dropbox' | 'google-drive'
|
||||||
[unionValueKey]: RR.AddCloudBackupTargetReq
|
[CT.unionValueKey]: RR.AddCloudBackupTargetReq
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: {
|
type: {
|
||||||
[unionSelectKey]: 'cifs'
|
[CT.unionSelectKey]: 'cifs'
|
||||||
[unionValueKey]: RR.AddCifsBackupTargetReq
|
[CT.unionValueKey]: RR.AddCifsBackupTargetReq
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
import { Config } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/config'
|
import { CB } from '@start9labs/start-sdk'
|
||||||
import { Value } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/value'
|
|
||||||
import { Variants } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/variants'
|
|
||||||
|
|
||||||
export const dropboxSpec = Config.of({
|
export const dropboxSpec = CB.Config.of({
|
||||||
name: Value.text({
|
name: CB.Value.text({
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
description: 'A friendly name for this Dropbox target',
|
description: 'A friendly name for this Dropbox target',
|
||||||
placeholder: 'My Dropbox',
|
placeholder: 'My Dropbox',
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
}),
|
}),
|
||||||
token: Value.text({
|
token: CB.Value.text({
|
||||||
name: 'Access Token',
|
name: 'Access Token',
|
||||||
description: 'The secret access token for your custom Dropbox app',
|
description: 'The secret access token for your custom Dropbox app',
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
masked: true,
|
masked: true,
|
||||||
}),
|
}),
|
||||||
path: Value.text({
|
path: CB.Value.text({
|
||||||
name: 'Path',
|
name: 'Path',
|
||||||
description: 'The fully qualified path to the backup directory',
|
description: 'The fully qualified path to the backup directory',
|
||||||
placeholder: 'e.g. /Desktop/my-folder',
|
placeholder: 'e.g. /Desktop/my-folder',
|
||||||
@@ -23,20 +21,20 @@ export const dropboxSpec = Config.of({
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const googleDriveSpec = Config.of({
|
export const googleDriveSpec = CB.Config.of({
|
||||||
name: Value.text({
|
name: CB.Value.text({
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
description: 'A friendly name for this Google Drive target',
|
description: 'A friendly name for this Google Drive target',
|
||||||
placeholder: 'My Google Drive',
|
placeholder: 'My Google Drive',
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
}),
|
}),
|
||||||
path: Value.text({
|
path: CB.Value.text({
|
||||||
name: 'Path',
|
name: 'Path',
|
||||||
description: 'The fully qualified path to the backup directory',
|
description: 'The fully qualified path to the backup directory',
|
||||||
placeholder: 'e.g. /Desktop/my-folder',
|
placeholder: 'e.g. /Desktop/my-folder',
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
}),
|
}),
|
||||||
key: Value.file({
|
key: CB.Value.file({
|
||||||
name: 'Private Key File',
|
name: 'Private Key File',
|
||||||
description:
|
description:
|
||||||
'Your Google Drive service account private key file (.json file)',
|
'Your Google Drive service account private key file (.json file)',
|
||||||
@@ -45,14 +43,14 @@ export const googleDriveSpec = Config.of({
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const cifsSpec = Config.of({
|
export const cifsSpec = CB.Config.of({
|
||||||
name: Value.text({
|
name: CB.Value.text({
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
description: 'A friendly name for this Network Folder',
|
description: 'A friendly name for this Network Folder',
|
||||||
placeholder: 'My Network Folder',
|
placeholder: 'My Network Folder',
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
}),
|
}),
|
||||||
hostname: Value.text({
|
hostname: CB.Value.text({
|
||||||
name: 'Hostname',
|
name: 'Hostname',
|
||||||
description:
|
description:
|
||||||
'The hostname of your target device on the Local Area Network.',
|
'The hostname of your target device on the Local Area Network.',
|
||||||
@@ -61,19 +59,19 @@ export const cifsSpec = Config.of({
|
|||||||
required: { default: null },
|
required: { default: null },
|
||||||
patterns: [],
|
patterns: [],
|
||||||
}),
|
}),
|
||||||
path: Value.text({
|
path: CB.Value.text({
|
||||||
name: 'Path',
|
name: 'Path',
|
||||||
description: `On Windows, this is the fully qualified path to the shared folder, (e.g. /Desktop/my-folder).\n\n On Linux and Mac, this is the literal name of the shared folder (e.g. my-shared-folder).`,
|
description: `On Windows, this is the fully qualified path to the shared folder, (e.g. /Desktop/my-folder).\n\n On Linux and Mac, this is the literal name of the shared folder (e.g. my-shared-folder).`,
|
||||||
placeholder: 'e.g. my-shared-folder or /Desktop/my-folder',
|
placeholder: 'e.g. my-shared-folder or /Desktop/my-folder',
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
}),
|
}),
|
||||||
username: Value.text({
|
username: CB.Value.text({
|
||||||
name: 'Username',
|
name: 'Username',
|
||||||
description: `On Linux, this is the samba username you created when sharing the folder.\n\n On Mac and Windows, this is the username of the user who is sharing the folder.`,
|
description: `On Linux, this is the samba username you created when sharing the folder.\n\n On Mac and Windows, this is the username of the user who is sharing the folder.`,
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
placeholder: 'My Network Folder',
|
placeholder: 'My Network Folder',
|
||||||
}),
|
}),
|
||||||
password: Value.text({
|
password: CB.Value.text({
|
||||||
name: 'Password',
|
name: 'Password',
|
||||||
description: `On Linux, this is the samba password you created when sharing the folder.\n\n On Mac and Windows, this is the password of the user who is sharing the folder.`,
|
description: `On Linux, this is the samba password you created when sharing the folder.\n\n On Mac and Windows, this is the password of the user who is sharing the folder.`,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -82,13 +80,13 @@ export const cifsSpec = Config.of({
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const remoteBackupTargetSpec = Config.of({
|
export const remoteBackupTargetSpec = CB.Config.of({
|
||||||
type: Value.union(
|
type: CB.Value.union(
|
||||||
{
|
{
|
||||||
name: 'Target Type',
|
name: 'Target Type',
|
||||||
required: { default: 'dropbox' },
|
required: { default: 'dropbox' },
|
||||||
},
|
},
|
||||||
Variants.of({
|
CB.Variants.of({
|
||||||
dropbox: {
|
dropbox: {
|
||||||
name: 'Dropbox',
|
name: 'Dropbox',
|
||||||
spec: dropboxSpec,
|
spec: dropboxSpec,
|
||||||
@@ -105,14 +103,14 @@ export const remoteBackupTargetSpec = Config.of({
|
|||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const diskBackupTargetSpec = Config.of({
|
export const diskBackupTargetSpec = CB.Config.of({
|
||||||
name: Value.text({
|
name: CB.Value.text({
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
description: 'A friendly name for this physical target',
|
description: 'A friendly name for this physical target',
|
||||||
placeholder: 'My Physical Target',
|
placeholder: 'My Physical Target',
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
}),
|
}),
|
||||||
path: Value.text({
|
path: CB.Value.text({
|
||||||
name: 'Path',
|
name: 'Path',
|
||||||
description: 'The fully qualified path to the backup directory',
|
description: 'The fully qualified path to the backup directory',
|
||||||
placeholder: 'e.g. /Backups/my-folder',
|
placeholder: 'e.g. /Backups/my-folder',
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { ValueSpecObject } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { TuiDialogOptions } from '@taiga-ui/core'
|
import { TuiDialogOptions } from '@taiga-ui/core'
|
||||||
import { TuiPromptData } from '@taiga-ui/kit'
|
import { TuiPromptData } from '@taiga-ui/kit'
|
||||||
|
|
||||||
export function getMarketplaceValueSpec(): ValueSpecObject {
|
export function getMarketplaceValueSpec(): CT.ValueSpecObject {
|
||||||
return {
|
return {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
name: 'Add Custom Registry',
|
name: 'Add Custom Registry',
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
import { Config } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/config'
|
import { CB } from '@start9labs/start-sdk'
|
||||||
import { Value } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/value'
|
|
||||||
import { Variants } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/variants'
|
|
||||||
import { Proxy } from 'src/app/services/patch-db/data-model'
|
import { Proxy } from 'src/app/services/patch-db/data-model'
|
||||||
import { configBuilderToSpec } from 'src/app/util/configBuilderToSpec'
|
import { configBuilderToSpec } from 'src/app/util/configBuilderToSpec'
|
||||||
|
|
||||||
const auth = Config.of({
|
const auth = CB.Config.of({
|
||||||
username: Value.text({
|
username: CB.Value.text({
|
||||||
name: 'Username',
|
name: 'Username',
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
}),
|
}),
|
||||||
password: Value.text({
|
password: CB.Value.text({
|
||||||
name: 'Password',
|
name: 'Password',
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
masked: true,
|
masked: true,
|
||||||
@@ -26,7 +24,7 @@ function getStrategyUnion(proxies: Proxy[]) {
|
|||||||
}
|
}
|
||||||
}, {})
|
}, {})
|
||||||
|
|
||||||
return Value.union(
|
return CB.Value.union(
|
||||||
{
|
{
|
||||||
name: 'Networking Strategy',
|
name: 'Networking Strategy',
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
@@ -34,11 +32,11 @@ function getStrategyUnion(proxies: Proxy[]) {
|
|||||||
<h5>Proxy</h5>Select this option is you prefer to hide your home/business IP address from the Internet. This option requires running your own Virtual Private Server (VPS) <i>or</i> paying service provider such as Static Wire
|
<h5>Proxy</h5>Select this option is you prefer to hide your home/business IP address from the Internet. This option requires running your own Virtual Private Server (VPS) <i>or</i> paying service provider such as Static Wire
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
Variants.of({
|
CB.Variants.of({
|
||||||
local: {
|
local: {
|
||||||
name: 'Local',
|
name: 'Local',
|
||||||
spec: Config.of({
|
spec: CB.Config.of({
|
||||||
ipStrategy: Value.select({
|
ipStrategy: CB.Value.select({
|
||||||
name: 'IP Strategy',
|
name: 'IP Strategy',
|
||||||
description: `<h5>IPv6 Only (recommended)</h5><b>Requirements</b>:<ol><li>ISP IPv6 support</li><li>OpenWRT (recommended) or Linksys router</li></ol><b>Pros</b>: Ready for IPv6 Internet. Enhanced privacy. Run multiple clearnet servers from the same network
|
description: `<h5>IPv6 Only (recommended)</h5><b>Requirements</b>:<ol><li>ISP IPv6 support</li><li>OpenWRT (recommended) or Linksys router</li></ol><b>Pros</b>: Ready for IPv6 Internet. Enhanced privacy. Run multiple clearnet servers from the same network
|
||||||
<b>Cons</b>: Interfaces using this domain will only be accessible to people whose ISP supports IPv6
|
<b>Cons</b>: Interfaces using this domain will only be accessible to people whose ISP supports IPv6
|
||||||
@@ -58,8 +56,8 @@ function getStrategyUnion(proxies: Proxy[]) {
|
|||||||
},
|
},
|
||||||
proxy: {
|
proxy: {
|
||||||
name: 'Proxy',
|
name: 'Proxy',
|
||||||
spec: Config.of({
|
spec: CB.Config.of({
|
||||||
proxyId: Value.select({
|
proxyId: CB.Value.select({
|
||||||
name: 'Select Proxy',
|
name: 'Select Proxy',
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
values: inboundProxies,
|
values: inboundProxies,
|
||||||
@@ -72,7 +70,7 @@ function getStrategyUnion(proxies: Proxy[]) {
|
|||||||
|
|
||||||
export function getStart9ToSpec(proxies: Proxy[]) {
|
export function getStart9ToSpec(proxies: Proxy[]) {
|
||||||
return configBuilderToSpec(
|
return configBuilderToSpec(
|
||||||
Config.of({
|
CB.Config.of({
|
||||||
strategy: getStrategyUnion(proxies),
|
strategy: getStrategyUnion(proxies),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
@@ -80,21 +78,21 @@ export function getStart9ToSpec(proxies: Proxy[]) {
|
|||||||
|
|
||||||
export function getCustomSpec(proxies: Proxy[]) {
|
export function getCustomSpec(proxies: Proxy[]) {
|
||||||
return configBuilderToSpec(
|
return configBuilderToSpec(
|
||||||
Config.of({
|
CB.Config.of({
|
||||||
hostname: Value.text({
|
hostname: CB.Value.text({
|
||||||
name: 'Hostname',
|
name: 'Hostname',
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
placeholder: 'yourdomain.com',
|
placeholder: 'yourdomain.com',
|
||||||
}),
|
}),
|
||||||
provider: Value.union(
|
provider: CB.Value.union(
|
||||||
{
|
{
|
||||||
name: 'Dynamic DNS Provider',
|
name: 'Dynamic DNS Provider',
|
||||||
required: { default: 'start9' },
|
required: { default: 'start9' },
|
||||||
},
|
},
|
||||||
Variants.of({
|
CB.Variants.of({
|
||||||
start9: {
|
start9: {
|
||||||
name: 'Start9',
|
name: 'Start9',
|
||||||
spec: Config.of({}),
|
spec: CB.Config.of({}),
|
||||||
},
|
},
|
||||||
njalla: {
|
njalla: {
|
||||||
name: 'Njalla',
|
name: 'Njalla',
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ import { DataModel } from 'src/app/services/patch-db/data-model'
|
|||||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||||
import { FormService } from 'src/app/services/form.service'
|
import { FormService } from 'src/app/services/form.service'
|
||||||
import { EmailInfoComponent } from './info.component'
|
import { EmailInfoComponent } from './info.component'
|
||||||
import { InputSpec } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT, config } from '@start9labs/start-sdk'
|
||||||
import { customSmtp } from '@start9labs/start-sdk/cjs/sdk/lib/config/configConstants'
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
@@ -82,7 +81,9 @@ export class SettingsEmailComponent {
|
|||||||
private readonly api = inject(ApiService)
|
private readonly api = inject(ApiService)
|
||||||
|
|
||||||
testAddress = ''
|
testAddress = ''
|
||||||
readonly spec: Promise<InputSpec> = configBuilderToSpec(customSmtp)
|
readonly spec: Promise<CT.InputSpec> = configBuilderToSpec(
|
||||||
|
config.constants.customSmtp,
|
||||||
|
)
|
||||||
readonly form$ = this.patch
|
readonly form$ = this.patch
|
||||||
.watch$('serverInfo', 'smtp')
|
.watch$('serverInfo', 'smtp')
|
||||||
.pipe(
|
.pipe(
|
||||||
@@ -95,7 +96,9 @@ export class SettingsEmailComponent {
|
|||||||
const loader = this.loader.open('Saving...').subscribe()
|
const loader = this.loader.open('Saving...').subscribe()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.api.configureEmail(customSmtp.validator.unsafeCast(value))
|
await this.api.configureEmail(
|
||||||
|
config.constants.customSmtp.validator.unsafeCast(value),
|
||||||
|
)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.errorService.handleError(e)
|
this.errorService.handleError(e)
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Config } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/config'
|
import { CB } from '@start9labs/start-sdk'
|
||||||
import { Value } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/value'
|
|
||||||
import { TuiDialogOptions } from '@taiga-ui/core'
|
import { TuiDialogOptions } from '@taiga-ui/core'
|
||||||
import { TuiPromptData } from '@taiga-ui/kit'
|
import { TuiPromptData } from '@taiga-ui/kit'
|
||||||
|
|
||||||
@@ -13,13 +12,13 @@ export const DELETE_OPTIONS: Partial<TuiDialogOptions<TuiPromptData>> = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const wireguardSpec = Config.of({
|
export const wireguardSpec = CB.Config.of({
|
||||||
name: Value.text({
|
name: CB.Value.text({
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
description: 'A friendly name to help you remember and identify this proxy',
|
description: 'A friendly name to help you remember and identify this proxy',
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
}),
|
}),
|
||||||
config: Value.file({
|
config: CB.Value.file({
|
||||||
name: 'Wiregaurd Config',
|
name: 'Wiregaurd Config',
|
||||||
required: { default: null },
|
required: { default: null },
|
||||||
extensions: ['.conf'],
|
extensions: ['.conf'],
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import { Proxy } from 'src/app/services/patch-db/data-model'
|
|||||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||||
import { FormDialogService } from 'src/app/services/form-dialog.service'
|
import { FormDialogService } from 'src/app/services/form-dialog.service'
|
||||||
import { DELETE_OPTIONS, ProxyUpdate } from './constants'
|
import { DELETE_OPTIONS, ProxyUpdate } from './constants'
|
||||||
import { Value } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/value'
|
import { CB } from '@start9labs/start-sdk'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'proxies-menu',
|
selector: 'proxies-menu',
|
||||||
@@ -90,7 +90,7 @@ export class ProxiesMenuComponent {
|
|||||||
|
|
||||||
async rename() {
|
async rename() {
|
||||||
const spec = { name: 'Name', required: { default: this.proxy.name } }
|
const spec = { name: 'Name', required: { default: this.proxy.name } }
|
||||||
const name = await Value.text(spec).build({} as any)
|
const name = await CB.Value.text(spec).build({} as any)
|
||||||
const options: Partial<TuiDialogOptions<FormContext<{ name: string }>>> = {
|
const options: Partial<TuiDialogOptions<FormContext<{ name: string }>>> = {
|
||||||
label: `Rename ${this.proxy.name}`,
|
label: `Rename ${this.proxy.name}`,
|
||||||
data: {
|
data: {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { Pipe, PipeTransform } from '@angular/core'
|
import { Pipe, PipeTransform } from '@angular/core'
|
||||||
import { HostnameInfo } from '@start9labs/start-sdk/cjs/sdk/lib/types'
|
import { T } from '@start9labs/start-sdk'
|
||||||
|
|
||||||
@Pipe({
|
@Pipe({
|
||||||
standalone: true,
|
standalone: true,
|
||||||
name: 'primaryIp',
|
name: 'primaryIp',
|
||||||
})
|
})
|
||||||
export class PrimaryIpPipe implements PipeTransform {
|
export class PrimaryIpPipe implements PipeTransform {
|
||||||
transform(hostnames: HostnameInfo[]): string {
|
transform(hostnames: T.HostnameInfo[]): string {
|
||||||
return (
|
return (
|
||||||
hostnames.map(
|
hostnames.map(
|
||||||
h => h.kind === 'ip' && h.hostname.kind === 'ipv4' && h.hostname.value,
|
h => h.kind === 'ip' && h.hostname.kind === 'ipv4' && h.hostname.value,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ValueSpecObject } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { AvailableWifi } from 'src/app/services/api/api.types'
|
import { AvailableWifi } from 'src/app/services/api/api.types'
|
||||||
import { RR } from 'src/app/services/api/api.types'
|
import { RR } from 'src/app/services/api/api.types'
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ export function parseWifi(res: RR.GetWifiRes): WifiData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const wifiSpec: ValueSpecObject = {
|
export const wifiSpec: CT.ValueSpecObject = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
name: 'WiFi Credentials',
|
name: 'WiFi Credentials',
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ValueSpecObject } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
|
|
||||||
export const wifiSpec: ValueSpecObject = {
|
export const wifiSpec: CT.ValueSpecObject = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
name: 'WiFi Credentials',
|
name: 'WiFi Credentials',
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Config } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/config'
|
import { CB } from '@start9labs/start-sdk'
|
||||||
import { Value } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/value'
|
|
||||||
|
|
||||||
export interface SettingBtn {
|
export interface SettingBtn {
|
||||||
title: string
|
title: string
|
||||||
@@ -9,22 +8,22 @@ export interface SettingBtn {
|
|||||||
routerLink?: string
|
routerLink?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const passwordSpec = Config.of({
|
export const passwordSpec = CB.Config.of({
|
||||||
currentPassword: Value.text({
|
currentPassword: CB.Value.text({
|
||||||
name: 'Current Password',
|
name: 'Current Password',
|
||||||
required: {
|
required: {
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
masked: true,
|
masked: true,
|
||||||
}),
|
}),
|
||||||
newPassword1: Value.text({
|
newPassword1: CB.Value.text({
|
||||||
name: 'New Password',
|
name: 'New Password',
|
||||||
required: {
|
required: {
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
masked: true,
|
masked: true,
|
||||||
}),
|
}),
|
||||||
newPassword2: Value.text({
|
newPassword2: CB.Value.text({
|
||||||
name: 'Retype New Password',
|
name: 'Retype New Password',
|
||||||
required: {
|
required: {
|
||||||
default: null,
|
default: null,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { inject } from '@angular/core'
|
import { inject } from '@angular/core'
|
||||||
import { FormControlComponent } from './form-control/form-control.component'
|
import { FormControlComponent } from './form-control/form-control.component'
|
||||||
import { ValueSpec } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
|
|
||||||
export abstract class Control<Spec extends ValueSpec, Value> {
|
export abstract class Control<Spec extends CT.ValueSpec, Value> {
|
||||||
private readonly control: FormControlComponent<Spec, Value> =
|
private readonly control: FormControlComponent<Spec, Value> =
|
||||||
inject(FormControlComponent)
|
inject(FormControlComponent)
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
tuiHeightCollapse,
|
tuiHeightCollapse,
|
||||||
} from '@taiga-ui/core'
|
} from '@taiga-ui/core'
|
||||||
import { TUI_PROMPT } from '@taiga-ui/kit'
|
import { TUI_PROMPT } from '@taiga-ui/kit'
|
||||||
import { ValueSpecList } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { filter, takeUntil } from 'rxjs'
|
import { filter, takeUntil } from 'rxjs'
|
||||||
import { FormService } from 'src/app/services/form.service'
|
import { FormService } from 'src/app/services/form.service'
|
||||||
import { ERRORS } from '../form-group/form-group.component'
|
import { ERRORS } from '../form-group/form-group.component'
|
||||||
@@ -22,7 +22,7 @@ import { ERRORS } from '../form-group/form-group.component'
|
|||||||
})
|
})
|
||||||
export class FormArrayComponent {
|
export class FormArrayComponent {
|
||||||
@Input({ required: true })
|
@Input({ required: true })
|
||||||
spec!: ValueSpecList
|
spec!: CT.ValueSpecList
|
||||||
|
|
||||||
@HostBinding('@tuiParentStop')
|
@HostBinding('@tuiParentStop')
|
||||||
readonly animation = { value: '', ...inject(TUI_ANIMATION_OPTIONS) }
|
readonly animation = { value: '', ...inject(TUI_ANIMATION_OPTIONS) }
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { ValueSpecColor } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { Control } from '../control'
|
import { Control } from '../control'
|
||||||
import { MaskitoOptions } from '@maskito/core'
|
import { MaskitoOptions } from '@maskito/core'
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ import { MaskitoOptions } from '@maskito/core'
|
|||||||
templateUrl: './form-color.component.html',
|
templateUrl: './form-color.component.html',
|
||||||
styleUrls: ['./form-color.component.scss'],
|
styleUrls: ['./form-color.component.scss'],
|
||||||
})
|
})
|
||||||
export class FormColorComponent extends Control<ValueSpecColor, string> {
|
export class FormColorComponent extends Control<CT.ValueSpecColor, string> {
|
||||||
readonly mask: MaskitoOptions = {
|
readonly mask: MaskitoOptions = {
|
||||||
mask: ['#', ...Array(6).fill(/[0-9a-f]/i)],
|
mask: ['#', ...Array(6).fill(/[0-9a-f]/i)],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
TuiNotification,
|
TuiNotification,
|
||||||
} from '@taiga-ui/core'
|
} from '@taiga-ui/core'
|
||||||
import { filter, takeUntil } from 'rxjs'
|
import { filter, takeUntil } from 'rxjs'
|
||||||
import { ValueSpec } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { ERRORS } from '../form-group/form-group.component'
|
import { ERRORS } from '../form-group/form-group.component'
|
||||||
import { FORM_CONTROL_PROVIDERS } from './form-control.providers'
|
import { FORM_CONTROL_PROVIDERS } from './form-control.providers'
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ import { FORM_CONTROL_PROVIDERS } from './form-control.providers'
|
|||||||
providers: FORM_CONTROL_PROVIDERS,
|
providers: FORM_CONTROL_PROVIDERS,
|
||||||
})
|
})
|
||||||
export class FormControlComponent<
|
export class FormControlComponent<
|
||||||
T extends ValueSpec,
|
T extends CT.ValueSpec,
|
||||||
V,
|
V,
|
||||||
> extends AbstractTuiNullableControl<V> {
|
> extends AbstractTuiNullableControl<V> {
|
||||||
@Input({ required: true })
|
@Input({ required: true })
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { forwardRef, Provider } from '@angular/core'
|
import { forwardRef, Provider } from '@angular/core'
|
||||||
import { TUI_VALIDATION_ERRORS } from '@taiga-ui/kit'
|
import { TUI_VALIDATION_ERRORS } from '@taiga-ui/kit'
|
||||||
import { ValueSpec } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { FormControlComponent } from './form-control.component'
|
import { FormControlComponent } from './form-control.component'
|
||||||
|
|
||||||
interface ValidatorsPatternError {
|
interface ValidatorsPatternError {
|
||||||
@@ -12,7 +12,7 @@ export const FORM_CONTROL_PROVIDERS: Provider[] = [
|
|||||||
{
|
{
|
||||||
provide: TUI_VALIDATION_ERRORS,
|
provide: TUI_VALIDATION_ERRORS,
|
||||||
deps: [forwardRef(() => FormControlComponent)],
|
deps: [forwardRef(() => FormControlComponent)],
|
||||||
useFactory: (control: FormControlComponent<ValueSpec, string>) => ({
|
useFactory: (control: FormControlComponent<CT.ValueSpec, string>) => ({
|
||||||
required: 'Required',
|
required: 'Required',
|
||||||
pattern: ({ requiredPattern }: ValidatorsPatternError) =>
|
pattern: ({ requiredPattern }: ValidatorsPatternError) =>
|
||||||
('patterns' in control.spec &&
|
('patterns' in control.spec &&
|
||||||
|
|||||||
@@ -6,14 +6,17 @@ import {
|
|||||||
tuiPure,
|
tuiPure,
|
||||||
TuiTime,
|
TuiTime,
|
||||||
} from '@taiga-ui/cdk'
|
} from '@taiga-ui/cdk'
|
||||||
import { ValueSpecDatetime } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { Control } from '../control'
|
import { Control } from '../control'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'form-datetime',
|
selector: 'form-datetime',
|
||||||
templateUrl: './form-datetime.component.html',
|
templateUrl: './form-datetime.component.html',
|
||||||
})
|
})
|
||||||
export class FormDatetimeComponent extends Control<ValueSpecDatetime, string> {
|
export class FormDatetimeComponent extends Control<
|
||||||
|
CT.ValueSpecDatetime,
|
||||||
|
string
|
||||||
|
> {
|
||||||
readonly min = TUI_FIRST_DAY
|
readonly min = TUI_FIRST_DAY
|
||||||
readonly max = TUI_LAST_DAY
|
readonly max = TUI_LAST_DAY
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { TuiFileLike } from '@taiga-ui/kit'
|
import { TuiFileLike } from '@taiga-ui/kit'
|
||||||
import { ValueSpecFile } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { Control } from '../control'
|
import { Control } from '../control'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -8,4 +8,4 @@ import { Control } from '../control'
|
|||||||
templateUrl: './form-file.component.html',
|
templateUrl: './form-file.component.html',
|
||||||
styleUrls: ['./form-file.component.scss'],
|
styleUrls: ['./form-file.component.scss'],
|
||||||
})
|
})
|
||||||
export class FormFileComponent extends Control<ValueSpecFile, TuiFileLike> {}
|
export class FormFileComponent extends Control<CT.ValueSpecFile, TuiFileLike> {}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
ViewEncapsulation,
|
ViewEncapsulation,
|
||||||
} from '@angular/core'
|
} from '@angular/core'
|
||||||
import { InputSpec } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { FORM_GROUP_PROVIDERS } from './form-group.providers'
|
import { FORM_GROUP_PROVIDERS } from './form-group.providers'
|
||||||
|
|
||||||
export const ERRORS = [
|
export const ERRORS = [
|
||||||
@@ -27,7 +27,7 @@ export const ERRORS = [
|
|||||||
viewProviders: [FORM_GROUP_PROVIDERS],
|
viewProviders: [FORM_GROUP_PROVIDERS],
|
||||||
})
|
})
|
||||||
export class FormGroupComponent {
|
export class FormGroupComponent {
|
||||||
@Input() spec: InputSpec = {}
|
@Input() spec: CT.InputSpec = {}
|
||||||
|
|
||||||
asIsOrder() {
|
asIsOrder() {
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { ValueSpecMultiselect } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { Control } from '../control'
|
import { Control } from '../control'
|
||||||
import { tuiPure } from '@taiga-ui/cdk'
|
import { tuiPure } from '@taiga-ui/cdk'
|
||||||
import { invert } from '@start9labs/shared'
|
import { invert } from '@start9labs/shared'
|
||||||
@@ -9,7 +9,7 @@ import { invert } from '@start9labs/shared'
|
|||||||
templateUrl: './form-multiselect.component.html',
|
templateUrl: './form-multiselect.component.html',
|
||||||
})
|
})
|
||||||
export class FormMultiselectComponent extends Control<
|
export class FormMultiselectComponent extends Control<
|
||||||
ValueSpecMultiselect,
|
CT.ValueSpecMultiselect,
|
||||||
readonly string[]
|
readonly string[]
|
||||||
> {
|
> {
|
||||||
private readonly inverted = invert(this.spec.values)
|
private readonly inverted = invert(this.spec.values)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { ValueSpecNumber } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { Control } from '../control'
|
import { Control } from '../control'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'form-number',
|
selector: 'form-number',
|
||||||
templateUrl: './form-number.component.html',
|
templateUrl: './form-number.component.html',
|
||||||
})
|
})
|
||||||
export class FormNumberComponent extends Control<ValueSpecNumber, number> {
|
export class FormNumberComponent extends Control<CT.ValueSpecNumber, number> {
|
||||||
protected readonly Infinity = Infinity
|
protected readonly Infinity = Infinity
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
Output,
|
Output,
|
||||||
} from '@angular/core'
|
} from '@angular/core'
|
||||||
import { ControlContainer } from '@angular/forms'
|
import { ControlContainer } from '@angular/forms'
|
||||||
import { ValueSpecObject } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'form-object',
|
selector: 'form-object',
|
||||||
@@ -17,7 +17,7 @@ import { ValueSpecObject } from '@start9labs/start-sdk/cjs/sdk/lib/config/config
|
|||||||
})
|
})
|
||||||
export class FormObjectComponent {
|
export class FormObjectComponent {
|
||||||
@Input({ required: true })
|
@Input({ required: true })
|
||||||
spec!: ValueSpecObject
|
spec!: CT.ValueSpecObject
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
open = false
|
open = false
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { ValueSpecSelect } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { invert } from '@start9labs/shared'
|
import { invert } from '@start9labs/shared'
|
||||||
import { Control } from '../control'
|
import { Control } from '../control'
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ import { Control } from '../control'
|
|||||||
selector: 'form-select',
|
selector: 'form-select',
|
||||||
templateUrl: './form-select.component.html',
|
templateUrl: './form-select.component.html',
|
||||||
})
|
})
|
||||||
export class FormSelectComponent extends Control<ValueSpecSelect, string> {
|
export class FormSelectComponent extends Control<CT.ValueSpecSelect, string> {
|
||||||
private readonly inverted = invert(this.spec.values)
|
private readonly inverted = invert(this.spec.values)
|
||||||
|
|
||||||
readonly items = Object.values(this.spec.values)
|
readonly items = Object.values(this.spec.values)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { ValueSpecText } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { Control } from '../control'
|
import { Control } from '../control'
|
||||||
import { getDefaultString } from 'src/app/util/config-utilities'
|
import { getDefaultString } from 'src/app/util/config-utilities'
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ import { getDefaultString } from 'src/app/util/config-utilities'
|
|||||||
templateUrl: './form-text.component.html',
|
templateUrl: './form-text.component.html',
|
||||||
styleUrls: ['./form-text.component.scss'],
|
styleUrls: ['./form-text.component.scss'],
|
||||||
})
|
})
|
||||||
export class FormTextComponent extends Control<ValueSpecText, string> {
|
export class FormTextComponent extends Control<CT.ValueSpecText, string> {
|
||||||
masked = true
|
masked = true
|
||||||
|
|
||||||
generate() {
|
generate() {
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { ValueSpecTextarea } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { Control } from '../control'
|
import { Control } from '../control'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'form-textarea',
|
selector: 'form-textarea',
|
||||||
templateUrl: './form-textarea.component.html',
|
templateUrl: './form-textarea.component.html',
|
||||||
})
|
})
|
||||||
export class FormTextareaComponent extends Control<ValueSpecTextarea, string> {}
|
export class FormTextareaComponent extends Control<
|
||||||
|
CT.ValueSpecTextarea,
|
||||||
|
string
|
||||||
|
> {}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { ValueSpecToggle } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { Control } from '../control'
|
import { Control } from '../control'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -7,4 +7,4 @@ import { Control } from '../control'
|
|||||||
templateUrl: './form-toggle.component.html',
|
templateUrl: './form-toggle.component.html',
|
||||||
host: { class: 'g-toggle' },
|
host: { class: 'g-toggle' },
|
||||||
})
|
})
|
||||||
export class FormToggleComponent extends Control<ValueSpecToggle, boolean> {}
|
export class FormToggleComponent extends Control<CT.ValueSpecToggle, boolean> {}
|
||||||
|
|||||||
@@ -6,12 +6,7 @@ import {
|
|||||||
OnChanges,
|
OnChanges,
|
||||||
} from '@angular/core'
|
} from '@angular/core'
|
||||||
import { ControlContainer, FormGroupName } from '@angular/forms'
|
import { ControlContainer, FormGroupName } from '@angular/forms'
|
||||||
import {
|
import { CT } from '@start9labs/start-sdk'
|
||||||
unionSelectKey,
|
|
||||||
unionValueKey,
|
|
||||||
ValueSpecSelect,
|
|
||||||
ValueSpecUnion,
|
|
||||||
} from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
|
||||||
import { FormService } from 'src/app/services/form.service'
|
import { FormService } from 'src/app/services/form.service'
|
||||||
import { tuiPure } from '@taiga-ui/cdk'
|
import { tuiPure } from '@taiga-ui/cdk'
|
||||||
|
|
||||||
@@ -29,24 +24,24 @@ import { tuiPure } from '@taiga-ui/cdk'
|
|||||||
})
|
})
|
||||||
export class FormUnionComponent implements OnChanges {
|
export class FormUnionComponent implements OnChanges {
|
||||||
@Input({ required: true })
|
@Input({ required: true })
|
||||||
spec!: ValueSpecUnion
|
spec!: CT.ValueSpecUnion
|
||||||
|
|
||||||
selectSpec!: ValueSpecSelect
|
selectSpec!: CT.ValueSpecSelect
|
||||||
|
|
||||||
readonly select = unionSelectKey
|
readonly select = CT.unionSelectKey
|
||||||
readonly value = unionValueKey
|
readonly value = CT.unionValueKey
|
||||||
|
|
||||||
private readonly form = inject(FormGroupName)
|
private readonly form = inject(FormGroupName)
|
||||||
private readonly formService = inject(FormService)
|
private readonly formService = inject(FormService)
|
||||||
|
|
||||||
get union(): string {
|
get union(): string {
|
||||||
return this.form.value[unionSelectKey]
|
return this.form.value[CT.unionSelectKey]
|
||||||
}
|
}
|
||||||
|
|
||||||
@tuiPure
|
@tuiPure
|
||||||
onUnion(union: string) {
|
onUnion(union: string) {
|
||||||
this.form.control.setControl(
|
this.form.control.setControl(
|
||||||
unionValueKey,
|
CT.unionValueKey,
|
||||||
this.formService.getFormGroup(
|
this.formService.getFormGroup(
|
||||||
union ? this.spec.variants[union].spec : {},
|
union ? this.spec.variants[union].spec : {},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Pipe, PipeTransform } from '@angular/core'
|
import { Pipe, PipeTransform } from '@angular/core'
|
||||||
import { ValueSpec } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
|
|
||||||
@Pipe({
|
@Pipe({
|
||||||
name: 'hint',
|
name: 'hint',
|
||||||
})
|
})
|
||||||
export class HintPipe implements PipeTransform {
|
export class HintPipe implements PipeTransform {
|
||||||
transform(spec: ValueSpec): string {
|
transform(spec: CT.ValueSpec): string {
|
||||||
const hint = []
|
const hint = []
|
||||||
|
|
||||||
if (spec.description) {
|
if (spec.description) {
|
||||||
|
|||||||
@@ -19,11 +19,8 @@ import {
|
|||||||
} from '@start9labs/marketplace'
|
} from '@start9labs/marketplace'
|
||||||
import { Log } from '@start9labs/shared'
|
import { Log } from '@start9labs/shared'
|
||||||
import { configBuilderToSpec } from 'src/app/util/configBuilderToSpec'
|
import { configBuilderToSpec } from 'src/app/util/configBuilderToSpec'
|
||||||
import { Config } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/config'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { Value } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/value'
|
import { CB } from '@start9labs/start-sdk'
|
||||||
import { Variants } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/variants'
|
|
||||||
import { List } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/list'
|
|
||||||
import { unionSelectKey } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
|
||||||
|
|
||||||
export module Mock {
|
export module Mock {
|
||||||
export const ServerUpdated: ServerStatusInfo = {
|
export const ServerUpdated: ServerStatusInfo = {
|
||||||
@@ -715,27 +712,27 @@ export module Mock {
|
|||||||
RR.GetPackageConfigRes['spec']
|
RR.GetPackageConfigRes['spec']
|
||||||
> =>
|
> =>
|
||||||
configBuilderToSpec(
|
configBuilderToSpec(
|
||||||
Config.of({
|
CB.Config.of({
|
||||||
bitcoin: Value.object(
|
bitcoin: CB.Value.object(
|
||||||
{
|
{
|
||||||
name: 'Bitcoin Settings',
|
name: 'Bitcoin Settings',
|
||||||
description:
|
description:
|
||||||
'RPC and P2P interface configuration options for Bitcoin Core',
|
'RPC and P2P interface configuration options for Bitcoin Core',
|
||||||
},
|
},
|
||||||
Config.of({
|
CB.Config.of({
|
||||||
'bitcoind-p2p': Value.union(
|
'bitcoind-p2p': CB.Value.union(
|
||||||
{
|
{
|
||||||
name: 'P2P Settings',
|
name: 'P2P Settings',
|
||||||
description:
|
description:
|
||||||
'<p>The Bitcoin Core node to connect to over the peer-to-peer (P2P) interface:</p><ul><li><strong>Bitcoin Core</strong>: The Bitcoin Core service installed on this device</li><li><strong>External Node</strong>: A Bitcoin node running on a different device</li></ul>',
|
'<p>The Bitcoin Core node to connect to over the peer-to-peer (P2P) interface:</p><ul><li><strong>Bitcoin Core</strong>: The Bitcoin Core service installed on this device</li><li><strong>External Node</strong>: A Bitcoin node running on a different device</li></ul>',
|
||||||
required: { default: 'internal' },
|
required: { default: 'internal' },
|
||||||
},
|
},
|
||||||
Variants.of({
|
CB.Variants.of({
|
||||||
internal: { name: 'Bitcoin Core', spec: Config.of({}) },
|
internal: { name: 'Bitcoin Core', spec: CB.Config.of({}) },
|
||||||
external: {
|
external: {
|
||||||
name: 'External Node',
|
name: 'External Node',
|
||||||
spec: Config.of({
|
spec: CB.Config.of({
|
||||||
'p2p-host': Value.text({
|
'p2p-host': CB.Value.text({
|
||||||
name: 'Public Address',
|
name: 'Public Address',
|
||||||
required: {
|
required: {
|
||||||
default: null,
|
default: null,
|
||||||
@@ -743,7 +740,7 @@ export module Mock {
|
|||||||
description:
|
description:
|
||||||
'The public address of your Bitcoin Core server',
|
'The public address of your Bitcoin Core server',
|
||||||
}),
|
}),
|
||||||
'p2p-port': Value.number({
|
'p2p-port': CB.Value.number({
|
||||||
name: 'P2P Port',
|
name: 'P2P Port',
|
||||||
description:
|
description:
|
||||||
'The port that your Bitcoin Core P2P server is bound to',
|
'The port that your Bitcoin Core P2P server is bound to',
|
||||||
@@ -760,7 +757,7 @@ export module Mock {
|
|||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
users: Value.multiselect({
|
users: CB.Value.multiselect({
|
||||||
name: 'Users',
|
name: 'Users',
|
||||||
default: [],
|
default: [],
|
||||||
maxLength: 2,
|
maxLength: 2,
|
||||||
@@ -772,21 +769,21 @@ export module Mock {
|
|||||||
lucy: 'Lucy',
|
lucy: 'Lucy',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
advanced: Value.object(
|
advanced: CB.Value.object(
|
||||||
{
|
{
|
||||||
name: 'Advanced',
|
name: 'Advanced',
|
||||||
description: 'Advanced settings',
|
description: 'Advanced settings',
|
||||||
},
|
},
|
||||||
Config.of({
|
CB.Config.of({
|
||||||
rpcsettings: Value.object(
|
rpcsettings: CB.Value.object(
|
||||||
{
|
{
|
||||||
name: 'RPC Settings',
|
name: 'RPC Settings',
|
||||||
description: 'rpc username and password',
|
description: 'rpc username and password',
|
||||||
warning:
|
warning:
|
||||||
'Adding RPC users gives them special permissions on your node.',
|
'Adding RPC users gives them special permissions on your node.',
|
||||||
},
|
},
|
||||||
Config.of({
|
CB.Config.of({
|
||||||
rpcuser2: Value.text({
|
rpcuser2: CB.Value.text({
|
||||||
name: 'RPC Username',
|
name: 'RPC Username',
|
||||||
required: {
|
required: {
|
||||||
default: 'defaultrpcusername',
|
default: 'defaultrpcusername',
|
||||||
@@ -799,7 +796,7 @@ export module Mock {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
rpcuser: Value.text({
|
rpcuser: CB.Value.text({
|
||||||
name: 'RPC Username',
|
name: 'RPC Username',
|
||||||
required: {
|
required: {
|
||||||
default: 'defaultrpcusername',
|
default: 'defaultrpcusername',
|
||||||
@@ -812,7 +809,7 @@ export module Mock {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
rpcpass: Value.text({
|
rpcpass: CB.Value.text({
|
||||||
name: 'RPC User Password',
|
name: 'RPC User Password',
|
||||||
required: {
|
required: {
|
||||||
default: {
|
default: {
|
||||||
@@ -822,7 +819,7 @@ export module Mock {
|
|||||||
},
|
},
|
||||||
description: 'rpc password',
|
description: 'rpc password',
|
||||||
}),
|
}),
|
||||||
rpcpass2: Value.text({
|
rpcpass2: CB.Value.text({
|
||||||
name: 'RPC User Password',
|
name: 'RPC User Password',
|
||||||
required: {
|
required: {
|
||||||
default: {
|
default: {
|
||||||
@@ -836,15 +833,15 @@ export module Mock {
|
|||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
testnet: Value.toggle({
|
testnet: CB.Value.toggle({
|
||||||
name: 'Testnet',
|
name: 'Testnet',
|
||||||
default: true,
|
default: true,
|
||||||
description:
|
description:
|
||||||
'<ul><li>determines whether your node is running on testnet or mainnet</li></ul><script src="fake"></script>',
|
'<ul><li>determines whether your node is running on testnet or mainnet</li></ul><script src="fake"></script>',
|
||||||
warning: 'Chain will have to resync!',
|
warning: 'Chain will have to resync!',
|
||||||
}),
|
}),
|
||||||
'object-list': Value.list(
|
'object-list': CB.Value.list(
|
||||||
List.obj(
|
CB.List.obj(
|
||||||
{
|
{
|
||||||
name: 'Object List',
|
name: 'Object List',
|
||||||
minLength: 0,
|
minLength: 0,
|
||||||
@@ -856,13 +853,13 @@ export module Mock {
|
|||||||
description: 'This is a list of objects, like users or something',
|
description: 'This is a list of objects, like users or something',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
spec: Config.of({
|
spec: CB.Config.of({
|
||||||
'first-name': Value.text({
|
'first-name': CB.Value.text({
|
||||||
name: 'First Name',
|
name: 'First Name',
|
||||||
required: false,
|
required: false,
|
||||||
description: 'User first name',
|
description: 'User first name',
|
||||||
}),
|
}),
|
||||||
'last-name': Value.text({
|
'last-name': CB.Value.text({
|
||||||
name: 'Last Name',
|
name: 'Last Name',
|
||||||
required: {
|
required: {
|
||||||
default: {
|
default: {
|
||||||
@@ -878,7 +875,7 @@ export module Mock {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
age: Value.number({
|
age: CB.Value.number({
|
||||||
name: 'Age',
|
name: 'Age',
|
||||||
description: 'The age of the user',
|
description: 'The age of the user',
|
||||||
warning: 'User must be at least 18.',
|
warning: 'User must be at least 18.',
|
||||||
@@ -887,13 +884,13 @@ export module Mock {
|
|||||||
integer: false,
|
integer: false,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
displayAs: "I'm {{last-name}}, {{first-name}} {{last-name}}",
|
displayAs: 'I\'m {{last-name}}, {{first-name}} {{last-name}}',
|
||||||
uniqueBy: 'last-name',
|
uniqueBy: 'last-name',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'union-list': Value.list(
|
'union-list': CB.Value.list(
|
||||||
List.obj(
|
CB.List.obj(
|
||||||
{
|
{
|
||||||
name: 'Union List',
|
name: 'Union List',
|
||||||
minLength: 0,
|
minLength: 0,
|
||||||
@@ -903,27 +900,27 @@ export module Mock {
|
|||||||
warning: 'If you change this, things may work.',
|
warning: 'If you change this, things may work.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
spec: Config.of({
|
spec: CB.Config.of({
|
||||||
/* TODO: Convert range for this value ([0, 2])*/
|
/* TODO: Convert range for this value ([0, 2])*/
|
||||||
union: Value.union(
|
union: CB.Value.union(
|
||||||
{
|
{
|
||||||
name: 'Preference',
|
name: 'Preference',
|
||||||
description: null,
|
description: null,
|
||||||
warning: null,
|
warning: null,
|
||||||
required: { default: 'summer' },
|
required: { default: 'summer' },
|
||||||
},
|
},
|
||||||
Variants.of({
|
CB.Variants.of({
|
||||||
summer: {
|
summer: {
|
||||||
name: 'summer',
|
name: 'summer',
|
||||||
spec: Config.of({
|
spec: CB.Config.of({
|
||||||
'favorite-tree': Value.text({
|
'favorite-tree': CB.Value.text({
|
||||||
name: 'Favorite Tree',
|
name: 'Favorite Tree',
|
||||||
required: {
|
required: {
|
||||||
default: 'Maple',
|
default: 'Maple',
|
||||||
},
|
},
|
||||||
description: 'What is your favorite tree?',
|
description: 'What is your favorite tree?',
|
||||||
}),
|
}),
|
||||||
'favorite-flower': Value.select({
|
'favorite-flower': CB.Value.select({
|
||||||
name: 'Favorite Flower',
|
name: 'Favorite Flower',
|
||||||
description: 'Select your favorite flower',
|
description: 'Select your favorite flower',
|
||||||
required: {
|
required: {
|
||||||
@@ -940,8 +937,8 @@ export module Mock {
|
|||||||
},
|
},
|
||||||
winter: {
|
winter: {
|
||||||
name: 'winter',
|
name: 'winter',
|
||||||
spec: Config.of({
|
spec: CB.Config.of({
|
||||||
'like-snow': Value.toggle({
|
'like-snow': CB.Value.toggle({
|
||||||
name: 'Like Snow?',
|
name: 'Like Snow?',
|
||||||
default: true,
|
default: true,
|
||||||
description: 'Do you like snow or not?',
|
description: 'Do you like snow or not?',
|
||||||
@@ -955,7 +952,7 @@ export module Mock {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'random-select': Value.select({
|
'random-select': CB.Value.select({
|
||||||
name: 'Random select',
|
name: 'Random select',
|
||||||
description: 'This is not even real.',
|
description: 'This is not even real.',
|
||||||
warning: 'Be careful changing this!',
|
warning: 'Be careful changing this!',
|
||||||
@@ -970,7 +967,7 @@ export module Mock {
|
|||||||
disabled: ['option2'],
|
disabled: ['option2'],
|
||||||
}),
|
}),
|
||||||
'favorite-number':
|
'favorite-number':
|
||||||
/* TODO: Convert range for this value ((-100,100])*/ Value.number({
|
/* TODO: Convert range for this value ((-100,100])*/ CB.Value.number({
|
||||||
name: 'Favorite Number',
|
name: 'Favorite Number',
|
||||||
description: 'Your favorite number of all time',
|
description: 'Your favorite number of all time',
|
||||||
warning:
|
warning:
|
||||||
@@ -981,8 +978,8 @@ export module Mock {
|
|||||||
integer: false,
|
integer: false,
|
||||||
units: 'BTC',
|
units: 'BTC',
|
||||||
}),
|
}),
|
||||||
'unlucky-numbers': Value.list(
|
'unlucky-numbers': CB.Value.list(
|
||||||
List.number(
|
CB.List.number(
|
||||||
{
|
{
|
||||||
name: 'Unlucky Numbers',
|
name: 'Unlucky Numbers',
|
||||||
minLength: 0,
|
minLength: 0,
|
||||||
@@ -996,34 +993,34 @@ export module Mock {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
rpcsettings: Value.object(
|
rpcsettings: CB.Value.object(
|
||||||
{
|
{
|
||||||
name: 'RPC Settings',
|
name: 'RPC Settings',
|
||||||
description: 'rpc username and password',
|
description: 'rpc username and password',
|
||||||
warning:
|
warning:
|
||||||
'Adding RPC users gives them special permissions on your node.',
|
'Adding RPC users gives them special permissions on your node.',
|
||||||
},
|
},
|
||||||
Config.of({
|
CB.Config.of({
|
||||||
laws: Value.object(
|
laws: CB.Value.object(
|
||||||
{
|
{
|
||||||
name: 'Laws',
|
name: 'Laws',
|
||||||
description: 'the law of the realm',
|
description: 'the law of the realm',
|
||||||
},
|
},
|
||||||
Config.of({
|
CB.Config.of({
|
||||||
law1: Value.text({
|
law1: CB.Value.text({
|
||||||
name: 'First Law',
|
name: 'First Law',
|
||||||
required: false,
|
required: false,
|
||||||
description: 'the first law',
|
description: 'the first law',
|
||||||
}),
|
}),
|
||||||
law2: Value.text({
|
law2: CB.Value.text({
|
||||||
name: 'Second Law',
|
name: 'Second Law',
|
||||||
required: false,
|
required: false,
|
||||||
description: 'the second law',
|
description: 'the second law',
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
rulemakers: Value.list(
|
rulemakers: CB.Value.list(
|
||||||
List.obj(
|
CB.List.obj(
|
||||||
{
|
{
|
||||||
name: 'Rule Makers',
|
name: 'Rule Makers',
|
||||||
minLength: 0,
|
minLength: 0,
|
||||||
@@ -1031,8 +1028,8 @@ export module Mock {
|
|||||||
description: 'the people who make the rules',
|
description: 'the people who make the rules',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
spec: Config.of({
|
spec: CB.Config.of({
|
||||||
rulemakername: Value.text({
|
rulemakername: CB.Value.text({
|
||||||
name: 'Rulemaker Name',
|
name: 'Rulemaker Name',
|
||||||
required: {
|
required: {
|
||||||
default: {
|
default: {
|
||||||
@@ -1042,7 +1039,7 @@ export module Mock {
|
|||||||
},
|
},
|
||||||
description: 'the name of the rule maker',
|
description: 'the name of the rule maker',
|
||||||
}),
|
}),
|
||||||
rulemakerip: Value.text({
|
rulemakerip: CB.Value.text({
|
||||||
name: 'Rulemaker IP',
|
name: 'Rulemaker IP',
|
||||||
required: {
|
required: {
|
||||||
default: '192.168.1.0',
|
default: '192.168.1.0',
|
||||||
@@ -1060,7 +1057,7 @@ export module Mock {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
rpcuser: Value.text({
|
rpcuser: CB.Value.text({
|
||||||
name: 'RPC Username',
|
name: 'RPC Username',
|
||||||
required: {
|
required: {
|
||||||
default: 'defaultrpcusername',
|
default: 'defaultrpcusername',
|
||||||
@@ -1073,7 +1070,7 @@ export module Mock {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
rpcpass: Value.text({
|
rpcpass: CB.Value.text({
|
||||||
name: 'RPC User Password',
|
name: 'RPC User Password',
|
||||||
required: {
|
required: {
|
||||||
default: {
|
default: {
|
||||||
@@ -1086,7 +1083,7 @@ export module Mock {
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
'bitcoin-node': Value.union(
|
'bitcoin-node': CB.Value.union(
|
||||||
{
|
{
|
||||||
name: 'Bitcoin Node',
|
name: 'Bitcoin Node',
|
||||||
description: 'Options<ul><li>Item 1</li><li>Item 2</li></ul>',
|
description: 'Options<ul><li>Item 1</li><li>Item 2</li></ul>',
|
||||||
@@ -1094,25 +1091,25 @@ export module Mock {
|
|||||||
required: { default: 'internal' },
|
required: { default: 'internal' },
|
||||||
disabled: ['fake'],
|
disabled: ['fake'],
|
||||||
},
|
},
|
||||||
Variants.of({
|
CB.Variants.of({
|
||||||
fake: {
|
fake: {
|
||||||
name: 'Fake',
|
name: 'Fake',
|
||||||
spec: Config.of({}),
|
spec: CB.Config.of({}),
|
||||||
},
|
},
|
||||||
internal: {
|
internal: {
|
||||||
name: 'Internal',
|
name: 'Internal',
|
||||||
spec: Config.of({}),
|
spec: CB.Config.of({}),
|
||||||
},
|
},
|
||||||
external: {
|
external: {
|
||||||
name: 'External',
|
name: 'External',
|
||||||
spec: Config.of({
|
spec: CB.Config.of({
|
||||||
'emergency-contact': Value.object(
|
'emergency-contact': CB.Value.object(
|
||||||
{
|
{
|
||||||
name: 'Emergency Contact',
|
name: 'Emergency Contact',
|
||||||
description: 'The person to contact in case of emergency.',
|
description: 'The person to contact in case of emergency.',
|
||||||
},
|
},
|
||||||
Config.of({
|
CB.Config.of({
|
||||||
name: Value.text({
|
name: CB.Value.text({
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
required: {
|
required: {
|
||||||
default: null,
|
default: null,
|
||||||
@@ -1124,7 +1121,7 @@ export module Mock {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
email: Value.text({
|
email: CB.Value.text({
|
||||||
name: 'Email',
|
name: 'Email',
|
||||||
inputmode: 'email',
|
inputmode: 'email',
|
||||||
required: {
|
required: {
|
||||||
@@ -1133,7 +1130,7 @@ export module Mock {
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
'public-domain': Value.text({
|
'public-domain': CB.Value.text({
|
||||||
name: 'Public Domain',
|
name: 'Public Domain',
|
||||||
required: {
|
required: {
|
||||||
default: 'bitcoinnode.com',
|
default: 'bitcoinnode.com',
|
||||||
@@ -1146,7 +1143,7 @@ export module Mock {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
'private-domain': Value.text({
|
'private-domain': CB.Value.text({
|
||||||
name: 'Private Domain',
|
name: 'Private Domain',
|
||||||
required: {
|
required: {
|
||||||
default: null,
|
default: null,
|
||||||
@@ -1159,7 +1156,7 @@ export module Mock {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
port: Value.number({
|
port: CB.Value.number({
|
||||||
name: 'Port',
|
name: 'Port',
|
||||||
description:
|
description:
|
||||||
'the default port for your Bitcoin node. default: 8333, testnet: 18333, regtest: 18444',
|
'the default port for your Bitcoin node. default: 8333, testnet: 18333, regtest: 18444',
|
||||||
@@ -1171,7 +1168,7 @@ export module Mock {
|
|||||||
step: 1,
|
step: 1,
|
||||||
integer: true,
|
integer: true,
|
||||||
}),
|
}),
|
||||||
'favorite-slogan': Value.text({
|
'favorite-slogan': CB.Value.text({
|
||||||
name: 'Favorite Slogan',
|
name: 'Favorite Slogan',
|
||||||
generate: {
|
generate: {
|
||||||
charset: 'a-z,A-Z,2-9',
|
charset: 'a-z,A-Z,2-9',
|
||||||
@@ -1182,8 +1179,8 @@ export module Mock {
|
|||||||
'You most favorite slogan in the whole world, used for paying you.',
|
'You most favorite slogan in the whole world, used for paying you.',
|
||||||
masked: true,
|
masked: true,
|
||||||
}),
|
}),
|
||||||
rpcallowip: Value.list(
|
rpcallowip: CB.Value.list(
|
||||||
List.text(
|
CB.List.text(
|
||||||
{
|
{
|
||||||
name: 'RPC Allowed IPs',
|
name: 'RPC Allowed IPs',
|
||||||
minLength: 1,
|
minLength: 1,
|
||||||
@@ -1205,8 +1202,8 @@ export module Mock {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
rpcauth: Value.list(
|
rpcauth: CB.Value.list(
|
||||||
List.text(
|
CB.List.text(
|
||||||
{
|
{
|
||||||
name: 'RPC Auth',
|
name: 'RPC Auth',
|
||||||
description:
|
description:
|
||||||
@@ -1251,7 +1248,7 @@ export module Mock {
|
|||||||
rulemakers: [],
|
rulemakers: [],
|
||||||
},
|
},
|
||||||
'bitcoin-node': {
|
'bitcoin-node': {
|
||||||
[unionSelectKey]: 'internal',
|
[CT.unionSelectKey]: 'internal',
|
||||||
},
|
},
|
||||||
port: 20,
|
port: 20,
|
||||||
rpcallowip: undefined,
|
rpcallowip: undefined,
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import {
|
|||||||
FollowLogsRes,
|
FollowLogsRes,
|
||||||
FollowLogsReq,
|
FollowLogsReq,
|
||||||
} from '@start9labs/shared'
|
} from '@start9labs/shared'
|
||||||
import { customSmtp } from '@start9labs/start-sdk/cjs/sdk/lib/config/configConstants'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
import { InputSpec } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { config } from '@start9labs/start-sdk'
|
||||||
|
|
||||||
export module RR {
|
export module RR {
|
||||||
// DB
|
// DB
|
||||||
@@ -205,7 +205,8 @@ export module RR {
|
|||||||
|
|
||||||
// email
|
// email
|
||||||
|
|
||||||
export type ConfigureEmailReq = typeof customSmtp.validator._TYPE // email.configure
|
export type ConfigureEmailReq =
|
||||||
|
typeof config.constants.customSmtp.validator._TYPE // email.configure
|
||||||
export type ConfigureEmailRes = null
|
export type ConfigureEmailRes = null
|
||||||
|
|
||||||
export type TestEmailReq = ConfigureEmailReq & { to: string } // email.test
|
export type TestEmailReq = ConfigureEmailReq & { to: string } // email.test
|
||||||
@@ -319,7 +320,7 @@ export module RR {
|
|||||||
export type InstallPackageRes = null
|
export type InstallPackageRes = null
|
||||||
|
|
||||||
export type GetPackageConfigReq = { id: string } // package.config.get
|
export type GetPackageConfigReq = { id: string } // package.config.get
|
||||||
export type GetPackageConfigRes = { spec: InputSpec; config: object }
|
export type GetPackageConfigRes = { spec: CT.InputSpec; config: object }
|
||||||
|
|
||||||
export type DrySetPackageConfigReq = { id: string; config: object } // package.config.set.dry
|
export type DrySetPackageConfigReq = { id: string; config: object } // package.config.set.dry
|
||||||
export type DrySetPackageConfigRes = Breakages
|
export type DrySetPackageConfigRes = Breakages
|
||||||
@@ -361,7 +362,7 @@ export module RR {
|
|||||||
export type DryConfigureDependencyRes = {
|
export type DryConfigureDependencyRes = {
|
||||||
oldConfig: object
|
oldConfig: object
|
||||||
newConfig: object
|
newConfig: object
|
||||||
spec: InputSpec
|
spec: CT.InputSpec
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SideloadPackageReq = {
|
export type SideloadPackageReq = {
|
||||||
|
|||||||
@@ -8,29 +8,7 @@ import {
|
|||||||
Validators,
|
Validators,
|
||||||
} from '@angular/forms'
|
} from '@angular/forms'
|
||||||
import { getDefaultString } from '../util/config-utilities'
|
import { getDefaultString } from '../util/config-utilities'
|
||||||
import {
|
import { CT } from '@start9labs/start-sdk'
|
||||||
InputSpec,
|
|
||||||
ListValueSpecNumber,
|
|
||||||
ListValueSpecObject,
|
|
||||||
ListValueSpecOf,
|
|
||||||
ListValueSpecText,
|
|
||||||
UniqueBy,
|
|
||||||
ValueSpec,
|
|
||||||
ValueSpecSelect,
|
|
||||||
ValueSpecMultiselect,
|
|
||||||
ValueSpecFile,
|
|
||||||
ValueSpecList,
|
|
||||||
ValueSpecNumber,
|
|
||||||
ValueSpecObject,
|
|
||||||
ValueSpecText,
|
|
||||||
ValueSpecUnion,
|
|
||||||
ValueSpecTextarea,
|
|
||||||
ValueSpecColor,
|
|
||||||
ValueSpecDatetime,
|
|
||||||
unionSelectKey,
|
|
||||||
unionValueKey,
|
|
||||||
isValueSpecListOf,
|
|
||||||
} from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
|
||||||
const Mustache = require('mustache')
|
const Mustache = require('mustache')
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
@@ -40,16 +18,16 @@ export class FormService {
|
|||||||
constructor(private readonly formBuilder: UntypedFormBuilder) {}
|
constructor(private readonly formBuilder: UntypedFormBuilder) {}
|
||||||
|
|
||||||
createForm(
|
createForm(
|
||||||
spec: InputSpec,
|
spec: CT.InputSpec,
|
||||||
current: Record<string, any> = {},
|
current: Record<string, any> = {},
|
||||||
): UntypedFormGroup {
|
): UntypedFormGroup {
|
||||||
return this.getFormGroup(spec, [], current)
|
return this.getFormGroup(spec, [], current)
|
||||||
}
|
}
|
||||||
|
|
||||||
getUnionSelectSpec(
|
getUnionSelectSpec(
|
||||||
spec: ValueSpecUnion,
|
spec: CT.ValueSpecUnion,
|
||||||
selection: string | null,
|
selection: string | null,
|
||||||
): ValueSpecSelect {
|
): CT.ValueSpecSelect {
|
||||||
return {
|
return {
|
||||||
...spec,
|
...spec,
|
||||||
type: 'select',
|
type: 'select',
|
||||||
@@ -61,34 +39,34 @@ export class FormService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getUnionObject(
|
getUnionObject(
|
||||||
spec: ValueSpecUnion,
|
spec: CT.ValueSpecUnion,
|
||||||
selection: string | null,
|
selection: string | null,
|
||||||
): UntypedFormGroup {
|
): UntypedFormGroup {
|
||||||
const group = this.getFormGroup({
|
const group = this.getFormGroup({
|
||||||
[unionSelectKey]: this.getUnionSelectSpec(spec, selection),
|
[CT.unionSelectKey]: this.getUnionSelectSpec(spec, selection),
|
||||||
})
|
})
|
||||||
|
|
||||||
group.setControl(
|
group.setControl(
|
||||||
unionValueKey,
|
CT.unionValueKey,
|
||||||
this.getFormGroup(selection ? spec.variants[selection].spec : {}),
|
this.getFormGroup(selection ? spec.variants[selection].spec : {}),
|
||||||
)
|
)
|
||||||
|
|
||||||
return group
|
return group
|
||||||
}
|
}
|
||||||
|
|
||||||
getListItem(spec: ValueSpecList, entry?: any) {
|
getListItem(spec: CT.ValueSpecList, entry?: any) {
|
||||||
const listItemValidators = getListItemValidators(spec)
|
const listItemValidators = getListItemValidators(spec)
|
||||||
if (isValueSpecListOf(spec, 'text')) {
|
if (CT.isValueSpecListOf(spec, 'text')) {
|
||||||
return this.formBuilder.control(entry, listItemValidators)
|
return this.formBuilder.control(entry, listItemValidators)
|
||||||
} else if (isValueSpecListOf(spec, 'number')) {
|
} else if (CT.isValueSpecListOf(spec, 'number')) {
|
||||||
return this.formBuilder.control(entry, listItemValidators)
|
return this.formBuilder.control(entry, listItemValidators)
|
||||||
} else if (isValueSpecListOf(spec, 'object')) {
|
} else if (CT.isValueSpecListOf(spec, 'object')) {
|
||||||
return this.getFormGroup(spec.spec.spec, listItemValidators, entry)
|
return this.getFormGroup(spec.spec.spec, listItemValidators, entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getFormGroup(
|
getFormGroup(
|
||||||
config: InputSpec,
|
config: CT.InputSpec,
|
||||||
validators: ValidatorFn[] = [],
|
validators: ValidatorFn[] = [],
|
||||||
current?: Record<string, any> | null,
|
current?: Record<string, any> | null,
|
||||||
): UntypedFormGroup {
|
): UntypedFormGroup {
|
||||||
@@ -103,7 +81,7 @@ export class FormService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getFormEntry(
|
private getFormEntry(
|
||||||
spec: ValueSpec,
|
spec: CT.ValueSpec,
|
||||||
currentValue?: any,
|
currentValue?: any,
|
||||||
): UntypedFormGroup | UntypedFormArray | UntypedFormControl {
|
): UntypedFormGroup | UntypedFormArray | UntypedFormControl {
|
||||||
let value: any
|
let value: any
|
||||||
@@ -154,7 +132,7 @@ export class FormService {
|
|||||||
fileValidators(spec),
|
fileValidators(spec),
|
||||||
)
|
)
|
||||||
case 'union':
|
case 'union':
|
||||||
const currentSelection = currentValue?.[unionSelectKey]
|
const currentSelection = currentValue?.[CT.unionSelectKey]
|
||||||
const isValid = !!spec.variants[currentSelection]
|
const isValid = !!spec.variants[currentSelection]
|
||||||
|
|
||||||
return this.getUnionObject(
|
return this.getUnionObject(
|
||||||
@@ -176,20 +154,20 @@ export class FormService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getListItemValidators(spec: ValueSpecList) {
|
function getListItemValidators(spec: CT.ValueSpecList) {
|
||||||
if (isValueSpecListOf(spec, 'text')) {
|
if (CT.isValueSpecListOf(spec, 'text')) {
|
||||||
return stringValidators(spec.spec)
|
return stringValidators(spec.spec)
|
||||||
} else if (isValueSpecListOf(spec, 'number')) {
|
} else if (CT.isValueSpecListOf(spec, 'number')) {
|
||||||
return numberValidators(spec.spec)
|
return numberValidators(spec.spec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function stringValidators(
|
function stringValidators(
|
||||||
spec: ValueSpecText | ListValueSpecText,
|
spec: CT.ValueSpecText | CT.ListValueSpecText,
|
||||||
): ValidatorFn[] {
|
): ValidatorFn[] {
|
||||||
const validators: ValidatorFn[] = []
|
const validators: ValidatorFn[] = []
|
||||||
|
|
||||||
if ((spec as ValueSpecText).required) {
|
if ((spec as CT.ValueSpecText).required) {
|
||||||
validators.push(Validators.required)
|
validators.push(Validators.required)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,7 +180,7 @@ function stringValidators(
|
|||||||
return validators
|
return validators
|
||||||
}
|
}
|
||||||
|
|
||||||
function textareaValidators(spec: ValueSpecTextarea): ValidatorFn[] {
|
function textareaValidators(spec: CT.ValueSpecTextarea): ValidatorFn[] {
|
||||||
const validators: ValidatorFn[] = []
|
const validators: ValidatorFn[] = []
|
||||||
|
|
||||||
if (spec.required) {
|
if (spec.required) {
|
||||||
@@ -214,7 +192,7 @@ function textareaValidators(spec: ValueSpecTextarea): ValidatorFn[] {
|
|||||||
return validators
|
return validators
|
||||||
}
|
}
|
||||||
|
|
||||||
function colorValidators({ required }: ValueSpecColor): ValidatorFn[] {
|
function colorValidators({ required }: CT.ValueSpecColor): ValidatorFn[] {
|
||||||
const validators: ValidatorFn[] = [Validators.pattern(/^#[0-9a-f]{6}$/i)]
|
const validators: ValidatorFn[] = [Validators.pattern(/^#[0-9a-f]{6}$/i)]
|
||||||
|
|
||||||
if (required) {
|
if (required) {
|
||||||
@@ -228,7 +206,7 @@ function datetimeValidators({
|
|||||||
required,
|
required,
|
||||||
min,
|
min,
|
||||||
max,
|
max,
|
||||||
}: ValueSpecDatetime): ValidatorFn[] {
|
}: CT.ValueSpecDatetime): ValidatorFn[] {
|
||||||
const validators: ValidatorFn[] = []
|
const validators: ValidatorFn[] = []
|
||||||
|
|
||||||
if (required) {
|
if (required) {
|
||||||
@@ -247,13 +225,13 @@ function datetimeValidators({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function numberValidators(
|
function numberValidators(
|
||||||
spec: ValueSpecNumber | ListValueSpecNumber,
|
spec: CT.ValueSpecNumber | CT.ListValueSpecNumber,
|
||||||
): ValidatorFn[] {
|
): ValidatorFn[] {
|
||||||
const validators: ValidatorFn[] = []
|
const validators: ValidatorFn[] = []
|
||||||
|
|
||||||
validators.push(isNumber())
|
validators.push(isNumber())
|
||||||
|
|
||||||
if ((spec as ValueSpecNumber).required) {
|
if ((spec as CT.ValueSpecNumber).required) {
|
||||||
validators.push(Validators.required)
|
validators.push(Validators.required)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,7 +244,7 @@ function numberValidators(
|
|||||||
return validators
|
return validators
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectValidators(spec: ValueSpecSelect): ValidatorFn[] {
|
function selectValidators(spec: CT.ValueSpecSelect): ValidatorFn[] {
|
||||||
const validators: ValidatorFn[] = []
|
const validators: ValidatorFn[] = []
|
||||||
|
|
||||||
if (spec.required) {
|
if (spec.required) {
|
||||||
@@ -276,20 +254,20 @@ function selectValidators(spec: ValueSpecSelect): ValidatorFn[] {
|
|||||||
return validators
|
return validators
|
||||||
}
|
}
|
||||||
|
|
||||||
function multiselectValidators(spec: ValueSpecMultiselect): ValidatorFn[] {
|
function multiselectValidators(spec: CT.ValueSpecMultiselect): ValidatorFn[] {
|
||||||
const validators: ValidatorFn[] = []
|
const validators: ValidatorFn[] = []
|
||||||
validators.push(listInRange(spec.minLength, spec.maxLength))
|
validators.push(listInRange(spec.minLength, spec.maxLength))
|
||||||
return validators
|
return validators
|
||||||
}
|
}
|
||||||
|
|
||||||
function listValidators(spec: ValueSpecList): ValidatorFn[] {
|
function listValidators(spec: CT.ValueSpecList): ValidatorFn[] {
|
||||||
const validators: ValidatorFn[] = []
|
const validators: ValidatorFn[] = []
|
||||||
validators.push(listInRange(spec.minLength, spec.maxLength))
|
validators.push(listInRange(spec.minLength, spec.maxLength))
|
||||||
validators.push(listItemIssue())
|
validators.push(listItemIssue())
|
||||||
return validators
|
return validators
|
||||||
}
|
}
|
||||||
|
|
||||||
function fileValidators(spec: ValueSpecFile): ValidatorFn[] {
|
function fileValidators(spec: CT.ValueSpecFile): ValidatorFn[] {
|
||||||
const validators: ValidatorFn[] = []
|
const validators: ValidatorFn[] = []
|
||||||
|
|
||||||
if (spec.required) {
|
if (spec.required) {
|
||||||
@@ -397,7 +375,7 @@ export function listItemIssue(): ValidatorFn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function listUnique(spec: ValueSpecList): ValidatorFn {
|
export function listUnique(spec: CT.ValueSpecList): ValidatorFn {
|
||||||
return control => {
|
return control => {
|
||||||
const list = control.value
|
const list = control.value
|
||||||
for (let idx = 0; idx < list.length; idx++) {
|
for (let idx = 0; idx < list.length; idx++) {
|
||||||
@@ -407,7 +385,7 @@ export function listUnique(spec: ValueSpecList): ValidatorFn {
|
|||||||
let display1: string
|
let display1: string
|
||||||
let display2: string
|
let display2: string
|
||||||
let uniqueMessage = isObject(objSpec)
|
let uniqueMessage = isObject(objSpec)
|
||||||
? uniqueByMessageWrapper(objSpec.uniqueBy, objSpec, list[idx])
|
? uniqueByMessageWrapper(objSpec.uniqueBy, objSpec)
|
||||||
: ''
|
: ''
|
||||||
|
|
||||||
if (isObject(objSpec) && objSpec.displayAs) {
|
if (isObject(objSpec) && objSpec.displayAs) {
|
||||||
@@ -434,7 +412,7 @@ export function listUnique(spec: ValueSpecList): ValidatorFn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function listItemEquals(spec: ValueSpecList, val1: any, val2: any): boolean {
|
function listItemEquals(spec: CT.ValueSpecList, val1: any, val2: any): boolean {
|
||||||
// TODO: fix types
|
// TODO: fix types
|
||||||
switch (spec.spec.type) {
|
switch (spec.spec.type) {
|
||||||
case 'text':
|
case 'text':
|
||||||
@@ -448,7 +426,7 @@ function listItemEquals(spec: ValueSpecList, val1: any, val2: any): boolean {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function itemEquals(spec: ValueSpec, val1: any, val2: any): boolean {
|
function itemEquals(spec: CT.ValueSpec, val1: any, val2: any): boolean {
|
||||||
switch (spec.type) {
|
switch (spec.type) {
|
||||||
case 'text':
|
case 'text':
|
||||||
case 'textarea':
|
case 'textarea':
|
||||||
@@ -460,15 +438,15 @@ function itemEquals(spec: ValueSpec, val1: any, val2: any): boolean {
|
|||||||
// TODO: 'unique-by' does not exist on ValueSpecObject, fix types
|
// TODO: 'unique-by' does not exist on ValueSpecObject, fix types
|
||||||
return objEquals(
|
return objEquals(
|
||||||
(spec as any)['unique-by'],
|
(spec as any)['unique-by'],
|
||||||
spec as ValueSpecObject,
|
spec as CT.ValueSpecObject,
|
||||||
val1,
|
val1,
|
||||||
val2,
|
val2,
|
||||||
)
|
)
|
||||||
case 'union':
|
case 'union':
|
||||||
// TODO: 'unique-by' does not exist on ValueSpecUnion, fix types
|
// TODO: 'unique-by' does not exist on CT.ValueSpecUnion, fix types
|
||||||
return unionEquals(
|
return unionEquals(
|
||||||
(spec as any)['unique-by'],
|
(spec as any)['unique-by'],
|
||||||
spec as ValueSpecUnion,
|
spec as CT.ValueSpecUnion,
|
||||||
val1,
|
val1,
|
||||||
val2,
|
val2,
|
||||||
)
|
)
|
||||||
@@ -488,8 +466,8 @@ function itemEquals(spec: ValueSpec, val1: any, val2: any): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function listObjEquals(
|
function listObjEquals(
|
||||||
uniqueBy: UniqueBy,
|
uniqueBy: CT.UniqueBy,
|
||||||
spec: ListValueSpecObject,
|
spec: CT.ListValueSpecObject,
|
||||||
val1: any,
|
val1: any,
|
||||||
val2: any,
|
val2: any,
|
||||||
): boolean {
|
): boolean {
|
||||||
@@ -516,8 +494,8 @@ function listObjEquals(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function objEquals(
|
function objEquals(
|
||||||
uniqueBy: UniqueBy,
|
uniqueBy: CT.UniqueBy,
|
||||||
spec: ValueSpecObject,
|
spec: CT.ValueSpecObject,
|
||||||
val1: any,
|
val1: any,
|
||||||
val2: any,
|
val2: any,
|
||||||
): boolean {
|
): boolean {
|
||||||
@@ -545,17 +523,17 @@ function objEquals(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function unionEquals(
|
function unionEquals(
|
||||||
uniqueBy: UniqueBy,
|
uniqueBy: CT.UniqueBy,
|
||||||
spec: ValueSpecUnion,
|
spec: CT.ValueSpecUnion,
|
||||||
val1: any,
|
val1: any,
|
||||||
val2: any,
|
val2: any,
|
||||||
): boolean {
|
): boolean {
|
||||||
const variantSpec = spec.variants[val1[unionSelectKey]].spec
|
const variantSpec = spec.variants[val1[CT.unionSelectKey]].spec
|
||||||
if (!uniqueBy) {
|
if (!uniqueBy) {
|
||||||
return false
|
return false
|
||||||
} else if (typeof uniqueBy === 'string') {
|
} else if (typeof uniqueBy === 'string') {
|
||||||
if (uniqueBy === unionSelectKey) {
|
if (uniqueBy === CT.unionSelectKey) {
|
||||||
return val1[unionSelectKey] === val2[unionSelectKey]
|
return val1[CT.unionSelectKey] === val2[CT.unionSelectKey]
|
||||||
} else {
|
} else {
|
||||||
return itemEquals(variantSpec[uniqueBy], val1[uniqueBy], val2[uniqueBy])
|
return itemEquals(variantSpec[uniqueBy], val1[uniqueBy], val2[uniqueBy])
|
||||||
}
|
}
|
||||||
@@ -578,9 +556,8 @@ function unionEquals(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function uniqueByMessageWrapper(
|
function uniqueByMessageWrapper(
|
||||||
uniqueBy: UniqueBy,
|
uniqueBy: CT.UniqueBy,
|
||||||
spec: ListValueSpecObject,
|
spec: CT.ListValueSpecObject,
|
||||||
obj: Record<string, string>,
|
|
||||||
) {
|
) {
|
||||||
let configSpec = spec.spec
|
let configSpec = spec.spec
|
||||||
|
|
||||||
@@ -591,8 +568,8 @@ function uniqueByMessageWrapper(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function uniqueByMessage(
|
function uniqueByMessage(
|
||||||
uniqueBy: UniqueBy,
|
uniqueBy: CT.UniqueBy,
|
||||||
configSpec: InputSpec,
|
configSpec: CT.InputSpec,
|
||||||
outermost = true,
|
outermost = true,
|
||||||
): string {
|
): string {
|
||||||
let joinFunc
|
let joinFunc
|
||||||
@@ -601,7 +578,7 @@ function uniqueByMessage(
|
|||||||
return ''
|
return ''
|
||||||
} else if (typeof uniqueBy === 'string') {
|
} else if (typeof uniqueBy === 'string') {
|
||||||
return configSpec[uniqueBy]
|
return configSpec[uniqueBy]
|
||||||
? (configSpec[uniqueBy] as ValueSpecObject).name
|
? (configSpec[uniqueBy] as CT.ValueSpecObject).name
|
||||||
: uniqueBy
|
: uniqueBy
|
||||||
} else if ('any' in uniqueBy) {
|
} else if ('any' in uniqueBy) {
|
||||||
joinFunc = ' OR '
|
joinFunc = ' OR '
|
||||||
@@ -620,13 +597,15 @@ function uniqueByMessage(
|
|||||||
: '(' + ret + ')'
|
: '(' + ret + ')'
|
||||||
}
|
}
|
||||||
|
|
||||||
function isObject(spec: ListValueSpecOf<any>): spec is ListValueSpecObject {
|
function isObject(
|
||||||
|
spec: CT.ListValueSpecOf<any>,
|
||||||
|
): spec is CT.ListValueSpecObject {
|
||||||
// only lists of objects have uniqueBy
|
// only lists of objects have uniqueBy
|
||||||
return 'uniqueBy' in spec
|
return 'uniqueBy' in spec
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertValuesRecursive(
|
export function convertValuesRecursive(
|
||||||
configSpec: InputSpec,
|
configSpec: CT.InputSpec,
|
||||||
group: UntypedFormGroup,
|
group: UntypedFormGroup,
|
||||||
) {
|
) {
|
||||||
Object.entries(configSpec).forEach(([key, valueSpec]) => {
|
Object.entries(configSpec).forEach(([key, valueSpec]) => {
|
||||||
@@ -645,7 +624,7 @@ export function convertValuesRecursive(
|
|||||||
} else if (valueSpec.type === 'union') {
|
} else if (valueSpec.type === 'union') {
|
||||||
const formGr = group.get(key) as UntypedFormGroup
|
const formGr = group.get(key) as UntypedFormGroup
|
||||||
const spec =
|
const spec =
|
||||||
valueSpec.variants[formGr.controls[unionSelectKey].value].spec
|
valueSpec.variants[formGr.controls[CT.unionSelectKey].value].spec
|
||||||
convertValuesRecursive(spec, formGr)
|
convertValuesRecursive(spec, formGr)
|
||||||
} else if (valueSpec.type === 'list') {
|
} else if (valueSpec.type === 'list') {
|
||||||
const formArr = group.get(key) as UntypedFormArray
|
const formArr = group.get(key) as UntypedFormArray
|
||||||
@@ -661,7 +640,7 @@ export function convertValuesRecursive(
|
|||||||
})
|
})
|
||||||
} else if (valueSpec.spec.type === 'object') {
|
} else if (valueSpec.spec.type === 'object') {
|
||||||
controls.forEach(formGroup => {
|
controls.forEach(formGroup => {
|
||||||
const objectSpec = valueSpec.spec as ListValueSpecObject
|
const objectSpec = valueSpec.spec as CT.ListValueSpecObject
|
||||||
convertValuesRecursive(objectSpec.spec, formGroup as UntypedFormGroup)
|
convertValuesRecursive(objectSpec.spec, formGroup as UntypedFormGroup)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,7 @@ import { BackupJob, ServerNotifications } from '../api/api.types'
|
|||||||
import { Url } from '@start9labs/shared'
|
import { Url } from '@start9labs/shared'
|
||||||
import { Manifest } from '@start9labs/marketplace'
|
import { Manifest } from '@start9labs/marketplace'
|
||||||
import { T } from '@start9labs/start-sdk'
|
import { T } from '@start9labs/start-sdk'
|
||||||
import {
|
import { config } from '@start9labs/start-sdk'
|
||||||
ActionMetadata,
|
|
||||||
HostnameInfo,
|
|
||||||
} from '@start9labs/start-sdk/cjs/sdk/lib/types'
|
|
||||||
import { customSmtp } from '@start9labs/start-sdk/cjs/sdk/lib/config/configConstants'
|
|
||||||
|
|
||||||
export interface DataModel {
|
export interface DataModel {
|
||||||
serverInfo: ServerInfo
|
serverInfo: ServerInfo
|
||||||
@@ -59,7 +55,7 @@ export interface ServerInfo {
|
|||||||
id: string
|
id: string
|
||||||
version: string
|
version: string
|
||||||
country: string
|
country: string
|
||||||
ui: HostnameInfo[]
|
ui: T.HostnameInfo[]
|
||||||
network: NetworkInfo
|
network: NetworkInfo
|
||||||
lastBackup: string | null
|
lastBackup: string | null
|
||||||
unreadNotifications: {
|
unreadNotifications: {
|
||||||
@@ -71,7 +67,7 @@ export interface ServerInfo {
|
|||||||
pubkey: string
|
pubkey: string
|
||||||
caFingerprint: string
|
caFingerprint: string
|
||||||
ntpSynced: boolean
|
ntpSynced: boolean
|
||||||
smtp: typeof customSmtp.validator._TYPE
|
smtp: typeof config.constants.customSmtp.validator._TYPE
|
||||||
passwordHash: string
|
passwordHash: string
|
||||||
platform: string
|
platform: string
|
||||||
}
|
}
|
||||||
@@ -156,7 +152,7 @@ export type PackageDataEntry<T extends StateInfo = StateInfo> = {
|
|||||||
stateInfo: T
|
stateInfo: T
|
||||||
icon: Url
|
icon: Url
|
||||||
status: Status
|
status: Status
|
||||||
actions: Record<string, ActionMetadata>
|
actions: Record<string, T.ActionMetadata>
|
||||||
lastBackup: string | null
|
lastBackup: string | null
|
||||||
currentDependencies: { [id: string]: CurrentDependencyInfo }
|
currentDependencies: { [id: string]: CurrentDependencyInfo }
|
||||||
dependencyInfo: {
|
dependencyInfo: {
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ import { FormDialogService } from 'src/app/services/form-dialog.service'
|
|||||||
import { configBuilderToSpec } from 'src/app/util/configBuilderToSpec'
|
import { configBuilderToSpec } from 'src/app/util/configBuilderToSpec'
|
||||||
import { ApiService } from './api/embassy-api.service'
|
import { ApiService } from './api/embassy-api.service'
|
||||||
import { DataModel } from './patch-db/data-model'
|
import { DataModel } from './patch-db/data-model'
|
||||||
import { Config } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/config'
|
import { CB } from '@start9labs/start-sdk'
|
||||||
import { Value } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/value'
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
@@ -30,14 +29,12 @@ export class ProxyService {
|
|||||||
const network = await firstValueFrom(
|
const network = await firstValueFrom(
|
||||||
this.patch.watch$('serverInfo', 'network'),
|
this.patch.watch$('serverInfo', 'network'),
|
||||||
)
|
)
|
||||||
const config = Config.of({
|
const config = CB.Config.of({
|
||||||
proxyId: Value.select({
|
proxyId: CB.Value.select({
|
||||||
name: 'Select Proxy',
|
name: 'Select Proxy',
|
||||||
required: { default: current },
|
required: { default: current },
|
||||||
values: network.proxies
|
values: network.proxies
|
||||||
.filter(
|
.filter(p => p.type === 'outbound' || p.type === 'inbound-outbound')
|
||||||
p => p.type === 'outbound' || p.type === 'inbound-outbound',
|
|
||||||
)
|
|
||||||
.reduce((prev, curr) => {
|
.reduce((prev, curr) => {
|
||||||
return {
|
return {
|
||||||
[curr.id]: curr.name,
|
[curr.id]: curr.name,
|
||||||
@@ -71,10 +68,7 @@ export class ProxyService {
|
|||||||
this.formDialog.open(FormComponent, options)
|
this.formDialog.open(FormComponent, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async saveOutboundProxy(
|
private async saveOutboundProxy(proxy: string | null, packageId?: string) {
|
||||||
proxy: string | null,
|
|
||||||
packageId?: string,
|
|
||||||
) {
|
|
||||||
const loader = this.loader.open(`Saving`).subscribe()
|
const loader = this.loader.open(`Saving`).subscribe()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { DefaultString } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
import { CT } from '@start9labs/start-sdk'
|
||||||
|
|
||||||
export class Range {
|
export class Range {
|
||||||
min?: number
|
min?: number
|
||||||
@@ -48,7 +48,7 @@ export class Range {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDefaultString(defaultSpec: DefaultString): string {
|
export function getDefaultString(defaultSpec: CT.DefaultString): string {
|
||||||
if (typeof defaultSpec === 'string') {
|
if (typeof defaultSpec === 'string') {
|
||||||
return defaultSpec
|
return defaultSpec
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Config } from "@start9labs/start-sdk/cjs/sdk/lib/config/builder/config";
|
import { CB } from '@start9labs/start-sdk'
|
||||||
|
|
||||||
export async function configBuilderToSpec(
|
export async function configBuilderToSpec(
|
||||||
builder:
|
builder:
|
||||||
| Config<Record<string, unknown>, unknown>
|
| CB.Config<Record<string, unknown>, unknown>
|
||||||
| Config<Record<string, unknown>, never>,
|
| CB.Config<Record<string, unknown>, never>,
|
||||||
) {
|
) {
|
||||||
return builder.build({} as any)
|
return builder.build({} as any)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user