how can I load a file from inside a component resource into an AssetArchive?
TypeScriptSure! You can do this by using the
pulumi.asset.FileAssetto identify the file andpulumi.asset.AssetArchiveto archive it. Below is a TypeScript example where we define a new ComponentResource, and inside of it we create anAssetArchivethat includes a file:import * as pulumi from "@pulumi/pulumi"; import { ComponentResourceOptions } from "@pulumi/pulumi/ComponentResource"; import { AssetArchive, FileAsset } from "@pulumi/pulumi/asset"; class MyComponent extends pulumi.ComponentResource { public readonly archive: pulumi.Output<AssetArchive>; constructor(name: string, opts?: ComponentResourceOptions) { super("pkg:index:MyComponent", name, {}, opts); // This assumes you have a local file named `example.txt` available. this.archive = pulumi.output(new AssetArchive({ "example.txt": new FileAsset("example.txt"), })); // To finish the initialization of this component resource, // register its outputs using `this.registerOutputs()`. // You do not ordinarily need to register inputs, but you may choose to register // outputs to ensure they are available as properties off of `this` before `this`'s constructor finishes running. this.registerOutputs({ archive: this.archive }) } } // Create an instance of the component const comp = new MyComponent("myComponent");Here,
example.txtis the name of the local file, and we're loading it into anAssetArchiveinside ourMyComponentresource. This archive is then accessible from the component instance viacomp.archive. This assumes thatexample.txtis in your Pulumi project's root directory. If it isn't, you'll need to adjust the path to the file accordingly.More information can be found in the Pulumi Programming Model documentation.
this loads from the consuming project's path. how can I load the file from the path of the ComponentResource?
TypeScriptYou need to compute the absolute path to the file you want to load, relative to your ComponentResource file. You can achieve that by using Node.js built-in
pathmodule. Here is an example:import * as pulumi from "@pulumi/pulumi"; import { AssetArchive, FileAsset } from "@pulumi/pulumi/asset"; import * as path from "path"; class MyComponent extends pulumi.ComponentResource { public readonly archive: pulumi.Output<AssetArchive>; constructor(name: string, opts?: pulumi.ComponentResourceOptions) { super("pkg:index:MyComponent", name, {}, opts); const filePath = path.join(__dirname, "example.txt"); this.archive = pulumi.output(new AssetArchive({ "example.txt": new FileAsset(filePath), })); this.registerOutputs({ archive: this.archive }); } } // Create an instance of the component const comp = new MyComponent("myComponent");In this example,
__dirnameis a Node.js variable that gets the directory name of the current module (in this case, the filepath where your ComponentResource resides). It uses the path module to join__dirnameand the filename to get the absolute path. This way, it will always load the file starting from the Component's own directory path, regardless of the consuming project's path.That doesn't work in ES modules, how can I make it work there?
TypeScriptThe issue you're facing may be related to how CommonJS modules (like the original Pulumi SDK) are imported into ESModules. In ESModules, the syntax is slightly different. You can convert the example to work with ES modules by using the
import * assyntax and then referencing the constructors properly. Here is the updated code:import * as pulumi from "@pulumi/pulumi"; import { Output } from "@pulumi/pulumi"; import { AssetArchive, FileAsset } from "@pulumi/pulumi/asset"; import * as path from "path"; class MyComponent extends pulumi.ComponentResource { public readonly archive: Output<AssetArchive>; constructor(name: string, opts?: pulumi.ComponentResourceOptions) { super("pkg:index:MyComponent", name, {}, opts); const filePath = path.join(__dirname, "example.txt"); this.archive = new Output( new AssetArchive({ "example.txt": new FileAsset(filePath), }) ); this.registerOutputs({ archive: this.archive }); } } // Create an instance of the component const comp = new MyComponent("myComponent");I hope this helps! Let me know if you have further questions.
no, it doesn't work because __dirname is not defined
TypeScriptI see you're having trouble with
__dirnamebeing undefined. This could be happening if you are using a module system other than CommonJS, such as ESM. In Node.js,__dirnameis a local variable that's made available to modules by the CommonJS module system. It contains the directory path of the current module file.Here's how you can replicate the
__dirnamefunctionality in ESM:import { fileURLToPath } from 'url'; import { dirname } from 'path'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename);The above code creates two variables,
__filenameand__dirname, which are the equivalent of their CommonJS counterparts. First,import.meta.urlis converted from a URL to a file path to get the file path of the current module. Then this file path is used to get the directory path.If you are using CommonJS (i.e., you are using
requireto load modules and your file extension is.jsrather than.mjs),__dirnameshould be defined. If it's not, there's likely another issue with your code. If you're not able to resolve the issue, please provide the code that's causing this error so I can assist you better.