npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@flow-as-code/tf

v0.2.1

Published

Terraform/OpenTofu emitter: FlowDoc to aws_connect_* resources, .tftpl content, and an awscc version/alias scaffold. One-way in v1.

Readme

flow-as-code

@flow-as-code/tf

npm i @flow-as-code/tf

Apache-2.0, Node 22.12 or newer.

Site and docs: https://flow-as-code.dev/. This package on npm: https://www.npmjs.com/package/@flow-as-code/tf.

Implements docs/03-tf-emitter.md. Deterministic HCL emission, terraform validate-clean when the address map is complete, loud TODO placeholders when it is not. Never emits literal ARNs, provider blocks, or backend config.

One-way: FlowDoc in, HCL out, and this output is not read back. @flow-as-code/hcl writes and reads the provider-native shape (a resource per flow with its actions as blocks), for the flow-as-code/flowascode provider; docs/06-terraform-provider.md says when to pick which.

Use

import { emitTf, writeTf } from "@flow-as-code/tf";

const { files } = emitTf([doc], {
  addressMap: { "queue:front-desk": "aws_connect_queue.front_desk.arn" },
});

writeTf([doc], "infra/flows", { addressMap });

emitTf is pure: documents in, a relative path to content map out, sorted by path and byte-identical across runs. writeTf is the filesystem wrapper; it creates directories, overwrites the files it emits, and touches nothing else in the target directory.

@flow-as-code/tf/emit is the same emitter without the filesystem half. The package index re-exports writeTf, which imports node:fs, so a browser bundle (@flow-as-code/studio's Terraform export) imports the subpath instead.

Output

| File | What it holds | | ------------------------- | ------------------------------------------------------------------------------------------------------------- | | flows/<name>.flow.tftpl | Deployable Flow language JSON, each reference replaced by a templatefile interpolation | | flows.tf | aws_connect_contact_flow / aws_connect_contact_flow_module, plus awscc module version and alias resources | | flow_refs.tf | locals holding the terraform address behind every reference | | variables.tf | The Connect instance id variable, unless instanceIdExpression supplies one | | versions.tf.example | Required providers and versions, as an example; not loaded by either tool |

Provider configuration, credentials, and backend configuration are yours. The emitter writes none of them, by rule.

References

Every ${cdref:type:name} token becomes a template variable named <type>_<name>_arn, hyphens as underscores, with a module alias folded in: queue_front_desk_arn, module_survey_prod_arn. Addresses come from three places, in this order:

  1. The document set itself. A ${cdref:module:x@prod} whose module x is emitted here resolves to awscc_connect_contact_flow_module_alias.x_prod.contact_flow_module_alias_arn; a ${cdref:flow:y} whose flow y is emitted here resolves to that flow. An address map entry for one of these is ignored, and the emitted file says so on the line above.
  2. The address map. Keys are a token (${cdref:queue:front-desk}), the token body (queue:front-desk, module:survey@prod), or the variable name (queue_front_desk_arn). Values are HCL address expressions. A literal ARN is refused, as is anything that would comment out or overrun its line. Entries matching no reference in the set are ignored, so one shared map can serve several flow sets.
  3. Nothing. The entry becomes TODO_MISSING_ADDRESS_<type>_<name> with a # TODO naming the reference. That is an undeclared reference, so terraform validate and tofu validate fail loudly rather than an apply writing a broken flow.

Addresses of resources the set emits itself live in a per-document local (merge(local.flow_refs, { ... })) rather than in the shared map. Putting them in the shared map makes the map depend on the resources rendered from it, and both tools report that as a dependency cycle. Two flows that reference each other are still a cycle, because it is one.

Escaping

The .tftpl body is JSON containing caller text, and caller text legitimately contains ${ and %{, the two sequences HCL reads as template introducers. Every one of them is escaped ($${, %%{) and only the emitter's own reference interpolations are left live. The substitution runs through unique sentinels chosen so they cannot collide with the document, so text that looks like a sentinel is caller text and stays caller text. conformance/emit-tf/hostile-text holds the fixture, and the gated tests render it with a real tofu and compare against a reference implementation of the template grammar.

Versions and aliases

Flow versioning is not available: CreateContactFlowVersion "only supports creating versions for flows of type Campaign" (API reference). Flows update their content in place. Modules get awscc_connect_contact_flow_module_version and awscc_connect_contact_flow_module_alias, which is how a caller pins the module content it invokes. A version snapshots content at create time, so a module content change needs the version resource replaced for aliases to serve it.

Tests

npm test runs the goldens in conformance/emit-tf and the unit tests. The tests that run a real tofu init, tofu validate, tofu fmt, and tofu console need the network and a few minutes on a cold provider cache, so they are gated behind RUN_TOFU_VALIDATE=1:

RUN_TOFU_VALIDATE=1 npx vitest run --project @flow-as-code/tf

CI runs them in the emit-tf job, and an ungated test asserts that the job still sets the variable. Regenerate goldens deliberately with UPDATE_GOLDENS=1 and read the diff.