mirror of
https://github.com/nocobase/nocobase.git
synced 2026-09-24 16:02:20 +08:00
refactor(plugin-js-template): remove legacy SSH compatibility
This commit is contained in:
@@ -117,7 +117,7 @@ Push and Pull require the exact local Head, remote revision, target version, and
|
||||
|
||||
Git credentials are optional. Private HTTPS requires a complete `{{ $env.NAME }}` reference to a Secret JSON value containing `kind: "https"`, `username`, and `password`; literal credentials are rejected and only the Secret reference is stored in the remote record. HTTP is restricted to public repositories and rejects every authentication reference or credential input.
|
||||
|
||||
New requests do not send a `transport` field; the server derives `http` or `https` from the repository URL. For compatibility, a legacy matching HTTP/HTTPS `transport` value is accepted and ignored, while a mismatching or unknown value is rejected. SSH URLs and SSH execution are not supported. Existing legacy SSH records remain readable so administrators can inspect, disconnect, or delete them, but they cannot be tested, planned, pulled, pushed, or executed. Removal of that persisted compatibility shape requires verified inventory across every supported environment.
|
||||
New requests do not send a `transport` field; the server derives `http` or `https` from the repository URL. For compatibility, a legacy matching HTTP/HTTPS `transport` value is accepted and ignored, while a mismatching or unknown value is rejected. SSH URLs, SSH execution, and persisted SSH remote compatibility are not supported.
|
||||
|
||||
Branch is optional while configuring or creating from a non-empty Git repository. When omitted, the remote symbolic `HEAD` is resolved and the resulting branch is persisted. An empty repository has no default branch, so its branch must be supplied explicitly; NocoBase does not guess `main` or another branch name.
|
||||
|
||||
|
||||
+4
-15
@@ -355,21 +355,10 @@ export function JsTemplateSyncDrawer(props: JsTemplateSyncDrawerProps) {
|
||||
|
||||
{loadState === 'ready' && source && plan ? (
|
||||
<>
|
||||
{source.status === 'unsupported' ? (
|
||||
<Alert
|
||||
description={t('Legacy SSH sync sources can only be disconnected or replaced with HTTP/HTTPS.')}
|
||||
message={t('Legacy SSH sync source is unsupported')}
|
||||
role="alert"
|
||||
showIcon
|
||||
type="warning"
|
||||
/>
|
||||
) : null}
|
||||
<Descriptions bordered column={1} size="small">
|
||||
<Descriptions.Item label={t('Provider')}>Git</Descriptions.Item>
|
||||
<Descriptions.Item label={t('Git repository URL')}>{source.config.url}</Descriptions.Item>
|
||||
<Descriptions.Item label={t('Transport')}>
|
||||
{source.config.transport === 'unsupported' ? 'SSH' : source.config.transport.toUpperCase()}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label={t('Transport')}>{source.config.transport.toUpperCase()}</Descriptions.Item>
|
||||
<Descriptions.Item label={t('Branch')}>
|
||||
{source.config.branch || t('Default branch')}
|
||||
</Descriptions.Item>
|
||||
@@ -413,21 +402,21 @@ export function JsTemplateSyncDrawer(props: JsTemplateSyncDrawerProps) {
|
||||
|
||||
<Space wrap>
|
||||
<Button
|
||||
disabled={actionsDisabled || source.status === 'unsupported'}
|
||||
disabled={actionsDisabled}
|
||||
loading={currentProjectOperation === 'testConnection'}
|
||||
onClick={runTestConnection}
|
||||
>
|
||||
{t('Test connection')}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!canPull || source.status === 'unsupported'}
|
||||
disabled={!canPull}
|
||||
loading={currentProjectOperation === 'pull'}
|
||||
onClick={() => runSyncOperation('pull')}
|
||||
>
|
||||
{t('Pull from Git')}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!canPush || source.status === 'unsupported'}
|
||||
disabled={!canPush}
|
||||
loading={currentProjectOperation === 'push'}
|
||||
onClick={confirmPush}
|
||||
type="primary"
|
||||
|
||||
@@ -70,8 +70,6 @@
|
||||
"The sync plan could not be loaded safely.": "The sync plan could not be loaded safely.",
|
||||
"The sync provider is unavailable": "The sync provider is unavailable",
|
||||
"The sync provider is unsupported": "The sync provider is unsupported",
|
||||
"Legacy SSH sync source is unsupported": "Legacy SSH sync source is unsupported",
|
||||
"Legacy SSH sync sources can only be disconnected or replaced with HTTP/HTTPS.": "Legacy SSH sync sources can only be disconnected or replaced with HTTP/HTTPS.",
|
||||
"This will update the remote branch only if its revision has not changed.": "This will update the remote branch only if its revision has not changed.",
|
||||
"The Git remote is temporarily unavailable. Try again later.": "The Git remote is temporarily unavailable. Try again later.",
|
||||
"Transport": "Transport",
|
||||
|
||||
@@ -70,8 +70,6 @@
|
||||
"The sync plan could not be loaded safely.": "无法安全加载同步计划。",
|
||||
"The sync provider is unavailable": "同步提供方不可用",
|
||||
"The sync provider is unsupported": "不支持此同步提供方",
|
||||
"Legacy SSH sync source is unsupported": "旧版 SSH 同步源已不受支持",
|
||||
"Legacy SSH sync sources can only be disconnected or replaced with HTTP/HTTPS.": "旧版 SSH 同步源只能断开连接或替换为 HTTP/HTTPS。",
|
||||
"This will update the remote branch only if its revision has not changed.": "仅当远端版本未变化时才会更新远端分支。",
|
||||
"The Git remote is temporarily unavailable. Try again later.": "Git 远端暂时不可用,请稍后重试。",
|
||||
"Transport": "传输协议",
|
||||
|
||||
-43
@@ -78,8 +78,6 @@ const createJob = {
|
||||
updatedAt: '2026-07-27T00:00:00.000Z',
|
||||
};
|
||||
|
||||
const unsupportedGitScheme = ['s', 's', 'h'].join('');
|
||||
|
||||
describe('jsTemplateSync resource', () => {
|
||||
it.each([
|
||||
['get', { projectId: repo.id }, 'pullFromSyncSource'],
|
||||
@@ -196,47 +194,6 @@ describe('jsTemplateSync resource', () => {
|
||||
expect(fixture.runtime.planUnconfigured).toHaveBeenCalledWith(repo.vscRepoId);
|
||||
});
|
||||
|
||||
it('exposes legacy SSH metadata as unsupported while allowing disconnect only', async () => {
|
||||
const unsupportedRemote: VscFileRemoteRecord = {
|
||||
...remote,
|
||||
status: 'unsupported',
|
||||
config: {
|
||||
url: `${unsupportedGitScheme}://git@example.com/project.git`,
|
||||
branch: 'main',
|
||||
subdirectory: null,
|
||||
transport: 'unsupported',
|
||||
legacyTransport: 'ssh',
|
||||
},
|
||||
};
|
||||
const fixture = createFixture({ remote: unsupportedRemote });
|
||||
|
||||
const get = await runAction(fixture, 'get', { projectId: repo.id }, ['manageSyncSource']);
|
||||
const planned = await runAction(fixture, 'plan', { projectId: repo.id }, ['manageSyncSource']);
|
||||
const tested = await runAction(fixture, 'testConnection', { projectId: repo.id }, ['manageSyncSource']);
|
||||
const disconnected = await runAction(fixture, 'disconnect', { projectId: repo.id }, ['manageSyncSource']);
|
||||
|
||||
expect(get.body).toMatchObject({
|
||||
source: {
|
||||
status: 'unsupported',
|
||||
config: { transport: 'unsupported', legacyTransport: 'ssh' },
|
||||
credentialConfigured: false,
|
||||
authRefDisplay: null,
|
||||
},
|
||||
});
|
||||
expect(JSON.stringify(get.body)).not.toContain('LEGACY_SSH');
|
||||
expect(planned.body).toMatchObject({
|
||||
source: { status: 'unsupported' },
|
||||
plan: { state: 'error', reasonCode: 'legacy-ssh-unsupported', canPull: false, canPush: false },
|
||||
});
|
||||
expect(tested).toMatchObject({
|
||||
status: 422,
|
||||
body: { errors: [{ code: 'JS_TEMPLATE_SYNC_CONFIG_INVALID' }] },
|
||||
});
|
||||
expect(fixture.runtime.testTarget).not.toHaveBeenCalled();
|
||||
expect(disconnected.status).toBeUndefined();
|
||||
expect(fixture.runtime.disconnectRemote).toHaveBeenCalledWith(unsupportedRemote.id);
|
||||
});
|
||||
|
||||
it('enforces strict input allowlists before calling the runtime', async () => {
|
||||
const fixture = createFixture();
|
||||
const ctx = await runAction(
|
||||
|
||||
@@ -56,12 +56,10 @@ describe('js-template swagger', () => {
|
||||
const schemas = swaggerDocument.components.schemas;
|
||||
const config = schemas.JsTemplateGitRemoteConfigDraft;
|
||||
const outputConfig = schemas.JsTemplateGitRemoteConfigOutput;
|
||||
const unsupportedOutputConfig = schemas.JsTemplateUnsupportedGitRemoteConfigOutput;
|
||||
const createRequest = schemas.JsTemplateSyncCreateFromGitRequest;
|
||||
|
||||
expect(config.properties).not.toHaveProperty('transport');
|
||||
expect(outputConfig.properties.transport).toMatchObject({ enum: ['http', 'https'], readOnly: true });
|
||||
expect(unsupportedOutputConfig.properties.transport).toMatchObject({ enum: ['unsupported'], readOnly: true });
|
||||
expect(config.properties.url.pattern).toBe('^https?://');
|
||||
expect(createRequest).toMatchObject({
|
||||
type: 'object',
|
||||
|
||||
+4
-45
@@ -17,7 +17,7 @@ import type {
|
||||
VscRemoteProvider,
|
||||
VscRemoteSyncPlan,
|
||||
} from '../../shared/vsc-file/remote-sync-types';
|
||||
import { isActiveVscRemote, isUnsupportedVscRemote } from '../../shared/vsc-file/remote-sync-types';
|
||||
import { isActiveVscRemote } from '../../shared/vsc-file/remote-sync-types';
|
||||
import { uid } from '@nocobase/utils';
|
||||
|
||||
import { JS_TEMPLATE_COLLECTIONS, type JsTemplateAclAction } from '../../constants';
|
||||
@@ -355,9 +355,6 @@ async function getSyncSource(
|
||||
): Promise<JsTemplateSyncGetResult> {
|
||||
const project = await services.projectService.getInternalProject(requireProjectId(input), ctx);
|
||||
const remote = await services.getRemoteSyncRuntime().getRemote(project.vscRepoId, remoteName);
|
||||
if (remote && isUnsupportedVscRemote(remote)) {
|
||||
return { projectId: project.id, source: toSourceSummary(remote, null) };
|
||||
}
|
||||
const activeRemote = remote?.status === 'active' ? remote : null;
|
||||
const revision = activeRemote ? await services.getRemoteSyncRuntime().getLatestMappedRevision(activeRemote.id) : null;
|
||||
return {
|
||||
@@ -374,9 +371,6 @@ async function configureSyncSource(
|
||||
const project = await services.projectService.getInternalProject(requireProjectId(input), ctx);
|
||||
const provider = requireProvider(input.provider);
|
||||
const saved = await services.getRemoteSyncRuntime().getRemote(project.vscRepoId, remoteName);
|
||||
if (saved && isUnsupportedVscRemote(saved) && typeof input.authRef === 'undefined') {
|
||||
throw unsupportedLegacyRemote();
|
||||
}
|
||||
const authRef = typeof input.authRef === 'undefined' ? saved?.authRef ?? null : requireNullableAuthRef(input.authRef);
|
||||
return runSyncAudit(services, ctx, project.id, 'syncConfigure', async () => {
|
||||
const runtime = services.getRemoteSyncRuntime();
|
||||
@@ -424,9 +418,6 @@ async function testConnection(
|
||||
): Promise<JsTemplateSyncTestConnectionResult> {
|
||||
const project = await services.projectService.getInternalProject(requireProjectId(input), ctx);
|
||||
const saved = await services.getRemoteSyncRuntime().getRemote(project.vscRepoId, remoteName);
|
||||
if (saved && isUnsupportedVscRemote(saved)) {
|
||||
throw unsupportedLegacyRemote();
|
||||
}
|
||||
const provider = typeof input.provider === 'undefined' ? saved?.provider : requireProvider(input.provider);
|
||||
const config = typeof input.config === 'undefined' ? saved?.config : requireRecord(input.config, 'config');
|
||||
const authRef = typeof input.authRef === 'undefined' ? saved?.authRef ?? null : requireNullableAuthRef(input.authRef);
|
||||
@@ -460,13 +451,6 @@ async function planSync(
|
||||
): Promise<JsTemplateSyncPlanResult> {
|
||||
const project = await services.projectService.getInternalProject(requireProjectId(input), ctx);
|
||||
const remote = await services.getRemoteSyncRuntime().getRemote(project.vscRepoId, remoteName);
|
||||
if (remote && isUnsupportedVscRemote(remote)) {
|
||||
return {
|
||||
projectId: project.id,
|
||||
source: toSourceSummary(remote, null),
|
||||
plan: unsupportedLegacyPlan(remote),
|
||||
};
|
||||
}
|
||||
const activeRemote = remote?.status === 'active' ? remote : null;
|
||||
return runSyncAudit(services, ctx, project.id, 'syncPlan', async () => {
|
||||
const plan = activeRemote
|
||||
@@ -483,21 +467,6 @@ async function planSync(
|
||||
});
|
||||
}
|
||||
|
||||
function unsupportedLegacyPlan(remote: VscFileRemoteRecord): VscRemoteSyncPlan {
|
||||
return {
|
||||
state: 'error',
|
||||
action: 'conflict',
|
||||
reasonCode: 'legacy-ssh-unsupported',
|
||||
canPull: false,
|
||||
canPush: false,
|
||||
fingerprint: `unsupported:${remote.id}:${remote.version}`,
|
||||
remoteTargetVersion: remote.version,
|
||||
local: { headCommitId: null, contentHash: null },
|
||||
remote: { revision: null, contentHash: null, contentHashKnown: false },
|
||||
baseline: null,
|
||||
};
|
||||
}
|
||||
|
||||
async function pullSync(
|
||||
services: SyncActionServices,
|
||||
input: ResourceActionInput,
|
||||
@@ -592,9 +561,6 @@ async function pushSync(
|
||||
|
||||
async function requireSavedRemote(services: SyncActionServices, vscRepoId: string): Promise<VscFileActiveRemoteRecord> {
|
||||
const remote = await services.getRemoteSyncRuntime().getRemote(vscRepoId, remoteName);
|
||||
if (remote && isUnsupportedVscRemote(remote)) {
|
||||
throw unsupportedLegacyRemote();
|
||||
}
|
||||
if (!remote || !isActiveVscRemote(remote)) {
|
||||
throw new JsTemplateError('JS_TEMPLATE_SYNC_CONFIG_INVALID', 'An active sync source is required', {
|
||||
details: { reasonCode: 'sync-source-not-configured' },
|
||||
@@ -603,12 +569,6 @@ async function requireSavedRemote(services: SyncActionServices, vscRepoId: strin
|
||||
return remote;
|
||||
}
|
||||
|
||||
function unsupportedLegacyRemote(): JsTemplateError {
|
||||
return new JsTemplateError('JS_TEMPLATE_SYNC_CONFIG_INVALID', 'Legacy SSH sync sources are unsupported', {
|
||||
details: { reasonCode: 'legacy-ssh-unsupported' },
|
||||
});
|
||||
}
|
||||
|
||||
async function assertScopedPermission(
|
||||
db: Database,
|
||||
ctx: JsTemplateServiceContext,
|
||||
@@ -739,15 +699,14 @@ function normalizeSyncError(error: unknown): unknown {
|
||||
}
|
||||
|
||||
function toSourceSummary(remote: VscFileRemoteRecord, revision: string | null = null): JsTemplateSyncSourceSummary {
|
||||
const unsupported = isUnsupportedVscRemote(remote);
|
||||
return {
|
||||
provider: remote.provider,
|
||||
config: { ...remote.config },
|
||||
status: unsupported ? 'unsupported' : remote.status,
|
||||
status: remote.status,
|
||||
remoteTargetVersion: remote.version,
|
||||
revision,
|
||||
credentialConfigured: unsupported ? false : remote.authRef !== null,
|
||||
authRefDisplay: unsupported ? null : toAuthRefDisplay(remote.authRef),
|
||||
credentialConfigured: remote.authRef !== null,
|
||||
authRefDisplay: toAuthRefDisplay(remote.authRef),
|
||||
lastSyncedAt: remote.lastSyncedAt,
|
||||
};
|
||||
}
|
||||
|
||||
-34
@@ -24,7 +24,6 @@ const normalizedConfig: VscRemoteNormalizedConfig = {
|
||||
transport: 'https',
|
||||
};
|
||||
|
||||
const unsupportedGitScheme = ['s', 's', 'h'].join('');
|
||||
const forbiddenCredentialKeyPattern = new RegExp(
|
||||
['private', 'Key|credential|authorization|password|secret|token'].join(''),
|
||||
'i',
|
||||
@@ -90,39 +89,6 @@ describe('vsc-file remote stores', () => {
|
||||
await expect(db.getRepository('vscFileRemotes').count()).resolves.toBe(0);
|
||||
});
|
||||
|
||||
it('keeps legacy SSH remotes readable, disconnectable, and deletable without executing them', async () => {
|
||||
const repoId = await createRepository('legacy-ssh');
|
||||
const record = await db.getRepository('vscFileRemotes').create({
|
||||
values: {
|
||||
repoId,
|
||||
name: 'origin',
|
||||
provider: 'git',
|
||||
config: {
|
||||
url: `${unsupportedGitScheme}://git@example.com/project.git`,
|
||||
branch: 'main',
|
||||
subdirectory: null,
|
||||
transport: 'ssh',
|
||||
},
|
||||
authRef: '{{ $env.LEGACY_SSH_KEY }}',
|
||||
status: 'active',
|
||||
version: 1,
|
||||
},
|
||||
});
|
||||
const store = new RemoteStore(db);
|
||||
|
||||
const remote = await store.get(record.get('id') as string);
|
||||
expect(remote).toMatchObject({
|
||||
status: 'unsupported',
|
||||
config: { transport: 'unsupported', legacyTransport: 'ssh', branch: 'main' },
|
||||
authRef: '{{ $env.LEGACY_SSH_KEY }}',
|
||||
});
|
||||
|
||||
const disconnected = await store.disconnect(remote.id);
|
||||
expect(disconnected).toMatchObject({ status: 'unsupported', config: { transport: 'unsupported' }, authRef: null });
|
||||
await store.deleteRemote(remote.id);
|
||||
await expect(db.getRepository('vscFileRemotes').count()).resolves.toBe(0);
|
||||
});
|
||||
|
||||
it('preserves mappings across auth rotation and isolates old target versions', async () => {
|
||||
const repoId = await createRepository('target-version');
|
||||
const remoteStore = new RemoteStore(db);
|
||||
|
||||
+1
-1
@@ -127,7 +127,7 @@ export class RemoteReconcileService {
|
||||
const remote = await this.remoteStore.get(claimed.remoteId);
|
||||
if (remote.status !== 'active') {
|
||||
const disabledError = new RemoteSyncError('CONFIG_INVALID', 'Remote is disabled', {
|
||||
details: { reasonCode: remote.status === 'unsupported' ? 'legacy-ssh-unsupported' : 'remote-disabled' },
|
||||
details: { reasonCode: 'remote-disabled' },
|
||||
});
|
||||
const failed = await this.jobStore.fail(claimed.id, claimToken, disabledError.code);
|
||||
await ctx.onRecoveryResult?.({ job: failed, errorCode: disabledError.code });
|
||||
|
||||
-29
@@ -16,7 +16,6 @@ import type {
|
||||
VscFileRemoteRecord,
|
||||
VscRemoteNormalizedConfig,
|
||||
VscRemoteProvider,
|
||||
VscUnsupportedGitRemoteConfig,
|
||||
} from '../../../shared/vsc-file/remote-sync-types';
|
||||
import { normalizeGitRemoteConfig } from './providers/git/gitConfig';
|
||||
import { RemoteSyncError } from './RemoteSyncAdapter';
|
||||
@@ -313,7 +312,6 @@ export class RemoteStore {
|
||||
export function remoteFromRecord(record: Model): VscFileRemoteRecord {
|
||||
const provider = record.get('provider') as VscRemoteProvider;
|
||||
const persistedConfig = record.get('config') as unknown;
|
||||
const unsupportedConfig = provider === 'git' ? normalizeUnsupportedPersistedGitConfig(persistedConfig) : null;
|
||||
const common = {
|
||||
id: record.get('id') as string,
|
||||
repoId: record.get('repoId') as string,
|
||||
@@ -327,9 +325,6 @@ export function remoteFromRecord(record: Model): VscFileRemoteRecord {
|
||||
createdAt: nullableDateString(record.get('createdAt')) || undefined,
|
||||
updatedAt: nullableDateString(record.get('updatedAt')) || undefined,
|
||||
};
|
||||
if (unsupportedConfig) {
|
||||
return { ...common, config: unsupportedConfig, status: 'unsupported' };
|
||||
}
|
||||
return {
|
||||
...common,
|
||||
config: validateNormalizedConfig(provider, persistedConfig as VscRemoteNormalizedConfig),
|
||||
@@ -350,27 +345,6 @@ function validateNormalizedConfig(
|
||||
throw new RemoteSyncError('UNSUPPORTED_PROVIDER', `Unsupported remote provider "${provider}"`);
|
||||
}
|
||||
|
||||
function normalizeUnsupportedPersistedGitConfig(value: unknown): VscUnsupportedGitRemoteConfig | null {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
||||
return null;
|
||||
}
|
||||
const config = value as Record<string, unknown>;
|
||||
if (config.transport !== 'ssh') {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
url: safeLegacyString(config.url),
|
||||
branch: safeLegacyString(config.branch),
|
||||
subdirectory: typeof config.subdirectory === 'string' ? config.subdirectory : null,
|
||||
transport: 'unsupported',
|
||||
legacyTransport: 'ssh',
|
||||
};
|
||||
}
|
||||
|
||||
function safeLegacyString(value: unknown): string {
|
||||
return typeof value === 'string' ? value : '';
|
||||
}
|
||||
|
||||
function assertNoSensitiveConfigKeys(value: unknown): void {
|
||||
if (!value || typeof value !== 'object') {
|
||||
return;
|
||||
@@ -396,9 +370,6 @@ function serializeNullableAuthRef(authRef: VscRemoteCredentialRef | null): strin
|
||||
}
|
||||
|
||||
function sameConfig(left: VscFileRemoteConfig, right: VscRemoteNormalizedConfig): boolean {
|
||||
if (left.transport === 'unsupported') {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
left.url === right.url &&
|
||||
left.branch === right.branch &&
|
||||
|
||||
@@ -21,7 +21,6 @@ import type { RunJSSourceLocator, VscCommitRecord } from '@nocobase/runjs/worksp
|
||||
import type {
|
||||
VscGitRemoteConfig,
|
||||
VscGitRemoteConfigDraft,
|
||||
VscUnsupportedGitRemoteConfig,
|
||||
VscRemotePlannerAction,
|
||||
VscRemotePlannerLocalSummary,
|
||||
VscRemotePlannerRemoteSummary,
|
||||
@@ -712,11 +711,11 @@ export type JsTemplateSyncState = VscRemotePlannerState;
|
||||
|
||||
export type JsTemplateSyncAction = VscRemotePlannerAction;
|
||||
|
||||
export type JsTemplateSyncSourceStatus = 'active' | 'disabled' | 'unsupported';
|
||||
export type JsTemplateSyncSourceStatus = 'active' | 'disabled';
|
||||
|
||||
export interface JsTemplateSyncRemoteTarget {
|
||||
provider: JsTemplateSyncProvider;
|
||||
config: VscGitRemoteConfig | VscUnsupportedGitRemoteConfig;
|
||||
config: VscGitRemoteConfig;
|
||||
}
|
||||
|
||||
export interface JsTemplateSyncRemoteTargetDraft {
|
||||
|
||||
+3
-21
@@ -26,17 +26,9 @@ export interface VscGitRemoteConfig {
|
||||
transport: VscGitRemoteTransport;
|
||||
}
|
||||
|
||||
export interface VscUnsupportedGitRemoteConfig {
|
||||
url: string;
|
||||
branch: string;
|
||||
subdirectory: string | null;
|
||||
transport: 'unsupported';
|
||||
legacyTransport: 'ssh';
|
||||
}
|
||||
|
||||
export type VscRemoteNormalizedConfig = VscGitRemoteConfig;
|
||||
|
||||
export type VscFileRemoteConfig = VscRemoteNormalizedConfig | VscUnsupportedGitRemoteConfig;
|
||||
export type VscFileRemoteConfig = VscRemoteNormalizedConfig;
|
||||
|
||||
export type GitRemoteCredential = {
|
||||
kind: 'https';
|
||||
@@ -152,7 +144,7 @@ export const remoteSyncErrorCodes = [
|
||||
|
||||
export type RemoteSyncErrorCode = (typeof remoteSyncErrorCodes)[number];
|
||||
|
||||
export type VscFileRemoteStatus = 'active' | 'disabled' | 'unsupported';
|
||||
export type VscFileRemoteStatus = 'active' | 'disabled';
|
||||
|
||||
interface VscFileRemoteRecordBase {
|
||||
id: string;
|
||||
@@ -169,11 +161,7 @@ interface VscFileRemoteRecordBase {
|
||||
}
|
||||
|
||||
export type VscFileRemoteRecord = VscFileRemoteRecordBase &
|
||||
(
|
||||
| { config: VscRemoteNormalizedConfig; status: 'active' }
|
||||
| { config: VscRemoteNormalizedConfig; status: 'disabled' }
|
||||
| { config: VscUnsupportedGitRemoteConfig; status: 'unsupported' }
|
||||
);
|
||||
({ config: VscRemoteNormalizedConfig; status: 'active' } | { config: VscRemoteNormalizedConfig; status: 'disabled' });
|
||||
|
||||
export type VscFileActiveRemoteRecord = VscFileRemoteRecordBase & {
|
||||
config: VscRemoteNormalizedConfig;
|
||||
@@ -184,12 +172,6 @@ export function isActiveVscRemote(remote: VscFileRemoteRecord): remote is VscFil
|
||||
return remote.status === 'active';
|
||||
}
|
||||
|
||||
export function isUnsupportedVscRemote(
|
||||
remote: Pick<VscFileRemoteRecord, 'config' | 'status'>,
|
||||
): remote is Pick<VscFileRemoteRecord, 'status'> & { config: VscUnsupportedGitRemoteConfig } {
|
||||
return remote.config.transport === 'unsupported';
|
||||
}
|
||||
|
||||
export type VscFileSyncOperation = 'probe' | 'push' | 'pull';
|
||||
|
||||
export type VscFileSyncJobStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'finalize-pending';
|
||||
|
||||
@@ -59,18 +59,6 @@ export const jsTemplateSchemas = {
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
JsTemplateUnsupportedGitRemoteConfigOutput: {
|
||||
type: 'object',
|
||||
required: ['url', 'branch', 'subdirectory', 'transport', 'legacyTransport'],
|
||||
properties: {
|
||||
url: { type: 'string' },
|
||||
branch: { type: 'string', minLength: 1 },
|
||||
subdirectory: nullableString,
|
||||
transport: { type: 'string', enum: ['unsupported'], readOnly: true },
|
||||
legacyTransport: { type: 'string', enum: ['ssh'], readOnly: true },
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
JsTemplateSyncProjectRequest: {
|
||||
type: 'object',
|
||||
required: ['projectId'],
|
||||
@@ -182,10 +170,7 @@ export const jsTemplateSchemas = {
|
||||
nullable: true,
|
||||
properties: {
|
||||
config: {
|
||||
oneOf: [
|
||||
{ $ref: '#/components/schemas/JsTemplateGitRemoteConfigOutput' },
|
||||
{ $ref: '#/components/schemas/JsTemplateUnsupportedGitRemoteConfigOutput' },
|
||||
],
|
||||
$ref: '#/components/schemas/JsTemplateGitRemoteConfigOutput',
|
||||
},
|
||||
},
|
||||
additionalProperties: true,
|
||||
|
||||
Reference in New Issue
Block a user