Change to use dpdm for circular import scanning (#5788)

Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
This commit is contained in:
James Brunton
2026-02-24 23:05:23 +00:00
committed by GitHub
parent 1b3bfaec20
commit eab84a13d0
17 changed files with 200 additions and 2230 deletions

View File

@@ -1,6 +1,7 @@
import React, { createContext, useContext, useState, useEffect, ReactNode, useCallback } from 'react';
import apiClient from '@app/services/apiClient';
import { getSimulatedAppConfig } from '@app/testing/serverExperienceSimulations';
import type { AppConfig, AppConfigBootstrapMode } from '@app/types/appConfig';
/**
* Sleep utility for delays
@@ -14,55 +15,7 @@ export interface AppConfigRetryOptions {
initialDelay?: number;
}
export interface AppConfig {
baseUrl?: string;
contextPath?: string;
serverPort?: number;
frontendUrl?: string;
appNameNavbar?: string;
languages?: string[];
defaultLocale?: string;
logoStyle?: 'modern' | 'classic';
enableLogin?: boolean;
showSettingsWhenNoLogin?: boolean;
enableEmailInvites?: boolean;
enableOAuth?: boolean;
enableSaml?: boolean;
isAdmin?: boolean;
enableAlphaFunctionality?: boolean;
enableAnalytics?: boolean | null;
enablePosthog?: boolean | null;
enableScarf?: boolean | null;
enableDesktopInstallSlide?: boolean;
premiumEnabled?: boolean;
premiumKey?: string;
termsAndConditions?: string;
privacyPolicy?: string;
cookiePolicy?: string;
impressum?: string;
accessibilityStatement?: string;
runningProOrHigher?: boolean;
runningEE?: boolean;
license?: string;
SSOAutoLogin?: boolean;
serverCertificateEnabled?: boolean;
enableMobileScanner?: boolean;
mobileScannerConvertToPdf?: boolean;
mobileScannerImageResolution?: string;
mobileScannerPageFormat?: string;
mobileScannerStretchToFit?: boolean;
appVersion?: string;
machineType?: string;
activeSecurity?: boolean;
dependenciesReady?: boolean;
error?: string;
isNewServer?: boolean;
isNewUser?: boolean;
defaultHideUnavailableTools?: boolean;
defaultHideUnavailableConversions?: boolean;
}
export type AppConfigBootstrapMode = 'blocking' | 'non-blocking';
export type { AppConfig, AppConfigBootstrapMode };
interface AppConfigContextValue {
config: AppConfig | null;

View File

@@ -6,10 +6,7 @@ import { downloadFiles } from '@app/utils/downloadUtils';
import { FileId } from '@app/types/file';
import { groupFilesByOriginal } from '@app/utils/fileHistoryUtils';
import { openFilesFromDisk } from '@app/services/openFilesFromDisk';
// Module-level storage for file path mappings (quickKey -> localFilePath)
// Used to pass file paths from Tauri file dialog to FileContext
export const pendingFilePathMappings = new Map<string, string>();
export { pendingFilePathMappings } from '@app/services/pendingFilePathMappings';
// Type for the context value - now contains everything directly
interface FileManagerContextValue {

View File

@@ -1,38 +1,17 @@
import { useCallback, useEffect, useMemo, useState } from 'react';
import { signatureStorageService, type StorageType } from '@app/services/signatureStorageService';
import { useAppConfig } from '@app/contexts/AppConfigContext';
import type {
SavedSignature,
SavedSignaturePayload,
SavedSignatureType,
SignatureScope,
} from '@app/types/signature';
export const MAX_SAVED_SIGNATURES_BACKEND = 20; // Backend limit per user
export const MAX_SAVED_SIGNATURES_LOCALSTORAGE = 10; // LocalStorage limit
export type SavedSignatureType = 'canvas' | 'image' | 'text';
export type SignatureScope = 'personal' | 'shared' | 'localStorage';
export type SavedSignaturePayload =
| {
type: 'canvas';
dataUrl: string;
}
| {
type: 'image';
dataUrl: string;
}
| {
type: 'text';
dataUrl: string;
signerName: string;
fontFamily: string;
fontSize: number;
textColor: string;
};
export type SavedSignature = SavedSignaturePayload & {
id: string;
label: string;
scope: SignatureScope;
createdAt: number;
updatedAt: number;
};
export type { SavedSignature, SavedSignaturePayload, SavedSignatureType, SignatureScope };
export type AddSignatureResult =
| { success: true; signature: SavedSignature }

View File

@@ -1,5 +1,5 @@
import { openFileDialog } from '@app/services/fileDialogService';
import { pendingFilePathMappings } from '@app/contexts/FileManagerContext';
import { pendingFilePathMappings } from '@app/services/pendingFilePathMappings';
import { getDocumentFileDialogFilter } from '@app/utils/fileDialogUtils';
interface OpenFilesFromDiskOptions {

View File

@@ -0,0 +1,3 @@
// Module-level storage for file path mappings (quickKey -> localFilePath)
// Used to pass file paths from Tauri file dialog to FileManagerContext
export const pendingFilePathMappings = new Map<string, string>();

View File

@@ -1,5 +1,5 @@
import apiClient from '@app/services/apiClient';
import type { SavedSignature } from '@app/hooks/tools/sign/useSavedSignatures';
import type { SavedSignature } from '@app/types/signature';
export type StorageType = 'backend' | 'localStorage';

View File

@@ -0,0 +1,49 @@
export interface AppConfig {
baseUrl?: string;
contextPath?: string;
serverPort?: number;
frontendUrl?: string;
appNameNavbar?: string;
languages?: string[];
defaultLocale?: string;
logoStyle?: 'modern' | 'classic';
enableLogin?: boolean;
showSettingsWhenNoLogin?: boolean;
enableEmailInvites?: boolean;
enableOAuth?: boolean;
enableSaml?: boolean;
isAdmin?: boolean;
enableAlphaFunctionality?: boolean;
enableAnalytics?: boolean | null;
enablePosthog?: boolean | null;
enableScarf?: boolean | null;
enableDesktopInstallSlide?: boolean;
premiumEnabled?: boolean;
premiumKey?: string;
termsAndConditions?: string;
privacyPolicy?: string;
cookiePolicy?: string;
impressum?: string;
accessibilityStatement?: string;
runningProOrHigher?: boolean;
runningEE?: boolean;
license?: string;
SSOAutoLogin?: boolean;
serverCertificateEnabled?: boolean;
enableMobileScanner?: boolean;
mobileScannerConvertToPdf?: boolean;
mobileScannerImageResolution?: string;
mobileScannerPageFormat?: string;
mobileScannerStretchToFit?: boolean;
appVersion?: string;
machineType?: string;
activeSecurity?: boolean;
dependenciesReady?: boolean;
error?: string;
isNewServer?: boolean;
isNewUser?: boolean;
defaultHideUnavailableTools?: boolean;
defaultHideUnavailableConversions?: boolean;
}
export type AppConfigBootstrapMode = 'blocking' | 'non-blocking';

View File

@@ -0,0 +1,28 @@
export type SavedSignatureType = 'canvas' | 'image' | 'text';
export type SignatureScope = 'personal' | 'shared' | 'localStorage';
export type SavedSignaturePayload =
| {
type: 'canvas';
dataUrl: string;
}
| {
type: 'image';
dataUrl: string;
}
| {
type: 'text';
dataUrl: string;
signerName: string;
fontFamily: string;
fontSize: number;
textColor: string;
};
export type SavedSignature = SavedSignaturePayload & {
id: string;
label: string;
scope: SignatureScope;
createdAt: number;
updatedAt: number;
};

View File

@@ -0,0 +1,27 @@
import { invoke } from '@tauri-apps/api/core';
const TOKEN_KEY = 'stirling_jwt';
/**
* Read auth token from any available source (Tauri store or localStorage).
* Kept separate to avoid circular dependencies between auth and backend services.
*/
export async function getAuthTokenFromAnySource(): Promise<string | null> {
// Try Tauri store first
try {
const token = await invoke<string | null>('get_auth_token');
if (token) {
return token;
}
} catch (error) {
console.error('[Desktop AuthTokenStore] Failed to read from Tauri store:', error);
}
// Fallback to localStorage
try {
return localStorage.getItem(TOKEN_KEY);
} catch (error) {
console.error('[Desktop AuthTokenStore] Failed to read from localStorage:', error);
return null;
}
}

View File

@@ -1,6 +1,7 @@
import { invoke } from '@tauri-apps/api/core';
import { fetch } from '@tauri-apps/plugin-http';
import { connectionModeService } from '@app/services/connectionModeService';
import { getAuthTokenFromAnySource } from '@app/services/authTokenStore';
export type BackendStatus = 'stopped' | 'starting' | 'healthy' | 'unhealthy';
@@ -122,8 +123,7 @@ export class TauriBackendService {
*/
private async getAuthToken(): Promise<string | null> {
try {
const { authService } = await import('./authService');
return await authService.getAuthToken();
return await getAuthTokenFromAnySource();
} catch (error) {
console.debug('[TauriBackendService] Failed to get auth token:', error);
return null;

View File

@@ -1,4 +1,4 @@
import { PlanFeature } from '@app/services/licenseService';
import type { PlanFeature } from '@app/types/license';
/**
* Shared plan feature definitions for Stirling PDF Self-Hosted

View File

@@ -2,11 +2,7 @@ import apiClient from '@app/services/apiClient';
import { supabase, isSupabaseConfigured } from '@app/services/supabaseClient';
import { getCheckoutMode } from '@app/utils/protocolDetection';
import { PLAN_FEATURES, PLAN_HIGHLIGHTS } from '@app/constants/planConstants';
export interface PlanFeature {
name: string;
included: boolean;
}
import type { LicenseInfo, PlanFeature } from '@app/types/license';
export interface PlanTier {
id: string;
@@ -69,13 +65,7 @@ export interface LicenseKeyResponse {
plan?: string;
}
export interface LicenseInfo {
licenseType: 'NORMAL' | 'SERVER' | 'ENTERPRISE';
enabled: boolean;
maxUsers: number;
hasKey: boolean;
licenseKey?: string; // The actual license key (for upgrades)
}
export type { LicenseInfo, PlanFeature };
export interface LicenseSaveResponse {
success: boolean;

View File

@@ -1,5 +1,5 @@
import type { AppConfig } from '@app/contexts/AppConfigContext';
import type { LicenseInfo } from '@app/services/licenseService';
import type { AppConfig } from '@app/types/appConfig';
import type { LicenseInfo } from '@app/types/license';
interface WauResponse {
trackingSince: string;
@@ -208,4 +208,3 @@ export function getSimulatedLicenseInfo(): LicenseInfo | null {
}
export const DEV_TESTING_ENABLED = DEV_TESTING_MODE;

View File

@@ -0,0 +1,12 @@
export interface PlanFeature {
name: string;
included: boolean;
}
export interface LicenseInfo {
licenseType: 'NORMAL' | 'SERVER' | 'ENTERPRISE';
enabled: boolean;
maxUsers: number;
hasKey: boolean;
licenseKey?: string;
}