( venvPath: string, workPath: string, env: NodeJS.ProcessEnv, outputStaticDir: string, settingsModule: string, djangoSettings: Record<string, unknown>, djangoVersion: DjangoVersion | null )
| 78 | * everything and return null. |
| 79 | */ |
| 80 | export async function runDjangoCollectStatic( |
| 81 | venvPath: string, |
| 82 | workPath: string, |
| 83 | env: NodeJS.ProcessEnv, |
| 84 | outputStaticDir: string, |
| 85 | settingsModule: string, |
| 86 | djangoSettings: Record<string, unknown>, |
| 87 | djangoVersion: DjangoVersion | null |
| 88 | ): Promise<DjangoCollectStaticResult | null> { |
| 89 | const pythonPath = getVenvPythonBin(venvPath); |
| 90 | |
| 91 | // Resolve storage backend |
| 92 | // First check STORAGES (Django 4.2+) then the legacy STATICFILES_STORAGE setting. |
| 93 | // STATICFILES_STORAGE was removed in Django 5.1. |
| 94 | const storages = djangoSettings['STORAGES'] as |
| 95 | | { staticfiles?: { BACKEND?: string } } |
| 96 | | undefined; |
| 97 | const useLegacySetting = |
| 98 | !djangoVersion || |
| 99 | djangoVersion[0] < 5 || |
| 100 | (djangoVersion[0] === 5 && djangoVersion[1] < 1); |
| 101 | const legacyBackend = useLegacySetting |
| 102 | ? (djangoSettings['STATICFILES_STORAGE'] as string | undefined) |
| 103 | : undefined; |
| 104 | const storageBackend: string = |
| 105 | storages?.staticfiles?.BACKEND ?? |
| 106 | legacyBackend ?? |
| 107 | 'django.contrib.staticfiles.storage.StaticFilesStorage'; |
| 108 | |
| 109 | const staticUrl = |
| 110 | (djangoSettings['STATIC_URL'] as string | undefined) ?? '/static/'; |
| 111 | const staticRoot = |
| 112 | djangoSettings['STATIC_ROOT'] != null |
| 113 | ? String(djangoSettings['STATIC_ROOT']) |
| 114 | : null; |
| 115 | const whitenoiseUseFinders = |
| 116 | djangoSettings['WHITENOISE_USE_FINDERS'] === true; |
| 117 | |
| 118 | // Get the static file directories. |
| 119 | // Each installed app may have a 'static' subdirectory. |
| 120 | // STATICFILES_DIRS is an additional list of directories. |
| 121 | const installedApps = |
| 122 | (djangoSettings['INSTALLED_APPS'] as string[] | undefined) ?? []; |
| 123 | const staticfilesDirs = |
| 124 | (djangoSettings['STATICFILES_DIRS'] as |
| 125 | | (string | [string, string])[] |
| 126 | | undefined) ?? []; |
| 127 | const staticSourceDirs = [ |
| 128 | ...installedApps.map(app => join(workPath, ...app.split('.'), 'static')), |
| 129 | // TODO: Deal with optional prefixes in STATICFILES_DIRS. |
| 130 | ...staticfilesDirs.map(d => (Array.isArray(d) ? d[1] : d)), |
| 131 | ].filter(d => fs.existsSync(d)); |
| 132 | |
| 133 | // When django-storages is the storage backend |
| 134 | // Run collectstatic with the user's real settings, it will upload to S3/GCS/etc. |
| 135 | // No CDN bundling or manifest work needed. |
| 136 | if (storageBackend.startsWith('storages.backends.')) { |
| 137 | console.log( |
no test coverage detected