Publishing & Streams

The three streaming methods—publish, encrypt, and ssl—each return a Node.js EventEmitter rather than taking a callback. The Surge API responds to these operations with a live stream of newline-delimited JSON, and the SDK re-emits each message as an event, so your tool can show real progress while the work happens.

These methods are only available when the client was constructed with the surge-stream module—see Client & Authentication.

Publishing a directory

sdk.publish(projectPath, domain, creds, headers, argv)
Argument Description
projectPath Directory to deploy. Files are gathered recursively, filtered by Surge's default ignore rules plus a .surgeignore file if one exists, then packed into a gzipped tarball and streamed to the API.
domain Target domain, e.g. "my-site.surge.sh".
creds Credentials—normally { user: "token", pass: token }.
headers Optional object of extra HTTP headers. This is how deploy metadata travels: version (your client's version), file-count, project-size, message, stage, and so on.
argv Optional parsed-arguments object; serialized into an argv header for the server.

A complete example, modelled on how the CLI itself deploys:

sdk.publish("./my-site", "my-site.surge.sh",
  { user: "token", pass: token },
  {
    "version":      "1.0.0",           // your tool's version
    "file-count":   42,
    "project-size": 123456,
    "timestamp":    new Date().toJSON()
  }
)
.on("progress", function(p){
  // p.id is the phase: "upload", "cdn", or "encrypt"
  // p.written / p.total track completion; p.file names the current file
})
.on("info", function(info){
  // The deploy result: info.urls, info.instances, info.metadata
})
.on("success", function(){ console.log("Published!") })
.on("fail",    function(){ console.error("Deploy failed") })

Stream events

Every JSON message from the server is emitted twice: once as a generic data event with the full object, and once as an event named after the message's type field. On top of those, the client emits lifecycle events of its own.

Server-sent events

Event Payload Meaning
progress { id, written, total, file } Progress through a phase. id is "upload" (tarball going up), "cdn" (files propagating to the edge), or "encrypt" (certificate provisioning).
info { urls, instances, metadata, config, certs } The deploy succeeded. urls lists where the project is reachable; metadata.preview holds the preview URL for staged deploys.
users { users: [...] } Collaborators on the project, when changed during publish.
cert / ssl { data: { issuer, altnames, expiresInWords } } Certificate details.
subscription { data: subscription } The project's plan, when applicable.
collect { plan, card, stripe_pk } The operation requires a plan or payment before it can proceed.
msg { payload: { msg, status } } A human-readable server message.

Client lifecycle events

Event Meaning
success The stream ended after an info message was received. The deploy is live.
fail The stream ended without an info message, or the request failed outright.
error A transport error occurred on the response stream.
unauthorized HTTP 401—the token is invalid or expired. Payload is the server's reason string.
forbidden HTTP 403—authenticated but not permitted (not a collaborator, rate limited, project too large). Payload is the reason string.
invalid HTTP 422—the domain is invalid.

Treat success/fail as the authoritative outcome; info merely carries the result payload.

Provisioning a certificate

encrypt asks the platform to provision a free SSL certificate for a custom domain. Same event model, no request body:

sdk.encrypt("example.com", { user: "token", pass: token }, { version: "1.0.0" })
  .on("cert",    function(c){ console.log("Issued by " + c.data.issuer) })
  .on("success", function(){ console.log("Certificate active") })
  .on("fail",    function(){ console.error("Could not provision certificate") })

Uploading a custom certificate

ssl streams a PEM file (certificate + key bundle) to the platform, for projects on a paid plan that bring their own certificate:

sdk.ssl("./cert.pem", "example.com",
  { user: "token", pass: token },
  { version: "1.0.0" }
)
.on("msg",  function(m){ console.log(m.payload.msg) })   // "the pem file has been applied"
.on("fail", function(){ console.error("PEM rejected") })

The server validates the PEM before accepting it; an invalid bundle produces a fail with an HTTP 400.