krishnax12/usb-c-control-dial

USB-C control dial PCB with an EC11 push encoder and a 16-LED ring for volume and brightness controls. Work in progress; firmware not included and not fabrication-ready.

Version
0.0.3
License
unset
Stars
1

scripts/publish.ts

import { homedir } from "node:os"
import { resolve } from "node:path"
import { isDeepStrictEqual } from "node:util"
import { gzipSync } from "node:zlib"
import { runAllChecks } from "@tscircuit/checks"
import type { AnyCircuitElement } from "circuit-json"

const projectDirectory = resolve(import.meta.dir, "..")
const packageName = "krishnax12/usb-c-control-dial"
const registryUrl = "https://registry-api.tscircuit.com"
const config: { sessionToken: string; accountId: string } = await Bun.file(
  resolve(homedir(), ".config/tscircuit-nodejs/config.json"),
).json()
const headers = {
  "Content-Type": "application/json",
  Authorization: `Bearer ${config.sessionToken}`,
}

async function registryRequest<T>(
  endpoint: string,
  request: Record<string, unknown>,
): Promise<T> {
  const response = await fetch(`${registryUrl}/${endpoint}`, {
    method: "POST",
    headers,
    body: JSON.stringify(request),
    signal: AbortSignal.timeout(60_000),
  })
  if (!response.ok)
    throw new Error(`${endpoint} failed: HTTP ${response.status}`)
  return response.json()
}

const { account } = await registryRequest<{
  account: { tscircuit_handle: string }
}>("accounts/get", { account_id: config.accountId })
if (account.tscircuit_handle.toLowerCase() !== "krishnax12")
  throw new Error("Expected the krishnax12 account; publication stopped")

const packageJson: { version: string; description: string } = await Bun.file(
  resolve(projectDirectory, "package.json"),
).json()
const nativeCircuit: AnyCircuitElement[] = await Bun.file(
  resolve(projectDirectory, "outputs/repro/circuit.json"),
).json()
const embeddedDiagnostics = nativeCircuit.filter((element) =>
  /error|warning/.test(element.type),
)
const independentDiagnostics = await runAllChecks(nativeCircuit)
const diagnostics = [...embeddedDiagnostics, ...independentDiagnostics]
if (diagnostics.some((element) => element.type.endsWith("_error")))
  throw new Error("Publication stopped: PCB or schematic errors remain")
if (diagnostics.length && !Bun.argv.includes("--allow-warnings"))
  throw new Error(
    "Publication stopped: warnings remain; --allow-warnings requires explicit approval",
  )
if (diagnostics.length)
  console.warn("Publishing with visible warnings:", [
    ...new Set(diagnostics.map((element) => element.type)),
  ])
await Bun.write(
  resolve(projectDirectory, "outputs/repro/independent-checks.json"),
  JSON.stringify(independentDiagnostics, null, 2),
)
const verification: { witnesses: object[] } = await Bun.file(
  resolve(projectDirectory, "outputs/repro/verification.json"),
).json()
if (verification.witnesses.length === 0)
  throw new Error("The saved export does not demonstrate the clearance bug")

const receiptFile = Bun.file(
  resolve(projectDirectory, "outputs/publication.json"),
)
type PublicationReceipt = {
  packageName: string
  packageId: string
  packageReleaseId: string
  version: string
  filesUploaded: string[]
  previewVerified: boolean
}
let receipt: PublicationReceipt
if (await receiptFile.exists()) {
  receipt = await receiptFile.json()
  if (receipt.packageName !== packageName)
    throw new Error(
      "Publication receipt does not match this package and version",
    )
  if (receipt.version !== packageJson.version) {
    const { package: existingPackage } = await registryRequest<{
      package: { package_id: string }
    }>("packages/get", { name: packageName })
    if (existingPackage.package_id !== receipt.packageId)
      throw new Error(
        "Target package differs from the saved publication receipt",
      )
    await Bun.write(
      resolve(projectDirectory, `outputs/publication.${receipt.version}.json`),
      JSON.stringify(receipt, null, 2),
    )
    const { package_release } = await registryRequest<{
      package_release: { package_release_id: string }
    }>("package_releases/create", {
      package_id: receipt.packageId,
      version: packageJson.version,
      is_latest: true,
      ready_to_build: false,
    })
    receipt = {
      ...receipt,
      packageReleaseId: package_release.package_release_id,
      version: packageJson.version,
      filesUploaded: [],
      previewVerified: false,
    }
    await Bun.write(receiptFile, JSON.stringify(receipt, null, 2))
  }
} else {
  const existingPackage = await fetch(`${registryUrl}/packages/get`, {
    method: "POST",
    headers,
    body: JSON.stringify({ name: packageName }),
    signal: AbortSignal.timeout(30_000),
  })
  if (existingPackage.status !== 404)
    throw new Error(
      "Target already exists or cannot be checked; refusing to replace it",
    )
  const { package: createdPackage } = await registryRequest<{
    package: { package_id: string }
  }>("packages/create", {
    name: packageName,
    is_private: false,
    is_unlisted: false,
  })
  const { package_release } = await registryRequest<{
    package_release: { package_release_id: string }
  }>("package_releases/create", {
    package_id: createdPackage.package_id,
    version: packageJson.version,
    is_latest: true,
    ready_to_build: false,
  })
  receipt = {
    packageName,
    packageId: createdPackage.package_id,
    packageReleaseId: package_release.package_release_id,
    version: packageJson.version,
    filesUploaded: [],
    previewVerified: false,
  }
  await Bun.write(receiptFile, JSON.stringify(receipt, null, 2))
}

const sourcePaths = [
  "board.circuit.json",
  "README.md",
  "package.json",
  "bun.lock",
  "tsconfig.json",
  "biome.json",
  "tscircuit.config.json",
  "assets.d.ts",
  "reference.json",
  "index.circuit.tsx",
  "repro.circuit.tsx",
  ...new Bun.Glob("{components,imports,scripts,tests}/**/*").scanSync({
    cwd: projectDirectory,
    onlyFiles: true,
  }),
  ...new Bun.Glob("outputs/repro/*").scanSync({
    cwd: projectDirectory,
    onlyFiles: true,
  }),
]
const uploads = [
  ...sourcePaths.map((path) => ({ localPath: path, file_path: path })),
  {
    localPath: "board.circuit.json",
    file_path: "dist/board.circuit.json",
  },
  {
    localPath: "board.circuit.json",
    file_path: "dist/board/circuit.json",
  },
  {
    localPath: "outputs/repro/circuit.json",
    file_path: "dist/repro.circuit/circuit.json",
  },
  {
    localPath: "outputs/repro/circuit.json",
    file_path: "dist/repro/circuit.json",
  },
  { localPath: "outputs/repro/circuit.json", file_path: "dist/circuit.json" },
]
for (const { localPath, file_path } of uploads) {
  if (receipt.filesUploaded.includes(file_path)) continue
  const localFile = Bun.file(resolve(projectDirectory, localPath))
  const archiveFile = {
    file_path,
    ...(file_path.endsWith(".png")
      ? {
          content_base64: Buffer.from(await localFile.arrayBuffer()).toString(
            "base64",
          ),
          content_mimetype: "image/png",
        }
      : {
          content_text: await localFile.text(),
          ...(file_path.endsWith(".svg") && {
            content_mimetype: "image/svg+xml",
          }),
        }),
  }
  await registryRequest("package_files/upload_archive", {
    package_name_with_version: `${packageName}@${receipt.version}`,
    archive_base64: gzipSync(JSON.stringify({ files: [archiveFile] }), {
      level: 9,
    }).toString("base64"),
  })
  receipt.filesUploaded.push(file_path)
  await Bun.write(receiptFile, JSON.stringify(receipt, null, 2))
  console.log(`Uploaded ${file_path}`)
}
await registryRequest("packages/update", {
  package_id: receipt.packageId,
  description: packageJson.description,
})
await registryRequest("package_releases/update", {
  package_release_id: receipt.packageReleaseId,
  ready_to_build: false,
})
const { preview_circuit_json_response: preview } = await registryRequest<{
  preview_circuit_json_response: {
    circuit_json_found: boolean
    circuit_json?: unknown
  }
}>("package_releases/get_preview_circuit_json", {
  package_release_id: receipt.packageReleaseId,
})
receipt.previewVerified =
  preview.circuit_json_found &&
  isDeepStrictEqual(preview.circuit_json, nativeCircuit)
await Bun.write(receiptFile, JSON.stringify(receipt, null, 2))
if (!receipt.previewVerified)
  throw new Error(
    "Published preview is not identical to the verified native export",
  )
console.log(
  JSON.stringify({
    url: `https://tscircuit.com/${packageName}#pcb`,
    files: receipt.filesUploaded.length,
    previewVerified: true,
  }),
)