{"version":3,"sources":["../src/index.cjs"],"sourcesContent":["const { pathToFileURL, fileURLToPath } = require(\"node:url\");\nconst { readFile } = require(\"node:fs/promises\");\n\nconst queueWgslUrl = new URL(\"./queue.wgsl\", pathToFileURL(__filename));\nconst dagQueueWgslUrl = new URL(\"./dag-queue.wgsl\", pathToFileURL(__filename));\nconst schedulerModes = Object.freeze([\"flat\", \"dag\"]);\nconst IDENTIFIER_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/u;\n\nfunction assertSchedulerMode(mode) {\n  const resolved = mode ?? \"flat\";\n  if (!schedulerModes.includes(resolved)) {\n    throw new Error(`mode must be one of: ${schedulerModes.join(\", \")}.`);\n  }\n  return resolved;\n}\n\nfunction assertIdentifier(name, value) {\n  if (typeof value !== \"string\" || !IDENTIFIER_PATTERN.test(value)) {\n    throw new Error(\n      `${name} must match ${IDENTIFIER_PATTERN.toString()} and be at most 64 characters long.`\n    );\n  }\n  return value;\n}\n\nfunction readNonNegativeInteger(name, value) {\n  if (value === undefined) {\n    return 0;\n  }\n  if (\n    typeof value !== \"number\" ||\n    !Number.isInteger(value) ||\n    value < 0 ||\n    !Number.isFinite(value)\n  ) {\n    throw new Error(`${name} must be a non-negative integer.`);\n  }\n  return value;\n}\n\nfunction normalizeDependencies(name, value) {\n  if (value === undefined) {\n    return [];\n  }\n  if (!Array.isArray(value)) {\n    throw new Error(`${name} must be an array of dependency ids.`);\n  }\n  return [...new Set(value.map((entry, index) =>\n    assertIdentifier(`${name}[${index}]`, entry)\n  ))];\n}\n\nfunction resolveGraphJobId(job, index) {\n  if (typeof job.id === \"string\") {\n    return assertIdentifier(`jobs[${index}].id`, job.id);\n  }\n  if (typeof job.label === \"string\") {\n    return assertIdentifier(`jobs[${index}].label`, job.label);\n  }\n  if (typeof job.key === \"string\") {\n    return assertIdentifier(`jobs[${index}].key`, job.key);\n  }\n  if (typeof job.jobType === \"string\") {\n    return assertIdentifier(`jobs[${index}].jobType`, job.jobType);\n  }\n  return assertIdentifier(`jobs[${index}].id`, `job-${index}`);\n}\n\nfunction buildPriorityLanes(graphJobs) {\n  const lanes = new Map();\n\n  for (const job of graphJobs) {\n    const lane = lanes.get(job.priority) ?? {\n      priority: job.priority,\n      jobIds: [],\n      rootJobIds: [],\n    };\n    lane.jobIds.push(job.id);\n    if (job.root) {\n      lane.rootJobIds.push(job.id);\n    }\n    lanes.set(job.priority, lane);\n  }\n\n  return Object.freeze(\n    [...lanes.values()]\n      .sort((left, right) => right.priority - left.priority)\n      .map((lane) =>\n        Object.freeze({\n          priority: lane.priority,\n          jobIds: Object.freeze([...lane.jobIds]),\n          rootJobIds: Object.freeze([...lane.rootJobIds]),\n          jobCount: lane.jobIds.length,\n          rootCount: lane.rootJobIds.length,\n        })\n      )\n  );\n}\n\nasync function loadWgslAsset(assetUrl, options = {}) {\n  const { url = assetUrl, fetcher = globalThis.fetch } = options ?? {};\n  const wgslUrl = url instanceof URL ? url : new URL(url, assetUrl);\n\n  if (!fetcher || wgslUrl.protocol === \"file:\") {\n    return readFile(fileURLToPath(wgslUrl), \"utf8\");\n  }\n\n  const response = await fetcher(wgslUrl);\n  if (!response.ok) {\n    const status = \"status\" in response ? response.status : \"unknown\";\n    const statusText = \"statusText\" in response ? response.statusText : \"\";\n    const detail = statusText ? `${status} ${statusText}` : `${status}`;\n    throw new Error(`Failed to load WGSL (${detail})`);\n  }\n  return response.text();\n}\n\nasync function loadQueueWgsl(options = {}) {\n  return loadWgslAsset(queueWgslUrl, options);\n}\n\nasync function loadDagQueueWgsl(options = {}) {\n  return loadWgslAsset(dagQueueWgslUrl, options);\n}\n\nasync function loadSchedulerWgsl(options = {}) {\n  const { mode = \"flat\", ...rest } = options ?? {};\n  const resolvedMode = assertSchedulerMode(mode);\n  if (resolvedMode === \"dag\") {\n    return loadDagQueueWgsl(rest);\n  }\n  return loadQueueWgsl(rest);\n}\n\nfunction createDagJobGraph(jobs = []) {\n  if (!Array.isArray(jobs)) {\n    throw new Error(\"jobs must be an array.\");\n  }\n\n  const normalized = jobs.map((job, index) => {\n    if (!job || typeof job !== \"object\" || Array.isArray(job)) {\n      throw new Error(`jobs[${index}] must be an object.`);\n    }\n\n    const id = resolveGraphJobId(job, index);\n    const dependencies = normalizeDependencies(\n      `jobs[${index}].dependencies`,\n      job.dependencies ?? job.dependsOn\n    );\n    const priority = readNonNegativeInteger(\n      `jobs[${index}].priority`,\n      job.priority\n    );\n\n    return {\n      id,\n      key: typeof job.key === \"string\" ? job.key : undefined,\n      label: typeof job.label === \"string\" ? job.label : undefined,\n      jobType: job.jobType,\n      queueClass: typeof job.queueClass === \"string\" ? job.queueClass : undefined,\n      priority,\n      dependencies,\n    };\n  });\n\n  const ids = new Set();\n  for (const job of normalized) {\n    if (ids.has(job.id)) {\n      throw new Error(`Duplicate DAG job id detected: ${job.id}`);\n    }\n    ids.add(job.id);\n  }\n\n  for (const job of normalized) {\n    for (const dependency of job.dependencies) {\n      if (!ids.has(dependency)) {\n        throw new Error(\n          `Job \"${job.id}\" depends on unknown job \"${dependency}\".`\n        );\n      }\n      if (dependency === job.id) {\n        throw new Error(`Job \"${job.id}\" cannot depend on itself.`);\n      }\n    }\n  }\n\n  const dependentsById = new Map(normalized.map((job) => [job.id, []]));\n  const indegree = new Map(normalized.map((job) => [job.id, job.dependencies.length]));\n  for (const job of normalized) {\n    for (const dependency of job.dependencies) {\n      dependentsById.get(dependency).push(job.id);\n    }\n  }\n\n  const ready = normalized\n    .filter((job) => job.dependencies.length === 0)\n    .map((job) => job.id);\n  const topo = [];\n  const queue = [...ready];\n  while (queue.length > 0) {\n    const currentId = queue.shift();\n    topo.push(currentId);\n    for (const dependentId of dependentsById.get(currentId) ?? []) {\n      const next = (indegree.get(dependentId) ?? 0) - 1;\n      indegree.set(dependentId, next);\n      if (next === 0) {\n        queue.push(dependentId);\n      }\n    }\n  }\n\n  if (topo.length !== normalized.length) {\n    throw new Error(\"DAG graph contains a cycle.\");\n  }\n\n  const maxPriority = normalized.reduce(\n    (current, job) => Math.max(current, job.priority),\n    0\n  );\n\n  const graphJobs = normalized.map((job) =>\n    Object.freeze({\n      ...job,\n      dependencies: Object.freeze([...job.dependencies]),\n      dependents: Object.freeze([...(dependentsById.get(job.id) ?? [])]),\n      dependencyCount: job.dependencies.length,\n      unresolvedDependencyCount: job.dependencies.length,\n      dependentCount: (dependentsById.get(job.id) ?? []).length,\n      root: job.dependencies.length === 0,\n    })\n  );\n\n  const priorityLanes = buildPriorityLanes(graphJobs);\n\n  return Object.freeze({\n    mode: \"dag\",\n    jobCount: graphJobs.length,\n    maxPriority,\n    jobIds: Object.freeze(graphJobs.map((job) => job.id)),\n    roots: Object.freeze(graphJobs.filter((job) => job.root).map((job) => job.id)),\n    topologicalOrder: Object.freeze(topo),\n    priorityLanes,\n    jobs: Object.freeze(graphJobs),\n  });\n}\n\nmodule.exports = {\n  queueWgslUrl,\n  dagQueueWgslUrl,\n  schedulerModes,\n  loadQueueWgsl,\n  loadDagQueueWgsl,\n  loadSchedulerWgsl,\n  createDagJobGraph,\n};\n"],"mappings":"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","names":[]}