| 224 | } |
| 225 | |
| 226 | export function createServer(options: ServerOptions): ServerInstance { |
| 227 | const { |
| 228 | contentDir, |
| 229 | projectDir = contentDir, |
| 230 | quiet = true, |
| 231 | debounce = 2000, |
| 232 | maxDebounce = 10000, |
| 233 | gitEnabled = true, |
| 234 | commitDebounceMs = 30_000, |
| 235 | wipRef = 'refs/wip/main', |
| 236 | configHomedirOverride, |
| 237 | enableTestRoutes = false, |
| 238 | shadowRepo, |
| 239 | contentRoot, |
| 240 | destroyTimeoutMs = 10_000, |
| 241 | localOpCliArgs, |
| 242 | skipStateManifestCheck = false, |
| 243 | singleDocRelPath, |
| 244 | ephemeral = false, |
| 245 | } = options; |
| 246 | |
| 247 | const log = getLogger('server'); |
| 248 | |
| 249 | function readProjectAttachmentFolderPath(): string { |
| 250 | const project = readConfigSafely({ |
| 251 | absPath: resolveConfigPath('project', projectDir), |
| 252 | sideline: false, |
| 253 | warn: (message) => log.warn({ message }, '[config] could not read project config'), |
| 254 | }); |
| 255 | if (!project.valid) { |
| 256 | const attachmentIssues = |
| 257 | isKnownConfigError(project.error) && project.error.code === 'SCHEMA_INVALID' |
| 258 | ? (project.error.issues as ConfigIssue[]).filter( |
| 259 | (issue) => issue.path.map(String).join('.') === 'content.attachmentFolderPath', |
| 260 | ) |
| 261 | : []; |
| 262 | if (attachmentIssues.length > 0) { |
| 263 | const details = attachmentIssues.map((issue) => issue.message).join('; '); |
| 264 | throw new Error(`Invalid content.attachmentFolderPath in project config: ${details}`); |
| 265 | } |
| 266 | log.warn( |
| 267 | {}, |
| 268 | '[config] committed content.attachmentFolderPath unavailable (project config invalid) — using default attachment placement', |
| 269 | ); |
| 270 | } |
| 271 | return project.value.content.attachmentFolderPath ?? DEFAULT_ATTACHMENT_FOLDER_PATH; |
| 272 | } |
| 273 | |
| 274 | function readProjectAutoSyncEnabled(): boolean { |
| 275 | const local = readConfigSafely({ |
| 276 | absPath: resolveConfigPath('project-local', projectDir), |
| 277 | sideline: false, |
| 278 | warn: (message) => log.warn({ message }, '[config] could not read project-local config'), |
| 279 | }); |
| 280 | const localEnabled = local.value.autoSync?.enabled; |
| 281 | if (localEnabled !== null && localEnabled !== undefined) { |
| 282 | return localEnabled === true; |
| 283 | } |