From a075fb96914d3ea2a4c7abb157c9ba41ede11f17 Mon Sep 17 00:00:00 2001 From: Tsiry Sandratraina Date: Tue, 30 Jan 2024 17:41:34 +0000 Subject: [PATCH] fix issue with dagger connect ci: fix zenith workflow ci: fix zenith workflow --- .github/workflows/ci.yml | 2 +- .github/workflows/example.yml | 4 +- .github/workflows/zenith.yml | 9 +- README.md | 2 +- ci.ts | 2 +- deno.json | 3 +- deps.ts | 2 +- example/.fluentci/deps.ts | 2 +- example/.fluentci/sdk/builder.ts | 30 + example/.fluentci/sdk/client.gen.ts | 5690 ++++++++++++++------------ example/.fluentci/sdk/client.ts | 9 + example/.fluentci/sdk/connect.ts | 50 +- example/.fluentci/sdk/context.ts | 53 + example/.fluentci/sdk/utils.ts | 9 +- example/.fluentci/src/dagger/jobs.ts | 135 +- example/.fluentci/src/dagger/lib.ts | 25 +- sdk/builder.ts | 30 + sdk/client.gen.ts | 5690 ++++++++++++++------------ sdk/client.ts | 9 + sdk/connect.ts | 50 +- sdk/context.ts | 53 + sdk/utils.ts | 9 +- src/dagger/jobs.ts | 135 +- src/dagger/lib.ts | 25 +- 24 files changed, 6698 insertions(+), 5330 deletions(-) create mode 100644 example/.fluentci/sdk/builder.ts create mode 100644 example/.fluentci/sdk/client.ts create mode 100644 example/.fluentci/sdk/context.ts create mode 100644 sdk/builder.ts create mode 100644 sdk/client.ts create mode 100644 sdk/context.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d042c82..e37c26d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: with: deno-version: v1.37 - name: Setup Fluent CI CLI - uses: fluentci-io/setup-fluentci@v2 + uses: fluentci-io/setup-fluentci@v3 - name: Run Dagger Pipelines run: fluentci run deno_pipeline fmt lint test - name: Upload to Codecov diff --git a/.github/workflows/example.yml b/.github/workflows/example.yml index 0c51744..4515916 100644 --- a/.github/workflows/example.yml +++ b/.github/workflows/example.yml @@ -9,7 +9,7 @@ jobs: tests: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: denoland/setup-deno@v1 with: deno-version: v1.37 @@ -17,7 +17,7 @@ jobs: run: deno install -A -r https://cli.fluentci.io -n fluentci - name: Setup Dagger run: | - curl -L https://dl.dagger.io/dagger/install.sh | DAGGER_VERSION=0.9.3 sh + curl -L https://dl.dagger.io/dagger/install.sh | DAGGER_VERSION=0.9.7 sh sudo mv bin/dagger /usr/local/bin dagger version - name: Setup Service Account diff --git a/.github/workflows/zenith.yml b/.github/workflows/zenith.yml index 49a83e9..6827fb8 100644 --- a/.github/workflows/zenith.yml +++ b/.github/workflows/zenith.yml @@ -10,10 +10,10 @@ jobs: tests: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup Dagger Zenith run: | - curl -L https://dl.dagger.io/dagger/install.sh | DAGGER_VERSION=0.9.3 sh + curl -L https://dl.dagger.io/dagger/install.sh | DAGGER_VERSION=0.9.7 sh sudo mv bin/dagger /usr/local/bin dagger version - name: Setup Pulumi Access Token @@ -30,8 +30,9 @@ jobs: working-directory: example - name: Run Dagger Pipelines run: | - dagger query --doc preview.gql - dagger query --doc up.gql + dagger call preview --src . --stack dev --token PULUMI_ACCESS_TOKEN --google-application-credentials ./fluentci-086b644d4c53.json + dagger call up --src . --stack dev --token PULUMI_ACCESS_TOKEN --google-application-credentials ./fluentci-086b644d4c53.json working-directory: example env: GOOGLE_APPLICATION_CREDENTIALS: ./fluentci-086b644d4c53.json + PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }} diff --git a/README.md b/README.md index a6a08c9..e607a9f 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ up( You can also use this pipeline programmatically: ```ts -import { preview, up } from "https://pkg.fluentci.io/pulumi_pipeline@v0.3.0/mod.ts"; +import { preview, up } from "https://pkg.fluentci.io/pulumi_pipeline@v0.3.1/mod.ts"; await preview( ".", diff --git a/ci.ts b/ci.ts index 80df3dd..5020b6c 100644 --- a/ci.ts +++ b/ci.ts @@ -1,7 +1,7 @@ import { preview, up, -} from "https://pkg.fluentci.io/pulumi_pipeline@v0.3.0/mod.ts"; +} from "https://pkg.fluentci.io/pulumi_pipeline@v0.3.1/mod.ts"; await preview(); await up(); diff --git a/deno.json b/deno.json index e0e77b5..b9812cf 100644 --- a/deno.json +++ b/deno.json @@ -25,7 +25,8 @@ "exclude": [ "example/", ".fluentci/", - "gen/" + "gen/", + "sdk/" ] } } \ No newline at end of file diff --git a/deps.ts b/deps.ts index 5c178a9..1ec36cc 100644 --- a/deps.ts +++ b/deps.ts @@ -1,7 +1,7 @@ export { assertEquals } from "https://deno.land/std@0.191.0/testing/asserts.ts"; export type { DirectoryID, SecretID } from "./sdk/client.gen.ts"; -export { Directory, Secret, File, Container } from "./sdk/client.gen.ts"; +export { Directory, Secret, File, Container, dag } from "./sdk/client.gen.ts"; export { connect, uploadContext } from "https://sdk.fluentci.io/v0.3.0/mod.ts"; export { brightGreen } from "https://deno.land/std@0.191.0/fmt/colors.ts"; export { withDevbox } from "https://nix.fluentci.io/v0.5.3/src/dagger/steps.ts"; diff --git a/example/.fluentci/deps.ts b/example/.fluentci/deps.ts index 5c178a9..1ec36cc 100644 --- a/example/.fluentci/deps.ts +++ b/example/.fluentci/deps.ts @@ -1,7 +1,7 @@ export { assertEquals } from "https://deno.land/std@0.191.0/testing/asserts.ts"; export type { DirectoryID, SecretID } from "./sdk/client.gen.ts"; -export { Directory, Secret, File, Container } from "./sdk/client.gen.ts"; +export { Directory, Secret, File, Container, dag } from "./sdk/client.gen.ts"; export { connect, uploadContext } from "https://sdk.fluentci.io/v0.3.0/mod.ts"; export { brightGreen } from "https://deno.land/std@0.191.0/fmt/colors.ts"; export { withDevbox } from "https://nix.fluentci.io/v0.5.3/src/dagger/steps.ts"; diff --git a/example/.fluentci/sdk/builder.ts b/example/.fluentci/sdk/builder.ts new file mode 100644 index 0000000..f06951a --- /dev/null +++ b/example/.fluentci/sdk/builder.ts @@ -0,0 +1,30 @@ +import { createGQLClient } from "./client.ts"; +import { Context } from "./context.ts"; + +/** + * @hidden + * + * Initialize a default client context from environment. + */ +export function initDefaultContext(): Context { + let ctx = new Context(); + + // Prefer DAGGER_SESSION_PORT if set + const daggerSessionPort = Deno.env.get("DAGGER_SESSION_PORT"); + if (daggerSessionPort) { + const sessionToken = Deno.env.get("DAGGER_SESSION_TOKEN"); + if (!sessionToken) { + throw new Error( + "DAGGER_SESSION_TOKEN must be set when using DAGGER_SESSION_PORT" + ); + } + + ctx = new Context({ + client: createGQLClient(Number(daggerSessionPort), sessionToken), + }); + } else { + throw new Error("DAGGER_SESSION_PORT must be set"); + } + + return ctx; +} diff --git a/example/.fluentci/sdk/client.gen.ts b/example/.fluentci/sdk/client.gen.ts index d18ad57..b128be8 100644 --- a/example/.fluentci/sdk/client.gen.ts +++ b/example/.fluentci/sdk/client.gen.ts @@ -2,62 +2,48 @@ * This file was auto-generated by `client-gen`. * Do not make direct changes to the file. */ -import { GraphQLClient } from "../deps.ts" - -import { computeQuery } from "./utils.ts" +import { Context, defaultContext } from "./context.ts"; +import { computeQuery } from "./utils.ts"; /** * @hidden */ export type QueryTree = { - operation: string - args?: Record -} + operation: string; + args?: Record; +}; /** * @hidden */ export type Metadata = { [key: string]: { - is_enum?: boolean - } -} + is_enum?: boolean; + }; +}; interface ClientConfig { - queryTree?: QueryTree[] - host?: string - sessionToken?: string + queryTree?: QueryTree[]; + ctx?: Context; } class BaseClient { - protected _queryTree: QueryTree[] - protected client: GraphQLClient - /** - * @defaultValue `127.0.0.1:8080` - */ - public clientHost: string - public sessionToken: string + protected _queryTree: QueryTree[]; + protected _ctx: Context; /** * @hidden */ - constructor({ queryTree, host, sessionToken }: ClientConfig = {}) { - this._queryTree = queryTree || [] - this.clientHost = host || "127.0.0.1:8080" - this.sessionToken = sessionToken || "" - this.client = new GraphQLClient(`http://${host}/query`, { - headers: { - Authorization: - "Basic " + btoa(sessionToken + ":"), - }, - }) + constructor({ queryTree, ctx }: ClientConfig = {}) { + this._queryTree = queryTree || []; + this._ctx = ctx || new Context(); } /** * @hidden */ get queryTree() { - return this._queryTree + return this._queryTree; } } @@ -65,22 +51,20 @@ export type BuildArg = { /** * The build argument name. */ - name: string + name: string; /** * The build argument value. */ - value: string -} + value: string; +}; /** * Sharing mode of the cache volume. */ export enum CacheSharingMode { - /** - * Shares the cache volume amongst many build pipelines, - * but will serialize the writes + * Shares the cache volume amongst many build pipelines, but will serialize the writes */ Locked = "LOCKED", @@ -95,555 +79,567 @@ export enum CacheSharingMode { Shared = "SHARED", } /** - * A global cache volume identifier. + * The `CacheVolumeID` scalar type represents an identifier for an object of type CacheVolume. */ -export type CacheVolumeID = string & {__CacheVolumeID: never} +export type CacheVolumeID = string & { __CacheVolumeID: never }; export type ContainerAsTarballOpts = { /** * Identifiers for other platform specific containers. - * Used for multi-platform image. + * + * Used for multi-platform images. */ - platformVariants?: Container[] + platformVariants?: Container[]; /** * Force each layer of the image to use the specified compression algorithm. - * If this is unset, then if a layer already has a compressed blob in the engine's - * cache, that will be used (this can result in a mix of compression algorithms for - * different layers). If this is unset and a layer has no compressed blob in the - * engine's cache, then it will be compressed using Gzip. + * + * If this is unset, then if a layer already has a compressed blob in the engine's cache, that will be used (this can result in a mix of compression algorithms for different layers). If this is unset and a layer has no compressed blob in the engine's cache, then it will be compressed using Gzip. */ - forcedCompression?: ImageLayerCompression + forcedCompression?: ImageLayerCompression; /** - * Use the specified media types for the image's layers. Defaults to OCI, which - * is largely compatible with most recent container runtimes, but Docker may be needed - * for older runtimes without OCI support. + * Use the specified media types for the image's layers. + * + * Defaults to OCI, which is largely compatible with most recent container runtimes, but Docker may be needed for older runtimes without OCI support. */ - mediaTypes?: ImageMediaTypes -} + mediaTypes?: ImageMediaTypes; +}; export type ContainerBuildOpts = { /** * Path to the Dockerfile to use. - * - * Default: './Dockerfile'. */ - dockerfile?: string + dockerfile?: string; /** - * Additional build arguments. + * Target build stage to build. */ - buildArgs?: BuildArg[] + target?: string; /** - * Target build stage to build. + * Additional build arguments. */ - target?: string + buildArgs?: BuildArg[]; /** * Secrets to pass to the build. - * + * * They will be mounted at /run/secrets/[secret-name] in the build container - * - * They can be accessed in the Dockerfile using the "secret" mount type - * and mount path /run/secrets/[secret-name] - * e.g. RUN --mount=type=secret,id=my-secret curl url?token=$(cat /run/secrets/my-secret)" + * + * They can be accessed in the Dockerfile using the "secret" mount type and mount path /run/secrets/[secret-name], e.g. RUN --mount=type=secret,id=my-secret curl http://example.com?token=$(cat /run/secrets/my-secret) */ - secrets?: Secret[] -} + secrets?: Secret[]; +}; export type ContainerExportOpts = { /** * Identifiers for other platform specific containers. + * * Used for multi-platform image. */ - platformVariants?: Container[] + platformVariants?: Container[]; /** * Force each layer of the exported image to use the specified compression algorithm. - * If this is unset, then if a layer already has a compressed blob in the engine's - * cache, that will be used (this can result in a mix of compression algorithms for - * different layers). If this is unset and a layer has no compressed blob in the - * engine's cache, then it will be compressed using Gzip. + * + * If this is unset, then if a layer already has a compressed blob in the engine's cache, that will be used (this can result in a mix of compression algorithms for different layers). If this is unset and a layer has no compressed blob in the engine's cache, then it will be compressed using Gzip. */ - forcedCompression?: ImageLayerCompression + forcedCompression?: ImageLayerCompression; /** - * Use the specified media types for the exported image's layers. Defaults to OCI, which - * is largely compatible with most recent container runtimes, but Docker may be needed - * for older runtimes without OCI support. + * Use the specified media types for the exported image's layers. + * + * Defaults to OCI, which is largely compatible with most recent container runtimes, but Docker may be needed for older runtimes without OCI support. */ - mediaTypes?: ImageMediaTypes -} + mediaTypes?: ImageMediaTypes; +}; export type ContainerImportOpts = { /** - * Identifies the tag to import from the archive, if the archive bundles - * multiple tags. + * Identifies the tag to import from the archive, if the archive bundles multiple tags. */ - tag?: string -} + tag?: string; +}; export type ContainerPipelineOpts = { /** - * Pipeline description. + * Description of the sub-pipeline. */ - description?: string + description?: string; /** - * Pipeline labels. + * Labels to apply to the sub-pipeline. */ - labels?: PipelineLabel[] -} + labels?: PipelineLabel[]; +}; export type ContainerPublishOpts = { /** * Identifiers for other platform specific containers. + * * Used for multi-platform image. */ - platformVariants?: Container[] + platformVariants?: Container[]; /** * Force each layer of the published image to use the specified compression algorithm. - * If this is unset, then if a layer already has a compressed blob in the engine's - * cache, that will be used (this can result in a mix of compression algorithms for - * different layers). If this is unset and a layer has no compressed blob in the - * engine's cache, then it will be compressed using Gzip. - */ - forcedCompression?: ImageLayerCompression - - /** - * Use the specified media types for the published image's layers. Defaults to OCI, which - * is largely compatible with most recent registries, but Docker may be needed for older - * registries without OCI support. + * + * If this is unset, then if a layer already has a compressed blob in the engine's cache, that will be used (this can result in a mix of compression algorithms for different layers). If this is unset and a layer has no compressed blob in the engine's cache, then it will be compressed using Gzip. */ - mediaTypes?: ImageMediaTypes -} + forcedCompression?: ImageLayerCompression; -export type ContainerWithDefaultArgsOpts = { /** - * Arguments to prepend to future executions (e.g., ["-v", "--no-cache"]). + * Use the specified media types for the published image's layers. + * + * Defaults to OCI, which is largely compatible with most recent registries, but Docker may be needed for older registries without OCI support. */ - args?: string[] -} + mediaTypes?: ImageMediaTypes; +}; export type ContainerWithDirectoryOpts = { /** - * Patterns to exclude in the written directory (e.g., ["node_modules/**", ".gitignore", ".git/"]). + * Patterns to exclude in the written directory (e.g. ["node_modules/**", ".gitignore", ".git/"]). */ - exclude?: string[] + exclude?: string[]; /** - * Patterns to include in the written directory (e.g., ["*.go", "go.mod", "go.sum"]). + * Patterns to include in the written directory (e.g. ["*.go", "go.mod", "go.sum"]). */ - include?: string[] + include?: string[]; /** * A user:group to set for the directory and its contents. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string -} + owner?: string; +}; + +export type ContainerWithEntrypointOpts = { + /** + * Don't remove the default arguments when setting the entrypoint. + */ + keepDefaultArgs?: boolean; +}; export type ContainerWithEnvVariableOpts = { /** - * Replace ${VAR} or $VAR in the value according to the current environment - * variables defined in the container (e.g., "/opt/bin:$PATH"). + * Replace `${VAR}` or `$VAR` in the value according to the current environment variables defined in the container (e.g., "/opt/bin:$PATH"). */ - expand?: boolean -} + expand?: boolean; +}; export type ContainerWithExecOpts = { /** * If the container has an entrypoint, ignore it for args rather than using it to wrap them. */ - skipEntrypoint?: boolean + skipEntrypoint?: boolean; /** * Content to write to the command's standard input before closing (e.g., "Hello world"). */ - stdin?: string + stdin?: string; /** * Redirect the command's standard output to a file in the container (e.g., "/tmp/stdout"). */ - redirectStdout?: string + redirectStdout?: string; /** * Redirect the command's standard error to a file in the container (e.g., "/tmp/stderr"). */ - redirectStderr?: string + redirectStderr?: string; /** * Provides dagger access to the executed command. - * - * Do not use this option unless you trust the command being executed. - * The command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM. + * + * Do not use this option unless you trust the command being executed; the command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM. */ - experimentalPrivilegedNesting?: boolean + experimentalPrivilegedNesting?: boolean; /** - * Execute the command with all root capabilities. This is similar to running a command - * with "sudo" or executing `docker run` with the `--privileged` flag. Containerization - * does not provide any security guarantees when using this option. It should only be used - * when absolutely necessary and only with trusted commands. + * Execute the command with all root capabilities. This is similar to running a command with "sudo" or executing "docker run" with the "--privileged" flag. Containerization does not provide any security guarantees when using this option. It should only be used when absolutely necessary and only with trusted commands. */ - insecureRootCapabilities?: boolean -} + insecureRootCapabilities?: boolean; +}; export type ContainerWithExposedPortOpts = { /** * Transport layer network protocol */ - protocol?: NetworkProtocol + protocol?: NetworkProtocol; /** * Optional port description */ - description?: string -} + description?: string; +}; export type ContainerWithFileOpts = { /** * Permission given to the copied file (e.g., 0600). - * - * Default: 0644. */ - permissions?: number + permissions?: number; /** * A user:group to set for the file. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string -} + owner?: string; +}; export type ContainerWithMountedCacheOpts = { /** * Identifier of the directory to use as the cache volume's root. */ - source?: Directory + source?: Directory; /** * Sharing mode of the cache volume. */ - sharing?: CacheSharingMode + sharing?: CacheSharingMode; /** * A user:group to set for the mounted cache directory. - * - * Note that this changes the ownership of the specified mount along with the - * initial filesystem provided by source (if any). It does not have any effect - * if/when the cache has already been created. - * + * + * Note that this changes the ownership of the specified mount along with the initial filesystem provided by source (if any). It does not have any effect if/when the cache has already been created. + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string -} + owner?: string; +}; export type ContainerWithMountedDirectoryOpts = { /** * A user:group to set for the mounted directory and its contents. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string -} + owner?: string; +}; export type ContainerWithMountedFileOpts = { /** * A user or user:group to set for the mounted file. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string -} + owner?: string; +}; export type ContainerWithMountedSecretOpts = { /** * A user:group to set for the mounted secret. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string + owner?: string; /** * Permission given to the mounted secret (e.g., 0600). + * * This option requires an owner to be set to be active. - * - * Default: 0400. */ - mode?: number -} + mode?: number; +}; export type ContainerWithNewFileOpts = { /** * Content of the file to write (e.g., "Hello world!"). */ - contents?: string + contents?: string; /** * Permission given to the written file (e.g., 0600). - * - * Default: 0644. */ - permissions?: number + permissions?: number; /** * A user:group to set for the file. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string -} + owner?: string; +}; export type ContainerWithUnixSocketOpts = { /** * A user:group to set for the mounted socket. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string -} + owner?: string; +}; + +export type ContainerWithoutEntrypointOpts = { + /** + * Don't remove the default arguments when unsetting the entrypoint. + */ + keepDefaultArgs?: boolean; +}; export type ContainerWithoutExposedPortOpts = { /** * Port protocol to unexpose */ - protocol?: NetworkProtocol -} - -/** - * A unique container identifier. Null designates an empty container (scratch). - */ -export type ContainerID = string & {__ContainerID: never} + protocol?: NetworkProtocol; +}; /** - * The `DateTime` scalar type represents a DateTime. The DateTime is serialized as an RFC 3339 quoted string + * The `ContainerID` scalar type represents an identifier for an object of type Container. */ -export type DateTime = string & {__DateTime: never} +export type ContainerID = string & { __ContainerID: never }; export type DirectoryAsModuleOpts = { /** - * An optional subpath of the directory which contains the module's source - * code. - * - * This is needed when the module code is in a subdirectory but requires - * parent directories to be loaded in order to execute. For example, the - * module source code may need a go.mod, project.toml, package.json, etc. file - * from a parent directory. - * - * If not set, the module source code is loaded from the root of the - * directory. - */ - sourceSubpath?: string -} + * An optional subpath of the directory which contains the module's source code. + * + * This is needed when the module code is in a subdirectory but requires parent directories to be loaded in order to execute. For example, the module source code may need a go.mod, project.toml, package.json, etc. file from a parent directory. + * + * If not set, the module source code is loaded from the root of the directory. + */ + sourceSubpath?: string; +}; export type DirectoryDockerBuildOpts = { /** - * Path to the Dockerfile to use (e.g., "frontend.Dockerfile"). - * - * Defaults: './Dockerfile'. + * The platform to build. */ - dockerfile?: string + platform?: Platform; /** - * The platform to build. + * Path to the Dockerfile to use (e.g., "frontend.Dockerfile"). */ - platform?: Platform + dockerfile?: string; /** - * Build arguments to use in the build. + * Target build stage to build. */ - buildArgs?: BuildArg[] + target?: string; /** - * Target build stage to build. + * Build arguments to use in the build. */ - target?: string + buildArgs?: BuildArg[]; /** * Secrets to pass to the build. - * + * * They will be mounted at /run/secrets/[secret-name]. */ - secrets?: Secret[] -} + secrets?: Secret[]; +}; export type DirectoryEntriesOpts = { /** * Location of the directory to look at (e.g., "/src"). */ - path?: string -} + path?: string; +}; export type DirectoryPipelineOpts = { /** - * Pipeline description. + * Description of the sub-pipeline. */ - description?: string + description?: string; /** - * Pipeline labels. + * Labels to apply to the sub-pipeline. */ - labels?: PipelineLabel[] -} + labels?: PipelineLabel[]; +}; export type DirectoryWithDirectoryOpts = { /** * Exclude artifacts that match the given pattern (e.g., ["node_modules/", ".git*"]). */ - exclude?: string[] + exclude?: string[]; /** * Include only artifacts that match the given pattern (e.g., ["app/", "package.*"]). */ - include?: string[] -} + include?: string[]; +}; export type DirectoryWithFileOpts = { /** * Permission given to the copied file (e.g., 0600). - * - * Default: 0644. */ - permissions?: number -} + permissions?: number; +}; export type DirectoryWithNewDirectoryOpts = { /** * Permission granted to the created directory (e.g., 0777). - * - * Default: 0755. */ - permissions?: number -} + permissions?: number; +}; export type DirectoryWithNewFileOpts = { /** * Permission given to the copied file (e.g., 0600). - * - * Default: 0644. */ - permissions?: number -} + permissions?: number; +}; + +/** + * The `DirectoryID` scalar type represents an identifier for an object of type Directory. + */ +export type DirectoryID = string & { __DirectoryID: never }; + +/** + * The `EnvVariableID` scalar type represents an identifier for an object of type EnvVariable. + */ +export type EnvVariableID = string & { __EnvVariableID: never }; /** - * A content-addressed directory identifier. + * The `FieldTypeDefID` scalar type represents an identifier for an object of type FieldTypeDef. */ -export type DirectoryID = string & {__DirectoryID: never} +export type FieldTypeDefID = string & { __FieldTypeDefID: never }; export type FileExportOpts = { /** - * If allowParentDirPath is true, the path argument can be a directory path, in which case - * the file will be created in that directory. + * If allowParentDirPath is true, the path argument can be a directory path, in which case the file will be created in that directory. */ - allowParentDirPath?: boolean -} + allowParentDirPath?: boolean; +}; /** - * A file identifier. + * The `FileID` scalar type represents an identifier for an object of type File. */ -export type FileID = string & {__FileID: never} +export type FileID = string & { __FileID: never }; export type FunctionWithArgOpts = { /** * A doc string for the argument, if any */ - description?: string + description?: string; /** * A default value to use for this argument if not explicitly set by the caller, if any */ - defaultValue?: JSON -} + defaultValue?: JSON; +}; + +/** + * The `FunctionArgID` scalar type represents an identifier for an object of type FunctionArg. + */ +export type FunctionArgID = string & { __FunctionArgID: never }; + +/** + * The `FunctionCallArgValueID` scalar type represents an identifier for an object of type FunctionCallArgValue. + */ +export type FunctionCallArgValueID = string & { + __FunctionCallArgValueID: never; +}; /** - * A reference to a FunctionArg. + * The `FunctionCallID` scalar type represents an identifier for an object of type FunctionCall. */ -export type FunctionArgID = string & {__FunctionArgID: never} +export type FunctionCallID = string & { __FunctionCallID: never }; /** - * A reference to a Function. + * The `FunctionID` scalar type represents an identifier for an object of type Function. */ -export type FunctionID = string & {__FunctionID: never} +export type FunctionID = string & { __FunctionID: never }; /** - * A reference to GeneratedCode. + * The `GeneratedCodeID` scalar type represents an identifier for an object of type GeneratedCode. */ -export type GeneratedCodeID = string & {__GeneratedCodeID: never} +export type GeneratedCodeID = string & { __GeneratedCodeID: never }; export type GitRefTreeOpts = { - sshKnownHosts?: string - sshAuthSocket?: Socket -} + /** + * DEPRECATED: This option should be passed to `git` instead. + */ + sshKnownHosts?: string; + + /** + * DEPRECATED: This option should be passed to `git` instead. + */ + sshAuthSocket?: Socket; +}; + +/** + * The `GitRefID` scalar type represents an identifier for an object of type GitRef. + */ +export type GitRefID = string & { __GitRefID: never }; + +/** + * The `GitRepositoryID` scalar type represents an identifier for an object of type GitRepository. + */ +export type GitRepositoryID = string & { __GitRepositoryID: never }; export type HostDirectoryOpts = { /** * Exclude artifacts that match the given pattern (e.g., ["node_modules/", ".git*"]). */ - exclude?: string[] + exclude?: string[]; /** * Include only artifacts that match the given pattern (e.g., ["app/", "package.*"]). */ - include?: string[] -} + include?: string[]; +}; export type HostServiceOpts = { /** * Upstream host to forward traffic to. */ - host?: string -} + host?: string; -export type HostTunnelOpts = { /** - * Map each service port to the same port on the host, as if the service were - * running natively. - * - * Note: enabling may result in port conflicts. + * Ports to expose via the service, forwarding through the host network. + * + * If a port's frontend is unspecified or 0, it defaults to the same as the backend port. + * + * An empty set of ports is not valid; an error will be returned. */ - native?: boolean + ports: PortForward[]; +}; +export type HostTunnelOpts = { /** * Configure explicit port forwarding rules for the tunnel. - * - * If a port's frontend is unspecified or 0, a random port will be chosen by - * the host. - * - * If no ports are given, all of the service's ports are forwarded. If native - * is true, each port maps to the same port on the host. If native is false, - * each port maps to a random port chosen by the host. - * + * + * If a port's frontend is unspecified or 0, a random port will be chosen by the host. + * + * If no ports are given, all of the service's ports are forwarded. If native is true, each port maps to the same port on the host. If native is false, each port maps to a random port chosen by the host. + * * If ports are given and native is true, the ports are additive. */ - ports?: PortForward[] -} + ports?: PortForward[]; + + /** + * Map each service port to the same port on the host, as if the service were running natively. + * + * Note: enabling may result in port conflicts. + */ + native?: boolean; +}; /** - * The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. + * The `HostID` scalar type represents an identifier for an object of type Host. */ -export type ID = string & {__ID: never} +export type HostID = string & { __HostID: never }; /** * Compression algorithm to use for image layers. @@ -661,253 +657,297 @@ export enum ImageMediaTypes { Dockermediatypes = "DockerMediaTypes", Ocimediatypes = "OCIMediaTypes", } +/** + * The `InterfaceTypeDefID` scalar type represents an identifier for an object of type InterfaceTypeDef. + */ +export type InterfaceTypeDefID = string & { __InterfaceTypeDefID: never }; + /** * An arbitrary JSON-encoded value. */ -export type JSON = string & {__JSON: never} +export type JSON = string & { __JSON: never }; /** - * A reference to a Module. + * The `LabelID` scalar type represents an identifier for an object of type Label. */ -export type ModuleID = string & {__ModuleID: never} +export type LabelID = string & { __LabelID: never }; /** - * Transport layer network protocol associated to a port. + * The `ListTypeDefID` scalar type represents an identifier for an object of type ListTypeDef. */ -export enum NetworkProtocol { +export type ListTypeDefID = string & { __ListTypeDefID: never }; +export type ModuleWithSourceOpts = { /** - * TCP (Transmission Control Protocol) + * An optional subpath of the directory which contains the module's source code. + * + * This is needed when the module code is in a subdirectory but requires parent directories to be loaded in order to execute. For example, the module source code may need a go.mod, project.toml, package.json, etc. file from a parent directory. + * + * If not set, the module source code is loaded from the root of the directory. */ - Tcp = "TCP", + subpath?: string; +}; - /** - * UDP (User Datagram Protocol) - */ +/** + * The `ModuleConfigID` scalar type represents an identifier for an object of type ModuleConfig. + */ +export type ModuleConfigID = string & { __ModuleConfigID: never }; + +/** + * The `ModuleID` scalar type represents an identifier for an object of type Module. + */ +export type ModuleID = string & { __ModuleID: never }; + +/** + * Transport layer network protocol associated to a port. + */ +export enum NetworkProtocol { + Tcp = "TCP", Udp = "UDP", } +/** + * The `ObjectTypeDefID` scalar type represents an identifier for an object of type ObjectTypeDef. + */ +export type ObjectTypeDefID = string & { __ObjectTypeDefID: never }; + export type PipelineLabel = { /** * Label name. */ - name: string + name: string; /** * Label value. */ - value: string -} + value: string; +}; /** * The platform config OS and architecture in a Container. - * + * * The format is [os]/[platform]/[version] (e.g., "darwin/arm64/v7", "windows/amd64", "linux/arm64"). */ -export type Platform = string & {__Platform: never} +export type Platform = string & { __Platform: never }; export type PortForward = { /** * Destination port for traffic. */ - backend: number + backend: number; /** * Port to expose to clients. If unspecified, a default will be chosen. */ - frontend?: number + frontend?: number; /** - * Protocol to use for traffic. + * Transport layer protocol to use for traffic. */ - protocol?: NetworkProtocol -} + protocol?: NetworkProtocol; +}; + +/** + * The `PortID` scalar type represents an identifier for an object of type Port. + */ +export type PortID = string & { __PortID: never }; export type ClientContainerOpts = { - id?: ContainerID - platform?: Platform -} + /** + * DEPRECATED: Use `loadContainerFromID` instead. + */ + id?: ContainerID; + + /** + * Platform to initialize the container with. + */ + platform?: Platform; +}; export type ClientDirectoryOpts = { - id?: DirectoryID -} + /** + * DEPRECATED: Use `loadDirectoryFromID` isntead. + */ + id?: DirectoryID; +}; export type ClientGitOpts = { /** * Set to true to keep .git directory. */ - keepGitDir?: boolean + keepGitDir?: boolean; /** - * Set SSH known hosts + * A service which must be started before the repo is fetched. */ - sshKnownHosts?: string + experimentalServiceHost?: Service; /** - * Set SSH auth socket + * Set SSH known hosts */ - sshAuthSocket?: Socket + sshKnownHosts?: string; /** - * A service which must be started before the repo is fetched. + * Set SSH auth socket */ - experimentalServiceHost?: Service -} + sshAuthSocket?: Socket; +}; export type ClientHttpOpts = { /** * A service which must be started before the URL is fetched. */ - experimentalServiceHost?: Service -} + experimentalServiceHost?: Service; +}; export type ClientModuleConfigOpts = { - subpath?: string -} + subpath?: string; +}; export type ClientPipelineOpts = { /** - * Pipeline description. + * Description of the sub-pipeline. */ - description?: string + description?: string; /** - * Pipeline labels. + * Labels to apply to the sub-pipeline. */ - labels?: PipelineLabel[] -} - -export type ClientSocketOpts = { - id?: SocketID -} + labels?: PipelineLabel[]; +}; /** - * A unique identifier for a secret. + * The `SecretID` scalar type represents an identifier for an object of type Secret. */ -export type SecretID = string & {__SecretID: never} +export type SecretID = string & { __SecretID: never }; export type ServiceEndpointOpts = { /** * The exposed port number for the endpoint */ - port?: number + port?: number; /** * Return a URL with the given scheme, eg. http for http:// */ - scheme?: string -} + scheme?: string; +}; /** - * A unique service identifier. + * The `ServiceID` scalar type represents an identifier for an object of type Service. */ -export type ServiceID = string & {__ServiceID: never} +export type ServiceID = string & { __ServiceID: never }; /** - * A content-addressed socket identifier. + * The `SocketID` scalar type represents an identifier for an object of type Socket. */ -export type SocketID = string & {__SocketID: never} +export type SocketID = string & { __SocketID: never }; export type TypeDefWithFieldOpts = { /** * A doc string for the field, if any */ - description?: string -} + description?: string; +}; + +export type TypeDefWithInterfaceOpts = { + description?: string; +}; export type TypeDefWithObjectOpts = { - description?: string -} + description?: string; +}; /** - * A reference to a TypeDef. + * The `TypeDefID` scalar type represents an identifier for an object of type TypeDef. */ -export type TypeDefID = string & {__TypeDefID: never} +export type TypeDefID = string & { __TypeDefID: never }; /** * Distinguishes the different kinds of TypeDefs. */ export enum TypeDefKind { + /** + * A boolean value. + */ + BooleanKind = "BOOLEAN_KIND", /** - * A boolean value + * An integer value. */ - Booleankind = "BooleanKind", + IntegerKind = "INTEGER_KIND", /** - * An integer value + * A named type of functions that can be matched+implemented by other objects+interfaces. + * + * Always paired with an InterfaceTypeDef. */ - Integerkind = "IntegerKind", + InterfaceKind = "INTERFACE_KIND", /** * A list of values all having the same type. - * + * * Always paired with a ListTypeDef. */ - Listkind = "ListKind", + ListKind = "LIST_KIND", /** * A named type defined in the GraphQL schema, with fields and functions. - * + * * Always paired with an ObjectTypeDef. */ - Objectkind = "ObjectKind", + ObjectKind = "OBJECT_KIND", /** - * A string value + * A string value. */ - Stringkind = "StringKind", + StringKind = "STRING_KIND", /** * A special kind used to signify that no value is returned. - * - * This is used for functions that have no return value. The outer TypeDef - * specifying this Kind is always Optional, as the Void is never actually - * represented. + * + * This is used for functions that have no return value. The outer TypeDef specifying this Kind is always Optional, as the Void is never actually represented. */ - Voidkind = "VoidKind", + VoidKind = "VOID_KIND", } /** - * The absense of a value. - * + * The absence of a value. + * * A Null Void is used as a placeholder for resolvers that do not return anything. */ -export type Void = string & {__Void: never} +export type Void = string & { __Void: never }; export type __TypeEnumValuesOpts = { - includeDeprecated?: boolean -} + includeDeprecated?: boolean; +}; export type __TypeFieldsOpts = { - includeDeprecated?: boolean -} - - - - - - - + includeDeprecated?: boolean; +}; /** * A directory whose contents persist across runs. */ export class CacheVolume extends BaseClient { - private readonly _id?: CacheVolumeID = undefined + private readonly _id?: CacheVolumeID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: CacheVolumeID, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: CacheVolumeID + ) { + super(parent); + + this._id = _id; + } - this._id = _id - } - async id(): Promise { + /** + * A unique identifier for this CacheVolume. + */ + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -917,76 +957,73 @@ export class CacheVolume extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } - - /** - * An OCI-compatible container, also known as a docker container. + * An OCI-compatible container, also known as a Docker container. */ export class Container extends BaseClient { - private readonly _id?: ContainerID = undefined - private readonly _envVariable?: string = undefined - private readonly _export?: boolean = undefined - private readonly _imageRef?: string = undefined - private readonly _label?: string = undefined - private readonly _platform?: Platform = undefined - private readonly _publish?: string = undefined - private readonly _shellEndpoint?: string = undefined - private readonly _stderr?: string = undefined - private readonly _stdout?: string = undefined - private readonly _sync?: ContainerID = undefined - private readonly _user?: string = undefined - private readonly _workdir?: string = undefined + private readonly _id?: ContainerID = undefined; + private readonly _envVariable?: string = undefined; + private readonly _export?: boolean = undefined; + private readonly _imageRef?: string = undefined; + private readonly _label?: string = undefined; + private readonly _platform?: Platform = undefined; + private readonly _publish?: string = undefined; + private readonly _shellEndpoint?: string = undefined; + private readonly _stderr?: string = undefined; + private readonly _stdout?: string = undefined; + private readonly _sync?: ContainerID = undefined; + private readonly _user?: string = undefined; + private readonly _workdir?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: ContainerID, - _envVariable?: string, - _export?: boolean, - _imageRef?: string, - _label?: string, - _platform?: Platform, - _publish?: string, - _shellEndpoint?: string, - _stderr?: string, - _stdout?: string, - _sync?: ContainerID, - _user?: string, - _workdir?: string, - ) { - super(parent) - - this._id = _id - this._envVariable = _envVariable - this._export = _export - this._imageRef = _imageRef - this._label = _label - this._platform = _platform - this._publish = _publish - this._shellEndpoint = _shellEndpoint - this._stderr = _stderr - this._stdout = _stdout - this._sync = _sync - this._user = _user - this._workdir = _workdir - } - - /** - * A unique identifier for this container. - */ - async id(): Promise { + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: ContainerID, + _envVariable?: string, + _export?: boolean, + _imageRef?: string, + _label?: string, + _platform?: Platform, + _publish?: string, + _shellEndpoint?: string, + _stderr?: string, + _stdout?: string, + _sync?: ContainerID, + _user?: string, + _workdir?: string + ) { + super(parent); + + this._id = _id; + this._envVariable = _envVariable; + this._export = _export; + this._imageRef = _imageRef; + this._label = _label; + this._platform = _platform; + this._publish = _publish; + this._shellEndpoint = _shellEndpoint; + this._stderr = _stderr; + this._stdout = _stdout; + this._sync = _sync; + this._user = _user; + this._workdir = _workdir; + } + + /** + * A unique identifier for this Container. + */ + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -996,19 +1033,18 @@ export class Container extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Turn the container into a Service. - * + * * Be sure to set any exposed ports before this conversion. */ - asService(): Service { + asService = (): Service => { return new Service({ queryTree: [ ...this._queryTree, @@ -1016,29 +1052,27 @@ export class Container extends BaseClient { operation: "asService", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Returns a File representing the container serialized to a tarball. * @param opts.platformVariants Identifiers for other platform specific containers. - * Used for multi-platform image. + * + * Used for multi-platform images. * @param opts.forcedCompression Force each layer of the image to use the specified compression algorithm. - * If this is unset, then if a layer already has a compressed blob in the engine's - * cache, that will be used (this can result in a mix of compression algorithms for - * different layers). If this is unset and a layer has no compressed blob in the - * engine's cache, then it will be compressed using Gzip. - * @param opts.mediaTypes Use the specified media types for the image's layers. Defaults to OCI, which - * is largely compatible with most recent container runtimes, but Docker may be needed - * for older runtimes without OCI support. - */ - asTarball(opts?: ContainerAsTarballOpts): File { - const metadata: Metadata = { - forcedCompression: { is_enum: true }, - mediaTypes: { is_enum: true }, - } + * + * If this is unset, then if a layer already has a compressed blob in the engine's cache, that will be used (this can result in a mix of compression algorithms for different layers). If this is unset and a layer has no compressed blob in the engine's cache, then it will be compressed using Gzip. + * @param opts.mediaTypes Use the specified media types for the image's layers. + * + * Defaults to OCI, which is largely compatible with most recent container runtimes, but Docker may be needed for older runtimes without OCI support. + */ + asTarball = (opts?: ContainerAsTarballOpts): File => { + const metadata: Metadata = { + forcedCompression: { is_enum: true }, + mediaTypes: { is_enum: true }, + }; return new File({ queryTree: [ @@ -1048,28 +1082,23 @@ export class Container extends BaseClient { args: { ...opts, __metadata: metadata }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Initializes this container from a Dockerfile build. * @param context Directory context used by the Dockerfile. * @param opts.dockerfile Path to the Dockerfile to use. - * - * Default: './Dockerfile'. - * @param opts.buildArgs Additional build arguments. * @param opts.target Target build stage to build. + * @param opts.buildArgs Additional build arguments. * @param opts.secrets Secrets to pass to the build. - * + * * They will be mounted at /run/secrets/[secret-name] in the build container - * - * They can be accessed in the Dockerfile using the "secret" mount type - * and mount path /run/secrets/[secret-name] - * e.g. RUN --mount=type=secret,id=my-secret curl url?token=$(cat /run/secrets/my-secret)" + * + * They can be accessed in the Dockerfile using the "secret" mount type and mount path /run/secrets/[secret-name], e.g. RUN --mount=type=secret,id=my-secret curl http://example.com?token=$(cat /run/secrets/my-secret) */ - build(context: Directory, opts?: ContainerBuildOpts): Container { + build = (context: Directory, opts?: ContainerBuildOpts): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1078,15 +1107,14 @@ export class Container extends BaseClient { args: { context, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves default arguments for future commands. */ - async defaultArgs(): Promise { + defaultArgs = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -1094,20 +1122,19 @@ export class Container extends BaseClient { operation: "defaultArgs", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves a directory at the given path. - * + * * Mounts are included. * @param path The path of the directory to retrieve (e.g., "./src"). */ - directory(path: string): Directory { + directory = (path: string): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -1116,15 +1143,14 @@ export class Container extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves entrypoint to be prepended to the arguments of all commands. */ - async entrypoint(): Promise { + entrypoint = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -1132,20 +1158,19 @@ export class Container extends BaseClient { operation: "entrypoint", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves the value of the specified environment variable. * @param name The name of the environment variable to retrieve (e.g., "PATH"). */ - async envVariable(name: string): Promise { + envVariable = async (name: string): Promise => { if (this._envVariable) { - return this._envVariable + return this._envVariable; } const response: Awaited = await computeQuery( @@ -1156,21 +1181,19 @@ export class Container extends BaseClient { args: { name }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves the list of environment variables passed to commands. */ - async envVariables(): Promise { + envVariables = async (): Promise => { type envVariables = { - name: string - value: string - } + id: EnvVariableID; + }; const response: Awaited = await computeQuery( [ @@ -1179,33 +1202,37 @@ export class Container extends BaseClient { operation: "envVariables", }, { - operation: "name value" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new EnvVariable( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.name, - r.value, - ) - ) - } + (r) => + new EnvVariable( + { + queryTree: [ + { + operation: "loadEnvVariableFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; /** * EXPERIMENTAL API! Subject to change/removal at any time. - * - * experimentalWithAllGPUs configures all available GPUs on the host to be accessible to this container. + * + * Configures all available GPUs on the host to be accessible to this container. + * * This currently works for Nvidia devices only. */ - experimentalWithAllGPUs(): Container { + experimentalWithAllGPUs = (): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1213,18 +1240,19 @@ export class Container extends BaseClient { operation: "experimentalWithAllGPUs", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * EXPERIMENTAL API! Subject to change/removal at any time. - * - * experimentalWithGPU configures the provided list of devices to be accesible to this container. + * + * Configures the provided list of devices to be accesible to this container. + * * This currently works for Nvidia devices only. + * @param devices List of devices to be accessible to this container. */ - experimentalWithGPU(devices: string[]): Container { + experimentalWithGPU = (devices: string[]): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1233,38 +1261,41 @@ export class Container extends BaseClient { args: { devices }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Writes the container as an OCI tarball to the destination file path on the host for the specified platform variants. - * + * Writes the container as an OCI tarball to the destination file path on the host. + * * Return true on success. - * It can also publishes platform variants. + * + * It can also export platform variants. * @param path Host's destination path (e.g., "./tarball"). + * * Path can be relative to the engine's workdir or absolute. * @param opts.platformVariants Identifiers for other platform specific containers. + * * Used for multi-platform image. * @param opts.forcedCompression Force each layer of the exported image to use the specified compression algorithm. - * If this is unset, then if a layer already has a compressed blob in the engine's - * cache, that will be used (this can result in a mix of compression algorithms for - * different layers). If this is unset and a layer has no compressed blob in the - * engine's cache, then it will be compressed using Gzip. - * @param opts.mediaTypes Use the specified media types for the exported image's layers. Defaults to OCI, which - * is largely compatible with most recent container runtimes, but Docker may be needed - * for older runtimes without OCI support. - */ - async export(path: string, opts?: ContainerExportOpts): Promise { + * + * If this is unset, then if a layer already has a compressed blob in the engine's cache, that will be used (this can result in a mix of compression algorithms for different layers). If this is unset and a layer has no compressed blob in the engine's cache, then it will be compressed using Gzip. + * @param opts.mediaTypes Use the specified media types for the exported image's layers. + * + * Defaults to OCI, which is largely compatible with most recent container runtimes, but Docker may be needed for older runtimes without OCI support. + */ + export = async ( + path: string, + opts?: ContainerExportOpts + ): Promise => { if (this._export) { - return this._export + return this._export; } - const metadata: Metadata = { - forcedCompression: { is_enum: true }, - mediaTypes: { is_enum: true }, - } + const metadata: Metadata = { + forcedCompression: { is_enum: true }, + mediaTypes: { is_enum: true }, + }; const response: Awaited = await computeQuery( [ @@ -1274,25 +1305,21 @@ export class Container extends BaseClient { args: { path, ...opts, __metadata: metadata }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves the list of exposed ports. - * - * This includes ports already exposed by the image, even if not - * explicitly added with dagger. + * + * This includes ports already exposed by the image, even if not explicitly added with dagger. */ - async exposedPorts(): Promise { + exposedPorts = async (): Promise => { type exposedPorts = { - description: string - port: number - protocol: NetworkProtocol - } + id: PortID; + }; const response: Awaited = await computeQuery( [ @@ -1301,34 +1328,36 @@ export class Container extends BaseClient { operation: "exposedPorts", }, { - operation: "description port protocol" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new Port( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.description, - r.port, - r.protocol, - ) - ) - } + (r) => + new Port( + { + queryTree: [ + { + operation: "loadPortFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; /** * Retrieves a file at the given path. - * + * * Mounts are included. * @param path The path of the file to retrieve (e.g., "./README.md"). */ - file(path: string): File { + file = (path: string): File => { return new File({ queryTree: [ ...this._queryTree, @@ -1337,18 +1366,17 @@ export class Container extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Initializes this container from a pulled base image. * @param address Image's address from its registry. - * + * * Formatted as [host]/[user]/[repo]:[tag] (e.g., "docker.io/dagger/dagger:main"). */ - from(address: string): Container { + from = (address: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1357,17 +1385,16 @@ export class Container extends BaseClient { args: { address }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * The unique image reference which can only be retrieved immediately after the 'Container.From' call. */ - async imageRef(): Promise { + imageRef = async (): Promise => { if (this._imageRef) { - return this._imageRef + return this._imageRef; } const response: Awaited = await computeQuery( @@ -1377,23 +1404,18 @@ export class Container extends BaseClient { operation: "imageRef", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Reads the container from an OCI tarball. - * - * NOTE: this involves unpacking the tarball to an OCI store on the host at - * $XDG_CACHE_DIR/dagger/oci. This directory can be removed whenever you like. * @param source File to read the container from. - * @param opts.tag Identifies the tag to import from the archive, if the archive bundles - * multiple tags. + * @param opts.tag Identifies the tag to import from the archive, if the archive bundles multiple tags. */ - import_(source: File, opts?: ContainerImportOpts): Container { + import_ = (source: File, opts?: ContainerImportOpts): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1402,17 +1424,17 @@ export class Container extends BaseClient { args: { source, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves the value of the specified label. + * @param name The name of the label (e.g., "org.opencontainers.artifact.created"). */ - async label(name: string): Promise { + label = async (name: string): Promise => { if (this._label) { - return this._label + return this._label; } const response: Awaited = await computeQuery( @@ -1423,21 +1445,19 @@ export class Container extends BaseClient { args: { name }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves the list of labels passed to container. */ - async labels(): Promise { + labels = async (): Promise => { type labels = { - name: string - value: string - } + id: LabelID; + }; const response: Awaited = await computeQuery( [ @@ -1446,30 +1466,33 @@ export class Container extends BaseClient { operation: "labels", }, { - operation: "name value" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new Label( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.name, - r.value, - ) - ) - } + (r) => + new Label( + { + queryTree: [ + { + operation: "loadLabelFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; /** * Retrieves the list of paths where a directory is mounted. */ - async mounts(): Promise { + mounts = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -1477,20 +1500,19 @@ export class Container extends BaseClient { operation: "mounts", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** - * Creates a named sub-pipeline - * @param name Pipeline name. - * @param opts.description Pipeline description. - * @param opts.labels Pipeline labels. + * Creates a named sub-pipeline. + * @param name Name of the sub-pipeline. + * @param opts.description Description of the sub-pipeline. + * @param opts.labels Labels to apply to the sub-pipeline. */ - pipeline(name: string, opts?: ContainerPipelineOpts): Container { + pipeline = (name: string, opts?: ContainerPipelineOpts): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1499,17 +1521,16 @@ export class Container extends BaseClient { args: { name, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * The platform this container executes and publishes as. */ - async platform(): Promise { + platform = async (): Promise => { if (this._platform) { - return this._platform + return this._platform; } const response: Awaited = await computeQuery( @@ -1519,41 +1540,43 @@ export class Container extends BaseClient { operation: "platform", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Publishes this container as a new image to the specified address. - * + * * Publish returns a fully qualified ref. + * * It can also publish platform variants. * @param address Registry's address to publish the image to. - * + * * Formatted as [host]/[user]/[repo]:[tag] (e.g. "docker.io/dagger/dagger:main"). * @param opts.platformVariants Identifiers for other platform specific containers. + * * Used for multi-platform image. * @param opts.forcedCompression Force each layer of the published image to use the specified compression algorithm. - * If this is unset, then if a layer already has a compressed blob in the engine's - * cache, that will be used (this can result in a mix of compression algorithms for - * different layers). If this is unset and a layer has no compressed blob in the - * engine's cache, then it will be compressed using Gzip. - * @param opts.mediaTypes Use the specified media types for the published image's layers. Defaults to OCI, which - * is largely compatible with most recent registries, but Docker may be needed for older - * registries without OCI support. - */ - async publish(address: string, opts?: ContainerPublishOpts): Promise { + * + * If this is unset, then if a layer already has a compressed blob in the engine's cache, that will be used (this can result in a mix of compression algorithms for different layers). If this is unset and a layer has no compressed blob in the engine's cache, then it will be compressed using Gzip. + * @param opts.mediaTypes Use the specified media types for the published image's layers. + * + * Defaults to OCI, which is largely compatible with most recent registries, but Docker may be needed for older registries without OCI support. + */ + publish = async ( + address: string, + opts?: ContainerPublishOpts + ): Promise => { if (this._publish) { - return this._publish + return this._publish; } - const metadata: Metadata = { - forcedCompression: { is_enum: true }, - mediaTypes: { is_enum: true }, - } + const metadata: Metadata = { + forcedCompression: { is_enum: true }, + mediaTypes: { is_enum: true }, + }; const response: Awaited = await computeQuery( [ @@ -1563,17 +1586,16 @@ export class Container extends BaseClient { args: { address, ...opts, __metadata: metadata }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves this container's root filesystem. Mounts are not included. */ - rootfs(): Directory { + rootfs = (): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -1581,20 +1603,18 @@ export class Container extends BaseClient { operation: "rootfs", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Return a websocket endpoint that, if connected to, will start the container with a TTY streamed - * over the websocket. - * + * Return a websocket endpoint that, if connected to, will start the container with a TTY streamed over the websocket. + * * Primarily intended for internal use with the dagger CLI. */ - async shellEndpoint(): Promise { + shellEndpoint = async (): Promise => { if (this._shellEndpoint) { - return this._shellEndpoint + return this._shellEndpoint; } const response: Awaited = await computeQuery( @@ -1604,21 +1624,20 @@ export class Container extends BaseClient { operation: "shellEndpoint", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * The error stream of the last executed command. - * + * * Will execute default command if none is set, or error if there's no default. */ - async stderr(): Promise { + stderr = async (): Promise => { if (this._stderr) { - return this._stderr + return this._stderr; } const response: Awaited = await computeQuery( @@ -1628,21 +1647,20 @@ export class Container extends BaseClient { operation: "stderr", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * The output stream of the last executed command. - * + * * Will execute default command if none is set, or error if there's no default. */ - async stdout(): Promise { + stdout = async (): Promise => { if (this._stdout) { - return this._stdout + return this._stdout; } const response: Awaited = await computeQuery( @@ -1652,19 +1670,18 @@ export class Container extends BaseClient { operation: "stdout", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Forces evaluation of the pipeline in the engine. - * + * * It doesn't run the default command if no exec has been set. */ - async sync(): Promise { + sync = async (): Promise => { await computeQuery( [ ...this._queryTree, @@ -1672,18 +1689,18 @@ export class Container extends BaseClient { operation: "sync", }, ], - this.client - ) + await this._ctx.connection() + ); - return this - } + return this; + }; /** * Retrieves the user to be set for all commands. */ - async user(): Promise { + user = async (): Promise => { if (this._user) { - return this._user + return this._user; } const response: Awaited = await computeQuery( @@ -1693,44 +1710,46 @@ export class Container extends BaseClient { operation: "user", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Configures default arguments for future commands. - * @param opts.args Arguments to prepend to future executions (e.g., ["-v", "--no-cache"]). + * @param args Arguments to prepend to future executions (e.g., ["-v", "--no-cache"]). */ - withDefaultArgs(opts?: ContainerWithDefaultArgsOpts): Container { + withDefaultArgs = (args: string[]): Container => { return new Container({ queryTree: [ ...this._queryTree, { operation: "withDefaultArgs", - args: { ...opts }, + args: { args }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a directory written at the given path. * @param path Location of the written directory (e.g., "/tmp/directory"). * @param directory Identifier of the directory to write - * @param opts.exclude Patterns to exclude in the written directory (e.g., ["node_modules/**", ".gitignore", ".git/"]). - * @param opts.include Patterns to include in the written directory (e.g., ["*.go", "go.mod", "go.sum"]). + * @param opts.exclude Patterns to exclude in the written directory (e.g. ["node_modules/**", ".gitignore", ".git/"]). + * @param opts.include Patterns to include in the written directory (e.g. ["*.go", "go.mod", "go.sum"]). * @param opts.owner A user:group to set for the directory and its contents. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - withDirectory(path: string, directory: Directory, opts?: ContainerWithDirectoryOpts): Container { + withDirectory = ( + path: string, + directory: Directory, + opts?: ContainerWithDirectoryOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1739,37 +1758,42 @@ export class Container extends BaseClient { args: { path, directory, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container but with a different command entrypoint. * @param args Entrypoint to use for future executions (e.g., ["go", "run"]). + * @param opts.keepDefaultArgs Don't remove the default arguments when setting the entrypoint. */ - withEntrypoint(args: string[]): Container { + withEntrypoint = ( + args: string[], + opts?: ContainerWithEntrypointOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, { operation: "withEntrypoint", - args: { args }, + args: { args, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus the given environment variable. * @param name The name of the environment variable (e.g., "HOST"). * @param value The value of the environment variable. (e.g., "localhost"). - * @param opts.expand Replace ${VAR} or $VAR in the value according to the current environment - * variables defined in the container (e.g., "/opt/bin:$PATH"). + * @param opts.expand Replace `${VAR}` or `$VAR` in the value according to the current environment variables defined in the container (e.g., "/opt/bin:$PATH"). */ - withEnvVariable(name: string, value: string, opts?: ContainerWithEnvVariableOpts): Container { + withEnvVariable = ( + name: string, + value: string, + opts?: ContainerWithEnvVariableOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1778,30 +1802,25 @@ export class Container extends BaseClient { args: { name, value, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container after executing the specified command inside it. * @param args Command to run instead of the container's default command (e.g., ["run", "main.go"]). - * + * * If empty, the container's default command is used. * @param opts.skipEntrypoint If the container has an entrypoint, ignore it for args rather than using it to wrap them. * @param opts.stdin Content to write to the command's standard input before closing (e.g., "Hello world"). * @param opts.redirectStdout Redirect the command's standard output to a file in the container (e.g., "/tmp/stdout"). * @param opts.redirectStderr Redirect the command's standard error to a file in the container (e.g., "/tmp/stderr"). * @param opts.experimentalPrivilegedNesting Provides dagger access to the executed command. - * - * Do not use this option unless you trust the command being executed. - * The command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM. - * @param opts.insecureRootCapabilities Execute the command with all root capabilities. This is similar to running a command - * with "sudo" or executing `docker run` with the `--privileged` flag. Containerization - * does not provide any security guarantees when using this option. It should only be used - * when absolutely necessary and only with trusted commands. - */ - withExec(args: string[], opts?: ContainerWithExecOpts): Container { + * + * Do not use this option unless you trust the command being executed; the command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM. + * @param opts.insecureRootCapabilities Execute the command with all root capabilities. This is similar to running a command with "sudo" or executing "docker run" with the "--privileged" flag. Containerization does not provide any security guarantees when using this option. It should only be used when absolutely necessary and only with trusted commands. + */ + withExec = (args: string[], opts?: ContainerWithExecOpts): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1810,25 +1829,29 @@ export class Container extends BaseClient { args: { args, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Expose a network port. - * + * * Exposed ports serve two purposes: - * - For health checks and introspection, when running services - * - For setting the EXPOSE OCI field when publishing the container + * + * - For health checks and introspection, when running services + * + * - For setting the EXPOSE OCI field when publishing the container * @param port Port number to expose * @param opts.protocol Transport layer network protocol * @param opts.description Optional port description */ - withExposedPort(port: number, opts?: ContainerWithExposedPortOpts): Container { - const metadata: Metadata = { - protocol: { is_enum: true }, - } + withExposedPort = ( + port: number, + opts?: ContainerWithExposedPortOpts + ): Container => { + const metadata: Metadata = { + protocol: { is_enum: true }, + }; return new Container({ queryTree: [ @@ -1838,25 +1861,26 @@ export class Container extends BaseClient { args: { port, ...opts, __metadata: metadata }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus the contents of the given file copied to the given path. * @param path Location of the copied file (e.g., "/tmp/file.txt"). * @param source Identifier of the file to copy. * @param opts.permissions Permission given to the copied file (e.g., 0600). - * - * Default: 0644. * @param opts.owner A user:group to set for the file. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - withFile(path: string, source: File, opts?: ContainerWithFileOpts): Container { + withFile = ( + path: string, + source: File, + opts?: ContainerWithFileOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1865,16 +1889,14 @@ export class Container extends BaseClient { args: { path, source, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Indicate that subsequent operations should be featured more prominently in - * the UI. + * Indicate that subsequent operations should be featured more prominently in the UI. */ - withFocus(): Container { + withFocus = (): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1882,17 +1904,16 @@ export class Container extends BaseClient { operation: "withFocus", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus the given label. * @param name The name of the label (e.g., "org.opencontainers.artifact.created"). * @param value The value of the label (e.g., "2023-01-01T00:00:00Z"). */ - withLabel(name: string, value: string): Container { + withLabel = (name: string, value: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1901,10 +1922,9 @@ export class Container extends BaseClient { args: { name, value }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a cache volume mounted at the given path. @@ -1913,19 +1933,21 @@ export class Container extends BaseClient { * @param opts.source Identifier of the directory to use as the cache volume's root. * @param opts.sharing Sharing mode of the cache volume. * @param opts.owner A user:group to set for the mounted cache directory. - * - * Note that this changes the ownership of the specified mount along with the - * initial filesystem provided by source (if any). It does not have any effect - * if/when the cache has already been created. - * + * + * Note that this changes the ownership of the specified mount along with the initial filesystem provided by source (if any). It does not have any effect if/when the cache has already been created. + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - withMountedCache(path: string, cache: CacheVolume, opts?: ContainerWithMountedCacheOpts): Container { - const metadata: Metadata = { - sharing: { is_enum: true }, - } + withMountedCache = ( + path: string, + cache: CacheVolume, + opts?: ContainerWithMountedCacheOpts + ): Container => { + const metadata: Metadata = { + sharing: { is_enum: true }, + }; return new Container({ queryTree: [ @@ -1935,22 +1957,25 @@ export class Container extends BaseClient { args: { path, cache, ...opts, __metadata: metadata }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a directory mounted at the given path. * @param path Location of the mounted directory (e.g., "/mnt/directory"). * @param source Identifier of the mounted directory. * @param opts.owner A user:group to set for the mounted directory and its contents. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - withMountedDirectory(path: string, source: Directory, opts?: ContainerWithMountedDirectoryOpts): Container { + withMountedDirectory = ( + path: string, + source: Directory, + opts?: ContainerWithMountedDirectoryOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1959,22 +1984,25 @@ export class Container extends BaseClient { args: { path, source, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a file mounted at the given path. * @param path Location of the mounted file (e.g., "/tmp/file.txt"). * @param source Identifier of the mounted file. * @param opts.owner A user or user:group to set for the mounted file. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - withMountedFile(path: string, source: File, opts?: ContainerWithMountedFileOpts): Container { + withMountedFile = ( + path: string, + source: File, + opts?: ContainerWithMountedFileOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1983,26 +2011,28 @@ export class Container extends BaseClient { args: { path, source, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a secret mounted into a file at the given path. * @param path Location of the secret file (e.g., "/tmp/secret.txt"). * @param source Identifier of the secret to mount. * @param opts.owner A user:group to set for the mounted secret. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. * @param opts.mode Permission given to the mounted secret (e.g., 0600). + * * This option requires an owner to be set to be active. - * - * Default: 0400. */ - withMountedSecret(path: string, source: Secret, opts?: ContainerWithMountedSecretOpts): Container { + withMountedSecret = ( + path: string, + source: Secret, + opts?: ContainerWithMountedSecretOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2011,16 +2041,15 @@ export class Container extends BaseClient { args: { path, source, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a temporary directory mounted at the given path. * @param path Location of the temporary directory (e.g., "/tmp/temp_dir"). */ - withMountedTemp(path: string): Container { + withMountedTemp = (path: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2029,25 +2058,22 @@ export class Container extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a new file written at the given path. * @param path Location of the written file (e.g., "/tmp/file.txt"). * @param opts.contents Content of the file to write (e.g., "Hello world!"). * @param opts.permissions Permission given to the written file (e.g., 0600). - * - * Default: 0644. * @param opts.owner A user:group to set for the file. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - withNewFile(path: string, opts?: ContainerWithNewFileOpts): Container { + withNewFile = (path: string, opts?: ContainerWithNewFileOpts): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2056,19 +2082,23 @@ export class Container extends BaseClient { args: { path, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container with a registry authentication for a given address. * @param address Registry's address to bind the authentication to. + * * Formatted as [host]/[user]/[repo]:[tag] (e.g. docker.io/dagger/dagger:main). * @param username The username of the registry's account (e.g., "Dagger"). * @param secret The API key, password or token to authenticate to this registry. */ - withRegistryAuth(address: string, username: string, secret: Secret): Container { + withRegistryAuth = ( + address: string, + username: string, + secret: Secret + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2077,15 +2107,15 @@ export class Container extends BaseClient { args: { address, username, secret }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Initializes this container from this DirectoryID. + * Retrieves the container with the given directory mounted to /. + * @param directory Directory to mount. */ - withRootfs(directory: Directory): Container { + withRootfs = (directory: Directory): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2094,17 +2124,16 @@ export class Container extends BaseClient { args: { directory }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus an env variable containing the given secret. * @param name The name of the secret variable (e.g., "API_SECRET"). * @param secret The identifier of the secret value. */ - withSecretVariable(name: string, secret: Secret): Container { + withSecretVariable = (name: string, secret: Secret): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2113,24 +2142,22 @@ export class Container extends BaseClient { args: { name, secret }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Establish a runtime dependency on a service. - * - * The service will be started automatically when needed and detached when it is - * no longer needed, executing the default command if none is set. - * + * + * The service will be started automatically when needed and detached when it is no longer needed, executing the default command if none is set. + * * The service will be reachable from the container via the provided hostname alias. - * + * * The service dependency will also convey to any files or directories produced by the container. * @param alias A name that can be used to reach the service from the container * @param service Identifier of the service container */ - withServiceBinding(alias: string, service: Service): Container { + withServiceBinding = (alias: string, service: Service): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2139,22 +2166,25 @@ export class Container extends BaseClient { args: { alias, service }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a socket forwarded to the given Unix socket path. * @param path Location of the forwarded Unix socket (e.g., "/tmp/socket"). * @param source Identifier of the socket to forward. * @param opts.owner A user:group to set for the mounted socket. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - withUnixSocket(path: string, source: Socket, opts?: ContainerWithUnixSocketOpts): Container { + withUnixSocket = ( + path: string, + source: Socket, + opts?: ContainerWithUnixSocketOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2163,16 +2193,15 @@ export class Container extends BaseClient { args: { path, source, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container with a different command user. * @param name The user to set (e.g., "root"). */ - withUser(name: string): Container { + withUser = (name: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2181,16 +2210,15 @@ export class Container extends BaseClient { args: { name }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container with a different working directory. * @param path The path to set as the working directory (e.g., "/app"). */ - withWorkdir(path: string): Container { + withWorkdir = (path: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2199,16 +2227,47 @@ export class Container extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Retrieves this container with unset default arguments for future commands. + */ + withoutDefaultArgs = (): Container => { + return new Container({ + queryTree: [ + ...this._queryTree, + { + operation: "withoutDefaultArgs", + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Retrieves this container with an unset command entrypoint. + * @param opts.keepDefaultArgs Don't remove the default arguments when unsetting the entrypoint. + */ + withoutEntrypoint = (opts?: ContainerWithoutEntrypointOpts): Container => { + return new Container({ + queryTree: [ + ...this._queryTree, + { + operation: "withoutEntrypoint", + args: { ...opts }, + }, + ], + ctx: this._ctx, + }); + }; /** * Retrieves this container minus the given environment variable. * @param name The name of the environment variable (e.g., "HOST"). */ - withoutEnvVariable(name: string): Container { + withoutEnvVariable = (name: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2217,20 +2276,22 @@ export class Container extends BaseClient { args: { name }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Unexpose a previously exposed port. * @param port Port number to unexpose * @param opts.protocol Port protocol to unexpose */ - withoutExposedPort(port: number, opts?: ContainerWithoutExposedPortOpts): Container { - const metadata: Metadata = { - protocol: { is_enum: true }, - } + withoutExposedPort = ( + port: number, + opts?: ContainerWithoutExposedPortOpts + ): Container => { + const metadata: Metadata = { + protocol: { is_enum: true }, + }; return new Container({ queryTree: [ @@ -2240,18 +2301,16 @@ export class Container extends BaseClient { args: { port, ...opts, __metadata: metadata }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Indicate that subsequent operations should not be featured more prominently - * in the UI. - * + * Indicate that subsequent operations should not be featured more prominently in the UI. + * * This is the initial state of all containers. */ - withoutFocus(): Container { + withoutFocus = (): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2259,16 +2318,15 @@ export class Container extends BaseClient { operation: "withoutFocus", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container minus the given environment label. * @param name The name of the label to remove (e.g., "org.opencontainers.artifact.created"). */ - withoutLabel(name: string): Container { + withoutLabel = (name: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2277,16 +2335,15 @@ export class Container extends BaseClient { args: { name }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container after unmounting everything at the given path. * @param path Location of the cache directory (e.g., "/cache/node_modules"). */ - withoutMount(path: string): Container { + withoutMount = (path: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2295,17 +2352,17 @@ export class Container extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container without the registry authentication of a given address. * @param address Registry's address to remove the authentication from. + * * Formatted as [host]/[user]/[repo]:[tag] (e.g. docker.io/dagger/dagger:main). */ - withoutRegistryAuth(address: string): Container { + withoutRegistryAuth = (address: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2314,16 +2371,15 @@ export class Container extends BaseClient { args: { address }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container with a previously added Unix socket removed. * @param path Location of the socket to remove (e.g., "/tmp/socket"). */ - withoutUnixSocket(path: string): Container { + withoutUnixSocket = (path: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2332,17 +2388,50 @@ export class Container extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Retrieves this container with an unset command user. + * + * Should default to root. + */ + withoutUser = (): Container => { + return new Container({ + queryTree: [ + ...this._queryTree, + { + operation: "withoutUser", + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Retrieves this container with an unset working directory. + * + * Should default to "/". + */ + withoutWorkdir = (): Container => { + return new Container({ + queryTree: [ + ...this._queryTree, + { + operation: "withoutWorkdir", + }, + ], + ctx: this._ctx, + }); + }; /** * Retrieves the working directory for all commands. */ - async workdir(): Promise { + workdir = async (): Promise => { if (this._workdir) { - return this._workdir + return this._workdir; } const response: Awaited = await computeQuery( @@ -2352,57 +2441,52 @@ export class Container extends BaseClient { operation: "workdir", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Call the provided function with current Container. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: Container) => Container) { - return arg(this) - } + with = (arg: (param: Container) => Container) => { + return arg(this); + }; } - - - - /** * A directory. */ export class Directory extends BaseClient { - private readonly _id?: DirectoryID = undefined - private readonly _export?: boolean = undefined - private readonly _sync?: DirectoryID = undefined + private readonly _id?: DirectoryID = undefined; + private readonly _export?: boolean = undefined; + private readonly _sync?: DirectoryID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: DirectoryID, - _export?: boolean, - _sync?: DirectoryID, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: DirectoryID, + _export?: boolean, + _sync?: DirectoryID + ) { + super(parent); - this._id = _id - this._export = _export - this._sync = _sync - } + this._id = _id; + this._export = _export; + this._sync = _sync; + } /** - * The content-addressed identifier of the directory. + * A unique identifier for this Directory. */ - async id(): Promise { + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -2412,27 +2496,21 @@ export class Directory extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Load the directory as a Dagger module - * @param opts.sourceSubpath An optional subpath of the directory which contains the module's source - * code. - * - * This is needed when the module code is in a subdirectory but requires - * parent directories to be loaded in order to execute. For example, the - * module source code may need a go.mod, project.toml, package.json, etc. file - * from a parent directory. - * - * If not set, the module source code is loaded from the root of the - * directory. - */ - asModule(opts?: DirectoryAsModuleOpts): Module_ { + * @param opts.sourceSubpath An optional subpath of the directory which contains the module's source code. + * + * This is needed when the module code is in a subdirectory but requires parent directories to be loaded in order to execute. For example, the module source code may need a go.mod, project.toml, package.json, etc. file from a parent directory. + * + * If not set, the module source code is loaded from the root of the directory. + */ + asModule = (opts?: DirectoryAsModuleOpts): Module_ => { return new Module_({ queryTree: [ ...this._queryTree, @@ -2441,16 +2519,15 @@ export class Directory extends BaseClient { args: { ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Gets the difference between this directory and an another directory. * @param other Identifier of the directory to compare. */ - diff(other: Directory): Directory { + diff = (other: Directory): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2459,16 +2536,15 @@ export class Directory extends BaseClient { args: { other }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves a directory at the given path. * @param path Location of the directory to retrieve (e.g., "/src"). */ - directory(path: string): Directory { + directory = (path: string): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2477,24 +2553,21 @@ export class Directory extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Builds a new Docker container from this directory. - * @param opts.dockerfile Path to the Dockerfile to use (e.g., "frontend.Dockerfile"). - * - * Defaults: './Dockerfile'. * @param opts.platform The platform to build. - * @param opts.buildArgs Build arguments to use in the build. + * @param opts.dockerfile Path to the Dockerfile to use (e.g., "frontend.Dockerfile"). * @param opts.target Target build stage to build. + * @param opts.buildArgs Build arguments to use in the build. * @param opts.secrets Secrets to pass to the build. - * + * * They will be mounted at /run/secrets/[secret-name]. */ - dockerBuild(opts?: DirectoryDockerBuildOpts): Container { + dockerBuild = (opts?: DirectoryDockerBuildOpts): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2503,16 +2576,15 @@ export class Directory extends BaseClient { args: { ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Returns a list of files and directories at the given path. * @param opts.path Location of the directory to look at (e.g., "/src"). */ - async entries(opts?: DirectoryEntriesOpts): Promise { + entries = async (opts?: DirectoryEntriesOpts): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -2521,20 +2593,19 @@ export class Directory extends BaseClient { args: { ...opts }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Writes the contents of the directory to a path on the host. * @param path Location of the copied directory (e.g., "logs/"). */ - async export(path: string): Promise { + export = async (path: string): Promise => { if (this._export) { - return this._export + return this._export; } const response: Awaited = await computeQuery( @@ -2545,18 +2616,17 @@ export class Directory extends BaseClient { args: { path }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves a file at the given path. * @param path Location of the file to retrieve (e.g., "README.md"). */ - file(path: string): File { + file = (path: string): File => { return new File({ queryTree: [ ...this._queryTree, @@ -2565,16 +2635,15 @@ export class Directory extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Returns a list of files and directories that matche the given pattern. * @param pattern Pattern to match (e.g., "*.md"). */ - async glob(pattern: string): Promise { + glob = async (pattern: string): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -2583,20 +2652,19 @@ export class Directory extends BaseClient { args: { pattern }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** - * Creates a named sub-pipeline - * @param name Pipeline name. - * @param opts.description Pipeline description. - * @param opts.labels Pipeline labels. + * Creates a named sub-pipeline. + * @param name Name of the sub-pipeline. + * @param opts.description Description of the sub-pipeline. + * @param opts.labels Labels to apply to the sub-pipeline. */ - pipeline(name: string, opts?: DirectoryPipelineOpts): Directory { + pipeline = (name: string, opts?: DirectoryPipelineOpts): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2605,15 +2673,14 @@ export class Directory extends BaseClient { args: { name, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Force evaluation in the engine. */ - async sync(): Promise { + sync = async (): Promise => { await computeQuery( [ ...this._queryTree, @@ -2621,11 +2688,11 @@ export class Directory extends BaseClient { operation: "sync", }, ], - this.client - ) + await this._ctx.connection() + ); - return this - } + return this; + }; /** * Retrieves this directory plus a directory written at the given path. @@ -2634,7 +2701,11 @@ export class Directory extends BaseClient { * @param opts.exclude Exclude artifacts that match the given pattern (e.g., ["node_modules/", ".git*"]). * @param opts.include Include only artifacts that match the given pattern (e.g., ["app/", "package.*"]). */ - withDirectory(path: string, directory: Directory, opts?: DirectoryWithDirectoryOpts): Directory { + withDirectory = ( + path: string, + directory: Directory, + opts?: DirectoryWithDirectoryOpts + ): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2643,20 +2714,21 @@ export class Directory extends BaseClient { args: { path, directory, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this directory plus the contents of the given file copied to the given path. * @param path Location of the copied file (e.g., "/file.txt"). * @param source Identifier of the file to copy. * @param opts.permissions Permission given to the copied file (e.g., 0600). - * - * Default: 0644. */ - withFile(path: string, source: File, opts?: DirectoryWithFileOpts): Directory { + withFile = ( + path: string, + source: File, + opts?: DirectoryWithFileOpts + ): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2665,19 +2737,19 @@ export class Directory extends BaseClient { args: { path, source, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this directory plus a new directory created at the given path. * @param path Location of the directory created (e.g., "/logs"). * @param opts.permissions Permission granted to the created directory (e.g., 0777). - * - * Default: 0755. */ - withNewDirectory(path: string, opts?: DirectoryWithNewDirectoryOpts): Directory { + withNewDirectory = ( + path: string, + opts?: DirectoryWithNewDirectoryOpts + ): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2686,20 +2758,21 @@ export class Directory extends BaseClient { args: { path, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this directory plus a new file written at the given path. * @param path Location of the written file (e.g., "/file.txt"). * @param contents Content of the written file (e.g., "Hello world!"). * @param opts.permissions Permission given to the copied file (e.g., 0600). - * - * Default: 0644. */ - withNewFile(path: string, contents: string, opts?: DirectoryWithNewFileOpts): Directory { + withNewFile = ( + path: string, + contents: string, + opts?: DirectoryWithNewFileOpts + ): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2708,18 +2781,17 @@ export class Directory extends BaseClient { args: { path, contents, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this directory with all file/dir timestamps set to the given time. * @param timestamp Timestamp to set dir/files in. - * + * * Formatted in seconds following Unix epoch (e.g., 1672531199). */ - withTimestamps(timestamp: number): Directory { + withTimestamps = (timestamp: number): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2728,16 +2800,15 @@ export class Directory extends BaseClient { args: { timestamp }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this directory with the directory at the given path removed. * @param path Location of the directory to remove (e.g., ".github/"). */ - withoutDirectory(path: string): Directory { + withoutDirectory = (path: string): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2746,16 +2817,15 @@ export class Directory extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this directory with the file at the given path removed. * @param path Location of the file to remove (e.g., "/file.txt"). */ - withoutFile(path: string): Directory { + withoutFile = (path: string): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2764,50 +2834,67 @@ export class Directory extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Call the provided function with current Directory. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: Directory) => Directory) { - return arg(this) - } + with = (arg: (param: Directory) => Directory) => { + return arg(this); + }; } - - /** - * A simple key value object that represents an environment variable. + * An environment variable name and value. */ export class EnvVariable extends BaseClient { - private readonly _name?: string = undefined - private readonly _value?: string = undefined + private readonly _id?: EnvVariableID = undefined; + private readonly _name?: string = undefined; + private readonly _value?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _name?: string, - _value?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: EnvVariableID, + _name?: string, + _value?: string + ) { + super(parent); - this._name = _name - this._value = _value - } + this._id = _id; + this._name = _name; + this._value = _value; + } /** - * The environment variable name. + * A unique identifier for this EnvVariable. */ - async name(): Promise { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -2817,19 +2904,14 @@ export class EnvVariable extends BaseClient { operation: "name", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The environment variable value. - */ - async value(): Promise { + return response; + }; + value = async (): Promise => { if (this._value) { - return this._value + return this._value; } const response: Awaited = await computeQuery( @@ -2839,43 +2921,62 @@ export class EnvVariable extends BaseClient { operation: "value", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } /** * A definition of a field on a custom object defined in a Module. - * A field on an object has a static value, as opposed to a function on an - * object whose value is computed by invoking code (and can accept arguments). + * + * A field on an object has a static value, as opposed to a function on an object whose value is computed by invoking code (and can accept arguments). */ export class FieldTypeDef extends BaseClient { - private readonly _description?: string = undefined - private readonly _name?: string = undefined + private readonly _id?: FieldTypeDefID = undefined; + private readonly _description?: string = undefined; + private readonly _name?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _description?: string, - _name?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: FieldTypeDefID, + _description?: string, + _name?: string + ) { + super(parent); - this._description = _description - this._name = _name - } + this._id = _id; + this._description = _description; + this._name = _name; + } /** - * A doc string for the field, if any + * A unique identifier for this FieldTypeDef. */ - async description(): Promise { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + description = async (): Promise => { if (this._description) { - return this._description + return this._description; } const response: Awaited = await computeQuery( @@ -2885,19 +2986,14 @@ export class FieldTypeDef extends BaseClient { operation: "description", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The name of the field in the object - */ - async name(): Promise { + return response; + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -2907,17 +3003,12 @@ export class FieldTypeDef extends BaseClient { operation: "name", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The type of the field - */ - typeDef(): TypeDef { + return response; + }; + typeDef = (): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -2925,48 +3016,50 @@ export class FieldTypeDef extends BaseClient { operation: "typeDef", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; } /** * A file. */ export class File extends BaseClient { - private readonly _id?: FileID = undefined - private readonly _contents?: string = undefined - private readonly _export?: boolean = undefined - private readonly _size?: number = undefined - private readonly _sync?: FileID = undefined + private readonly _id?: FileID = undefined; + private readonly _contents?: string = undefined; + private readonly _export?: boolean = undefined; + private readonly _name?: string = undefined; + private readonly _size?: number = undefined; + private readonly _sync?: FileID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: FileID, - _contents?: string, - _export?: boolean, - _size?: number, - _sync?: FileID, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: FileID, + _contents?: string, + _export?: boolean, + _name?: string, + _size?: number, + _sync?: FileID + ) { + super(parent); - this._id = _id - this._contents = _contents - this._export = _export - this._size = _size - this._sync = _sync - } + this._id = _id; + this._contents = _contents; + this._export = _export; + this._name = _name; + this._size = _size; + this._sync = _sync; + } /** - * Retrieves the content-addressed identifier of the file. + * A unique identifier for this File. */ - async id(): Promise { + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -2976,19 +3069,18 @@ export class File extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves the contents of the file. */ - async contents(): Promise { + contents = async (): Promise => { if (this._contents) { - return this._contents + return this._contents; } const response: Awaited = await computeQuery( @@ -2998,22 +3090,20 @@ export class File extends BaseClient { operation: "contents", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Writes the file to a file path on the host. * @param path Location of the written directory (e.g., "output.txt"). - * @param opts.allowParentDirPath If allowParentDirPath is true, the path argument can be a directory path, in which case - * the file will be created in that directory. + * @param opts.allowParentDirPath If allowParentDirPath is true, the path argument can be a directory path, in which case the file will be created in that directory. */ - async export(path: string, opts?: FileExportOpts): Promise { + export = async (path: string, opts?: FileExportOpts): Promise => { if (this._export) { - return this._export + return this._export; } const response: Awaited = await computeQuery( @@ -3024,19 +3114,39 @@ export class File extends BaseClient { args: { path, ...opts }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; + + /** + * Retrieves the name of the file. + */ + name = async (): Promise => { + if (this._name) { + return this._name; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "name", + }, + ], + await this._ctx.connection() + ); + + return response; + }; /** - * Gets the size of the file, in bytes. + * Retrieves the size of the file, in bytes. */ - async size(): Promise { + size = async (): Promise => { if (this._size) { - return this._size + return this._size; } const response: Awaited = await computeQuery( @@ -3046,17 +3156,16 @@ export class File extends BaseClient { operation: "size", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Force evaluation in the engine. */ - async sync(): Promise { + sync = async (): Promise => { await computeQuery( [ ...this._queryTree, @@ -3064,19 +3173,19 @@ export class File extends BaseClient { operation: "sync", }, ], - this.client - ) + await this._ctx.connection() + ); - return this - } + return this; + }; /** * Retrieves this file with its created/modified timestamps set to the given time. * @param timestamp Timestamp to set dir/files in. - * + * * Formatted in seconds following Unix epoch (e.g., 1672531199). */ - withTimestamps(timestamp: number): File { + withTimestamps = (timestamp: number): File => { return new File({ queryTree: [ ...this._queryTree, @@ -3085,58 +3194,52 @@ export class File extends BaseClient { args: { timestamp }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Call the provided function with current File. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: File) => File) { - return arg(this) - } + with = (arg: (param: File) => File) => { + return arg(this); + }; } - - - - /** * Function represents a resolver provided by a Module. - * - * A function always evaluates against a parent object and is given a set of - * named arguments. + * + * A function always evaluates against a parent object and is given a set of named arguments. */ export class Function_ extends BaseClient { - private readonly _id?: FunctionID = undefined - private readonly _description?: string = undefined - private readonly _name?: string = undefined + private readonly _id?: FunctionID = undefined; + private readonly _description?: string = undefined; + private readonly _name?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: FunctionID, - _description?: string, - _name?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: FunctionID, + _description?: string, + _name?: string + ) { + super(parent); - this._id = _id - this._description = _description - this._name = _name - } + this._id = _id; + this._description = _description; + this._name = _name; + } /** - * The ID of the function + * A unique identifier for this Function. */ - async id(): Promise { + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -3146,20 +3249,15 @@ export class Function_ extends BaseClient { operation: "id", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * Arguments accepted by this function, if any - */ - async args(): Promise { + return response; + }; + args = async (): Promise => { type args = { - id: FunctionArgID - } + id: FunctionArgID; + }; const response: Awaited = await computeQuery( [ @@ -3168,31 +3266,31 @@ export class Function_ extends BaseClient { operation: "args", }, { - operation: "id" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new FunctionArg( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.id, - ) - ) - } - - /** - * A doc string for the function, if any - */ - async description(): Promise { + (r) => + new FunctionArg( + { + queryTree: [ + { + operation: "loadFunctionArgFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + description = async (): Promise => { if (this._description) { - return this._description + return this._description; } const response: Awaited = await computeQuery( @@ -3202,19 +3300,14 @@ export class Function_ extends BaseClient { operation: "description", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The name of the function - */ - async name(): Promise { + return response; + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -3224,17 +3317,12 @@ export class Function_ extends BaseClient { operation: "name", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The type returned by this function - */ - returnType(): TypeDef { + return response; + }; + returnType = (): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -3242,10 +3330,9 @@ export class Function_ extends BaseClient { operation: "returnType", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Returns the function with the provided argument @@ -3254,7 +3341,11 @@ export class Function_ extends BaseClient { * @param opts.description A doc string for the argument, if any * @param opts.defaultValue A default value to use for this argument if not explicitly set by the caller, if any */ - withArg(name: string, typeDef: TypeDef, opts?: FunctionWithArgOpts): Function_ { + withArg = ( + name: string, + typeDef: TypeDef, + opts?: FunctionWithArgOpts + ): Function_ => { return new Function_({ queryTree: [ ...this._queryTree, @@ -3263,15 +3354,15 @@ export class Function_ extends BaseClient { args: { name, typeDef, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Returns the function with the doc string + * Returns the function with the given doc string. + * @param description The doc string to set. */ - withDescription(description: string): Function_ { + withDescription = (description: string): Function_ => { return new Function_({ queryTree: [ ...this._queryTree, @@ -3280,57 +3371,55 @@ export class Function_ extends BaseClient { args: { description }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Call the provided function with current Function. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: Function_) => Function_) { - return arg(this) - } + with = (arg: (param: Function_) => Function_) => { + return arg(this); + }; } /** * An argument accepted by a function. - * - * This is a specification for an argument at function definition time, not an - * argument passed at function call time. + * + * This is a specification for an argument at function definition time, not an argument passed at function call time. */ export class FunctionArg extends BaseClient { - private readonly _id?: FunctionArgID = undefined - private readonly _defaultValue?: JSON = undefined - private readonly _description?: string = undefined - private readonly _name?: string = undefined + private readonly _id?: FunctionArgID = undefined; + private readonly _defaultValue?: JSON = undefined; + private readonly _description?: string = undefined; + private readonly _name?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: FunctionArgID, - _defaultValue?: JSON, - _description?: string, - _name?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: FunctionArgID, + _defaultValue?: JSON, + _description?: string, + _name?: string + ) { + super(parent); - this._id = _id - this._defaultValue = _defaultValue - this._description = _description - this._name = _name - } + this._id = _id; + this._defaultValue = _defaultValue; + this._description = _description; + this._name = _name; + } /** - * The ID of the argument + * A unique identifier for this FunctionArg. */ - async id(): Promise { + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -3340,19 +3429,14 @@ export class FunctionArg extends BaseClient { operation: "id", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * A default value to use for this argument when not explicitly set by the caller, if any - */ - async defaultValue(): Promise { + return response; + }; + defaultValue = async (): Promise => { if (this._defaultValue) { - return this._defaultValue + return this._defaultValue; } const response: Awaited = await computeQuery( @@ -3362,19 +3446,14 @@ export class FunctionArg extends BaseClient { operation: "defaultValue", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * A doc string for the argument, if any - */ - async description(): Promise { + return response; + }; + description = async (): Promise => { if (this._description) { - return this._description + return this._description; } const response: Awaited = await computeQuery( @@ -3384,19 +3463,14 @@ export class FunctionArg extends BaseClient { operation: "description", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * The name of the argument - */ - async name(): Promise { + return response; + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -3406,17 +3480,12 @@ export class FunctionArg extends BaseClient { operation: "name", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * The type of the argument - */ - typeDef(): TypeDef { + return response; + }; + typeDef = (): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -3424,48 +3493,66 @@ export class FunctionArg extends BaseClient { operation: "typeDef", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; } - - - +/** + * An active function call. + */ export class FunctionCall extends BaseClient { - private readonly _name?: string = undefined - private readonly _parent?: JSON = undefined - private readonly _parentName?: string = undefined - private readonly _returnValue?: Void = undefined + private readonly _id?: FunctionCallID = undefined; + private readonly _name?: string = undefined; + private readonly _parent?: JSON = undefined; + private readonly _parentName?: string = undefined; + private readonly _returnValue?: Void = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _name?: string, - _parent?: JSON, - _parentName?: string, - _returnValue?: Void, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: FunctionCallID, + _name?: string, + _parent?: JSON, + _parentName?: string, + _returnValue?: Void + ) { + super(parent); - this._name = _name - this._parent = _parent - this._parentName = _parentName - this._returnValue = _returnValue - } + this._id = _id; + this._name = _name; + this._parent = _parent; + this._parentName = _parentName; + this._returnValue = _returnValue; + } /** - * The argument values the function is being invoked with. + * A unique identifier for this FunctionCall. */ - async inputArgs(): Promise { - type inputArgs = { - name: string - value: JSON + id = async (): Promise => { + if (this._id) { + return this._id; } + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + inputArgs = async (): Promise => { + type inputArgs = { + id: FunctionCallArgValueID; + }; + const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -3473,32 +3560,31 @@ export class FunctionCall extends BaseClient { operation: "inputArgs", }, { - operation: "name value" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new FunctionCallArgValue( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.name, - r.value, - ) - ) - } - - /** - * The name of the function being called. - */ - async name(): Promise { + (r) => + new FunctionCallArgValue( + { + queryTree: [ + { + operation: "loadFunctionCallArgValueFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -3508,20 +3594,14 @@ export class FunctionCall extends BaseClient { operation: "name", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * The value of the parent object of the function being called. - * If the function is "top-level" to the module, this is always an empty object. - */ - async parent(): Promise { + return response; + }; + parent = async (): Promise => { if (this._parent) { - return this._parent + return this._parent; } const response: Awaited = await computeQuery( @@ -3531,20 +3611,14 @@ export class FunctionCall extends BaseClient { operation: "parent", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The name of the parent object of the function being called. - * If the function is "top-level" to the module, this is the name of the module. - */ - async parentName(): Promise { + return response; + }; + parentName = async (): Promise => { if (this._parentName) { - return this._parentName + return this._parentName; } const response: Awaited = await computeQuery( @@ -3554,20 +3628,19 @@ export class FunctionCall extends BaseClient { operation: "parentName", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Set the return value of the function call to the provided value. - * The value should be a string of the JSON serialization of the return value. + * @param value JSON serialization of the return value. */ - async returnValue(value: JSON): Promise { + returnValue = async (value: JSON): Promise => { if (this._returnValue) { - return this._returnValue + return this._returnValue; } const response: Awaited = await computeQuery( @@ -3578,39 +3651,60 @@ export class FunctionCall extends BaseClient { args: { value }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } - +/** + * A value passed as a named argument to a function call. + */ export class FunctionCallArgValue extends BaseClient { - private readonly _name?: string = undefined - private readonly _value?: JSON = undefined + private readonly _id?: FunctionCallArgValueID = undefined; + private readonly _name?: string = undefined; + private readonly _value?: JSON = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _name?: string, - _value?: JSON, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: FunctionCallArgValueID, + _name?: string, + _value?: JSON + ) { + super(parent); - this._name = _name - this._value = _value - } + this._id = _id; + this._name = _name; + this._value = _value; + } /** - * The name of the argument. + * A unique identifier for this FunctionCallArgValue. */ - async name(): Promise { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -3620,19 +3714,14 @@ export class FunctionCallArgValue extends BaseClient { operation: "name", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * The value of the argument represented as a string of the JSON serialization. - */ - async value(): Promise { + return response; + }; + value = async (): Promise => { if (this._value) { - return this._value + return this._value; } const response: Awaited = await computeQuery( @@ -3642,34 +3731,37 @@ export class FunctionCallArgValue extends BaseClient { operation: "value", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } - - - +/** + * The result of running an SDK's codegen. + */ export class GeneratedCode extends BaseClient { - private readonly _id?: GeneratedCodeID = undefined + private readonly _id?: GeneratedCodeID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: GeneratedCodeID, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: GeneratedCodeID + ) { + super(parent); + + this._id = _id; + } - this._id = _id - } - async id(): Promise { + /** + * A unique identifier for this GeneratedCode. + */ + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -3679,17 +3771,12 @@ export class GeneratedCode extends BaseClient { operation: "id", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The directory containing the generated code - */ - code(): Directory { + return response; + }; + code = (): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -3697,15 +3784,10 @@ export class GeneratedCode extends BaseClient { operation: "code", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } - - /** - * List of paths to mark generated in version control (i.e. .gitattributes) - */ - async vcsGeneratedPaths(): Promise { + ctx: this._ctx, + }); + }; + vcsGeneratedPaths = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -3713,17 +3795,12 @@ export class GeneratedCode extends BaseClient { operation: "vcsGeneratedPaths", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * List of paths to ignore in version control (i.e. .gitignore) - */ - async vcsIgnoredPaths(): Promise { + return response; + }; + vcsIgnoredPaths = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -3731,17 +3808,16 @@ export class GeneratedCode extends BaseClient { operation: "vcsIgnoredPaths", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** - * Set the list of paths to mark generated in version control + * Set the list of paths to mark generated in version control. */ - withVCSGeneratedPaths(paths: string[]): GeneratedCode { + withVCSGeneratedPaths = (paths: string[]): GeneratedCode => { return new GeneratedCode({ queryTree: [ ...this._queryTree, @@ -3750,15 +3826,14 @@ export class GeneratedCode extends BaseClient { args: { paths }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Set the list of paths to ignore in version control + * Set the list of paths to ignore in version control. */ - withVCSIgnoredPaths(paths: string[]): GeneratedCode { + withVCSIgnoredPaths = (paths: string[]): GeneratedCode => { return new GeneratedCode({ queryTree: [ ...this._queryTree, @@ -3767,47 +3842,68 @@ export class GeneratedCode extends BaseClient { args: { paths }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Call the provided function with current GeneratedCode. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: GeneratedCode) => GeneratedCode) { - return arg(this) - } + with = (arg: (param: GeneratedCode) => GeneratedCode) => { + return arg(this); + }; } - - /** - * A git ref (tag, branch or commit). + * A git ref (tag, branch, or commit). */ export class GitRef extends BaseClient { - private readonly _commit?: string = undefined + private readonly _id?: GitRefID = undefined; + private readonly _commit?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _commit?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: GitRefID, + _commit?: string + ) { + super(parent); - this._commit = _commit - } + this._id = _id; + this._commit = _commit; + } + + /** + * A unique identifier for this GitRef. + */ + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; /** * The resolved commit id at this ref. */ - async commit(): Promise { + commit = async (): Promise => { if (this._commit) { - return this._commit + return this._commit; } const response: Awaited = await computeQuery( @@ -3817,17 +3913,18 @@ export class GitRef extends BaseClient { operation: "commit", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * The filesystem tree at this ref. + * @param opts.sshKnownHosts DEPRECATED: This option should be passed to `git` instead. + * @param opts.sshAuthSocket DEPRECATED: This option should be passed to `git` instead. */ - tree(opts?: GitRefTreeOpts): Directory { + tree = (opts?: GitRefTreeOpts): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -3836,32 +3933,55 @@ export class GitRef extends BaseClient { args: { ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; } /** * A git repository. */ export class GitRepository extends BaseClient { + private readonly _id?: GitRepositoryID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: GitRepositoryID + ) { + super(parent); + + this._id = _id; + } + + /** + * A unique identifier for this GitRepository. + */ + id = async (): Promise => { + if (this._id) { + return this._id; + } - } + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; /** - * Returns details on one branch. + * Returns details of a branch. * @param name Branch's name (e.g., "main"). */ - branch(name: string): GitRef { + branch = (name: string): GitRef => { return new GitRef({ queryTree: [ ...this._queryTree, @@ -3870,16 +3990,15 @@ export class GitRepository extends BaseClient { args: { name }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Returns details on one commit. + * Returns details of a commit. * @param id Identifier of the commit (e.g., "b6315d8f2810962c601af73f86831f6866ea798b"). */ - commit(id: string): GitRef { + commit = (id: string): GitRef => { return new GitRef({ queryTree: [ ...this._queryTree, @@ -3888,16 +4007,15 @@ export class GitRepository extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Returns details on one tag. + * Returns details of a tag. * @param name Tag's name (e.g., "v0.3.9"). */ - tag(name: string): GitRef { + tag = (name: string): GitRef => { return new GitRef({ queryTree: [ ...this._queryTree, @@ -3906,26 +4024,49 @@ export class GitRepository extends BaseClient { args: { name }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; } /** - * Information about the host execution environment. + * Information about the host environment. */ export class Host extends BaseClient { + private readonly _id?: HostID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: HostID + ) { + super(parent); + + this._id = _id; + } + + /** + * A unique identifier for this Host. + */ + id = async (): Promise => { + if (this._id) { + return this._id; + } - } + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; /** * Accesses a directory on the host. @@ -3933,7 +4074,7 @@ export class Host extends BaseClient { * @param opts.exclude Exclude artifacts that match the given pattern (e.g., ["node_modules/", ".git*"]). * @param opts.include Include only artifacts that match the given pattern (e.g., ["app/", "package.*"]). */ - directory(path: string, opts?: HostDirectoryOpts): Directory { + directory = (path: string, opts?: HostDirectoryOpts): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -3942,16 +4083,15 @@ export class Host extends BaseClient { args: { path, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Accesses a file on the host. * @param path Location of the file to retrieve (e.g., "README.md"). */ - file(path: string): File { + file = (path: string): File => { return new File({ queryTree: [ ...this._queryTree, @@ -3960,42 +4100,40 @@ export class Host extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Creates a service that forwards traffic to a specified address via the host. - * @param ports Ports to expose via the service, forwarding through the host network. - * - * If a port's frontend is unspecified or 0, it defaults to the same as the - * backend port. - * - * An empty set of ports is not valid; an error will be returned. * @param opts.host Upstream host to forward traffic to. + * @param opts.ports Ports to expose via the service, forwarding through the host network. + * + * If a port's frontend is unspecified or 0, it defaults to the same as the backend port. + * + * An empty set of ports is not valid; an error will be returned. */ - service(ports: PortForward[], opts?: HostServiceOpts): Service { + service = (opts?: HostServiceOpts): Service => { return new Service({ queryTree: [ ...this._queryTree, { operation: "service", - args: { ports, ...opts }, + args: { ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Sets a secret given a user-defined name and the file path on the host, and returns the secret. + * * The file is limited to a size of 512000 bytes. * @param name The user defined name for this secret. * @param path Location of the file to set as a secret. */ - setSecretFile(name: string, path: string): Secret { + setSecretFile = (name: string, path: string): Secret => { return new Secret({ queryTree: [ ...this._queryTree, @@ -4004,30 +4142,25 @@ export class Host extends BaseClient { args: { name, path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Creates a tunnel that forwards traffic from the host to a service. * @param service Service to send traffic from the tunnel. - * @param opts.native Map each service port to the same port on the host, as if the service were - * running natively. - * - * Note: enabling may result in port conflicts. * @param opts.ports Configure explicit port forwarding rules for the tunnel. - * - * If a port's frontend is unspecified or 0, a random port will be chosen by - * the host. - * - * If no ports are given, all of the service's ports are forwarded. If native - * is true, each port maps to the same port on the host. If native is false, - * each port maps to a random port chosen by the host. - * + * + * If a port's frontend is unspecified or 0, a random port will be chosen by the host. + * + * If no ports are given, all of the service's ports are forwarded. If native is true, each port maps to the same port on the host. If native is false, each port maps to a random port chosen by the host. + * * If ports are given and native is true, the ports are additive. + * @param opts.native Map each service port to the same port on the host, as if the service were running natively. + * + * Note: enabling may result in port conflicts. */ - tunnel(service: Service, opts?: HostTunnelOpts): Service { + tunnel = (service: Service, opts?: HostTunnelOpts): Service => { return new Service({ queryTree: [ ...this._queryTree, @@ -4036,16 +4169,15 @@ export class Host extends BaseClient { args: { service, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Accesses a Unix socket on the host. * @param path Location of the Unix socket (e.g., "/var/run/docker.sock"). */ - unixSocket(path: string): Socket { + unixSocket = (path: string): Socket => { return new Socket({ queryTree: [ ...this._queryTree, @@ -4054,49 +4186,192 @@ export class Host extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; } +/** + * A definition of a custom interface defined in a Module. + */ +export class InterfaceTypeDef extends BaseClient { + private readonly _id?: InterfaceTypeDefID = undefined; + private readonly _description?: string = undefined; + private readonly _name?: string = undefined; + private readonly _sourceModuleName?: string = undefined; + + /** + * Constructor is used for internal usage only, do not create object from it. + */ + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: InterfaceTypeDefID, + _description?: string, + _name?: string, + _sourceModuleName?: string + ) { + super(parent); + + this._id = _id; + this._description = _description; + this._name = _name; + this._sourceModuleName = _sourceModuleName; + } + + /** + * A unique identifier for this InterfaceTypeDef. + */ + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + return response; + }; + description = async (): Promise => { + if (this._description) { + return this._description; + } + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "description", + }, + ], + await this._ctx.connection() + ); + return response; + }; + functions = async (): Promise => { + type functions = { + id: FunctionID; + }; + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "functions", + }, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + return response.map( + (r) => + new Function_( + { + queryTree: [ + { + operation: "loadFunction_FromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + name = async (): Promise => { + if (this._name) { + return this._name; + } + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "name", + }, + ], + await this._ctx.connection() + ); + return response; + }; + sourceModuleName = async (): Promise => { + if (this._sourceModuleName) { + return this._sourceModuleName; + } + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "sourceModuleName", + }, + ], + await this._ctx.connection() + ); + return response; + }; +} /** * A simple key value object that represents a label. */ export class Label extends BaseClient { - private readonly _name?: string = undefined - private readonly _value?: string = undefined + private readonly _id?: LabelID = undefined; + private readonly _name?: string = undefined; + private readonly _value?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _name?: string, - _value?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: LabelID, + _name?: string, + _value?: string + ) { + super(parent); - this._name = _name - this._value = _value - } + this._id = _id; + this._name = _name; + this._value = _value; + } /** - * The label name. + * A unique identifier for this Label. */ - async name(): Promise { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -4106,19 +4381,14 @@ export class Label extends BaseClient { operation: "name", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * The label value. - */ - async value(): Promise { + return response; + }; + value = async (): Promise => { if (this._value) { - return this._value + return this._value; } const response: Awaited = await computeQuery( @@ -4128,33 +4398,52 @@ export class Label extends BaseClient { operation: "value", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } /** * A definition of a list type in a Module. */ export class ListTypeDef extends BaseClient { + private readonly _id?: ListTypeDefID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: ListTypeDefID + ) { + super(parent); - } + this._id = _id; + } /** - * The type of the elements in the list + * A unique identifier for this ListTypeDef. */ - elementTypeDef(): TypeDef { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + elementTypeDef = (): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -4162,49 +4451,50 @@ export class ListTypeDef extends BaseClient { operation: "elementTypeDef", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; } - +/** + * A Dagger module. + */ export class Module_ extends BaseClient { - private readonly _id?: ModuleID = undefined - private readonly _description?: string = undefined - private readonly _name?: string = undefined - private readonly _sdk?: string = undefined - private readonly _serve?: Void = undefined - private readonly _sourceDirectorySubPath?: string = undefined + private readonly _id?: ModuleID = undefined; + private readonly _description?: string = undefined; + private readonly _name?: string = undefined; + private readonly _sdk?: string = undefined; + private readonly _serve?: Void = undefined; + private readonly _sourceDirectorySubpath?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: ModuleID, - _description?: string, - _name?: string, - _sdk?: string, - _serve?: Void, - _sourceDirectorySubPath?: string, - ) { - super(parent) - - this._id = _id - this._description = _description - this._name = _name - this._sdk = _sdk - this._serve = _serve - this._sourceDirectorySubPath = _sourceDirectorySubPath - } - - /** - * The ID of the module - */ - async id(): Promise { + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: ModuleID, + _description?: string, + _name?: string, + _sdk?: string, + _serve?: Void, + _sourceDirectorySubpath?: string + ) { + super(parent); + + this._id = _id; + this._description = _description; + this._name = _name; + this._sdk = _sdk; + this._serve = _serve; + this._sourceDirectorySubpath = _sourceDirectorySubpath; + } + + /** + * A unique identifier for this Module. + */ + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -4214,20 +4504,15 @@ export class Module_ extends BaseClient { operation: "id", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * Modules used by this module - */ - async dependencies(): Promise { + return response; + }; + dependencies = async (): Promise => { type dependencies = { - id: ModuleID - } + id: ModuleID; + }; const response: Awaited = await computeQuery( [ @@ -4236,29 +4521,29 @@ export class Module_ extends BaseClient { operation: "dependencies", }, { - operation: "id" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new Module_( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.id, - ) - ) - } - - /** - * The dependencies as configured by the module - */ - async dependencyConfig(): Promise { + (r) => + new Module_( + { + queryTree: [ + { + operation: "loadModule_FromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + dependencyConfig = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -4266,19 +4551,14 @@ export class Module_ extends BaseClient { operation: "dependencyConfig", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The doc string of the module, if any - */ - async description(): Promise { + return response; + }; + description = async (): Promise => { if (this._description) { - return this._description + return this._description; } const response: Awaited = await computeQuery( @@ -4288,17 +4568,12 @@ export class Module_ extends BaseClient { operation: "description", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The code generated by the SDK's runtime - */ - generatedCode(): GeneratedCode { + return response; + }; + generatedCode = (): GeneratedCode => { return new GeneratedCode({ queryTree: [ ...this._queryTree, @@ -4306,17 +4581,61 @@ export class Module_ extends BaseClient { operation: "generatedCode", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * The name of the module + * Retrieves the module with the objects loaded via its SDK. */ - async name(): Promise { + initialize = (): Module_ => { + return new Module_({ + queryTree: [ + ...this._queryTree, + { + operation: "initialize", + }, + ], + ctx: this._ctx, + }); + }; + interfaces = async (): Promise => { + type interfaces = { + id: TypeDefID; + }; + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "interfaces", + }, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response.map( + (r) => + new TypeDef( + { + queryTree: [ + { + operation: "loadTypeDefFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -4326,20 +4645,15 @@ export class Module_ extends BaseClient { operation: "name", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * Objects served by this module - */ - async objects(): Promise { + return response; + }; + objects = async (): Promise => { type objects = { - id: TypeDefID - } + id: TypeDefID; + }; const response: Awaited = await computeQuery( [ @@ -4348,31 +4662,31 @@ export class Module_ extends BaseClient { operation: "objects", }, { - operation: "id" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new TypeDef( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.id, - ) - ) - } - - /** - * The SDK used by this module. Either a name of a builtin SDK or a module ref pointing to the SDK's implementation. - */ - async sdk(): Promise { + (r) => + new TypeDef( + { + queryTree: [ + { + operation: "loadTypeDefFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + sdk = async (): Promise => { if (this._sdk) { - return this._sdk + return this._sdk; } const response: Awaited = await computeQuery( @@ -4382,21 +4696,20 @@ export class Module_ extends BaseClient { operation: "sdk", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Serve a module's API in the current session. - * Note: this can only be called once per session. - * In the future, it could return a stream or service to remove the side effect. + * + * Note: this can only be called once per session. In the future, it could return a stream or service to remove the side effect. */ - async serve(): Promise { + serve = async (): Promise => { if (this._serve) { - return this._serve + return this._serve; } const response: Awaited = await computeQuery( @@ -4406,17 +4719,12 @@ export class Module_ extends BaseClient { operation: "serve", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The directory containing the module's source code - */ - sourceDirectory(): Directory { + return response; + }; + sourceDirectory = (): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -4424,37 +4732,47 @@ export class Module_ extends BaseClient { operation: "sourceDirectory", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } - - /** - * The module's subpath within the source directory - */ - async sourceDirectorySubPath(): Promise { - if (this._sourceDirectorySubPath) { - return this._sourceDirectorySubPath + ctx: this._ctx, + }); + }; + sourceDirectorySubpath = async (): Promise => { + if (this._sourceDirectorySubpath) { + return this._sourceDirectorySubpath; } const response: Awaited = await computeQuery( [ ...this._queryTree, { - operation: "sourceDirectorySubPath", + operation: "sourceDirectorySubpath", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** - * This module plus the given Object type and associated functions + * This module plus the given Interface type and associated functions */ - withObject(object: TypeDef): Module_ { + withInterface = (iface: TypeDef): Module_ => { + return new Module_({ + queryTree: [ + ...this._queryTree, + { + operation: "withInterface", + args: { iface }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * This module plus the given Object type and associated functions. + */ + withObject = (object: TypeDef): Module_ => { return new Module_({ queryTree: [ ...this._queryTree, @@ -4463,49 +4781,90 @@ export class Module_ extends BaseClient { args: { object }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Retrieves the module with basic configuration loaded, ready for initialization. + * @param directory The directory containing the module's source code. + * @param opts.subpath An optional subpath of the directory which contains the module's source code. + * + * This is needed when the module code is in a subdirectory but requires parent directories to be loaded in order to execute. For example, the module source code may need a go.mod, project.toml, package.json, etc. file from a parent directory. + * + * If not set, the module source code is loaded from the root of the directory. + */ + withSource = (directory: Directory, opts?: ModuleWithSourceOpts): Module_ => { + return new Module_({ + queryTree: [ + ...this._queryTree, + { + operation: "withSource", + args: { directory, ...opts }, + }, + ], + ctx: this._ctx, + }); + }; /** * Call the provided function with current Module. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: Module_) => Module_) { - return arg(this) - } + with = (arg: (param: Module_) => Module_) => { + return arg(this); + }; } /** * Static configuration for a module (e.g. parsed contents of dagger.json) */ export class ModuleConfig extends BaseClient { - private readonly _name?: string = undefined - private readonly _root?: string = undefined - private readonly _sdk?: string = undefined + private readonly _id?: ModuleConfigID = undefined; + private readonly _name?: string = undefined; + private readonly _root?: string = undefined; + private readonly _sdk?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _name?: string, - _root?: string, - _sdk?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: ModuleConfigID, + _name?: string, + _root?: string, + _sdk?: string + ) { + super(parent); - this._name = _name - this._root = _root - this._sdk = _sdk - } + this._id = _id; + this._name = _name; + this._root = _root; + this._sdk = _sdk; + } /** - * Modules that this module depends on. + * A unique identifier for this ModuleConfig. */ - async dependencies(): Promise { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + dependencies = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -4513,17 +4872,12 @@ export class ModuleConfig extends BaseClient { operation: "dependencies", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * Exclude these file globs when loading the module root. - */ - async exclude(): Promise { + return response; + }; + exclude = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -4531,17 +4885,12 @@ export class ModuleConfig extends BaseClient { operation: "exclude", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * Include only these file globs when loading the module root. - */ - async include(): Promise { + return response; + }; + include = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -4549,19 +4898,14 @@ export class ModuleConfig extends BaseClient { operation: "include", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The name of the module. - */ - async name(): Promise { + return response; + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -4571,19 +4915,14 @@ export class ModuleConfig extends BaseClient { operation: "name", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The root directory of the module's project, which may be above the module source code. - */ - async root(): Promise { + return response; + }; + root = async (): Promise => { if (this._root) { - return this._root + return this._root; } const response: Awaited = await computeQuery( @@ -4593,19 +4932,14 @@ export class ModuleConfig extends BaseClient { operation: "root", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * Either the name of a built-in SDK ('go', 'python', etc.) OR a module reference pointing to the SDK's module implementation. - */ - async sdk(): Promise { + return response; + }; + sdk = async (): Promise => { if (this._sdk) { - return this._sdk + return this._sdk; } const response: Awaited = await computeQuery( @@ -4615,45 +4949,74 @@ export class ModuleConfig extends BaseClient { operation: "sdk", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } - - - - /** * A definition of a custom object defined in a Module. */ export class ObjectTypeDef extends BaseClient { - private readonly _description?: string = undefined - private readonly _name?: string = undefined + private readonly _id?: ObjectTypeDefID = undefined; + private readonly _description?: string = undefined; + private readonly _name?: string = undefined; + private readonly _sourceModuleName?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _description?: string, - _name?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: ObjectTypeDefID, + _description?: string, + _name?: string, + _sourceModuleName?: string + ) { + super(parent); - this._description = _description - this._name = _name - } + this._id = _id; + this._description = _description; + this._name = _name; + this._sourceModuleName = _sourceModuleName; + } /** - * The doc string for the object, if any + * A unique identifier for this ObjectTypeDef. */ - async description(): Promise { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + constructor_ = (): Function_ => { + return new Function_({ + queryTree: [ + ...this._queryTree, + { + operation: "constructor", + }, + ], + ctx: this._ctx, + }); + }; + description = async (): Promise => { if (this._description) { - return this._description + return this._description; } const response: Awaited = await computeQuery( @@ -4663,21 +5026,15 @@ export class ObjectTypeDef extends BaseClient { operation: "description", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * Static fields defined on this object, if any - */ - async fields(): Promise { + return response; + }; + fields = async (): Promise => { type fields = { - description: string - name: string - } + id: FieldTypeDefID; + }; const response: Awaited = await computeQuery( [ @@ -4686,33 +5043,32 @@ export class ObjectTypeDef extends BaseClient { operation: "fields", }, { - operation: "description name" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new FieldTypeDef( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.description, - r.name, - ) - ) - } - - /** - * Functions defined on this object, if any - */ - async functions(): Promise { + (r) => + new FieldTypeDef( + { + queryTree: [ + { + operation: "loadFieldTypeDefFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + functions = async (): Promise => { type functions = { - id: FunctionID - } + id: FunctionID; + }; const response: Awaited = await computeQuery( [ @@ -4721,31 +5077,31 @@ export class ObjectTypeDef extends BaseClient { operation: "functions", }, { - operation: "id" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new Function_( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.id, - ) - ) - } - - /** - * The name of the object - */ - async name(): Promise { + (r) => + new Function_( + { + queryTree: [ + { + operation: "loadFunction_FromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -4755,48 +5111,80 @@ export class ObjectTypeDef extends BaseClient { operation: "name", }, ], - this.client - ) - - - return response - } -} - + await this._ctx.connection() + ); + return response; + }; + sourceModuleName = async (): Promise => { + if (this._sourceModuleName) { + return this._sourceModuleName; + } + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "sourceModuleName", + }, + ], + await this._ctx.connection() + ); + return response; + }; +} /** * A port exposed by a container. */ export class Port extends BaseClient { - private readonly _description?: string = undefined - private readonly _port?: number = undefined - private readonly _protocol?: NetworkProtocol = undefined + private readonly _id?: PortID = undefined; + private readonly _description?: string = undefined; + private readonly _port?: number = undefined; + private readonly _protocol?: NetworkProtocol = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _description?: string, - _port?: number, - _protocol?: NetworkProtocol, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: PortID, + _description?: string, + _port?: number, + _protocol?: NetworkProtocol + ) { + super(parent); - this._description = _description - this._port = _port - this._protocol = _protocol - } + this._id = _id; + this._description = _description; + this._port = _port; + this._protocol = _protocol; + } /** - * The port description. + * A unique identifier for this Port. */ - async description(): Promise { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + description = async (): Promise => { if (this._description) { - return this._description + return this._description; } const response: Awaited = await computeQuery( @@ -4806,19 +5194,14 @@ export class Port extends BaseClient { operation: "description", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * The port number. - */ - async port(): Promise { + return response; + }; + port = async (): Promise => { if (this._port) { - return this._port + return this._port; } const response: Awaited = await computeQuery( @@ -4828,19 +5211,14 @@ export class Port extends BaseClient { operation: "port", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * The transport layer network protocol. - */ - async protocol(): Promise { + return response; + }; + protocol = async (): Promise => { if (this._protocol) { - return this._protocol + return this._protocol; } const response: Awaited = await computeQuery( @@ -4850,40 +5228,64 @@ export class Port extends BaseClient { operation: "protocol", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } - - - +/** + * The root of the DAG. + */ export class Client extends BaseClient { - private readonly _checkVersionCompatibility?: boolean = undefined - private readonly _defaultPlatform?: Platform = undefined + private readonly _checkVersionCompatibility?: boolean = undefined; + private readonly _defaultPlatform?: Platform = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _checkVersionCompatibility?: boolean, - _defaultPlatform?: Platform, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _checkVersionCompatibility?: boolean, + _defaultPlatform?: Platform + ) { + super(parent); - this._checkVersionCompatibility = _checkVersionCompatibility - this._defaultPlatform = _defaultPlatform - } + this._checkVersionCompatibility = _checkVersionCompatibility; + this._defaultPlatform = _defaultPlatform; + } + + /** + * Retrieves a content-addressed blob. + * @param digest Digest of the blob + * @param size Size of the blob + * @param mediaType Media type of the blob + * @param uncompressed Digest of the uncompressed blob + */ + blob = ( + digest: string, + size: number, + mediaType: string, + uncompressed: string + ): Directory => { + return new Directory({ + queryTree: [ + ...this._queryTree, + { + operation: "blob", + args: { digest, size, mediaType, uncompressed }, + }, + ], + ctx: this._ctx, + }); + }; /** * Constructs a cache volume for a given cache key. * @param key A string identifier to target this cache volume (e.g., "modules-cache"). */ - cacheVolume(key: string): CacheVolume { + cacheVolume = (key: string): CacheVolume => { return new CacheVolume({ queryTree: [ ...this._queryTree, @@ -4892,16 +5294,15 @@ export class Client extends BaseClient { args: { key }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Checks if the current Dagger Engine is compatible with an SDK's required version. - * @param version The SDK's required version. + * @param version Version required by the SDK. */ - async checkVersionCompatibility(version: string): Promise { + checkVersionCompatibility = async (version: string): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -4910,20 +5311,20 @@ export class Client extends BaseClient { args: { version }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** - * Creates a scratch container or loads one by ID. - * - * Optional platform argument initializes new containers to execute and publish - * as that platform. Platform defaults to that of the builder's host. + * Creates a scratch container. + * + * Optional platform argument initializes new containers to execute and publish as that platform. Platform defaults to that of the builder's host. + * @param opts.id DEPRECATED: Use `loadContainerFromID` instead. + * @param opts.platform Platform to initialize the container with. */ - container(opts?: ClientContainerOpts): Container { + container = (opts?: ClientContainerOpts): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -4932,17 +5333,16 @@ export class Client extends BaseClient { args: { ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * The FunctionCall context that the SDK caller is currently executing in. - * If the caller is not currently executing in a function, this will return - * an error. + * + * If the caller is not currently executing in a function, this will return an error. */ - currentFunctionCall(): FunctionCall { + currentFunctionCall = (): FunctionCall => { return new FunctionCall({ queryTree: [ ...this._queryTree, @@ -4950,15 +5350,14 @@ export class Client extends BaseClient { operation: "currentFunctionCall", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * The module currently being served in the session, if any. */ - currentModule(): Module_ { + currentModule = (): Module_ => { return new Module_({ queryTree: [ ...this._queryTree, @@ -4966,15 +5365,52 @@ export class Client extends BaseClient { operation: "currentModule", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * The TypeDef representations of the objects currently being served in the session. + */ + currentTypeDefs = async (): Promise => { + type currentTypeDefs = { + id: TypeDefID; + }; + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "currentTypeDefs", + }, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); - /** - * The default platform of the builder. - */ - async defaultPlatform(): Promise { + return response.map( + (r) => + new TypeDef( + { + queryTree: [ + { + operation: "loadTypeDefFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + + /** + * The default platform of the engine. + */ + defaultPlatform = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -4982,17 +5418,17 @@ export class Client extends BaseClient { operation: "defaultPlatform", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** - * Creates an empty directory or loads one by ID. + * Creates an empty directory. + * @param opts.id DEPRECATED: Use `loadDirectoryFromID` isntead. */ - directory(opts?: ClientDirectoryOpts): Directory { + directory = (opts?: ClientDirectoryOpts): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -5001,16 +5437,14 @@ export class Client extends BaseClient { args: { ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Loads a file by ID. * @deprecated Use loadFileFromID instead. */ - file(id: FileID): File { + file = (id: FileID): File => { return new File({ queryTree: [ ...this._queryTree, @@ -5019,15 +5453,16 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Create a function. + * Creates a function. + * @param name Name of the function, in its original format from the implementation language. + * @param returnType Return type of the function. */ - function_(name: string, returnType: TypeDef): Function_ { + function_ = (name: string, returnType: TypeDef): Function_ => { return new Function_({ queryTree: [ ...this._queryTree, @@ -5036,16 +5471,14 @@ export class Client extends BaseClient { args: { name, returnType }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Create a code generation result, given a directory containing the generated - * code. + * Create a code generation result, given a directory containing the generated code. */ - generatedCode(code: Directory): GeneratedCode { + generatedCode = (code: Directory): GeneratedCode => { return new GeneratedCode({ queryTree: [ ...this._queryTree, @@ -5054,22 +5487,23 @@ export class Client extends BaseClient { args: { code }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Queries a git repository. - * @param url Url of the git repository. - * Can be formatted as https://{host}/{owner}/{repo}, git@{host}:{owner}/{repo} + * Queries a Git repository. + * @param url URL of the git repository. + * + * Can be formatted as `https://{host}/{owner}/{repo}`, `git@{host}:{owner}/{repo}`. + * * Suffix ".git" is optional. * @param opts.keepGitDir Set to true to keep .git directory. + * @param opts.experimentalServiceHost A service which must be started before the repo is fetched. * @param opts.sshKnownHosts Set SSH known hosts * @param opts.sshAuthSocket Set SSH auth socket - * @param opts.experimentalServiceHost A service which must be started before the repo is fetched. */ - git(url: string, opts?: ClientGitOpts): GitRepository { + git = (url: string, opts?: ClientGitOpts): GitRepository => { return new GitRepository({ queryTree: [ ...this._queryTree, @@ -5078,15 +5512,14 @@ export class Client extends BaseClient { args: { url, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Queries the host environment. */ - host(): Host { + host = (): Host => { return new Host({ queryTree: [ ...this._queryTree, @@ -5094,17 +5527,16 @@ export class Client extends BaseClient { operation: "host", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Returns a file containing an http remote url content. * @param url HTTP url to get the content from (e.g., "https://docs.dagger.io"). * @param opts.experimentalServiceHost A service which must be started before the URL is fetched. */ - http(url: string, opts?: ClientHttpOpts): File { + http = (url: string, opts?: ClientHttpOpts): File => { return new File({ queryTree: [ ...this._queryTree, @@ -5113,15 +5545,14 @@ export class Client extends BaseClient { args: { url, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Load a CacheVolume from its ID. */ - loadCacheVolumeFromID(id: CacheVolumeID): CacheVolume { + loadCacheVolumeFromID = (id: CacheVolumeID): CacheVolume => { return new CacheVolume({ queryTree: [ ...this._queryTree, @@ -5130,15 +5561,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Loads a container from an ID. + * Load a Container from its ID. */ - loadContainerFromID(id: ContainerID): Container { + loadContainerFromID = (id: ContainerID): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -5147,15 +5577,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Load a Directory from its ID. */ - loadDirectoryFromID(id: DirectoryID): Directory { + loadDirectoryFromID = (id: DirectoryID): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -5164,15 +5593,46 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Load a EnvVariable from its ID. + */ + loadEnvVariableFromID = (id: EnvVariableID): EnvVariable => { + return new EnvVariable({ + queryTree: [ + ...this._queryTree, + { + operation: "loadEnvVariableFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a FieldTypeDef from its ID. + */ + loadFieldTypeDefFromID = (id: FieldTypeDefID): FieldTypeDef => { + return new FieldTypeDef({ + queryTree: [ + ...this._queryTree, + { + operation: "loadFieldTypeDefFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; /** * Load a File from its ID. */ - loadFileFromID(id: FileID): File { + loadFileFromID = (id: FileID): File => { return new File({ queryTree: [ ...this._queryTree, @@ -5181,15 +5641,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Load a function argument by ID. + * Load a FunctionArg from its ID. */ - loadFunctionArgFromID(id: FunctionArgID): FunctionArg { + loadFunctionArgFromID = (id: FunctionArgID): FunctionArg => { return new FunctionArg({ queryTree: [ ...this._queryTree, @@ -5198,15 +5657,48 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Load a FunctionCallArgValue from its ID. + */ + loadFunctionCallArgValueFromID = ( + id: FunctionCallArgValueID + ): FunctionCallArgValue => { + return new FunctionCallArgValue({ + queryTree: [ + ...this._queryTree, + { + operation: "loadFunctionCallArgValueFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a FunctionCall from its ID. + */ + loadFunctionCallFromID = (id: FunctionCallID): FunctionCall => { + return new FunctionCall({ + queryTree: [ + ...this._queryTree, + { + operation: "loadFunctionCallFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; /** - * Load a function by ID. + * Load a Function from its ID. */ - loadFunctionFromID(id: FunctionID): Function_ { + loadFunctionFromID = (id: FunctionID): Function_ => { return new Function_({ queryTree: [ ...this._queryTree, @@ -5215,15 +5707,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Load a GeneratedCode by ID. + * Load a GeneratedCode from its ID. */ - loadGeneratedCodeFromID(id: GeneratedCodeID): GeneratedCode { + loadGeneratedCodeFromID = (id: GeneratedCodeID): GeneratedCode => { return new GeneratedCode({ queryTree: [ ...this._queryTree, @@ -5232,15 +5723,126 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Load a GitRef from its ID. + */ + loadGitRefFromID = (id: GitRefID): GitRef => { + return new GitRef({ + queryTree: [ + ...this._queryTree, + { + operation: "loadGitRefFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a GitRepository from its ID. + */ + loadGitRepositoryFromID = (id: GitRepositoryID): GitRepository => { + return new GitRepository({ + queryTree: [ + ...this._queryTree, + { + operation: "loadGitRepositoryFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a Host from its ID. + */ + loadHostFromID = (id: HostID): Host => { + return new Host({ + queryTree: [ + ...this._queryTree, + { + operation: "loadHostFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a InterfaceTypeDef from its ID. + */ + loadInterfaceTypeDefFromID = (id: InterfaceTypeDefID): InterfaceTypeDef => { + return new InterfaceTypeDef({ + queryTree: [ + ...this._queryTree, + { + operation: "loadInterfaceTypeDefFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a Label from its ID. + */ + loadLabelFromID = (id: LabelID): Label => { + return new Label({ + queryTree: [ + ...this._queryTree, + { + operation: "loadLabelFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a ListTypeDef from its ID. + */ + loadListTypeDefFromID = (id: ListTypeDefID): ListTypeDef => { + return new ListTypeDef({ + queryTree: [ + ...this._queryTree, + { + operation: "loadListTypeDefFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a ModuleConfig from its ID. + */ + loadModuleConfigFromID = (id: ModuleConfigID): ModuleConfig => { + return new ModuleConfig({ + queryTree: [ + ...this._queryTree, + { + operation: "loadModuleConfigFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; /** - * Load a module by ID. + * Load a Module from its ID. */ - loadModuleFromID(id: ModuleID): Module_ { + loadModuleFromID = (id: ModuleID): Module_ => { return new Module_({ queryTree: [ ...this._queryTree, @@ -5249,15 +5851,46 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Load a ObjectTypeDef from its ID. + */ + loadObjectTypeDefFromID = (id: ObjectTypeDefID): ObjectTypeDef => { + return new ObjectTypeDef({ + queryTree: [ + ...this._queryTree, + { + operation: "loadObjectTypeDefFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a Port from its ID. + */ + loadPortFromID = (id: PortID): Port => { + return new Port({ + queryTree: [ + ...this._queryTree, + { + operation: "loadPortFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; /** * Load a Secret from its ID. */ - loadSecretFromID(id: SecretID): Secret { + loadSecretFromID = (id: SecretID): Secret => { return new Secret({ queryTree: [ ...this._queryTree, @@ -5266,15 +5899,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Loads a service from ID. + * Load a Service from its ID. */ - loadServiceFromID(id: ServiceID): Service { + loadServiceFromID = (id: ServiceID): Service => { return new Service({ queryTree: [ ...this._queryTree, @@ -5283,15 +5915,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Load a Socket from its ID. */ - loadSocketFromID(id: SocketID): Socket { + loadSocketFromID = (id: SocketID): Socket => { return new Socket({ queryTree: [ ...this._queryTree, @@ -5300,15 +5931,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Load a TypeDef by ID. + * Load a TypeDef from its ID. */ - loadTypeDefFromID(id: TypeDefID): TypeDef { + loadTypeDefFromID = (id: TypeDefID): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -5317,15 +5947,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Create a new module. */ - module_(): Module_ { + module_ = (): Module_ => { return new Module_({ queryTree: [ ...this._queryTree, @@ -5333,15 +5962,17 @@ export class Client extends BaseClient { operation: "module", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Load the static configuration for a module from the given source directory and optional subpath. */ - moduleConfig(sourceDirectory: Directory, opts?: ClientModuleConfigOpts): ModuleConfig { + moduleConfig = ( + sourceDirectory: Directory, + opts?: ClientModuleConfigOpts + ): ModuleConfig => { return new ModuleConfig({ queryTree: [ ...this._queryTree, @@ -5350,18 +5981,17 @@ export class Client extends BaseClient { args: { sourceDirectory, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Creates a named sub-pipeline. - * @param name Pipeline name. - * @param opts.description Pipeline description. - * @param opts.labels Pipeline labels. + * @param name Name of the sub-pipeline. + * @param opts.description Description of the sub-pipeline. + * @param opts.labels Labels to apply to the sub-pipeline. */ - pipeline(name: string, opts?: ClientPipelineOpts): Client { + pipeline = (name: string, opts?: ClientPipelineOpts): Client => { return new Client({ queryTree: [ ...this._queryTree, @@ -5370,36 +6000,34 @@ export class Client extends BaseClient { args: { name, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Loads a secret from its ID. - * @deprecated Use loadSecretFromID instead + * Reference a secret by name. */ - secret(id: SecretID): Secret { + secret = (name: string): Secret => { return new Secret({ queryTree: [ ...this._queryTree, { operation: "secret", - args: { id }, + args: { name }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Sets a secret given a user defined name to its plaintext and returns the secret. + * * The plaintext value is limited to a size of 128000 bytes. * @param name The user defined name for this secret * @param plaintext The plaintext of the secret */ - setSecret(name: string, plaintext: string): Secret { + setSecret = (name: string, plaintext: string): Secret => { return new Secret({ queryTree: [ ...this._queryTree, @@ -5408,33 +6036,31 @@ export class Client extends BaseClient { args: { name, plaintext }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Loads a socket by its ID. * @deprecated Use loadSocketFromID instead. */ - socket(opts?: ClientSocketOpts): Socket { + socket = (id: SocketID): Socket => { return new Socket({ queryTree: [ ...this._queryTree, { operation: "socket", - args: { ...opts }, + args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Create a new TypeDef. */ - typeDef(): TypeDef { + typeDef = (): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -5442,48 +6068,47 @@ export class Client extends BaseClient { operation: "typeDef", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Call the provided function with current Client. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: Client) => Client) { - return arg(this) - } + with = (arg: (param: Client) => Client) => { + return arg(this); + }; } /** * A reference to a secret value, which can be handled more safely than the value itself. */ export class Secret extends BaseClient { - private readonly _id?: SecretID = undefined - private readonly _plaintext?: string = undefined + private readonly _id?: SecretID = undefined; + private readonly _plaintext?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: SecretID, - _plaintext?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: SecretID, + _plaintext?: string + ) { + super(parent); - this._id = _id - this._plaintext = _plaintext - } + this._id = _id; + this._plaintext = _plaintext; + } /** - * The identifier for this secret. + * A unique identifier for this Secret. */ - async id(): Promise { + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -5493,19 +6118,18 @@ export class Secret extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * The value of this secret. */ - async plaintext(): Promise { + plaintext = async (): Promise => { if (this._plaintext) { - return this._plaintext + return this._plaintext; } const response: Awaited = await computeQuery( @@ -5515,50 +6139,49 @@ export class Secret extends BaseClient { operation: "plaintext", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } - - - +/** + * A content-addressed service providing TCP connectivity. + */ export class Service extends BaseClient { - private readonly _id?: ServiceID = undefined - private readonly _endpoint?: string = undefined - private readonly _hostname?: string = undefined - private readonly _start?: ServiceID = undefined - private readonly _stop?: ServiceID = undefined + private readonly _id?: ServiceID = undefined; + private readonly _endpoint?: string = undefined; + private readonly _hostname?: string = undefined; + private readonly _start?: ServiceID = undefined; + private readonly _stop?: ServiceID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: ServiceID, - _endpoint?: string, - _hostname?: string, - _start?: ServiceID, - _stop?: ServiceID, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: ServiceID, + _endpoint?: string, + _hostname?: string, + _start?: ServiceID, + _stop?: ServiceID + ) { + super(parent); - this._id = _id - this._endpoint = _endpoint - this._hostname = _hostname - this._start = _start - this._stop = _stop - } + this._id = _id; + this._endpoint = _endpoint; + this._hostname = _hostname; + this._start = _start; + this._stop = _stop; + } /** - * A unique identifier for this service. + * A unique identifier for this Service. */ - async id(): Promise { + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -5568,25 +6191,24 @@ export class Service extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves an endpoint that clients can use to reach this container. - * + * * If no port is specified, the first exposed port is used. If none exist an error is returned. - * + * * If a scheme is specified, a URL is returned. Otherwise, a host:port pair is returned. * @param opts.port The exposed port number for the endpoint * @param opts.scheme Return a URL with the given scheme, eg. http for http:// */ - async endpoint(opts?: ServiceEndpointOpts): Promise { + endpoint = async (opts?: ServiceEndpointOpts): Promise => { if (this._endpoint) { - return this._endpoint + return this._endpoint; } const response: Awaited = await computeQuery( @@ -5597,19 +6219,18 @@ export class Service extends BaseClient { args: { ...opts }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves a hostname which can be used by clients to reach this container. */ - async hostname(): Promise { + hostname = async (): Promise => { if (this._hostname) { - return this._hostname + return this._hostname; } const response: Awaited = await computeQuery( @@ -5619,22 +6240,19 @@ export class Service extends BaseClient { operation: "hostname", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves the list of ports provided by the service. */ - async ports(): Promise { + ports = async (): Promise => { type ports = { - description: string - port: number - protocol: NetworkProtocol - } + id: PortID; + }; const response: Awaited = await computeQuery( [ @@ -5643,33 +6261,35 @@ export class Service extends BaseClient { operation: "ports", }, { - operation: "description port protocol" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new Port( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.description, - r.port, - r.protocol, - ) - ) - } + (r) => + new Port( + { + queryTree: [ + { + operation: "loadPortFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; /** * Start the service and wait for its health checks to succeed. - * + * * Services bound to a Container do not need to be manually started. */ - async start(): Promise { + start = async (): Promise => { await computeQuery( [ ...this._queryTree, @@ -5677,16 +6297,16 @@ export class Service extends BaseClient { operation: "start", }, ], - this.client - ) + await this._ctx.connection() + ); - return this - } + return this; + }; /** * Stop the service. */ - async stop(): Promise { + stop = async (): Promise => { await computeQuery( [ ...this._queryTree, @@ -5694,37 +6314,37 @@ export class Service extends BaseClient { operation: "stop", }, ], - this.client - ) + await this._ctx.connection() + ); - return this - } + return this; + }; } - - - +/** + * A Unix or TCP/IP socket that can be mounted into a container. + */ export class Socket extends BaseClient { - private readonly _id?: SocketID = undefined + private readonly _id?: SocketID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: SocketID, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: SocketID + ) { + super(parent); - this._id = _id - } + this._id = _id; + } /** - * The content-addressed identifier of the socket. + * A unique identifier for this Socket. */ - async id(): Promise { + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -5734,44 +6354,43 @@ export class Socket extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } - - - - /** * A definition of a parameter or return type in a Module. */ export class TypeDef extends BaseClient { - private readonly _id?: TypeDefID = undefined - private readonly _kind?: TypeDefKind = undefined - private readonly _optional?: boolean = undefined + private readonly _id?: TypeDefID = undefined; + private readonly _kind?: TypeDefKind = undefined; + private readonly _optional?: boolean = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: TypeDefID, - _kind?: TypeDefKind, - _optional?: boolean, - ) { - super(parent) - - this._id = _id - this._kind = _kind - this._optional = _optional - } - async id(): Promise { + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: TypeDefID, + _kind?: TypeDefKind, + _optional?: boolean + ) { + super(parent); + + this._id = _id; + this._kind = _kind; + this._optional = _optional; + } + + /** + * A unique identifier for this TypeDef. + */ + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -5781,18 +6400,23 @@ export class TypeDef extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * If kind is LIST, the list-specific type definition. - * If kind is not LIST, this will be null. - */ - asList(): ListTypeDef { + return response; + }; + asInterface = (): InterfaceTypeDef => { + return new InterfaceTypeDef({ + queryTree: [ + ...this._queryTree, + { + operation: "asInterface", + }, + ], + ctx: this._ctx, + }); + }; + asList = (): ListTypeDef => { return new ListTypeDef({ queryTree: [ ...this._queryTree, @@ -5800,16 +6424,10 @@ export class TypeDef extends BaseClient { operation: "asList", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } - - /** - * If kind is OBJECT, the object-specific type definition. - * If kind is not OBJECT, this will be null. - */ - asObject(): ObjectTypeDef { + ctx: this._ctx, + }); + }; + asObject = (): ObjectTypeDef => { return new ObjectTypeDef({ queryTree: [ ...this._queryTree, @@ -5817,17 +6435,12 @@ export class TypeDef extends BaseClient { operation: "asObject", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } - - /** - * The kind of type this is (e.g. primitive, list, object) - */ - async kind(): Promise { + ctx: this._ctx, + }); + }; + kind = async (): Promise => { if (this._kind) { - return this._kind + return this._kind; } const response: Awaited = await computeQuery( @@ -5837,19 +6450,14 @@ export class TypeDef extends BaseClient { operation: "kind", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * Whether this type can be set to null. Defaults to false. - */ - async optional(): Promise { + return response; + }; + optional = async (): Promise => { if (this._optional) { - return this._optional + return this._optional; } const response: Awaited = await computeQuery( @@ -5859,12 +6467,29 @@ export class TypeDef extends BaseClient { operation: "optional", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; + + /** + * Adds a function for constructing a new instance of an Object TypeDef, failing if the type is not an object. + */ + withConstructor = (function_: Function_): TypeDef => { + return new TypeDef({ + queryTree: [ + ...this._queryTree, + { + operation: "withConstructor", + args: { + function: function_, + }, + }, + ], + ctx: this._ctx, + }); + }; /** * Adds a static field for an Object TypeDef, failing if the type is not an object. @@ -5872,7 +6497,11 @@ export class TypeDef extends BaseClient { * @param typeDef The type of the field * @param opts.description A doc string for the field, if any */ - withField(name: string, typeDef: TypeDef, opts?: TypeDefWithFieldOpts): TypeDef { + withField = ( + name: string, + typeDef: TypeDef, + opts?: TypeDefWithFieldOpts + ): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -5881,49 +6510,68 @@ export class TypeDef extends BaseClient { args: { name, typeDef, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Adds a function for an Object TypeDef, failing if the type is not an object. + * Adds a function for an Object or Interface TypeDef, failing if the type is not one of those kinds. */ - withFunction(function_: Function_): TypeDef { + withFunction = (function_: Function_): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, { operation: "withFunction", - args: { function_ }, + args: { + function: function_, + }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Returns a TypeDef of kind Interface with the provided name. + */ + withInterface = (name: string, opts?: TypeDefWithInterfaceOpts): TypeDef => { + return new TypeDef({ + queryTree: [ + ...this._queryTree, + { + operation: "withInterface", + args: { name, ...opts }, + }, + ], + ctx: this._ctx, + }); + }; /** * Sets the kind of the type. */ - withKind(kind: TypeDefKind): TypeDef { + withKind = (kind: TypeDefKind): TypeDef => { + const metadata: Metadata = { + kind: { is_enum: true }, + }; + return new TypeDef({ queryTree: [ ...this._queryTree, { operation: "withKind", - args: { kind }, + args: { kind, __metadata: metadata }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Returns a TypeDef of kind List with the provided type for its elements. */ - withListOf(elementType: TypeDef): TypeDef { + withListOf = (elementType: TypeDef): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -5932,19 +6580,16 @@ export class TypeDef extends BaseClient { args: { elementType }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Returns a TypeDef of kind Object with the provided name. - * - * Note that an object's fields and functions may be omitted if the intent is - * only to refer to an object. This is how functions are able to return their - * own object, or any other circular reference. + * + * Note that an object's fields and functions may be omitted if the intent is only to refer to an object. This is how functions are able to return their own object, or any other circular reference. */ - withObject(name: string, opts?: TypeDefWithObjectOpts): TypeDef { + withObject = (name: string, opts?: TypeDefWithObjectOpts): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -5953,15 +6598,14 @@ export class TypeDef extends BaseClient { args: { name, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Sets whether this type can be set to null. */ - withOptional(optional: boolean): TypeDef { + withOptional = (optional: boolean): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -5970,24 +6614,18 @@ export class TypeDef extends BaseClient { args: { optional }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Call the provided function with current TypeDef. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: TypeDef) => TypeDef) { - return arg(this) - } + with = (arg: (param: TypeDef) => TypeDef) => { + return arg(this); + }; } - - - - - - +export const dag = new Client({ ctx: defaultContext }); diff --git a/example/.fluentci/sdk/client.ts b/example/.fluentci/sdk/client.ts new file mode 100644 index 0000000..22ef15e --- /dev/null +++ b/example/.fluentci/sdk/client.ts @@ -0,0 +1,9 @@ +import { GraphQLClient } from "../deps.ts"; + +export function createGQLClient(port: number, token: string): GraphQLClient { + return new GraphQLClient(`http://127.0.0.1:${port}/query`, { + headers: { + Authorization: "Basic " + btoa(token + ":"), + }, + }); +} diff --git a/example/.fluentci/sdk/connect.ts b/example/.fluentci/sdk/connect.ts index bd26cf7..02a97fa 100644 --- a/example/.fluentci/sdk/connect.ts +++ b/example/.fluentci/sdk/connect.ts @@ -1,6 +1,6 @@ import { Writable } from "node:stream"; - import { Client } from "./client.gen.ts"; +import { Context } from "./context.ts"; /** * ConnectOpts defines option used to connect to an engine. @@ -39,51 +39,15 @@ export interface ConnectParams { */ export async function connect( cb: CallbackFct, - config: ConnectOpts = {} + _config: ConnectOpts = {} ): Promise { - let client: Client; - // let close: null | (() => void) = null; - - if (Deno.env.has("FLUENTCI_TOKEN") && Deno.env.has("FLUENTCI_SESSION_ID")) { - const client = new Client({ - host: Deno.env.get("FLUENTCI_HOST") || "vm.fluentci.io", - sessionToken: Deno.env.get("FLUENTCI_TOKEN"), - }); - await cb(client).finally(() => { - if (close) { - close(); - } - }); - return; - } - - // Prefer DAGGER_SESSION_PORT if set - const daggerSessionPort = Deno.env.get("DAGGER_SESSION_PORT"); - if (daggerSessionPort) { - const sessionToken = Deno.env.get("DAGGER_SESSION_TOKEN"); - if (!sessionToken) { - throw new Error( - "DAGGER_SESSION_TOKEN must be set when using DAGGER_SESSION_PORT" - ); - } - - if (config.Workdir && config.Workdir !== "") { - throw new Error( - "cannot configure workdir for existing session (please use --workdir or host.directory with absolute paths instead)" - ); - } + const ctx = new Context(); + const client = new Client({ ctx: ctx }); - client = new Client({ - host: `127.0.0.1:${daggerSessionPort}`, - sessionToken: sessionToken, - }); - } else { - throw new Error("DAGGER_SESSION_PORT must be set"); - } + // Initialize connection + await ctx.connection(); await cb(client).finally(() => { - if (close) { - close(); - } + ctx.close(); }); } diff --git a/example/.fluentci/sdk/context.ts b/example/.fluentci/sdk/context.ts new file mode 100644 index 0000000..13b47cf --- /dev/null +++ b/example/.fluentci/sdk/context.ts @@ -0,0 +1,53 @@ +import { GraphQLClient } from "../deps.ts"; + +import { initDefaultContext } from "./builder.ts"; + +interface ContextConfig { + client?: GraphQLClient; +} + +/** + * Context abstracts the connection to the engine. + * + * It's required to implement the default global SDK. + * Its purpose is to store and returns the connection to the graphQL API, if + * no connection is set, it can create its own. + * + * This is also useful for lazy evaluation with the default global client, + * this one should only run the engine if it actually executes something. + */ +export class Context { + private _client?: GraphQLClient; + + constructor(config?: ContextConfig) { + this._client = config?.client; + } + + /** + * Returns a GraphQL client connected to the engine. + * + * If no client is set, it will create one. + */ + public async connection(): Promise { + if (!this._client) { + const defaultCtx = await initDefaultContext(); + this._client = defaultCtx._client as GraphQLClient; + } + + return this._client; + } + + /** + * Close the connection and the engine if this one was started by the node + * SDK. + */ + public close(): void { + // Reset client, so it can restart a new connection if necessary + this._client = undefined; + } +} + +/** + * Expose a default context for the global client + */ +export const defaultContext = new Context(); diff --git a/example/.fluentci/sdk/utils.ts b/example/.fluentci/sdk/utils.ts index 075e278..e779fad 100644 --- a/example/.fluentci/sdk/utils.ts +++ b/example/.fluentci/sdk/utils.ts @@ -140,14 +140,7 @@ export function buildQuery(q: QueryTree[]): string { return acc; }, ""); - return `{${query - .replaceAll('"StringKind"', "StringKind") - .replaceAll('"VoidKind"', "VoidKind") - .replaceAll('"IntegerKind"', "IntegerKind") - .replaceAll('"BooleanKind"', "BooleanKind") - .replaceAll('"ObjectKind"', "ObjectKind") - .replaceAll('"ListKind"', "ListKind") - .replaceAll("function_", "function")} }`; + return `{${query} }`; } /** diff --git a/example/.fluentci/src/dagger/jobs.ts b/example/.fluentci/src/dagger/jobs.ts index 60cb559..dccf85b 100644 --- a/example/.fluentci/src/dagger/jobs.ts +++ b/example/.fluentci/src/dagger/jobs.ts @@ -1,6 +1,4 @@ -import { Directory, Secret } from "../../deps.ts"; -import { Client } from "../../sdk/client.gen.ts"; -import { connect } from "../../sdk/connect.ts"; +import { Directory, Secret, dag } from "../../deps.ts"; import { filterObjectByPrefix, withEnvs, @@ -38,7 +36,6 @@ export async function preview( pulumiVersion = "latest", googleApplicationCredentials?: string ): Promise { - let result = ""; const GOOGLE_APPLICATION_CREDENTIALS = Deno.env.get("GOOGLE_APPLICATION_CREDENTIALS") || googleApplicationCredentials; @@ -46,40 +43,38 @@ export async function preview( const PULUMI_VERSION = Deno.env.get("PULUMI_VERSION") || pulumiVersion; - await connect(async (client: Client) => { - const context = getDirectory(client, src); - const secret = getPulumiAccessToken(client, token); - - if (!secret) { - console.error("PULUMI_ACCESS_TOKEN env var is required"); - Deno.exit(1); - } - - const baseCtr = withEnvs( - client - .pipeline(Job.preview) - .container() - .from(`pulumi/pulumi:${PULUMI_VERSION}`), - envs - ); - const ctr = baseCtr - .withSecretVariable("PULUMI_ACCESS_TOKEN", secret) - .withEnvVariable( - "GOOGLE_APPLICATION_CREDENTIALS", - GOOGLE_APPLICATION_CREDENTIALS || "" - ) - .withMountedCache("/root/.pulumi", client.cacheVolume("pulumi-cache")) - .withMountedCache( - "/app/node_modules", - client.cacheVolume("pulumi-node-modules") - ) - .withDirectory("/app", context, { exclude }) - .withWorkdir("/app") - .withExec(["npm", "install"], { skipEntrypoint: true }) - .withExec(["preview", "--non-interactive", "--stack", PULUMI_STACK]); - - result = await ctr.stdout(); - }); + const context = await getDirectory(dag, src); + const secret = await getPulumiAccessToken(dag, token); + + if (!secret) { + console.error("PULUMI_ACCESS_TOKEN env var is required"); + Deno.exit(1); + } + + const baseCtr = withEnvs( + dag + .pipeline(Job.preview) + .container() + .from(`pulumi/pulumi:${PULUMI_VERSION}`), + envs + ); + const ctr = baseCtr + .withSecretVariable("PULUMI_ACCESS_TOKEN", secret) + .withEnvVariable( + "GOOGLE_APPLICATION_CREDENTIALS", + GOOGLE_APPLICATION_CREDENTIALS || "" + ) + .withMountedCache("/root/.pulumi", dag.cacheVolume("pulumi-cache")) + .withMountedCache( + "/app/node_modules", + dag.cacheVolume("pulumi-node-modules") + ) + .withDirectory("/app", context, { exclude }) + .withWorkdir("/app") + .withExec(["npm", "install"], { skipEntrypoint: true }) + .withExec(["preview", "--non-interactive", "--stack", PULUMI_STACK]); + + const result = await ctr.stdout(); return result; } @@ -100,47 +95,41 @@ export async function up( pulumiVersion = "latest", googleApplicationCredentials?: string ): Promise { - let result = ""; const GOOGLE_APPLICATION_CREDENTIALS = Deno.env.get("GOOGLE_APPLICATION_CREDENTIALS") || googleApplicationCredentials; const PULUMI_STACK = Deno.env.get("PULUMI_STACK") || stack; const PULUMI_VERSION = Deno.env.get("PULUMI_VERSION") || pulumiVersion; - await connect(async (client: Client) => { - const context = getDirectory(client, src); - const secret = getPulumiAccessToken(client, token); - const baseCtr = withEnvs( - client - .pipeline(Job.up) - .container() - .from(`pulumi/pulumi:${PULUMI_VERSION}`), - envs - ); - - if (!secret) { - console.error("PULUMI_ACCESS_TOKEN env var is required"); - Deno.exit(1); - } - - const ctr = baseCtr - .withSecretVariable("PULUMI_ACCESS_TOKEN", secret) - .withEnvVariable( - "GOOGLE_APPLICATION_CREDENTIALS", - GOOGLE_APPLICATION_CREDENTIALS || "" - ) - .withMountedCache("/root/.pulumi", client.cacheVolume("pulumi-cache")) - .withMountedCache( - "/app/node_modules", - client.cacheVolume("pulumi-node-modules") - ) - .withDirectory("/app", context, { exclude }) - .withWorkdir("/app") - .withExec(["npm", "install"], { skipEntrypoint: true }) - .withExec(["up", "--yes", "--non-interactive", "--stack", PULUMI_STACK]); - - result = await ctr.stdout(); - }); + const context = await getDirectory(dag, src); + const secret = await getPulumiAccessToken(dag, token); + const baseCtr = withEnvs( + dag.pipeline(Job.up).container().from(`pulumi/pulumi:${PULUMI_VERSION}`), + envs + ); + + if (!secret) { + console.error("PULUMI_ACCESS_TOKEN env var is required"); + Deno.exit(1); + } + + const ctr = baseCtr + .withSecretVariable("PULUMI_ACCESS_TOKEN", secret) + .withEnvVariable( + "GOOGLE_APPLICATION_CREDENTIALS", + GOOGLE_APPLICATION_CREDENTIALS || "" + ) + .withMountedCache("/root/.pulumi", dag.cacheVolume("pulumi-cache")) + .withMountedCache( + "/app/node_modules", + dag.cacheVolume("pulumi-node-modules") + ) + .withDirectory("/app", context, { exclude }) + .withWorkdir("/app") + .withExec(["npm", "install"], { skipEntrypoint: true }) + .withExec(["up", "--yes", "--non-interactive", "--stack", PULUMI_STACK]); + + const result = await ctr.stdout(); return result; } diff --git a/example/.fluentci/src/dagger/lib.ts b/example/.fluentci/src/dagger/lib.ts index f7eb56f..32ea58a 100644 --- a/example/.fluentci/src/dagger/lib.ts +++ b/example/.fluentci/src/dagger/lib.ts @@ -2,19 +2,23 @@ import { Container } from "../../deps.ts"; import { Directory, DirectoryID, Secret, SecretID } from "../../deps.ts"; import { Client } from "../../sdk/client.gen.ts"; -export const getDirectory = ( +export const getDirectory = async ( client: Client, src: string | Directory | undefined = "." ) => { - if (typeof src === "string" && src.startsWith("core.Directory")) { - return client.directory({ - id: src as DirectoryID, - }); + if (typeof src === "string") { + try { + const directory = client.loadDirectoryFromID(src as DirectoryID); + await directory.id(); + return directory; + } catch (_) { + return client.host().directory(src); + } } return src instanceof Directory ? src : client.host().directory(src); }; -export const getPulumiAccessToken = ( +export const getPulumiAccessToken = async ( client: Client, token?: string | Secret ) => { @@ -25,10 +29,13 @@ export const getPulumiAccessToken = ( ); } if (token && typeof token === "string") { - if (token.startsWith("core.Secret")) { - return client.loadSecretFromID(token as SecretID); + try { + const secret = client.loadSecretFromID(token as SecretID); + await secret.id(); + return secret; + } catch (_) { + return client.setSecret("PULUMI_ACCESS_TOKEN", token); } - return client.setSecret("PULUMI_ACCESS_TOKEN", token); } if (token && token instanceof Secret) { return token; diff --git a/sdk/builder.ts b/sdk/builder.ts new file mode 100644 index 0000000..f06951a --- /dev/null +++ b/sdk/builder.ts @@ -0,0 +1,30 @@ +import { createGQLClient } from "./client.ts"; +import { Context } from "./context.ts"; + +/** + * @hidden + * + * Initialize a default client context from environment. + */ +export function initDefaultContext(): Context { + let ctx = new Context(); + + // Prefer DAGGER_SESSION_PORT if set + const daggerSessionPort = Deno.env.get("DAGGER_SESSION_PORT"); + if (daggerSessionPort) { + const sessionToken = Deno.env.get("DAGGER_SESSION_TOKEN"); + if (!sessionToken) { + throw new Error( + "DAGGER_SESSION_TOKEN must be set when using DAGGER_SESSION_PORT" + ); + } + + ctx = new Context({ + client: createGQLClient(Number(daggerSessionPort), sessionToken), + }); + } else { + throw new Error("DAGGER_SESSION_PORT must be set"); + } + + return ctx; +} diff --git a/sdk/client.gen.ts b/sdk/client.gen.ts index d18ad57..b128be8 100644 --- a/sdk/client.gen.ts +++ b/sdk/client.gen.ts @@ -2,62 +2,48 @@ * This file was auto-generated by `client-gen`. * Do not make direct changes to the file. */ -import { GraphQLClient } from "../deps.ts" - -import { computeQuery } from "./utils.ts" +import { Context, defaultContext } from "./context.ts"; +import { computeQuery } from "./utils.ts"; /** * @hidden */ export type QueryTree = { - operation: string - args?: Record -} + operation: string; + args?: Record; +}; /** * @hidden */ export type Metadata = { [key: string]: { - is_enum?: boolean - } -} + is_enum?: boolean; + }; +}; interface ClientConfig { - queryTree?: QueryTree[] - host?: string - sessionToken?: string + queryTree?: QueryTree[]; + ctx?: Context; } class BaseClient { - protected _queryTree: QueryTree[] - protected client: GraphQLClient - /** - * @defaultValue `127.0.0.1:8080` - */ - public clientHost: string - public sessionToken: string + protected _queryTree: QueryTree[]; + protected _ctx: Context; /** * @hidden */ - constructor({ queryTree, host, sessionToken }: ClientConfig = {}) { - this._queryTree = queryTree || [] - this.clientHost = host || "127.0.0.1:8080" - this.sessionToken = sessionToken || "" - this.client = new GraphQLClient(`http://${host}/query`, { - headers: { - Authorization: - "Basic " + btoa(sessionToken + ":"), - }, - }) + constructor({ queryTree, ctx }: ClientConfig = {}) { + this._queryTree = queryTree || []; + this._ctx = ctx || new Context(); } /** * @hidden */ get queryTree() { - return this._queryTree + return this._queryTree; } } @@ -65,22 +51,20 @@ export type BuildArg = { /** * The build argument name. */ - name: string + name: string; /** * The build argument value. */ - value: string -} + value: string; +}; /** * Sharing mode of the cache volume. */ export enum CacheSharingMode { - /** - * Shares the cache volume amongst many build pipelines, - * but will serialize the writes + * Shares the cache volume amongst many build pipelines, but will serialize the writes */ Locked = "LOCKED", @@ -95,555 +79,567 @@ export enum CacheSharingMode { Shared = "SHARED", } /** - * A global cache volume identifier. + * The `CacheVolumeID` scalar type represents an identifier for an object of type CacheVolume. */ -export type CacheVolumeID = string & {__CacheVolumeID: never} +export type CacheVolumeID = string & { __CacheVolumeID: never }; export type ContainerAsTarballOpts = { /** * Identifiers for other platform specific containers. - * Used for multi-platform image. + * + * Used for multi-platform images. */ - platformVariants?: Container[] + platformVariants?: Container[]; /** * Force each layer of the image to use the specified compression algorithm. - * If this is unset, then if a layer already has a compressed blob in the engine's - * cache, that will be used (this can result in a mix of compression algorithms for - * different layers). If this is unset and a layer has no compressed blob in the - * engine's cache, then it will be compressed using Gzip. + * + * If this is unset, then if a layer already has a compressed blob in the engine's cache, that will be used (this can result in a mix of compression algorithms for different layers). If this is unset and a layer has no compressed blob in the engine's cache, then it will be compressed using Gzip. */ - forcedCompression?: ImageLayerCompression + forcedCompression?: ImageLayerCompression; /** - * Use the specified media types for the image's layers. Defaults to OCI, which - * is largely compatible with most recent container runtimes, but Docker may be needed - * for older runtimes without OCI support. + * Use the specified media types for the image's layers. + * + * Defaults to OCI, which is largely compatible with most recent container runtimes, but Docker may be needed for older runtimes without OCI support. */ - mediaTypes?: ImageMediaTypes -} + mediaTypes?: ImageMediaTypes; +}; export type ContainerBuildOpts = { /** * Path to the Dockerfile to use. - * - * Default: './Dockerfile'. */ - dockerfile?: string + dockerfile?: string; /** - * Additional build arguments. + * Target build stage to build. */ - buildArgs?: BuildArg[] + target?: string; /** - * Target build stage to build. + * Additional build arguments. */ - target?: string + buildArgs?: BuildArg[]; /** * Secrets to pass to the build. - * + * * They will be mounted at /run/secrets/[secret-name] in the build container - * - * They can be accessed in the Dockerfile using the "secret" mount type - * and mount path /run/secrets/[secret-name] - * e.g. RUN --mount=type=secret,id=my-secret curl url?token=$(cat /run/secrets/my-secret)" + * + * They can be accessed in the Dockerfile using the "secret" mount type and mount path /run/secrets/[secret-name], e.g. RUN --mount=type=secret,id=my-secret curl http://example.com?token=$(cat /run/secrets/my-secret) */ - secrets?: Secret[] -} + secrets?: Secret[]; +}; export type ContainerExportOpts = { /** * Identifiers for other platform specific containers. + * * Used for multi-platform image. */ - platformVariants?: Container[] + platformVariants?: Container[]; /** * Force each layer of the exported image to use the specified compression algorithm. - * If this is unset, then if a layer already has a compressed blob in the engine's - * cache, that will be used (this can result in a mix of compression algorithms for - * different layers). If this is unset and a layer has no compressed blob in the - * engine's cache, then it will be compressed using Gzip. + * + * If this is unset, then if a layer already has a compressed blob in the engine's cache, that will be used (this can result in a mix of compression algorithms for different layers). If this is unset and a layer has no compressed blob in the engine's cache, then it will be compressed using Gzip. */ - forcedCompression?: ImageLayerCompression + forcedCompression?: ImageLayerCompression; /** - * Use the specified media types for the exported image's layers. Defaults to OCI, which - * is largely compatible with most recent container runtimes, but Docker may be needed - * for older runtimes without OCI support. + * Use the specified media types for the exported image's layers. + * + * Defaults to OCI, which is largely compatible with most recent container runtimes, but Docker may be needed for older runtimes without OCI support. */ - mediaTypes?: ImageMediaTypes -} + mediaTypes?: ImageMediaTypes; +}; export type ContainerImportOpts = { /** - * Identifies the tag to import from the archive, if the archive bundles - * multiple tags. + * Identifies the tag to import from the archive, if the archive bundles multiple tags. */ - tag?: string -} + tag?: string; +}; export type ContainerPipelineOpts = { /** - * Pipeline description. + * Description of the sub-pipeline. */ - description?: string + description?: string; /** - * Pipeline labels. + * Labels to apply to the sub-pipeline. */ - labels?: PipelineLabel[] -} + labels?: PipelineLabel[]; +}; export type ContainerPublishOpts = { /** * Identifiers for other platform specific containers. + * * Used for multi-platform image. */ - platformVariants?: Container[] + platformVariants?: Container[]; /** * Force each layer of the published image to use the specified compression algorithm. - * If this is unset, then if a layer already has a compressed blob in the engine's - * cache, that will be used (this can result in a mix of compression algorithms for - * different layers). If this is unset and a layer has no compressed blob in the - * engine's cache, then it will be compressed using Gzip. - */ - forcedCompression?: ImageLayerCompression - - /** - * Use the specified media types for the published image's layers. Defaults to OCI, which - * is largely compatible with most recent registries, but Docker may be needed for older - * registries without OCI support. + * + * If this is unset, then if a layer already has a compressed blob in the engine's cache, that will be used (this can result in a mix of compression algorithms for different layers). If this is unset and a layer has no compressed blob in the engine's cache, then it will be compressed using Gzip. */ - mediaTypes?: ImageMediaTypes -} + forcedCompression?: ImageLayerCompression; -export type ContainerWithDefaultArgsOpts = { /** - * Arguments to prepend to future executions (e.g., ["-v", "--no-cache"]). + * Use the specified media types for the published image's layers. + * + * Defaults to OCI, which is largely compatible with most recent registries, but Docker may be needed for older registries without OCI support. */ - args?: string[] -} + mediaTypes?: ImageMediaTypes; +}; export type ContainerWithDirectoryOpts = { /** - * Patterns to exclude in the written directory (e.g., ["node_modules/**", ".gitignore", ".git/"]). + * Patterns to exclude in the written directory (e.g. ["node_modules/**", ".gitignore", ".git/"]). */ - exclude?: string[] + exclude?: string[]; /** - * Patterns to include in the written directory (e.g., ["*.go", "go.mod", "go.sum"]). + * Patterns to include in the written directory (e.g. ["*.go", "go.mod", "go.sum"]). */ - include?: string[] + include?: string[]; /** * A user:group to set for the directory and its contents. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string -} + owner?: string; +}; + +export type ContainerWithEntrypointOpts = { + /** + * Don't remove the default arguments when setting the entrypoint. + */ + keepDefaultArgs?: boolean; +}; export type ContainerWithEnvVariableOpts = { /** - * Replace ${VAR} or $VAR in the value according to the current environment - * variables defined in the container (e.g., "/opt/bin:$PATH"). + * Replace `${VAR}` or `$VAR` in the value according to the current environment variables defined in the container (e.g., "/opt/bin:$PATH"). */ - expand?: boolean -} + expand?: boolean; +}; export type ContainerWithExecOpts = { /** * If the container has an entrypoint, ignore it for args rather than using it to wrap them. */ - skipEntrypoint?: boolean + skipEntrypoint?: boolean; /** * Content to write to the command's standard input before closing (e.g., "Hello world"). */ - stdin?: string + stdin?: string; /** * Redirect the command's standard output to a file in the container (e.g., "/tmp/stdout"). */ - redirectStdout?: string + redirectStdout?: string; /** * Redirect the command's standard error to a file in the container (e.g., "/tmp/stderr"). */ - redirectStderr?: string + redirectStderr?: string; /** * Provides dagger access to the executed command. - * - * Do not use this option unless you trust the command being executed. - * The command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM. + * + * Do not use this option unless you trust the command being executed; the command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM. */ - experimentalPrivilegedNesting?: boolean + experimentalPrivilegedNesting?: boolean; /** - * Execute the command with all root capabilities. This is similar to running a command - * with "sudo" or executing `docker run` with the `--privileged` flag. Containerization - * does not provide any security guarantees when using this option. It should only be used - * when absolutely necessary and only with trusted commands. + * Execute the command with all root capabilities. This is similar to running a command with "sudo" or executing "docker run" with the "--privileged" flag. Containerization does not provide any security guarantees when using this option. It should only be used when absolutely necessary and only with trusted commands. */ - insecureRootCapabilities?: boolean -} + insecureRootCapabilities?: boolean; +}; export type ContainerWithExposedPortOpts = { /** * Transport layer network protocol */ - protocol?: NetworkProtocol + protocol?: NetworkProtocol; /** * Optional port description */ - description?: string -} + description?: string; +}; export type ContainerWithFileOpts = { /** * Permission given to the copied file (e.g., 0600). - * - * Default: 0644. */ - permissions?: number + permissions?: number; /** * A user:group to set for the file. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string -} + owner?: string; +}; export type ContainerWithMountedCacheOpts = { /** * Identifier of the directory to use as the cache volume's root. */ - source?: Directory + source?: Directory; /** * Sharing mode of the cache volume. */ - sharing?: CacheSharingMode + sharing?: CacheSharingMode; /** * A user:group to set for the mounted cache directory. - * - * Note that this changes the ownership of the specified mount along with the - * initial filesystem provided by source (if any). It does not have any effect - * if/when the cache has already been created. - * + * + * Note that this changes the ownership of the specified mount along with the initial filesystem provided by source (if any). It does not have any effect if/when the cache has already been created. + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string -} + owner?: string; +}; export type ContainerWithMountedDirectoryOpts = { /** * A user:group to set for the mounted directory and its contents. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string -} + owner?: string; +}; export type ContainerWithMountedFileOpts = { /** * A user or user:group to set for the mounted file. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string -} + owner?: string; +}; export type ContainerWithMountedSecretOpts = { /** * A user:group to set for the mounted secret. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string + owner?: string; /** * Permission given to the mounted secret (e.g., 0600). + * * This option requires an owner to be set to be active. - * - * Default: 0400. */ - mode?: number -} + mode?: number; +}; export type ContainerWithNewFileOpts = { /** * Content of the file to write (e.g., "Hello world!"). */ - contents?: string + contents?: string; /** * Permission given to the written file (e.g., 0600). - * - * Default: 0644. */ - permissions?: number + permissions?: number; /** * A user:group to set for the file. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string -} + owner?: string; +}; export type ContainerWithUnixSocketOpts = { /** * A user:group to set for the mounted socket. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - owner?: string -} + owner?: string; +}; + +export type ContainerWithoutEntrypointOpts = { + /** + * Don't remove the default arguments when unsetting the entrypoint. + */ + keepDefaultArgs?: boolean; +}; export type ContainerWithoutExposedPortOpts = { /** * Port protocol to unexpose */ - protocol?: NetworkProtocol -} - -/** - * A unique container identifier. Null designates an empty container (scratch). - */ -export type ContainerID = string & {__ContainerID: never} + protocol?: NetworkProtocol; +}; /** - * The `DateTime` scalar type represents a DateTime. The DateTime is serialized as an RFC 3339 quoted string + * The `ContainerID` scalar type represents an identifier for an object of type Container. */ -export type DateTime = string & {__DateTime: never} +export type ContainerID = string & { __ContainerID: never }; export type DirectoryAsModuleOpts = { /** - * An optional subpath of the directory which contains the module's source - * code. - * - * This is needed when the module code is in a subdirectory but requires - * parent directories to be loaded in order to execute. For example, the - * module source code may need a go.mod, project.toml, package.json, etc. file - * from a parent directory. - * - * If not set, the module source code is loaded from the root of the - * directory. - */ - sourceSubpath?: string -} + * An optional subpath of the directory which contains the module's source code. + * + * This is needed when the module code is in a subdirectory but requires parent directories to be loaded in order to execute. For example, the module source code may need a go.mod, project.toml, package.json, etc. file from a parent directory. + * + * If not set, the module source code is loaded from the root of the directory. + */ + sourceSubpath?: string; +}; export type DirectoryDockerBuildOpts = { /** - * Path to the Dockerfile to use (e.g., "frontend.Dockerfile"). - * - * Defaults: './Dockerfile'. + * The platform to build. */ - dockerfile?: string + platform?: Platform; /** - * The platform to build. + * Path to the Dockerfile to use (e.g., "frontend.Dockerfile"). */ - platform?: Platform + dockerfile?: string; /** - * Build arguments to use in the build. + * Target build stage to build. */ - buildArgs?: BuildArg[] + target?: string; /** - * Target build stage to build. + * Build arguments to use in the build. */ - target?: string + buildArgs?: BuildArg[]; /** * Secrets to pass to the build. - * + * * They will be mounted at /run/secrets/[secret-name]. */ - secrets?: Secret[] -} + secrets?: Secret[]; +}; export type DirectoryEntriesOpts = { /** * Location of the directory to look at (e.g., "/src"). */ - path?: string -} + path?: string; +}; export type DirectoryPipelineOpts = { /** - * Pipeline description. + * Description of the sub-pipeline. */ - description?: string + description?: string; /** - * Pipeline labels. + * Labels to apply to the sub-pipeline. */ - labels?: PipelineLabel[] -} + labels?: PipelineLabel[]; +}; export type DirectoryWithDirectoryOpts = { /** * Exclude artifacts that match the given pattern (e.g., ["node_modules/", ".git*"]). */ - exclude?: string[] + exclude?: string[]; /** * Include only artifacts that match the given pattern (e.g., ["app/", "package.*"]). */ - include?: string[] -} + include?: string[]; +}; export type DirectoryWithFileOpts = { /** * Permission given to the copied file (e.g., 0600). - * - * Default: 0644. */ - permissions?: number -} + permissions?: number; +}; export type DirectoryWithNewDirectoryOpts = { /** * Permission granted to the created directory (e.g., 0777). - * - * Default: 0755. */ - permissions?: number -} + permissions?: number; +}; export type DirectoryWithNewFileOpts = { /** * Permission given to the copied file (e.g., 0600). - * - * Default: 0644. */ - permissions?: number -} + permissions?: number; +}; + +/** + * The `DirectoryID` scalar type represents an identifier for an object of type Directory. + */ +export type DirectoryID = string & { __DirectoryID: never }; + +/** + * The `EnvVariableID` scalar type represents an identifier for an object of type EnvVariable. + */ +export type EnvVariableID = string & { __EnvVariableID: never }; /** - * A content-addressed directory identifier. + * The `FieldTypeDefID` scalar type represents an identifier for an object of type FieldTypeDef. */ -export type DirectoryID = string & {__DirectoryID: never} +export type FieldTypeDefID = string & { __FieldTypeDefID: never }; export type FileExportOpts = { /** - * If allowParentDirPath is true, the path argument can be a directory path, in which case - * the file will be created in that directory. + * If allowParentDirPath is true, the path argument can be a directory path, in which case the file will be created in that directory. */ - allowParentDirPath?: boolean -} + allowParentDirPath?: boolean; +}; /** - * A file identifier. + * The `FileID` scalar type represents an identifier for an object of type File. */ -export type FileID = string & {__FileID: never} +export type FileID = string & { __FileID: never }; export type FunctionWithArgOpts = { /** * A doc string for the argument, if any */ - description?: string + description?: string; /** * A default value to use for this argument if not explicitly set by the caller, if any */ - defaultValue?: JSON -} + defaultValue?: JSON; +}; + +/** + * The `FunctionArgID` scalar type represents an identifier for an object of type FunctionArg. + */ +export type FunctionArgID = string & { __FunctionArgID: never }; + +/** + * The `FunctionCallArgValueID` scalar type represents an identifier for an object of type FunctionCallArgValue. + */ +export type FunctionCallArgValueID = string & { + __FunctionCallArgValueID: never; +}; /** - * A reference to a FunctionArg. + * The `FunctionCallID` scalar type represents an identifier for an object of type FunctionCall. */ -export type FunctionArgID = string & {__FunctionArgID: never} +export type FunctionCallID = string & { __FunctionCallID: never }; /** - * A reference to a Function. + * The `FunctionID` scalar type represents an identifier for an object of type Function. */ -export type FunctionID = string & {__FunctionID: never} +export type FunctionID = string & { __FunctionID: never }; /** - * A reference to GeneratedCode. + * The `GeneratedCodeID` scalar type represents an identifier for an object of type GeneratedCode. */ -export type GeneratedCodeID = string & {__GeneratedCodeID: never} +export type GeneratedCodeID = string & { __GeneratedCodeID: never }; export type GitRefTreeOpts = { - sshKnownHosts?: string - sshAuthSocket?: Socket -} + /** + * DEPRECATED: This option should be passed to `git` instead. + */ + sshKnownHosts?: string; + + /** + * DEPRECATED: This option should be passed to `git` instead. + */ + sshAuthSocket?: Socket; +}; + +/** + * The `GitRefID` scalar type represents an identifier for an object of type GitRef. + */ +export type GitRefID = string & { __GitRefID: never }; + +/** + * The `GitRepositoryID` scalar type represents an identifier for an object of type GitRepository. + */ +export type GitRepositoryID = string & { __GitRepositoryID: never }; export type HostDirectoryOpts = { /** * Exclude artifacts that match the given pattern (e.g., ["node_modules/", ".git*"]). */ - exclude?: string[] + exclude?: string[]; /** * Include only artifacts that match the given pattern (e.g., ["app/", "package.*"]). */ - include?: string[] -} + include?: string[]; +}; export type HostServiceOpts = { /** * Upstream host to forward traffic to. */ - host?: string -} + host?: string; -export type HostTunnelOpts = { /** - * Map each service port to the same port on the host, as if the service were - * running natively. - * - * Note: enabling may result in port conflicts. + * Ports to expose via the service, forwarding through the host network. + * + * If a port's frontend is unspecified or 0, it defaults to the same as the backend port. + * + * An empty set of ports is not valid; an error will be returned. */ - native?: boolean + ports: PortForward[]; +}; +export type HostTunnelOpts = { /** * Configure explicit port forwarding rules for the tunnel. - * - * If a port's frontend is unspecified or 0, a random port will be chosen by - * the host. - * - * If no ports are given, all of the service's ports are forwarded. If native - * is true, each port maps to the same port on the host. If native is false, - * each port maps to a random port chosen by the host. - * + * + * If a port's frontend is unspecified or 0, a random port will be chosen by the host. + * + * If no ports are given, all of the service's ports are forwarded. If native is true, each port maps to the same port on the host. If native is false, each port maps to a random port chosen by the host. + * * If ports are given and native is true, the ports are additive. */ - ports?: PortForward[] -} + ports?: PortForward[]; + + /** + * Map each service port to the same port on the host, as if the service were running natively. + * + * Note: enabling may result in port conflicts. + */ + native?: boolean; +}; /** - * The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. + * The `HostID` scalar type represents an identifier for an object of type Host. */ -export type ID = string & {__ID: never} +export type HostID = string & { __HostID: never }; /** * Compression algorithm to use for image layers. @@ -661,253 +657,297 @@ export enum ImageMediaTypes { Dockermediatypes = "DockerMediaTypes", Ocimediatypes = "OCIMediaTypes", } +/** + * The `InterfaceTypeDefID` scalar type represents an identifier for an object of type InterfaceTypeDef. + */ +export type InterfaceTypeDefID = string & { __InterfaceTypeDefID: never }; + /** * An arbitrary JSON-encoded value. */ -export type JSON = string & {__JSON: never} +export type JSON = string & { __JSON: never }; /** - * A reference to a Module. + * The `LabelID` scalar type represents an identifier for an object of type Label. */ -export type ModuleID = string & {__ModuleID: never} +export type LabelID = string & { __LabelID: never }; /** - * Transport layer network protocol associated to a port. + * The `ListTypeDefID` scalar type represents an identifier for an object of type ListTypeDef. */ -export enum NetworkProtocol { +export type ListTypeDefID = string & { __ListTypeDefID: never }; +export type ModuleWithSourceOpts = { /** - * TCP (Transmission Control Protocol) + * An optional subpath of the directory which contains the module's source code. + * + * This is needed when the module code is in a subdirectory but requires parent directories to be loaded in order to execute. For example, the module source code may need a go.mod, project.toml, package.json, etc. file from a parent directory. + * + * If not set, the module source code is loaded from the root of the directory. */ - Tcp = "TCP", + subpath?: string; +}; - /** - * UDP (User Datagram Protocol) - */ +/** + * The `ModuleConfigID` scalar type represents an identifier for an object of type ModuleConfig. + */ +export type ModuleConfigID = string & { __ModuleConfigID: never }; + +/** + * The `ModuleID` scalar type represents an identifier for an object of type Module. + */ +export type ModuleID = string & { __ModuleID: never }; + +/** + * Transport layer network protocol associated to a port. + */ +export enum NetworkProtocol { + Tcp = "TCP", Udp = "UDP", } +/** + * The `ObjectTypeDefID` scalar type represents an identifier for an object of type ObjectTypeDef. + */ +export type ObjectTypeDefID = string & { __ObjectTypeDefID: never }; + export type PipelineLabel = { /** * Label name. */ - name: string + name: string; /** * Label value. */ - value: string -} + value: string; +}; /** * The platform config OS and architecture in a Container. - * + * * The format is [os]/[platform]/[version] (e.g., "darwin/arm64/v7", "windows/amd64", "linux/arm64"). */ -export type Platform = string & {__Platform: never} +export type Platform = string & { __Platform: never }; export type PortForward = { /** * Destination port for traffic. */ - backend: number + backend: number; /** * Port to expose to clients. If unspecified, a default will be chosen. */ - frontend?: number + frontend?: number; /** - * Protocol to use for traffic. + * Transport layer protocol to use for traffic. */ - protocol?: NetworkProtocol -} + protocol?: NetworkProtocol; +}; + +/** + * The `PortID` scalar type represents an identifier for an object of type Port. + */ +export type PortID = string & { __PortID: never }; export type ClientContainerOpts = { - id?: ContainerID - platform?: Platform -} + /** + * DEPRECATED: Use `loadContainerFromID` instead. + */ + id?: ContainerID; + + /** + * Platform to initialize the container with. + */ + platform?: Platform; +}; export type ClientDirectoryOpts = { - id?: DirectoryID -} + /** + * DEPRECATED: Use `loadDirectoryFromID` isntead. + */ + id?: DirectoryID; +}; export type ClientGitOpts = { /** * Set to true to keep .git directory. */ - keepGitDir?: boolean + keepGitDir?: boolean; /** - * Set SSH known hosts + * A service which must be started before the repo is fetched. */ - sshKnownHosts?: string + experimentalServiceHost?: Service; /** - * Set SSH auth socket + * Set SSH known hosts */ - sshAuthSocket?: Socket + sshKnownHosts?: string; /** - * A service which must be started before the repo is fetched. + * Set SSH auth socket */ - experimentalServiceHost?: Service -} + sshAuthSocket?: Socket; +}; export type ClientHttpOpts = { /** * A service which must be started before the URL is fetched. */ - experimentalServiceHost?: Service -} + experimentalServiceHost?: Service; +}; export type ClientModuleConfigOpts = { - subpath?: string -} + subpath?: string; +}; export type ClientPipelineOpts = { /** - * Pipeline description. + * Description of the sub-pipeline. */ - description?: string + description?: string; /** - * Pipeline labels. + * Labels to apply to the sub-pipeline. */ - labels?: PipelineLabel[] -} - -export type ClientSocketOpts = { - id?: SocketID -} + labels?: PipelineLabel[]; +}; /** - * A unique identifier for a secret. + * The `SecretID` scalar type represents an identifier for an object of type Secret. */ -export type SecretID = string & {__SecretID: never} +export type SecretID = string & { __SecretID: never }; export type ServiceEndpointOpts = { /** * The exposed port number for the endpoint */ - port?: number + port?: number; /** * Return a URL with the given scheme, eg. http for http:// */ - scheme?: string -} + scheme?: string; +}; /** - * A unique service identifier. + * The `ServiceID` scalar type represents an identifier for an object of type Service. */ -export type ServiceID = string & {__ServiceID: never} +export type ServiceID = string & { __ServiceID: never }; /** - * A content-addressed socket identifier. + * The `SocketID` scalar type represents an identifier for an object of type Socket. */ -export type SocketID = string & {__SocketID: never} +export type SocketID = string & { __SocketID: never }; export type TypeDefWithFieldOpts = { /** * A doc string for the field, if any */ - description?: string -} + description?: string; +}; + +export type TypeDefWithInterfaceOpts = { + description?: string; +}; export type TypeDefWithObjectOpts = { - description?: string -} + description?: string; +}; /** - * A reference to a TypeDef. + * The `TypeDefID` scalar type represents an identifier for an object of type TypeDef. */ -export type TypeDefID = string & {__TypeDefID: never} +export type TypeDefID = string & { __TypeDefID: never }; /** * Distinguishes the different kinds of TypeDefs. */ export enum TypeDefKind { + /** + * A boolean value. + */ + BooleanKind = "BOOLEAN_KIND", /** - * A boolean value + * An integer value. */ - Booleankind = "BooleanKind", + IntegerKind = "INTEGER_KIND", /** - * An integer value + * A named type of functions that can be matched+implemented by other objects+interfaces. + * + * Always paired with an InterfaceTypeDef. */ - Integerkind = "IntegerKind", + InterfaceKind = "INTERFACE_KIND", /** * A list of values all having the same type. - * + * * Always paired with a ListTypeDef. */ - Listkind = "ListKind", + ListKind = "LIST_KIND", /** * A named type defined in the GraphQL schema, with fields and functions. - * + * * Always paired with an ObjectTypeDef. */ - Objectkind = "ObjectKind", + ObjectKind = "OBJECT_KIND", /** - * A string value + * A string value. */ - Stringkind = "StringKind", + StringKind = "STRING_KIND", /** * A special kind used to signify that no value is returned. - * - * This is used for functions that have no return value. The outer TypeDef - * specifying this Kind is always Optional, as the Void is never actually - * represented. + * + * This is used for functions that have no return value. The outer TypeDef specifying this Kind is always Optional, as the Void is never actually represented. */ - Voidkind = "VoidKind", + VoidKind = "VOID_KIND", } /** - * The absense of a value. - * + * The absence of a value. + * * A Null Void is used as a placeholder for resolvers that do not return anything. */ -export type Void = string & {__Void: never} +export type Void = string & { __Void: never }; export type __TypeEnumValuesOpts = { - includeDeprecated?: boolean -} + includeDeprecated?: boolean; +}; export type __TypeFieldsOpts = { - includeDeprecated?: boolean -} - - - - - - - + includeDeprecated?: boolean; +}; /** * A directory whose contents persist across runs. */ export class CacheVolume extends BaseClient { - private readonly _id?: CacheVolumeID = undefined + private readonly _id?: CacheVolumeID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: CacheVolumeID, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: CacheVolumeID + ) { + super(parent); + + this._id = _id; + } - this._id = _id - } - async id(): Promise { + /** + * A unique identifier for this CacheVolume. + */ + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -917,76 +957,73 @@ export class CacheVolume extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } - - /** - * An OCI-compatible container, also known as a docker container. + * An OCI-compatible container, also known as a Docker container. */ export class Container extends BaseClient { - private readonly _id?: ContainerID = undefined - private readonly _envVariable?: string = undefined - private readonly _export?: boolean = undefined - private readonly _imageRef?: string = undefined - private readonly _label?: string = undefined - private readonly _platform?: Platform = undefined - private readonly _publish?: string = undefined - private readonly _shellEndpoint?: string = undefined - private readonly _stderr?: string = undefined - private readonly _stdout?: string = undefined - private readonly _sync?: ContainerID = undefined - private readonly _user?: string = undefined - private readonly _workdir?: string = undefined + private readonly _id?: ContainerID = undefined; + private readonly _envVariable?: string = undefined; + private readonly _export?: boolean = undefined; + private readonly _imageRef?: string = undefined; + private readonly _label?: string = undefined; + private readonly _platform?: Platform = undefined; + private readonly _publish?: string = undefined; + private readonly _shellEndpoint?: string = undefined; + private readonly _stderr?: string = undefined; + private readonly _stdout?: string = undefined; + private readonly _sync?: ContainerID = undefined; + private readonly _user?: string = undefined; + private readonly _workdir?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: ContainerID, - _envVariable?: string, - _export?: boolean, - _imageRef?: string, - _label?: string, - _platform?: Platform, - _publish?: string, - _shellEndpoint?: string, - _stderr?: string, - _stdout?: string, - _sync?: ContainerID, - _user?: string, - _workdir?: string, - ) { - super(parent) - - this._id = _id - this._envVariable = _envVariable - this._export = _export - this._imageRef = _imageRef - this._label = _label - this._platform = _platform - this._publish = _publish - this._shellEndpoint = _shellEndpoint - this._stderr = _stderr - this._stdout = _stdout - this._sync = _sync - this._user = _user - this._workdir = _workdir - } - - /** - * A unique identifier for this container. - */ - async id(): Promise { + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: ContainerID, + _envVariable?: string, + _export?: boolean, + _imageRef?: string, + _label?: string, + _platform?: Platform, + _publish?: string, + _shellEndpoint?: string, + _stderr?: string, + _stdout?: string, + _sync?: ContainerID, + _user?: string, + _workdir?: string + ) { + super(parent); + + this._id = _id; + this._envVariable = _envVariable; + this._export = _export; + this._imageRef = _imageRef; + this._label = _label; + this._platform = _platform; + this._publish = _publish; + this._shellEndpoint = _shellEndpoint; + this._stderr = _stderr; + this._stdout = _stdout; + this._sync = _sync; + this._user = _user; + this._workdir = _workdir; + } + + /** + * A unique identifier for this Container. + */ + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -996,19 +1033,18 @@ export class Container extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Turn the container into a Service. - * + * * Be sure to set any exposed ports before this conversion. */ - asService(): Service { + asService = (): Service => { return new Service({ queryTree: [ ...this._queryTree, @@ -1016,29 +1052,27 @@ export class Container extends BaseClient { operation: "asService", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Returns a File representing the container serialized to a tarball. * @param opts.platformVariants Identifiers for other platform specific containers. - * Used for multi-platform image. + * + * Used for multi-platform images. * @param opts.forcedCompression Force each layer of the image to use the specified compression algorithm. - * If this is unset, then if a layer already has a compressed blob in the engine's - * cache, that will be used (this can result in a mix of compression algorithms for - * different layers). If this is unset and a layer has no compressed blob in the - * engine's cache, then it will be compressed using Gzip. - * @param opts.mediaTypes Use the specified media types for the image's layers. Defaults to OCI, which - * is largely compatible with most recent container runtimes, but Docker may be needed - * for older runtimes without OCI support. - */ - asTarball(opts?: ContainerAsTarballOpts): File { - const metadata: Metadata = { - forcedCompression: { is_enum: true }, - mediaTypes: { is_enum: true }, - } + * + * If this is unset, then if a layer already has a compressed blob in the engine's cache, that will be used (this can result in a mix of compression algorithms for different layers). If this is unset and a layer has no compressed blob in the engine's cache, then it will be compressed using Gzip. + * @param opts.mediaTypes Use the specified media types for the image's layers. + * + * Defaults to OCI, which is largely compatible with most recent container runtimes, but Docker may be needed for older runtimes without OCI support. + */ + asTarball = (opts?: ContainerAsTarballOpts): File => { + const metadata: Metadata = { + forcedCompression: { is_enum: true }, + mediaTypes: { is_enum: true }, + }; return new File({ queryTree: [ @@ -1048,28 +1082,23 @@ export class Container extends BaseClient { args: { ...opts, __metadata: metadata }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Initializes this container from a Dockerfile build. * @param context Directory context used by the Dockerfile. * @param opts.dockerfile Path to the Dockerfile to use. - * - * Default: './Dockerfile'. - * @param opts.buildArgs Additional build arguments. * @param opts.target Target build stage to build. + * @param opts.buildArgs Additional build arguments. * @param opts.secrets Secrets to pass to the build. - * + * * They will be mounted at /run/secrets/[secret-name] in the build container - * - * They can be accessed in the Dockerfile using the "secret" mount type - * and mount path /run/secrets/[secret-name] - * e.g. RUN --mount=type=secret,id=my-secret curl url?token=$(cat /run/secrets/my-secret)" + * + * They can be accessed in the Dockerfile using the "secret" mount type and mount path /run/secrets/[secret-name], e.g. RUN --mount=type=secret,id=my-secret curl http://example.com?token=$(cat /run/secrets/my-secret) */ - build(context: Directory, opts?: ContainerBuildOpts): Container { + build = (context: Directory, opts?: ContainerBuildOpts): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1078,15 +1107,14 @@ export class Container extends BaseClient { args: { context, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves default arguments for future commands. */ - async defaultArgs(): Promise { + defaultArgs = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -1094,20 +1122,19 @@ export class Container extends BaseClient { operation: "defaultArgs", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves a directory at the given path. - * + * * Mounts are included. * @param path The path of the directory to retrieve (e.g., "./src"). */ - directory(path: string): Directory { + directory = (path: string): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -1116,15 +1143,14 @@ export class Container extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves entrypoint to be prepended to the arguments of all commands. */ - async entrypoint(): Promise { + entrypoint = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -1132,20 +1158,19 @@ export class Container extends BaseClient { operation: "entrypoint", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves the value of the specified environment variable. * @param name The name of the environment variable to retrieve (e.g., "PATH"). */ - async envVariable(name: string): Promise { + envVariable = async (name: string): Promise => { if (this._envVariable) { - return this._envVariable + return this._envVariable; } const response: Awaited = await computeQuery( @@ -1156,21 +1181,19 @@ export class Container extends BaseClient { args: { name }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves the list of environment variables passed to commands. */ - async envVariables(): Promise { + envVariables = async (): Promise => { type envVariables = { - name: string - value: string - } + id: EnvVariableID; + }; const response: Awaited = await computeQuery( [ @@ -1179,33 +1202,37 @@ export class Container extends BaseClient { operation: "envVariables", }, { - operation: "name value" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new EnvVariable( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.name, - r.value, - ) - ) - } + (r) => + new EnvVariable( + { + queryTree: [ + { + operation: "loadEnvVariableFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; /** * EXPERIMENTAL API! Subject to change/removal at any time. - * - * experimentalWithAllGPUs configures all available GPUs on the host to be accessible to this container. + * + * Configures all available GPUs on the host to be accessible to this container. + * * This currently works for Nvidia devices only. */ - experimentalWithAllGPUs(): Container { + experimentalWithAllGPUs = (): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1213,18 +1240,19 @@ export class Container extends BaseClient { operation: "experimentalWithAllGPUs", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * EXPERIMENTAL API! Subject to change/removal at any time. - * - * experimentalWithGPU configures the provided list of devices to be accesible to this container. + * + * Configures the provided list of devices to be accesible to this container. + * * This currently works for Nvidia devices only. + * @param devices List of devices to be accessible to this container. */ - experimentalWithGPU(devices: string[]): Container { + experimentalWithGPU = (devices: string[]): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1233,38 +1261,41 @@ export class Container extends BaseClient { args: { devices }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Writes the container as an OCI tarball to the destination file path on the host for the specified platform variants. - * + * Writes the container as an OCI tarball to the destination file path on the host. + * * Return true on success. - * It can also publishes platform variants. + * + * It can also export platform variants. * @param path Host's destination path (e.g., "./tarball"). + * * Path can be relative to the engine's workdir or absolute. * @param opts.platformVariants Identifiers for other platform specific containers. + * * Used for multi-platform image. * @param opts.forcedCompression Force each layer of the exported image to use the specified compression algorithm. - * If this is unset, then if a layer already has a compressed blob in the engine's - * cache, that will be used (this can result in a mix of compression algorithms for - * different layers). If this is unset and a layer has no compressed blob in the - * engine's cache, then it will be compressed using Gzip. - * @param opts.mediaTypes Use the specified media types for the exported image's layers. Defaults to OCI, which - * is largely compatible with most recent container runtimes, but Docker may be needed - * for older runtimes without OCI support. - */ - async export(path: string, opts?: ContainerExportOpts): Promise { + * + * If this is unset, then if a layer already has a compressed blob in the engine's cache, that will be used (this can result in a mix of compression algorithms for different layers). If this is unset and a layer has no compressed blob in the engine's cache, then it will be compressed using Gzip. + * @param opts.mediaTypes Use the specified media types for the exported image's layers. + * + * Defaults to OCI, which is largely compatible with most recent container runtimes, but Docker may be needed for older runtimes without OCI support. + */ + export = async ( + path: string, + opts?: ContainerExportOpts + ): Promise => { if (this._export) { - return this._export + return this._export; } - const metadata: Metadata = { - forcedCompression: { is_enum: true }, - mediaTypes: { is_enum: true }, - } + const metadata: Metadata = { + forcedCompression: { is_enum: true }, + mediaTypes: { is_enum: true }, + }; const response: Awaited = await computeQuery( [ @@ -1274,25 +1305,21 @@ export class Container extends BaseClient { args: { path, ...opts, __metadata: metadata }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves the list of exposed ports. - * - * This includes ports already exposed by the image, even if not - * explicitly added with dagger. + * + * This includes ports already exposed by the image, even if not explicitly added with dagger. */ - async exposedPorts(): Promise { + exposedPorts = async (): Promise => { type exposedPorts = { - description: string - port: number - protocol: NetworkProtocol - } + id: PortID; + }; const response: Awaited = await computeQuery( [ @@ -1301,34 +1328,36 @@ export class Container extends BaseClient { operation: "exposedPorts", }, { - operation: "description port protocol" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new Port( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.description, - r.port, - r.protocol, - ) - ) - } + (r) => + new Port( + { + queryTree: [ + { + operation: "loadPortFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; /** * Retrieves a file at the given path. - * + * * Mounts are included. * @param path The path of the file to retrieve (e.g., "./README.md"). */ - file(path: string): File { + file = (path: string): File => { return new File({ queryTree: [ ...this._queryTree, @@ -1337,18 +1366,17 @@ export class Container extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Initializes this container from a pulled base image. * @param address Image's address from its registry. - * + * * Formatted as [host]/[user]/[repo]:[tag] (e.g., "docker.io/dagger/dagger:main"). */ - from(address: string): Container { + from = (address: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1357,17 +1385,16 @@ export class Container extends BaseClient { args: { address }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * The unique image reference which can only be retrieved immediately after the 'Container.From' call. */ - async imageRef(): Promise { + imageRef = async (): Promise => { if (this._imageRef) { - return this._imageRef + return this._imageRef; } const response: Awaited = await computeQuery( @@ -1377,23 +1404,18 @@ export class Container extends BaseClient { operation: "imageRef", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Reads the container from an OCI tarball. - * - * NOTE: this involves unpacking the tarball to an OCI store on the host at - * $XDG_CACHE_DIR/dagger/oci. This directory can be removed whenever you like. * @param source File to read the container from. - * @param opts.tag Identifies the tag to import from the archive, if the archive bundles - * multiple tags. + * @param opts.tag Identifies the tag to import from the archive, if the archive bundles multiple tags. */ - import_(source: File, opts?: ContainerImportOpts): Container { + import_ = (source: File, opts?: ContainerImportOpts): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1402,17 +1424,17 @@ export class Container extends BaseClient { args: { source, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves the value of the specified label. + * @param name The name of the label (e.g., "org.opencontainers.artifact.created"). */ - async label(name: string): Promise { + label = async (name: string): Promise => { if (this._label) { - return this._label + return this._label; } const response: Awaited = await computeQuery( @@ -1423,21 +1445,19 @@ export class Container extends BaseClient { args: { name }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves the list of labels passed to container. */ - async labels(): Promise { + labels = async (): Promise => { type labels = { - name: string - value: string - } + id: LabelID; + }; const response: Awaited = await computeQuery( [ @@ -1446,30 +1466,33 @@ export class Container extends BaseClient { operation: "labels", }, { - operation: "name value" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new Label( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.name, - r.value, - ) - ) - } + (r) => + new Label( + { + queryTree: [ + { + operation: "loadLabelFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; /** * Retrieves the list of paths where a directory is mounted. */ - async mounts(): Promise { + mounts = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -1477,20 +1500,19 @@ export class Container extends BaseClient { operation: "mounts", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** - * Creates a named sub-pipeline - * @param name Pipeline name. - * @param opts.description Pipeline description. - * @param opts.labels Pipeline labels. + * Creates a named sub-pipeline. + * @param name Name of the sub-pipeline. + * @param opts.description Description of the sub-pipeline. + * @param opts.labels Labels to apply to the sub-pipeline. */ - pipeline(name: string, opts?: ContainerPipelineOpts): Container { + pipeline = (name: string, opts?: ContainerPipelineOpts): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1499,17 +1521,16 @@ export class Container extends BaseClient { args: { name, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * The platform this container executes and publishes as. */ - async platform(): Promise { + platform = async (): Promise => { if (this._platform) { - return this._platform + return this._platform; } const response: Awaited = await computeQuery( @@ -1519,41 +1540,43 @@ export class Container extends BaseClient { operation: "platform", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Publishes this container as a new image to the specified address. - * + * * Publish returns a fully qualified ref. + * * It can also publish platform variants. * @param address Registry's address to publish the image to. - * + * * Formatted as [host]/[user]/[repo]:[tag] (e.g. "docker.io/dagger/dagger:main"). * @param opts.platformVariants Identifiers for other platform specific containers. + * * Used for multi-platform image. * @param opts.forcedCompression Force each layer of the published image to use the specified compression algorithm. - * If this is unset, then if a layer already has a compressed blob in the engine's - * cache, that will be used (this can result in a mix of compression algorithms for - * different layers). If this is unset and a layer has no compressed blob in the - * engine's cache, then it will be compressed using Gzip. - * @param opts.mediaTypes Use the specified media types for the published image's layers. Defaults to OCI, which - * is largely compatible with most recent registries, but Docker may be needed for older - * registries without OCI support. - */ - async publish(address: string, opts?: ContainerPublishOpts): Promise { + * + * If this is unset, then if a layer already has a compressed blob in the engine's cache, that will be used (this can result in a mix of compression algorithms for different layers). If this is unset and a layer has no compressed blob in the engine's cache, then it will be compressed using Gzip. + * @param opts.mediaTypes Use the specified media types for the published image's layers. + * + * Defaults to OCI, which is largely compatible with most recent registries, but Docker may be needed for older registries without OCI support. + */ + publish = async ( + address: string, + opts?: ContainerPublishOpts + ): Promise => { if (this._publish) { - return this._publish + return this._publish; } - const metadata: Metadata = { - forcedCompression: { is_enum: true }, - mediaTypes: { is_enum: true }, - } + const metadata: Metadata = { + forcedCompression: { is_enum: true }, + mediaTypes: { is_enum: true }, + }; const response: Awaited = await computeQuery( [ @@ -1563,17 +1586,16 @@ export class Container extends BaseClient { args: { address, ...opts, __metadata: metadata }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves this container's root filesystem. Mounts are not included. */ - rootfs(): Directory { + rootfs = (): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -1581,20 +1603,18 @@ export class Container extends BaseClient { operation: "rootfs", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Return a websocket endpoint that, if connected to, will start the container with a TTY streamed - * over the websocket. - * + * Return a websocket endpoint that, if connected to, will start the container with a TTY streamed over the websocket. + * * Primarily intended for internal use with the dagger CLI. */ - async shellEndpoint(): Promise { + shellEndpoint = async (): Promise => { if (this._shellEndpoint) { - return this._shellEndpoint + return this._shellEndpoint; } const response: Awaited = await computeQuery( @@ -1604,21 +1624,20 @@ export class Container extends BaseClient { operation: "shellEndpoint", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * The error stream of the last executed command. - * + * * Will execute default command if none is set, or error if there's no default. */ - async stderr(): Promise { + stderr = async (): Promise => { if (this._stderr) { - return this._stderr + return this._stderr; } const response: Awaited = await computeQuery( @@ -1628,21 +1647,20 @@ export class Container extends BaseClient { operation: "stderr", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * The output stream of the last executed command. - * + * * Will execute default command if none is set, or error if there's no default. */ - async stdout(): Promise { + stdout = async (): Promise => { if (this._stdout) { - return this._stdout + return this._stdout; } const response: Awaited = await computeQuery( @@ -1652,19 +1670,18 @@ export class Container extends BaseClient { operation: "stdout", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Forces evaluation of the pipeline in the engine. - * + * * It doesn't run the default command if no exec has been set. */ - async sync(): Promise { + sync = async (): Promise => { await computeQuery( [ ...this._queryTree, @@ -1672,18 +1689,18 @@ export class Container extends BaseClient { operation: "sync", }, ], - this.client - ) + await this._ctx.connection() + ); - return this - } + return this; + }; /** * Retrieves the user to be set for all commands. */ - async user(): Promise { + user = async (): Promise => { if (this._user) { - return this._user + return this._user; } const response: Awaited = await computeQuery( @@ -1693,44 +1710,46 @@ export class Container extends BaseClient { operation: "user", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Configures default arguments for future commands. - * @param opts.args Arguments to prepend to future executions (e.g., ["-v", "--no-cache"]). + * @param args Arguments to prepend to future executions (e.g., ["-v", "--no-cache"]). */ - withDefaultArgs(opts?: ContainerWithDefaultArgsOpts): Container { + withDefaultArgs = (args: string[]): Container => { return new Container({ queryTree: [ ...this._queryTree, { operation: "withDefaultArgs", - args: { ...opts }, + args: { args }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a directory written at the given path. * @param path Location of the written directory (e.g., "/tmp/directory"). * @param directory Identifier of the directory to write - * @param opts.exclude Patterns to exclude in the written directory (e.g., ["node_modules/**", ".gitignore", ".git/"]). - * @param opts.include Patterns to include in the written directory (e.g., ["*.go", "go.mod", "go.sum"]). + * @param opts.exclude Patterns to exclude in the written directory (e.g. ["node_modules/**", ".gitignore", ".git/"]). + * @param opts.include Patterns to include in the written directory (e.g. ["*.go", "go.mod", "go.sum"]). * @param opts.owner A user:group to set for the directory and its contents. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - withDirectory(path: string, directory: Directory, opts?: ContainerWithDirectoryOpts): Container { + withDirectory = ( + path: string, + directory: Directory, + opts?: ContainerWithDirectoryOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1739,37 +1758,42 @@ export class Container extends BaseClient { args: { path, directory, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container but with a different command entrypoint. * @param args Entrypoint to use for future executions (e.g., ["go", "run"]). + * @param opts.keepDefaultArgs Don't remove the default arguments when setting the entrypoint. */ - withEntrypoint(args: string[]): Container { + withEntrypoint = ( + args: string[], + opts?: ContainerWithEntrypointOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, { operation: "withEntrypoint", - args: { args }, + args: { args, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus the given environment variable. * @param name The name of the environment variable (e.g., "HOST"). * @param value The value of the environment variable. (e.g., "localhost"). - * @param opts.expand Replace ${VAR} or $VAR in the value according to the current environment - * variables defined in the container (e.g., "/opt/bin:$PATH"). + * @param opts.expand Replace `${VAR}` or `$VAR` in the value according to the current environment variables defined in the container (e.g., "/opt/bin:$PATH"). */ - withEnvVariable(name: string, value: string, opts?: ContainerWithEnvVariableOpts): Container { + withEnvVariable = ( + name: string, + value: string, + opts?: ContainerWithEnvVariableOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1778,30 +1802,25 @@ export class Container extends BaseClient { args: { name, value, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container after executing the specified command inside it. * @param args Command to run instead of the container's default command (e.g., ["run", "main.go"]). - * + * * If empty, the container's default command is used. * @param opts.skipEntrypoint If the container has an entrypoint, ignore it for args rather than using it to wrap them. * @param opts.stdin Content to write to the command's standard input before closing (e.g., "Hello world"). * @param opts.redirectStdout Redirect the command's standard output to a file in the container (e.g., "/tmp/stdout"). * @param opts.redirectStderr Redirect the command's standard error to a file in the container (e.g., "/tmp/stderr"). * @param opts.experimentalPrivilegedNesting Provides dagger access to the executed command. - * - * Do not use this option unless you trust the command being executed. - * The command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM. - * @param opts.insecureRootCapabilities Execute the command with all root capabilities. This is similar to running a command - * with "sudo" or executing `docker run` with the `--privileged` flag. Containerization - * does not provide any security guarantees when using this option. It should only be used - * when absolutely necessary and only with trusted commands. - */ - withExec(args: string[], opts?: ContainerWithExecOpts): Container { + * + * Do not use this option unless you trust the command being executed; the command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM. + * @param opts.insecureRootCapabilities Execute the command with all root capabilities. This is similar to running a command with "sudo" or executing "docker run" with the "--privileged" flag. Containerization does not provide any security guarantees when using this option. It should only be used when absolutely necessary and only with trusted commands. + */ + withExec = (args: string[], opts?: ContainerWithExecOpts): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1810,25 +1829,29 @@ export class Container extends BaseClient { args: { args, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Expose a network port. - * + * * Exposed ports serve two purposes: - * - For health checks and introspection, when running services - * - For setting the EXPOSE OCI field when publishing the container + * + * - For health checks and introspection, when running services + * + * - For setting the EXPOSE OCI field when publishing the container * @param port Port number to expose * @param opts.protocol Transport layer network protocol * @param opts.description Optional port description */ - withExposedPort(port: number, opts?: ContainerWithExposedPortOpts): Container { - const metadata: Metadata = { - protocol: { is_enum: true }, - } + withExposedPort = ( + port: number, + opts?: ContainerWithExposedPortOpts + ): Container => { + const metadata: Metadata = { + protocol: { is_enum: true }, + }; return new Container({ queryTree: [ @@ -1838,25 +1861,26 @@ export class Container extends BaseClient { args: { port, ...opts, __metadata: metadata }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus the contents of the given file copied to the given path. * @param path Location of the copied file (e.g., "/tmp/file.txt"). * @param source Identifier of the file to copy. * @param opts.permissions Permission given to the copied file (e.g., 0600). - * - * Default: 0644. * @param opts.owner A user:group to set for the file. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - withFile(path: string, source: File, opts?: ContainerWithFileOpts): Container { + withFile = ( + path: string, + source: File, + opts?: ContainerWithFileOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1865,16 +1889,14 @@ export class Container extends BaseClient { args: { path, source, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Indicate that subsequent operations should be featured more prominently in - * the UI. + * Indicate that subsequent operations should be featured more prominently in the UI. */ - withFocus(): Container { + withFocus = (): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1882,17 +1904,16 @@ export class Container extends BaseClient { operation: "withFocus", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus the given label. * @param name The name of the label (e.g., "org.opencontainers.artifact.created"). * @param value The value of the label (e.g., "2023-01-01T00:00:00Z"). */ - withLabel(name: string, value: string): Container { + withLabel = (name: string, value: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1901,10 +1922,9 @@ export class Container extends BaseClient { args: { name, value }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a cache volume mounted at the given path. @@ -1913,19 +1933,21 @@ export class Container extends BaseClient { * @param opts.source Identifier of the directory to use as the cache volume's root. * @param opts.sharing Sharing mode of the cache volume. * @param opts.owner A user:group to set for the mounted cache directory. - * - * Note that this changes the ownership of the specified mount along with the - * initial filesystem provided by source (if any). It does not have any effect - * if/when the cache has already been created. - * + * + * Note that this changes the ownership of the specified mount along with the initial filesystem provided by source (if any). It does not have any effect if/when the cache has already been created. + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - withMountedCache(path: string, cache: CacheVolume, opts?: ContainerWithMountedCacheOpts): Container { - const metadata: Metadata = { - sharing: { is_enum: true }, - } + withMountedCache = ( + path: string, + cache: CacheVolume, + opts?: ContainerWithMountedCacheOpts + ): Container => { + const metadata: Metadata = { + sharing: { is_enum: true }, + }; return new Container({ queryTree: [ @@ -1935,22 +1957,25 @@ export class Container extends BaseClient { args: { path, cache, ...opts, __metadata: metadata }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a directory mounted at the given path. * @param path Location of the mounted directory (e.g., "/mnt/directory"). * @param source Identifier of the mounted directory. * @param opts.owner A user:group to set for the mounted directory and its contents. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - withMountedDirectory(path: string, source: Directory, opts?: ContainerWithMountedDirectoryOpts): Container { + withMountedDirectory = ( + path: string, + source: Directory, + opts?: ContainerWithMountedDirectoryOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1959,22 +1984,25 @@ export class Container extends BaseClient { args: { path, source, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a file mounted at the given path. * @param path Location of the mounted file (e.g., "/tmp/file.txt"). * @param source Identifier of the mounted file. * @param opts.owner A user or user:group to set for the mounted file. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - withMountedFile(path: string, source: File, opts?: ContainerWithMountedFileOpts): Container { + withMountedFile = ( + path: string, + source: File, + opts?: ContainerWithMountedFileOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -1983,26 +2011,28 @@ export class Container extends BaseClient { args: { path, source, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a secret mounted into a file at the given path. * @param path Location of the secret file (e.g., "/tmp/secret.txt"). * @param source Identifier of the secret to mount. * @param opts.owner A user:group to set for the mounted secret. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. * @param opts.mode Permission given to the mounted secret (e.g., 0600). + * * This option requires an owner to be set to be active. - * - * Default: 0400. */ - withMountedSecret(path: string, source: Secret, opts?: ContainerWithMountedSecretOpts): Container { + withMountedSecret = ( + path: string, + source: Secret, + opts?: ContainerWithMountedSecretOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2011,16 +2041,15 @@ export class Container extends BaseClient { args: { path, source, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a temporary directory mounted at the given path. * @param path Location of the temporary directory (e.g., "/tmp/temp_dir"). */ - withMountedTemp(path: string): Container { + withMountedTemp = (path: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2029,25 +2058,22 @@ export class Container extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a new file written at the given path. * @param path Location of the written file (e.g., "/tmp/file.txt"). * @param opts.contents Content of the file to write (e.g., "Hello world!"). * @param opts.permissions Permission given to the written file (e.g., 0600). - * - * Default: 0644. * @param opts.owner A user:group to set for the file. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - withNewFile(path: string, opts?: ContainerWithNewFileOpts): Container { + withNewFile = (path: string, opts?: ContainerWithNewFileOpts): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2056,19 +2082,23 @@ export class Container extends BaseClient { args: { path, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container with a registry authentication for a given address. * @param address Registry's address to bind the authentication to. + * * Formatted as [host]/[user]/[repo]:[tag] (e.g. docker.io/dagger/dagger:main). * @param username The username of the registry's account (e.g., "Dagger"). * @param secret The API key, password or token to authenticate to this registry. */ - withRegistryAuth(address: string, username: string, secret: Secret): Container { + withRegistryAuth = ( + address: string, + username: string, + secret: Secret + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2077,15 +2107,15 @@ export class Container extends BaseClient { args: { address, username, secret }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Initializes this container from this DirectoryID. + * Retrieves the container with the given directory mounted to /. + * @param directory Directory to mount. */ - withRootfs(directory: Directory): Container { + withRootfs = (directory: Directory): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2094,17 +2124,16 @@ export class Container extends BaseClient { args: { directory }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus an env variable containing the given secret. * @param name The name of the secret variable (e.g., "API_SECRET"). * @param secret The identifier of the secret value. */ - withSecretVariable(name: string, secret: Secret): Container { + withSecretVariable = (name: string, secret: Secret): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2113,24 +2142,22 @@ export class Container extends BaseClient { args: { name, secret }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Establish a runtime dependency on a service. - * - * The service will be started automatically when needed and detached when it is - * no longer needed, executing the default command if none is set. - * + * + * The service will be started automatically when needed and detached when it is no longer needed, executing the default command if none is set. + * * The service will be reachable from the container via the provided hostname alias. - * + * * The service dependency will also convey to any files or directories produced by the container. * @param alias A name that can be used to reach the service from the container * @param service Identifier of the service container */ - withServiceBinding(alias: string, service: Service): Container { + withServiceBinding = (alias: string, service: Service): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2139,22 +2166,25 @@ export class Container extends BaseClient { args: { alias, service }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container plus a socket forwarded to the given Unix socket path. * @param path Location of the forwarded Unix socket (e.g., "/tmp/socket"). * @param source Identifier of the socket to forward. * @param opts.owner A user:group to set for the mounted socket. - * + * * The user and group can either be an ID (1000:1000) or a name (foo:bar). - * + * * If the group is omitted, it defaults to the same as the user. */ - withUnixSocket(path: string, source: Socket, opts?: ContainerWithUnixSocketOpts): Container { + withUnixSocket = ( + path: string, + source: Socket, + opts?: ContainerWithUnixSocketOpts + ): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2163,16 +2193,15 @@ export class Container extends BaseClient { args: { path, source, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container with a different command user. * @param name The user to set (e.g., "root"). */ - withUser(name: string): Container { + withUser = (name: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2181,16 +2210,15 @@ export class Container extends BaseClient { args: { name }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container with a different working directory. * @param path The path to set as the working directory (e.g., "/app"). */ - withWorkdir(path: string): Container { + withWorkdir = (path: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2199,16 +2227,47 @@ export class Container extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Retrieves this container with unset default arguments for future commands. + */ + withoutDefaultArgs = (): Container => { + return new Container({ + queryTree: [ + ...this._queryTree, + { + operation: "withoutDefaultArgs", + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Retrieves this container with an unset command entrypoint. + * @param opts.keepDefaultArgs Don't remove the default arguments when unsetting the entrypoint. + */ + withoutEntrypoint = (opts?: ContainerWithoutEntrypointOpts): Container => { + return new Container({ + queryTree: [ + ...this._queryTree, + { + operation: "withoutEntrypoint", + args: { ...opts }, + }, + ], + ctx: this._ctx, + }); + }; /** * Retrieves this container minus the given environment variable. * @param name The name of the environment variable (e.g., "HOST"). */ - withoutEnvVariable(name: string): Container { + withoutEnvVariable = (name: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2217,20 +2276,22 @@ export class Container extends BaseClient { args: { name }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Unexpose a previously exposed port. * @param port Port number to unexpose * @param opts.protocol Port protocol to unexpose */ - withoutExposedPort(port: number, opts?: ContainerWithoutExposedPortOpts): Container { - const metadata: Metadata = { - protocol: { is_enum: true }, - } + withoutExposedPort = ( + port: number, + opts?: ContainerWithoutExposedPortOpts + ): Container => { + const metadata: Metadata = { + protocol: { is_enum: true }, + }; return new Container({ queryTree: [ @@ -2240,18 +2301,16 @@ export class Container extends BaseClient { args: { port, ...opts, __metadata: metadata }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Indicate that subsequent operations should not be featured more prominently - * in the UI. - * + * Indicate that subsequent operations should not be featured more prominently in the UI. + * * This is the initial state of all containers. */ - withoutFocus(): Container { + withoutFocus = (): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2259,16 +2318,15 @@ export class Container extends BaseClient { operation: "withoutFocus", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container minus the given environment label. * @param name The name of the label to remove (e.g., "org.opencontainers.artifact.created"). */ - withoutLabel(name: string): Container { + withoutLabel = (name: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2277,16 +2335,15 @@ export class Container extends BaseClient { args: { name }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container after unmounting everything at the given path. * @param path Location of the cache directory (e.g., "/cache/node_modules"). */ - withoutMount(path: string): Container { + withoutMount = (path: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2295,17 +2352,17 @@ export class Container extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container without the registry authentication of a given address. * @param address Registry's address to remove the authentication from. + * * Formatted as [host]/[user]/[repo]:[tag] (e.g. docker.io/dagger/dagger:main). */ - withoutRegistryAuth(address: string): Container { + withoutRegistryAuth = (address: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2314,16 +2371,15 @@ export class Container extends BaseClient { args: { address }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this container with a previously added Unix socket removed. * @param path Location of the socket to remove (e.g., "/tmp/socket"). */ - withoutUnixSocket(path: string): Container { + withoutUnixSocket = (path: string): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2332,17 +2388,50 @@ export class Container extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Retrieves this container with an unset command user. + * + * Should default to root. + */ + withoutUser = (): Container => { + return new Container({ + queryTree: [ + ...this._queryTree, + { + operation: "withoutUser", + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Retrieves this container with an unset working directory. + * + * Should default to "/". + */ + withoutWorkdir = (): Container => { + return new Container({ + queryTree: [ + ...this._queryTree, + { + operation: "withoutWorkdir", + }, + ], + ctx: this._ctx, + }); + }; /** * Retrieves the working directory for all commands. */ - async workdir(): Promise { + workdir = async (): Promise => { if (this._workdir) { - return this._workdir + return this._workdir; } const response: Awaited = await computeQuery( @@ -2352,57 +2441,52 @@ export class Container extends BaseClient { operation: "workdir", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Call the provided function with current Container. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: Container) => Container) { - return arg(this) - } + with = (arg: (param: Container) => Container) => { + return arg(this); + }; } - - - - /** * A directory. */ export class Directory extends BaseClient { - private readonly _id?: DirectoryID = undefined - private readonly _export?: boolean = undefined - private readonly _sync?: DirectoryID = undefined + private readonly _id?: DirectoryID = undefined; + private readonly _export?: boolean = undefined; + private readonly _sync?: DirectoryID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: DirectoryID, - _export?: boolean, - _sync?: DirectoryID, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: DirectoryID, + _export?: boolean, + _sync?: DirectoryID + ) { + super(parent); - this._id = _id - this._export = _export - this._sync = _sync - } + this._id = _id; + this._export = _export; + this._sync = _sync; + } /** - * The content-addressed identifier of the directory. + * A unique identifier for this Directory. */ - async id(): Promise { + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -2412,27 +2496,21 @@ export class Directory extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Load the directory as a Dagger module - * @param opts.sourceSubpath An optional subpath of the directory which contains the module's source - * code. - * - * This is needed when the module code is in a subdirectory but requires - * parent directories to be loaded in order to execute. For example, the - * module source code may need a go.mod, project.toml, package.json, etc. file - * from a parent directory. - * - * If not set, the module source code is loaded from the root of the - * directory. - */ - asModule(opts?: DirectoryAsModuleOpts): Module_ { + * @param opts.sourceSubpath An optional subpath of the directory which contains the module's source code. + * + * This is needed when the module code is in a subdirectory but requires parent directories to be loaded in order to execute. For example, the module source code may need a go.mod, project.toml, package.json, etc. file from a parent directory. + * + * If not set, the module source code is loaded from the root of the directory. + */ + asModule = (opts?: DirectoryAsModuleOpts): Module_ => { return new Module_({ queryTree: [ ...this._queryTree, @@ -2441,16 +2519,15 @@ export class Directory extends BaseClient { args: { ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Gets the difference between this directory and an another directory. * @param other Identifier of the directory to compare. */ - diff(other: Directory): Directory { + diff = (other: Directory): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2459,16 +2536,15 @@ export class Directory extends BaseClient { args: { other }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves a directory at the given path. * @param path Location of the directory to retrieve (e.g., "/src"). */ - directory(path: string): Directory { + directory = (path: string): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2477,24 +2553,21 @@ export class Directory extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Builds a new Docker container from this directory. - * @param opts.dockerfile Path to the Dockerfile to use (e.g., "frontend.Dockerfile"). - * - * Defaults: './Dockerfile'. * @param opts.platform The platform to build. - * @param opts.buildArgs Build arguments to use in the build. + * @param opts.dockerfile Path to the Dockerfile to use (e.g., "frontend.Dockerfile"). * @param opts.target Target build stage to build. + * @param opts.buildArgs Build arguments to use in the build. * @param opts.secrets Secrets to pass to the build. - * + * * They will be mounted at /run/secrets/[secret-name]. */ - dockerBuild(opts?: DirectoryDockerBuildOpts): Container { + dockerBuild = (opts?: DirectoryDockerBuildOpts): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -2503,16 +2576,15 @@ export class Directory extends BaseClient { args: { ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Returns a list of files and directories at the given path. * @param opts.path Location of the directory to look at (e.g., "/src"). */ - async entries(opts?: DirectoryEntriesOpts): Promise { + entries = async (opts?: DirectoryEntriesOpts): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -2521,20 +2593,19 @@ export class Directory extends BaseClient { args: { ...opts }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Writes the contents of the directory to a path on the host. * @param path Location of the copied directory (e.g., "logs/"). */ - async export(path: string): Promise { + export = async (path: string): Promise => { if (this._export) { - return this._export + return this._export; } const response: Awaited = await computeQuery( @@ -2545,18 +2616,17 @@ export class Directory extends BaseClient { args: { path }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves a file at the given path. * @param path Location of the file to retrieve (e.g., "README.md"). */ - file(path: string): File { + file = (path: string): File => { return new File({ queryTree: [ ...this._queryTree, @@ -2565,16 +2635,15 @@ export class Directory extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Returns a list of files and directories that matche the given pattern. * @param pattern Pattern to match (e.g., "*.md"). */ - async glob(pattern: string): Promise { + glob = async (pattern: string): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -2583,20 +2652,19 @@ export class Directory extends BaseClient { args: { pattern }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** - * Creates a named sub-pipeline - * @param name Pipeline name. - * @param opts.description Pipeline description. - * @param opts.labels Pipeline labels. + * Creates a named sub-pipeline. + * @param name Name of the sub-pipeline. + * @param opts.description Description of the sub-pipeline. + * @param opts.labels Labels to apply to the sub-pipeline. */ - pipeline(name: string, opts?: DirectoryPipelineOpts): Directory { + pipeline = (name: string, opts?: DirectoryPipelineOpts): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2605,15 +2673,14 @@ export class Directory extends BaseClient { args: { name, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Force evaluation in the engine. */ - async sync(): Promise { + sync = async (): Promise => { await computeQuery( [ ...this._queryTree, @@ -2621,11 +2688,11 @@ export class Directory extends BaseClient { operation: "sync", }, ], - this.client - ) + await this._ctx.connection() + ); - return this - } + return this; + }; /** * Retrieves this directory plus a directory written at the given path. @@ -2634,7 +2701,11 @@ export class Directory extends BaseClient { * @param opts.exclude Exclude artifacts that match the given pattern (e.g., ["node_modules/", ".git*"]). * @param opts.include Include only artifacts that match the given pattern (e.g., ["app/", "package.*"]). */ - withDirectory(path: string, directory: Directory, opts?: DirectoryWithDirectoryOpts): Directory { + withDirectory = ( + path: string, + directory: Directory, + opts?: DirectoryWithDirectoryOpts + ): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2643,20 +2714,21 @@ export class Directory extends BaseClient { args: { path, directory, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this directory plus the contents of the given file copied to the given path. * @param path Location of the copied file (e.g., "/file.txt"). * @param source Identifier of the file to copy. * @param opts.permissions Permission given to the copied file (e.g., 0600). - * - * Default: 0644. */ - withFile(path: string, source: File, opts?: DirectoryWithFileOpts): Directory { + withFile = ( + path: string, + source: File, + opts?: DirectoryWithFileOpts + ): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2665,19 +2737,19 @@ export class Directory extends BaseClient { args: { path, source, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this directory plus a new directory created at the given path. * @param path Location of the directory created (e.g., "/logs"). * @param opts.permissions Permission granted to the created directory (e.g., 0777). - * - * Default: 0755. */ - withNewDirectory(path: string, opts?: DirectoryWithNewDirectoryOpts): Directory { + withNewDirectory = ( + path: string, + opts?: DirectoryWithNewDirectoryOpts + ): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2686,20 +2758,21 @@ export class Directory extends BaseClient { args: { path, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this directory plus a new file written at the given path. * @param path Location of the written file (e.g., "/file.txt"). * @param contents Content of the written file (e.g., "Hello world!"). * @param opts.permissions Permission given to the copied file (e.g., 0600). - * - * Default: 0644. */ - withNewFile(path: string, contents: string, opts?: DirectoryWithNewFileOpts): Directory { + withNewFile = ( + path: string, + contents: string, + opts?: DirectoryWithNewFileOpts + ): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2708,18 +2781,17 @@ export class Directory extends BaseClient { args: { path, contents, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this directory with all file/dir timestamps set to the given time. * @param timestamp Timestamp to set dir/files in. - * + * * Formatted in seconds following Unix epoch (e.g., 1672531199). */ - withTimestamps(timestamp: number): Directory { + withTimestamps = (timestamp: number): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2728,16 +2800,15 @@ export class Directory extends BaseClient { args: { timestamp }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this directory with the directory at the given path removed. * @param path Location of the directory to remove (e.g., ".github/"). */ - withoutDirectory(path: string): Directory { + withoutDirectory = (path: string): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2746,16 +2817,15 @@ export class Directory extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Retrieves this directory with the file at the given path removed. * @param path Location of the file to remove (e.g., "/file.txt"). */ - withoutFile(path: string): Directory { + withoutFile = (path: string): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -2764,50 +2834,67 @@ export class Directory extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Call the provided function with current Directory. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: Directory) => Directory) { - return arg(this) - } + with = (arg: (param: Directory) => Directory) => { + return arg(this); + }; } - - /** - * A simple key value object that represents an environment variable. + * An environment variable name and value. */ export class EnvVariable extends BaseClient { - private readonly _name?: string = undefined - private readonly _value?: string = undefined + private readonly _id?: EnvVariableID = undefined; + private readonly _name?: string = undefined; + private readonly _value?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _name?: string, - _value?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: EnvVariableID, + _name?: string, + _value?: string + ) { + super(parent); - this._name = _name - this._value = _value - } + this._id = _id; + this._name = _name; + this._value = _value; + } /** - * The environment variable name. + * A unique identifier for this EnvVariable. */ - async name(): Promise { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -2817,19 +2904,14 @@ export class EnvVariable extends BaseClient { operation: "name", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The environment variable value. - */ - async value(): Promise { + return response; + }; + value = async (): Promise => { if (this._value) { - return this._value + return this._value; } const response: Awaited = await computeQuery( @@ -2839,43 +2921,62 @@ export class EnvVariable extends BaseClient { operation: "value", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } /** * A definition of a field on a custom object defined in a Module. - * A field on an object has a static value, as opposed to a function on an - * object whose value is computed by invoking code (and can accept arguments). + * + * A field on an object has a static value, as opposed to a function on an object whose value is computed by invoking code (and can accept arguments). */ export class FieldTypeDef extends BaseClient { - private readonly _description?: string = undefined - private readonly _name?: string = undefined + private readonly _id?: FieldTypeDefID = undefined; + private readonly _description?: string = undefined; + private readonly _name?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _description?: string, - _name?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: FieldTypeDefID, + _description?: string, + _name?: string + ) { + super(parent); - this._description = _description - this._name = _name - } + this._id = _id; + this._description = _description; + this._name = _name; + } /** - * A doc string for the field, if any + * A unique identifier for this FieldTypeDef. */ - async description(): Promise { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + description = async (): Promise => { if (this._description) { - return this._description + return this._description; } const response: Awaited = await computeQuery( @@ -2885,19 +2986,14 @@ export class FieldTypeDef extends BaseClient { operation: "description", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The name of the field in the object - */ - async name(): Promise { + return response; + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -2907,17 +3003,12 @@ export class FieldTypeDef extends BaseClient { operation: "name", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The type of the field - */ - typeDef(): TypeDef { + return response; + }; + typeDef = (): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -2925,48 +3016,50 @@ export class FieldTypeDef extends BaseClient { operation: "typeDef", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; } /** * A file. */ export class File extends BaseClient { - private readonly _id?: FileID = undefined - private readonly _contents?: string = undefined - private readonly _export?: boolean = undefined - private readonly _size?: number = undefined - private readonly _sync?: FileID = undefined + private readonly _id?: FileID = undefined; + private readonly _contents?: string = undefined; + private readonly _export?: boolean = undefined; + private readonly _name?: string = undefined; + private readonly _size?: number = undefined; + private readonly _sync?: FileID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: FileID, - _contents?: string, - _export?: boolean, - _size?: number, - _sync?: FileID, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: FileID, + _contents?: string, + _export?: boolean, + _name?: string, + _size?: number, + _sync?: FileID + ) { + super(parent); - this._id = _id - this._contents = _contents - this._export = _export - this._size = _size - this._sync = _sync - } + this._id = _id; + this._contents = _contents; + this._export = _export; + this._name = _name; + this._size = _size; + this._sync = _sync; + } /** - * Retrieves the content-addressed identifier of the file. + * A unique identifier for this File. */ - async id(): Promise { + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -2976,19 +3069,18 @@ export class File extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves the contents of the file. */ - async contents(): Promise { + contents = async (): Promise => { if (this._contents) { - return this._contents + return this._contents; } const response: Awaited = await computeQuery( @@ -2998,22 +3090,20 @@ export class File extends BaseClient { operation: "contents", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Writes the file to a file path on the host. * @param path Location of the written directory (e.g., "output.txt"). - * @param opts.allowParentDirPath If allowParentDirPath is true, the path argument can be a directory path, in which case - * the file will be created in that directory. + * @param opts.allowParentDirPath If allowParentDirPath is true, the path argument can be a directory path, in which case the file will be created in that directory. */ - async export(path: string, opts?: FileExportOpts): Promise { + export = async (path: string, opts?: FileExportOpts): Promise => { if (this._export) { - return this._export + return this._export; } const response: Awaited = await computeQuery( @@ -3024,19 +3114,39 @@ export class File extends BaseClient { args: { path, ...opts }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; + + /** + * Retrieves the name of the file. + */ + name = async (): Promise => { + if (this._name) { + return this._name; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "name", + }, + ], + await this._ctx.connection() + ); + + return response; + }; /** - * Gets the size of the file, in bytes. + * Retrieves the size of the file, in bytes. */ - async size(): Promise { + size = async (): Promise => { if (this._size) { - return this._size + return this._size; } const response: Awaited = await computeQuery( @@ -3046,17 +3156,16 @@ export class File extends BaseClient { operation: "size", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Force evaluation in the engine. */ - async sync(): Promise { + sync = async (): Promise => { await computeQuery( [ ...this._queryTree, @@ -3064,19 +3173,19 @@ export class File extends BaseClient { operation: "sync", }, ], - this.client - ) + await this._ctx.connection() + ); - return this - } + return this; + }; /** * Retrieves this file with its created/modified timestamps set to the given time. * @param timestamp Timestamp to set dir/files in. - * + * * Formatted in seconds following Unix epoch (e.g., 1672531199). */ - withTimestamps(timestamp: number): File { + withTimestamps = (timestamp: number): File => { return new File({ queryTree: [ ...this._queryTree, @@ -3085,58 +3194,52 @@ export class File extends BaseClient { args: { timestamp }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Call the provided function with current File. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: File) => File) { - return arg(this) - } + with = (arg: (param: File) => File) => { + return arg(this); + }; } - - - - /** * Function represents a resolver provided by a Module. - * - * A function always evaluates against a parent object and is given a set of - * named arguments. + * + * A function always evaluates against a parent object and is given a set of named arguments. */ export class Function_ extends BaseClient { - private readonly _id?: FunctionID = undefined - private readonly _description?: string = undefined - private readonly _name?: string = undefined + private readonly _id?: FunctionID = undefined; + private readonly _description?: string = undefined; + private readonly _name?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: FunctionID, - _description?: string, - _name?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: FunctionID, + _description?: string, + _name?: string + ) { + super(parent); - this._id = _id - this._description = _description - this._name = _name - } + this._id = _id; + this._description = _description; + this._name = _name; + } /** - * The ID of the function + * A unique identifier for this Function. */ - async id(): Promise { + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -3146,20 +3249,15 @@ export class Function_ extends BaseClient { operation: "id", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * Arguments accepted by this function, if any - */ - async args(): Promise { + return response; + }; + args = async (): Promise => { type args = { - id: FunctionArgID - } + id: FunctionArgID; + }; const response: Awaited = await computeQuery( [ @@ -3168,31 +3266,31 @@ export class Function_ extends BaseClient { operation: "args", }, { - operation: "id" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new FunctionArg( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.id, - ) - ) - } - - /** - * A doc string for the function, if any - */ - async description(): Promise { + (r) => + new FunctionArg( + { + queryTree: [ + { + operation: "loadFunctionArgFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + description = async (): Promise => { if (this._description) { - return this._description + return this._description; } const response: Awaited = await computeQuery( @@ -3202,19 +3300,14 @@ export class Function_ extends BaseClient { operation: "description", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The name of the function - */ - async name(): Promise { + return response; + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -3224,17 +3317,12 @@ export class Function_ extends BaseClient { operation: "name", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The type returned by this function - */ - returnType(): TypeDef { + return response; + }; + returnType = (): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -3242,10 +3330,9 @@ export class Function_ extends BaseClient { operation: "returnType", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Returns the function with the provided argument @@ -3254,7 +3341,11 @@ export class Function_ extends BaseClient { * @param opts.description A doc string for the argument, if any * @param opts.defaultValue A default value to use for this argument if not explicitly set by the caller, if any */ - withArg(name: string, typeDef: TypeDef, opts?: FunctionWithArgOpts): Function_ { + withArg = ( + name: string, + typeDef: TypeDef, + opts?: FunctionWithArgOpts + ): Function_ => { return new Function_({ queryTree: [ ...this._queryTree, @@ -3263,15 +3354,15 @@ export class Function_ extends BaseClient { args: { name, typeDef, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Returns the function with the doc string + * Returns the function with the given doc string. + * @param description The doc string to set. */ - withDescription(description: string): Function_ { + withDescription = (description: string): Function_ => { return new Function_({ queryTree: [ ...this._queryTree, @@ -3280,57 +3371,55 @@ export class Function_ extends BaseClient { args: { description }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Call the provided function with current Function. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: Function_) => Function_) { - return arg(this) - } + with = (arg: (param: Function_) => Function_) => { + return arg(this); + }; } /** * An argument accepted by a function. - * - * This is a specification for an argument at function definition time, not an - * argument passed at function call time. + * + * This is a specification for an argument at function definition time, not an argument passed at function call time. */ export class FunctionArg extends BaseClient { - private readonly _id?: FunctionArgID = undefined - private readonly _defaultValue?: JSON = undefined - private readonly _description?: string = undefined - private readonly _name?: string = undefined + private readonly _id?: FunctionArgID = undefined; + private readonly _defaultValue?: JSON = undefined; + private readonly _description?: string = undefined; + private readonly _name?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: FunctionArgID, - _defaultValue?: JSON, - _description?: string, - _name?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: FunctionArgID, + _defaultValue?: JSON, + _description?: string, + _name?: string + ) { + super(parent); - this._id = _id - this._defaultValue = _defaultValue - this._description = _description - this._name = _name - } + this._id = _id; + this._defaultValue = _defaultValue; + this._description = _description; + this._name = _name; + } /** - * The ID of the argument + * A unique identifier for this FunctionArg. */ - async id(): Promise { + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -3340,19 +3429,14 @@ export class FunctionArg extends BaseClient { operation: "id", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * A default value to use for this argument when not explicitly set by the caller, if any - */ - async defaultValue(): Promise { + return response; + }; + defaultValue = async (): Promise => { if (this._defaultValue) { - return this._defaultValue + return this._defaultValue; } const response: Awaited = await computeQuery( @@ -3362,19 +3446,14 @@ export class FunctionArg extends BaseClient { operation: "defaultValue", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * A doc string for the argument, if any - */ - async description(): Promise { + return response; + }; + description = async (): Promise => { if (this._description) { - return this._description + return this._description; } const response: Awaited = await computeQuery( @@ -3384,19 +3463,14 @@ export class FunctionArg extends BaseClient { operation: "description", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * The name of the argument - */ - async name(): Promise { + return response; + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -3406,17 +3480,12 @@ export class FunctionArg extends BaseClient { operation: "name", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * The type of the argument - */ - typeDef(): TypeDef { + return response; + }; + typeDef = (): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -3424,48 +3493,66 @@ export class FunctionArg extends BaseClient { operation: "typeDef", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; } - - - +/** + * An active function call. + */ export class FunctionCall extends BaseClient { - private readonly _name?: string = undefined - private readonly _parent?: JSON = undefined - private readonly _parentName?: string = undefined - private readonly _returnValue?: Void = undefined + private readonly _id?: FunctionCallID = undefined; + private readonly _name?: string = undefined; + private readonly _parent?: JSON = undefined; + private readonly _parentName?: string = undefined; + private readonly _returnValue?: Void = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _name?: string, - _parent?: JSON, - _parentName?: string, - _returnValue?: Void, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: FunctionCallID, + _name?: string, + _parent?: JSON, + _parentName?: string, + _returnValue?: Void + ) { + super(parent); - this._name = _name - this._parent = _parent - this._parentName = _parentName - this._returnValue = _returnValue - } + this._id = _id; + this._name = _name; + this._parent = _parent; + this._parentName = _parentName; + this._returnValue = _returnValue; + } /** - * The argument values the function is being invoked with. + * A unique identifier for this FunctionCall. */ - async inputArgs(): Promise { - type inputArgs = { - name: string - value: JSON + id = async (): Promise => { + if (this._id) { + return this._id; } + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + inputArgs = async (): Promise => { + type inputArgs = { + id: FunctionCallArgValueID; + }; + const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -3473,32 +3560,31 @@ export class FunctionCall extends BaseClient { operation: "inputArgs", }, { - operation: "name value" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new FunctionCallArgValue( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.name, - r.value, - ) - ) - } - - /** - * The name of the function being called. - */ - async name(): Promise { + (r) => + new FunctionCallArgValue( + { + queryTree: [ + { + operation: "loadFunctionCallArgValueFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -3508,20 +3594,14 @@ export class FunctionCall extends BaseClient { operation: "name", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * The value of the parent object of the function being called. - * If the function is "top-level" to the module, this is always an empty object. - */ - async parent(): Promise { + return response; + }; + parent = async (): Promise => { if (this._parent) { - return this._parent + return this._parent; } const response: Awaited = await computeQuery( @@ -3531,20 +3611,14 @@ export class FunctionCall extends BaseClient { operation: "parent", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The name of the parent object of the function being called. - * If the function is "top-level" to the module, this is the name of the module. - */ - async parentName(): Promise { + return response; + }; + parentName = async (): Promise => { if (this._parentName) { - return this._parentName + return this._parentName; } const response: Awaited = await computeQuery( @@ -3554,20 +3628,19 @@ export class FunctionCall extends BaseClient { operation: "parentName", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Set the return value of the function call to the provided value. - * The value should be a string of the JSON serialization of the return value. + * @param value JSON serialization of the return value. */ - async returnValue(value: JSON): Promise { + returnValue = async (value: JSON): Promise => { if (this._returnValue) { - return this._returnValue + return this._returnValue; } const response: Awaited = await computeQuery( @@ -3578,39 +3651,60 @@ export class FunctionCall extends BaseClient { args: { value }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } - +/** + * A value passed as a named argument to a function call. + */ export class FunctionCallArgValue extends BaseClient { - private readonly _name?: string = undefined - private readonly _value?: JSON = undefined + private readonly _id?: FunctionCallArgValueID = undefined; + private readonly _name?: string = undefined; + private readonly _value?: JSON = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _name?: string, - _value?: JSON, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: FunctionCallArgValueID, + _name?: string, + _value?: JSON + ) { + super(parent); - this._name = _name - this._value = _value - } + this._id = _id; + this._name = _name; + this._value = _value; + } /** - * The name of the argument. + * A unique identifier for this FunctionCallArgValue. */ - async name(): Promise { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -3620,19 +3714,14 @@ export class FunctionCallArgValue extends BaseClient { operation: "name", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * The value of the argument represented as a string of the JSON serialization. - */ - async value(): Promise { + return response; + }; + value = async (): Promise => { if (this._value) { - return this._value + return this._value; } const response: Awaited = await computeQuery( @@ -3642,34 +3731,37 @@ export class FunctionCallArgValue extends BaseClient { operation: "value", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } - - - +/** + * The result of running an SDK's codegen. + */ export class GeneratedCode extends BaseClient { - private readonly _id?: GeneratedCodeID = undefined + private readonly _id?: GeneratedCodeID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: GeneratedCodeID, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: GeneratedCodeID + ) { + super(parent); + + this._id = _id; + } - this._id = _id - } - async id(): Promise { + /** + * A unique identifier for this GeneratedCode. + */ + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -3679,17 +3771,12 @@ export class GeneratedCode extends BaseClient { operation: "id", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The directory containing the generated code - */ - code(): Directory { + return response; + }; + code = (): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -3697,15 +3784,10 @@ export class GeneratedCode extends BaseClient { operation: "code", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } - - /** - * List of paths to mark generated in version control (i.e. .gitattributes) - */ - async vcsGeneratedPaths(): Promise { + ctx: this._ctx, + }); + }; + vcsGeneratedPaths = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -3713,17 +3795,12 @@ export class GeneratedCode extends BaseClient { operation: "vcsGeneratedPaths", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * List of paths to ignore in version control (i.e. .gitignore) - */ - async vcsIgnoredPaths(): Promise { + return response; + }; + vcsIgnoredPaths = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -3731,17 +3808,16 @@ export class GeneratedCode extends BaseClient { operation: "vcsIgnoredPaths", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** - * Set the list of paths to mark generated in version control + * Set the list of paths to mark generated in version control. */ - withVCSGeneratedPaths(paths: string[]): GeneratedCode { + withVCSGeneratedPaths = (paths: string[]): GeneratedCode => { return new GeneratedCode({ queryTree: [ ...this._queryTree, @@ -3750,15 +3826,14 @@ export class GeneratedCode extends BaseClient { args: { paths }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Set the list of paths to ignore in version control + * Set the list of paths to ignore in version control. */ - withVCSIgnoredPaths(paths: string[]): GeneratedCode { + withVCSIgnoredPaths = (paths: string[]): GeneratedCode => { return new GeneratedCode({ queryTree: [ ...this._queryTree, @@ -3767,47 +3842,68 @@ export class GeneratedCode extends BaseClient { args: { paths }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Call the provided function with current GeneratedCode. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: GeneratedCode) => GeneratedCode) { - return arg(this) - } + with = (arg: (param: GeneratedCode) => GeneratedCode) => { + return arg(this); + }; } - - /** - * A git ref (tag, branch or commit). + * A git ref (tag, branch, or commit). */ export class GitRef extends BaseClient { - private readonly _commit?: string = undefined + private readonly _id?: GitRefID = undefined; + private readonly _commit?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _commit?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: GitRefID, + _commit?: string + ) { + super(parent); - this._commit = _commit - } + this._id = _id; + this._commit = _commit; + } + + /** + * A unique identifier for this GitRef. + */ + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; /** * The resolved commit id at this ref. */ - async commit(): Promise { + commit = async (): Promise => { if (this._commit) { - return this._commit + return this._commit; } const response: Awaited = await computeQuery( @@ -3817,17 +3913,18 @@ export class GitRef extends BaseClient { operation: "commit", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * The filesystem tree at this ref. + * @param opts.sshKnownHosts DEPRECATED: This option should be passed to `git` instead. + * @param opts.sshAuthSocket DEPRECATED: This option should be passed to `git` instead. */ - tree(opts?: GitRefTreeOpts): Directory { + tree = (opts?: GitRefTreeOpts): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -3836,32 +3933,55 @@ export class GitRef extends BaseClient { args: { ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; } /** * A git repository. */ export class GitRepository extends BaseClient { + private readonly _id?: GitRepositoryID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: GitRepositoryID + ) { + super(parent); + + this._id = _id; + } + + /** + * A unique identifier for this GitRepository. + */ + id = async (): Promise => { + if (this._id) { + return this._id; + } - } + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; /** - * Returns details on one branch. + * Returns details of a branch. * @param name Branch's name (e.g., "main"). */ - branch(name: string): GitRef { + branch = (name: string): GitRef => { return new GitRef({ queryTree: [ ...this._queryTree, @@ -3870,16 +3990,15 @@ export class GitRepository extends BaseClient { args: { name }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Returns details on one commit. + * Returns details of a commit. * @param id Identifier of the commit (e.g., "b6315d8f2810962c601af73f86831f6866ea798b"). */ - commit(id: string): GitRef { + commit = (id: string): GitRef => { return new GitRef({ queryTree: [ ...this._queryTree, @@ -3888,16 +4007,15 @@ export class GitRepository extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Returns details on one tag. + * Returns details of a tag. * @param name Tag's name (e.g., "v0.3.9"). */ - tag(name: string): GitRef { + tag = (name: string): GitRef => { return new GitRef({ queryTree: [ ...this._queryTree, @@ -3906,26 +4024,49 @@ export class GitRepository extends BaseClient { args: { name }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; } /** - * Information about the host execution environment. + * Information about the host environment. */ export class Host extends BaseClient { + private readonly _id?: HostID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: HostID + ) { + super(parent); + + this._id = _id; + } + + /** + * A unique identifier for this Host. + */ + id = async (): Promise => { + if (this._id) { + return this._id; + } - } + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; /** * Accesses a directory on the host. @@ -3933,7 +4074,7 @@ export class Host extends BaseClient { * @param opts.exclude Exclude artifacts that match the given pattern (e.g., ["node_modules/", ".git*"]). * @param opts.include Include only artifacts that match the given pattern (e.g., ["app/", "package.*"]). */ - directory(path: string, opts?: HostDirectoryOpts): Directory { + directory = (path: string, opts?: HostDirectoryOpts): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -3942,16 +4083,15 @@ export class Host extends BaseClient { args: { path, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Accesses a file on the host. * @param path Location of the file to retrieve (e.g., "README.md"). */ - file(path: string): File { + file = (path: string): File => { return new File({ queryTree: [ ...this._queryTree, @@ -3960,42 +4100,40 @@ export class Host extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Creates a service that forwards traffic to a specified address via the host. - * @param ports Ports to expose via the service, forwarding through the host network. - * - * If a port's frontend is unspecified or 0, it defaults to the same as the - * backend port. - * - * An empty set of ports is not valid; an error will be returned. * @param opts.host Upstream host to forward traffic to. + * @param opts.ports Ports to expose via the service, forwarding through the host network. + * + * If a port's frontend is unspecified or 0, it defaults to the same as the backend port. + * + * An empty set of ports is not valid; an error will be returned. */ - service(ports: PortForward[], opts?: HostServiceOpts): Service { + service = (opts?: HostServiceOpts): Service => { return new Service({ queryTree: [ ...this._queryTree, { operation: "service", - args: { ports, ...opts }, + args: { ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Sets a secret given a user-defined name and the file path on the host, and returns the secret. + * * The file is limited to a size of 512000 bytes. * @param name The user defined name for this secret. * @param path Location of the file to set as a secret. */ - setSecretFile(name: string, path: string): Secret { + setSecretFile = (name: string, path: string): Secret => { return new Secret({ queryTree: [ ...this._queryTree, @@ -4004,30 +4142,25 @@ export class Host extends BaseClient { args: { name, path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Creates a tunnel that forwards traffic from the host to a service. * @param service Service to send traffic from the tunnel. - * @param opts.native Map each service port to the same port on the host, as if the service were - * running natively. - * - * Note: enabling may result in port conflicts. * @param opts.ports Configure explicit port forwarding rules for the tunnel. - * - * If a port's frontend is unspecified or 0, a random port will be chosen by - * the host. - * - * If no ports are given, all of the service's ports are forwarded. If native - * is true, each port maps to the same port on the host. If native is false, - * each port maps to a random port chosen by the host. - * + * + * If a port's frontend is unspecified or 0, a random port will be chosen by the host. + * + * If no ports are given, all of the service's ports are forwarded. If native is true, each port maps to the same port on the host. If native is false, each port maps to a random port chosen by the host. + * * If ports are given and native is true, the ports are additive. + * @param opts.native Map each service port to the same port on the host, as if the service were running natively. + * + * Note: enabling may result in port conflicts. */ - tunnel(service: Service, opts?: HostTunnelOpts): Service { + tunnel = (service: Service, opts?: HostTunnelOpts): Service => { return new Service({ queryTree: [ ...this._queryTree, @@ -4036,16 +4169,15 @@ export class Host extends BaseClient { args: { service, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Accesses a Unix socket on the host. * @param path Location of the Unix socket (e.g., "/var/run/docker.sock"). */ - unixSocket(path: string): Socket { + unixSocket = (path: string): Socket => { return new Socket({ queryTree: [ ...this._queryTree, @@ -4054,49 +4186,192 @@ export class Host extends BaseClient { args: { path }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; } +/** + * A definition of a custom interface defined in a Module. + */ +export class InterfaceTypeDef extends BaseClient { + private readonly _id?: InterfaceTypeDefID = undefined; + private readonly _description?: string = undefined; + private readonly _name?: string = undefined; + private readonly _sourceModuleName?: string = undefined; + + /** + * Constructor is used for internal usage only, do not create object from it. + */ + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: InterfaceTypeDefID, + _description?: string, + _name?: string, + _sourceModuleName?: string + ) { + super(parent); + + this._id = _id; + this._description = _description; + this._name = _name; + this._sourceModuleName = _sourceModuleName; + } + + /** + * A unique identifier for this InterfaceTypeDef. + */ + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + return response; + }; + description = async (): Promise => { + if (this._description) { + return this._description; + } + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "description", + }, + ], + await this._ctx.connection() + ); + return response; + }; + functions = async (): Promise => { + type functions = { + id: FunctionID; + }; + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "functions", + }, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + return response.map( + (r) => + new Function_( + { + queryTree: [ + { + operation: "loadFunction_FromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + name = async (): Promise => { + if (this._name) { + return this._name; + } + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "name", + }, + ], + await this._ctx.connection() + ); + return response; + }; + sourceModuleName = async (): Promise => { + if (this._sourceModuleName) { + return this._sourceModuleName; + } + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "sourceModuleName", + }, + ], + await this._ctx.connection() + ); + return response; + }; +} /** * A simple key value object that represents a label. */ export class Label extends BaseClient { - private readonly _name?: string = undefined - private readonly _value?: string = undefined + private readonly _id?: LabelID = undefined; + private readonly _name?: string = undefined; + private readonly _value?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _name?: string, - _value?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: LabelID, + _name?: string, + _value?: string + ) { + super(parent); - this._name = _name - this._value = _value - } + this._id = _id; + this._name = _name; + this._value = _value; + } /** - * The label name. + * A unique identifier for this Label. */ - async name(): Promise { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -4106,19 +4381,14 @@ export class Label extends BaseClient { operation: "name", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * The label value. - */ - async value(): Promise { + return response; + }; + value = async (): Promise => { if (this._value) { - return this._value + return this._value; } const response: Awaited = await computeQuery( @@ -4128,33 +4398,52 @@ export class Label extends BaseClient { operation: "value", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } /** * A definition of a list type in a Module. */ export class ListTypeDef extends BaseClient { + private readonly _id?: ListTypeDefID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: ListTypeDefID + ) { + super(parent); - } + this._id = _id; + } /** - * The type of the elements in the list + * A unique identifier for this ListTypeDef. */ - elementTypeDef(): TypeDef { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + elementTypeDef = (): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -4162,49 +4451,50 @@ export class ListTypeDef extends BaseClient { operation: "elementTypeDef", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; } - +/** + * A Dagger module. + */ export class Module_ extends BaseClient { - private readonly _id?: ModuleID = undefined - private readonly _description?: string = undefined - private readonly _name?: string = undefined - private readonly _sdk?: string = undefined - private readonly _serve?: Void = undefined - private readonly _sourceDirectorySubPath?: string = undefined + private readonly _id?: ModuleID = undefined; + private readonly _description?: string = undefined; + private readonly _name?: string = undefined; + private readonly _sdk?: string = undefined; + private readonly _serve?: Void = undefined; + private readonly _sourceDirectorySubpath?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: ModuleID, - _description?: string, - _name?: string, - _sdk?: string, - _serve?: Void, - _sourceDirectorySubPath?: string, - ) { - super(parent) - - this._id = _id - this._description = _description - this._name = _name - this._sdk = _sdk - this._serve = _serve - this._sourceDirectorySubPath = _sourceDirectorySubPath - } - - /** - * The ID of the module - */ - async id(): Promise { + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: ModuleID, + _description?: string, + _name?: string, + _sdk?: string, + _serve?: Void, + _sourceDirectorySubpath?: string + ) { + super(parent); + + this._id = _id; + this._description = _description; + this._name = _name; + this._sdk = _sdk; + this._serve = _serve; + this._sourceDirectorySubpath = _sourceDirectorySubpath; + } + + /** + * A unique identifier for this Module. + */ + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -4214,20 +4504,15 @@ export class Module_ extends BaseClient { operation: "id", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * Modules used by this module - */ - async dependencies(): Promise { + return response; + }; + dependencies = async (): Promise => { type dependencies = { - id: ModuleID - } + id: ModuleID; + }; const response: Awaited = await computeQuery( [ @@ -4236,29 +4521,29 @@ export class Module_ extends BaseClient { operation: "dependencies", }, { - operation: "id" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new Module_( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.id, - ) - ) - } - - /** - * The dependencies as configured by the module - */ - async dependencyConfig(): Promise { + (r) => + new Module_( + { + queryTree: [ + { + operation: "loadModule_FromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + dependencyConfig = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -4266,19 +4551,14 @@ export class Module_ extends BaseClient { operation: "dependencyConfig", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The doc string of the module, if any - */ - async description(): Promise { + return response; + }; + description = async (): Promise => { if (this._description) { - return this._description + return this._description; } const response: Awaited = await computeQuery( @@ -4288,17 +4568,12 @@ export class Module_ extends BaseClient { operation: "description", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The code generated by the SDK's runtime - */ - generatedCode(): GeneratedCode { + return response; + }; + generatedCode = (): GeneratedCode => { return new GeneratedCode({ queryTree: [ ...this._queryTree, @@ -4306,17 +4581,61 @@ export class Module_ extends BaseClient { operation: "generatedCode", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * The name of the module + * Retrieves the module with the objects loaded via its SDK. */ - async name(): Promise { + initialize = (): Module_ => { + return new Module_({ + queryTree: [ + ...this._queryTree, + { + operation: "initialize", + }, + ], + ctx: this._ctx, + }); + }; + interfaces = async (): Promise => { + type interfaces = { + id: TypeDefID; + }; + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "interfaces", + }, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response.map( + (r) => + new TypeDef( + { + queryTree: [ + { + operation: "loadTypeDefFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -4326,20 +4645,15 @@ export class Module_ extends BaseClient { operation: "name", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * Objects served by this module - */ - async objects(): Promise { + return response; + }; + objects = async (): Promise => { type objects = { - id: TypeDefID - } + id: TypeDefID; + }; const response: Awaited = await computeQuery( [ @@ -4348,31 +4662,31 @@ export class Module_ extends BaseClient { operation: "objects", }, { - operation: "id" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new TypeDef( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.id, - ) - ) - } - - /** - * The SDK used by this module. Either a name of a builtin SDK or a module ref pointing to the SDK's implementation. - */ - async sdk(): Promise { + (r) => + new TypeDef( + { + queryTree: [ + { + operation: "loadTypeDefFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + sdk = async (): Promise => { if (this._sdk) { - return this._sdk + return this._sdk; } const response: Awaited = await computeQuery( @@ -4382,21 +4696,20 @@ export class Module_ extends BaseClient { operation: "sdk", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Serve a module's API in the current session. - * Note: this can only be called once per session. - * In the future, it could return a stream or service to remove the side effect. + * + * Note: this can only be called once per session. In the future, it could return a stream or service to remove the side effect. */ - async serve(): Promise { + serve = async (): Promise => { if (this._serve) { - return this._serve + return this._serve; } const response: Awaited = await computeQuery( @@ -4406,17 +4719,12 @@ export class Module_ extends BaseClient { operation: "serve", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The directory containing the module's source code - */ - sourceDirectory(): Directory { + return response; + }; + sourceDirectory = (): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -4424,37 +4732,47 @@ export class Module_ extends BaseClient { operation: "sourceDirectory", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } - - /** - * The module's subpath within the source directory - */ - async sourceDirectorySubPath(): Promise { - if (this._sourceDirectorySubPath) { - return this._sourceDirectorySubPath + ctx: this._ctx, + }); + }; + sourceDirectorySubpath = async (): Promise => { + if (this._sourceDirectorySubpath) { + return this._sourceDirectorySubpath; } const response: Awaited = await computeQuery( [ ...this._queryTree, { - operation: "sourceDirectorySubPath", + operation: "sourceDirectorySubpath", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** - * This module plus the given Object type and associated functions + * This module plus the given Interface type and associated functions */ - withObject(object: TypeDef): Module_ { + withInterface = (iface: TypeDef): Module_ => { + return new Module_({ + queryTree: [ + ...this._queryTree, + { + operation: "withInterface", + args: { iface }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * This module plus the given Object type and associated functions. + */ + withObject = (object: TypeDef): Module_ => { return new Module_({ queryTree: [ ...this._queryTree, @@ -4463,49 +4781,90 @@ export class Module_ extends BaseClient { args: { object }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Retrieves the module with basic configuration loaded, ready for initialization. + * @param directory The directory containing the module's source code. + * @param opts.subpath An optional subpath of the directory which contains the module's source code. + * + * This is needed when the module code is in a subdirectory but requires parent directories to be loaded in order to execute. For example, the module source code may need a go.mod, project.toml, package.json, etc. file from a parent directory. + * + * If not set, the module source code is loaded from the root of the directory. + */ + withSource = (directory: Directory, opts?: ModuleWithSourceOpts): Module_ => { + return new Module_({ + queryTree: [ + ...this._queryTree, + { + operation: "withSource", + args: { directory, ...opts }, + }, + ], + ctx: this._ctx, + }); + }; /** * Call the provided function with current Module. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: Module_) => Module_) { - return arg(this) - } + with = (arg: (param: Module_) => Module_) => { + return arg(this); + }; } /** * Static configuration for a module (e.g. parsed contents of dagger.json) */ export class ModuleConfig extends BaseClient { - private readonly _name?: string = undefined - private readonly _root?: string = undefined - private readonly _sdk?: string = undefined + private readonly _id?: ModuleConfigID = undefined; + private readonly _name?: string = undefined; + private readonly _root?: string = undefined; + private readonly _sdk?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _name?: string, - _root?: string, - _sdk?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: ModuleConfigID, + _name?: string, + _root?: string, + _sdk?: string + ) { + super(parent); - this._name = _name - this._root = _root - this._sdk = _sdk - } + this._id = _id; + this._name = _name; + this._root = _root; + this._sdk = _sdk; + } /** - * Modules that this module depends on. + * A unique identifier for this ModuleConfig. */ - async dependencies(): Promise { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + dependencies = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -4513,17 +4872,12 @@ export class ModuleConfig extends BaseClient { operation: "dependencies", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * Exclude these file globs when loading the module root. - */ - async exclude(): Promise { + return response; + }; + exclude = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -4531,17 +4885,12 @@ export class ModuleConfig extends BaseClient { operation: "exclude", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * Include only these file globs when loading the module root. - */ - async include(): Promise { + return response; + }; + include = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -4549,19 +4898,14 @@ export class ModuleConfig extends BaseClient { operation: "include", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The name of the module. - */ - async name(): Promise { + return response; + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -4571,19 +4915,14 @@ export class ModuleConfig extends BaseClient { operation: "name", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * The root directory of the module's project, which may be above the module source code. - */ - async root(): Promise { + return response; + }; + root = async (): Promise => { if (this._root) { - return this._root + return this._root; } const response: Awaited = await computeQuery( @@ -4593,19 +4932,14 @@ export class ModuleConfig extends BaseClient { operation: "root", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * Either the name of a built-in SDK ('go', 'python', etc.) OR a module reference pointing to the SDK's module implementation. - */ - async sdk(): Promise { + return response; + }; + sdk = async (): Promise => { if (this._sdk) { - return this._sdk + return this._sdk; } const response: Awaited = await computeQuery( @@ -4615,45 +4949,74 @@ export class ModuleConfig extends BaseClient { operation: "sdk", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } - - - - /** * A definition of a custom object defined in a Module. */ export class ObjectTypeDef extends BaseClient { - private readonly _description?: string = undefined - private readonly _name?: string = undefined + private readonly _id?: ObjectTypeDefID = undefined; + private readonly _description?: string = undefined; + private readonly _name?: string = undefined; + private readonly _sourceModuleName?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _description?: string, - _name?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: ObjectTypeDefID, + _description?: string, + _name?: string, + _sourceModuleName?: string + ) { + super(parent); - this._description = _description - this._name = _name - } + this._id = _id; + this._description = _description; + this._name = _name; + this._sourceModuleName = _sourceModuleName; + } /** - * The doc string for the object, if any + * A unique identifier for this ObjectTypeDef. */ - async description(): Promise { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + constructor_ = (): Function_ => { + return new Function_({ + queryTree: [ + ...this._queryTree, + { + operation: "constructor", + }, + ], + ctx: this._ctx, + }); + }; + description = async (): Promise => { if (this._description) { - return this._description + return this._description; } const response: Awaited = await computeQuery( @@ -4663,21 +5026,15 @@ export class ObjectTypeDef extends BaseClient { operation: "description", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * Static fields defined on this object, if any - */ - async fields(): Promise { + return response; + }; + fields = async (): Promise => { type fields = { - description: string - name: string - } + id: FieldTypeDefID; + }; const response: Awaited = await computeQuery( [ @@ -4686,33 +5043,32 @@ export class ObjectTypeDef extends BaseClient { operation: "fields", }, { - operation: "description name" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new FieldTypeDef( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.description, - r.name, - ) - ) - } - - /** - * Functions defined on this object, if any - */ - async functions(): Promise { + (r) => + new FieldTypeDef( + { + queryTree: [ + { + operation: "loadFieldTypeDefFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + functions = async (): Promise => { type functions = { - id: FunctionID - } + id: FunctionID; + }; const response: Awaited = await computeQuery( [ @@ -4721,31 +5077,31 @@ export class ObjectTypeDef extends BaseClient { operation: "functions", }, { - operation: "id" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new Function_( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.id, - ) - ) - } - - /** - * The name of the object - */ - async name(): Promise { + (r) => + new Function_( + { + queryTree: [ + { + operation: "loadFunction_FromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + name = async (): Promise => { if (this._name) { - return this._name + return this._name; } const response: Awaited = await computeQuery( @@ -4755,48 +5111,80 @@ export class ObjectTypeDef extends BaseClient { operation: "name", }, ], - this.client - ) - - - return response - } -} - + await this._ctx.connection() + ); + return response; + }; + sourceModuleName = async (): Promise => { + if (this._sourceModuleName) { + return this._sourceModuleName; + } + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "sourceModuleName", + }, + ], + await this._ctx.connection() + ); + return response; + }; +} /** * A port exposed by a container. */ export class Port extends BaseClient { - private readonly _description?: string = undefined - private readonly _port?: number = undefined - private readonly _protocol?: NetworkProtocol = undefined + private readonly _id?: PortID = undefined; + private readonly _description?: string = undefined; + private readonly _port?: number = undefined; + private readonly _protocol?: NetworkProtocol = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _description?: string, - _port?: number, - _protocol?: NetworkProtocol, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: PortID, + _description?: string, + _port?: number, + _protocol?: NetworkProtocol + ) { + super(parent); - this._description = _description - this._port = _port - this._protocol = _protocol - } + this._id = _id; + this._description = _description; + this._port = _port; + this._protocol = _protocol; + } /** - * The port description. + * A unique identifier for this Port. */ - async description(): Promise { + id = async (): Promise => { + if (this._id) { + return this._id; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + description = async (): Promise => { if (this._description) { - return this._description + return this._description; } const response: Awaited = await computeQuery( @@ -4806,19 +5194,14 @@ export class Port extends BaseClient { operation: "description", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * The port number. - */ - async port(): Promise { + return response; + }; + port = async (): Promise => { if (this._port) { - return this._port + return this._port; } const response: Awaited = await computeQuery( @@ -4828,19 +5211,14 @@ export class Port extends BaseClient { operation: "port", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * The transport layer network protocol. - */ - async protocol(): Promise { + return response; + }; + protocol = async (): Promise => { if (this._protocol) { - return this._protocol + return this._protocol; } const response: Awaited = await computeQuery( @@ -4850,40 +5228,64 @@ export class Port extends BaseClient { operation: "protocol", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } - - - +/** + * The root of the DAG. + */ export class Client extends BaseClient { - private readonly _checkVersionCompatibility?: boolean = undefined - private readonly _defaultPlatform?: Platform = undefined + private readonly _checkVersionCompatibility?: boolean = undefined; + private readonly _defaultPlatform?: Platform = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _checkVersionCompatibility?: boolean, - _defaultPlatform?: Platform, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _checkVersionCompatibility?: boolean, + _defaultPlatform?: Platform + ) { + super(parent); - this._checkVersionCompatibility = _checkVersionCompatibility - this._defaultPlatform = _defaultPlatform - } + this._checkVersionCompatibility = _checkVersionCompatibility; + this._defaultPlatform = _defaultPlatform; + } + + /** + * Retrieves a content-addressed blob. + * @param digest Digest of the blob + * @param size Size of the blob + * @param mediaType Media type of the blob + * @param uncompressed Digest of the uncompressed blob + */ + blob = ( + digest: string, + size: number, + mediaType: string, + uncompressed: string + ): Directory => { + return new Directory({ + queryTree: [ + ...this._queryTree, + { + operation: "blob", + args: { digest, size, mediaType, uncompressed }, + }, + ], + ctx: this._ctx, + }); + }; /** * Constructs a cache volume for a given cache key. * @param key A string identifier to target this cache volume (e.g., "modules-cache"). */ - cacheVolume(key: string): CacheVolume { + cacheVolume = (key: string): CacheVolume => { return new CacheVolume({ queryTree: [ ...this._queryTree, @@ -4892,16 +5294,15 @@ export class Client extends BaseClient { args: { key }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Checks if the current Dagger Engine is compatible with an SDK's required version. - * @param version The SDK's required version. + * @param version Version required by the SDK. */ - async checkVersionCompatibility(version: string): Promise { + checkVersionCompatibility = async (version: string): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -4910,20 +5311,20 @@ export class Client extends BaseClient { args: { version }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** - * Creates a scratch container or loads one by ID. - * - * Optional platform argument initializes new containers to execute and publish - * as that platform. Platform defaults to that of the builder's host. + * Creates a scratch container. + * + * Optional platform argument initializes new containers to execute and publish as that platform. Platform defaults to that of the builder's host. + * @param opts.id DEPRECATED: Use `loadContainerFromID` instead. + * @param opts.platform Platform to initialize the container with. */ - container(opts?: ClientContainerOpts): Container { + container = (opts?: ClientContainerOpts): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -4932,17 +5333,16 @@ export class Client extends BaseClient { args: { ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * The FunctionCall context that the SDK caller is currently executing in. - * If the caller is not currently executing in a function, this will return - * an error. + * + * If the caller is not currently executing in a function, this will return an error. */ - currentFunctionCall(): FunctionCall { + currentFunctionCall = (): FunctionCall => { return new FunctionCall({ queryTree: [ ...this._queryTree, @@ -4950,15 +5350,14 @@ export class Client extends BaseClient { operation: "currentFunctionCall", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * The module currently being served in the session, if any. */ - currentModule(): Module_ { + currentModule = (): Module_ => { return new Module_({ queryTree: [ ...this._queryTree, @@ -4966,15 +5365,52 @@ export class Client extends BaseClient { operation: "currentModule", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * The TypeDef representations of the objects currently being served in the session. + */ + currentTypeDefs = async (): Promise => { + type currentTypeDefs = { + id: TypeDefID; + }; + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "currentTypeDefs", + }, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); - /** - * The default platform of the builder. - */ - async defaultPlatform(): Promise { + return response.map( + (r) => + new TypeDef( + { + queryTree: [ + { + operation: "loadTypeDefFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + + /** + * The default platform of the engine. + */ + defaultPlatform = async (): Promise => { const response: Awaited = await computeQuery( [ ...this._queryTree, @@ -4982,17 +5418,17 @@ export class Client extends BaseClient { operation: "defaultPlatform", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** - * Creates an empty directory or loads one by ID. + * Creates an empty directory. + * @param opts.id DEPRECATED: Use `loadDirectoryFromID` isntead. */ - directory(opts?: ClientDirectoryOpts): Directory { + directory = (opts?: ClientDirectoryOpts): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -5001,16 +5437,14 @@ export class Client extends BaseClient { args: { ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Loads a file by ID. * @deprecated Use loadFileFromID instead. */ - file(id: FileID): File { + file = (id: FileID): File => { return new File({ queryTree: [ ...this._queryTree, @@ -5019,15 +5453,16 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Create a function. + * Creates a function. + * @param name Name of the function, in its original format from the implementation language. + * @param returnType Return type of the function. */ - function_(name: string, returnType: TypeDef): Function_ { + function_ = (name: string, returnType: TypeDef): Function_ => { return new Function_({ queryTree: [ ...this._queryTree, @@ -5036,16 +5471,14 @@ export class Client extends BaseClient { args: { name, returnType }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Create a code generation result, given a directory containing the generated - * code. + * Create a code generation result, given a directory containing the generated code. */ - generatedCode(code: Directory): GeneratedCode { + generatedCode = (code: Directory): GeneratedCode => { return new GeneratedCode({ queryTree: [ ...this._queryTree, @@ -5054,22 +5487,23 @@ export class Client extends BaseClient { args: { code }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Queries a git repository. - * @param url Url of the git repository. - * Can be formatted as https://{host}/{owner}/{repo}, git@{host}:{owner}/{repo} + * Queries a Git repository. + * @param url URL of the git repository. + * + * Can be formatted as `https://{host}/{owner}/{repo}`, `git@{host}:{owner}/{repo}`. + * * Suffix ".git" is optional. * @param opts.keepGitDir Set to true to keep .git directory. + * @param opts.experimentalServiceHost A service which must be started before the repo is fetched. * @param opts.sshKnownHosts Set SSH known hosts * @param opts.sshAuthSocket Set SSH auth socket - * @param opts.experimentalServiceHost A service which must be started before the repo is fetched. */ - git(url: string, opts?: ClientGitOpts): GitRepository { + git = (url: string, opts?: ClientGitOpts): GitRepository => { return new GitRepository({ queryTree: [ ...this._queryTree, @@ -5078,15 +5512,14 @@ export class Client extends BaseClient { args: { url, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Queries the host environment. */ - host(): Host { + host = (): Host => { return new Host({ queryTree: [ ...this._queryTree, @@ -5094,17 +5527,16 @@ export class Client extends BaseClient { operation: "host", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Returns a file containing an http remote url content. * @param url HTTP url to get the content from (e.g., "https://docs.dagger.io"). * @param opts.experimentalServiceHost A service which must be started before the URL is fetched. */ - http(url: string, opts?: ClientHttpOpts): File { + http = (url: string, opts?: ClientHttpOpts): File => { return new File({ queryTree: [ ...this._queryTree, @@ -5113,15 +5545,14 @@ export class Client extends BaseClient { args: { url, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Load a CacheVolume from its ID. */ - loadCacheVolumeFromID(id: CacheVolumeID): CacheVolume { + loadCacheVolumeFromID = (id: CacheVolumeID): CacheVolume => { return new CacheVolume({ queryTree: [ ...this._queryTree, @@ -5130,15 +5561,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Loads a container from an ID. + * Load a Container from its ID. */ - loadContainerFromID(id: ContainerID): Container { + loadContainerFromID = (id: ContainerID): Container => { return new Container({ queryTree: [ ...this._queryTree, @@ -5147,15 +5577,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Load a Directory from its ID. */ - loadDirectoryFromID(id: DirectoryID): Directory { + loadDirectoryFromID = (id: DirectoryID): Directory => { return new Directory({ queryTree: [ ...this._queryTree, @@ -5164,15 +5593,46 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Load a EnvVariable from its ID. + */ + loadEnvVariableFromID = (id: EnvVariableID): EnvVariable => { + return new EnvVariable({ + queryTree: [ + ...this._queryTree, + { + operation: "loadEnvVariableFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a FieldTypeDef from its ID. + */ + loadFieldTypeDefFromID = (id: FieldTypeDefID): FieldTypeDef => { + return new FieldTypeDef({ + queryTree: [ + ...this._queryTree, + { + operation: "loadFieldTypeDefFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; /** * Load a File from its ID. */ - loadFileFromID(id: FileID): File { + loadFileFromID = (id: FileID): File => { return new File({ queryTree: [ ...this._queryTree, @@ -5181,15 +5641,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Load a function argument by ID. + * Load a FunctionArg from its ID. */ - loadFunctionArgFromID(id: FunctionArgID): FunctionArg { + loadFunctionArgFromID = (id: FunctionArgID): FunctionArg => { return new FunctionArg({ queryTree: [ ...this._queryTree, @@ -5198,15 +5657,48 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Load a FunctionCallArgValue from its ID. + */ + loadFunctionCallArgValueFromID = ( + id: FunctionCallArgValueID + ): FunctionCallArgValue => { + return new FunctionCallArgValue({ + queryTree: [ + ...this._queryTree, + { + operation: "loadFunctionCallArgValueFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a FunctionCall from its ID. + */ + loadFunctionCallFromID = (id: FunctionCallID): FunctionCall => { + return new FunctionCall({ + queryTree: [ + ...this._queryTree, + { + operation: "loadFunctionCallFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; /** - * Load a function by ID. + * Load a Function from its ID. */ - loadFunctionFromID(id: FunctionID): Function_ { + loadFunctionFromID = (id: FunctionID): Function_ => { return new Function_({ queryTree: [ ...this._queryTree, @@ -5215,15 +5707,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Load a GeneratedCode by ID. + * Load a GeneratedCode from its ID. */ - loadGeneratedCodeFromID(id: GeneratedCodeID): GeneratedCode { + loadGeneratedCodeFromID = (id: GeneratedCodeID): GeneratedCode => { return new GeneratedCode({ queryTree: [ ...this._queryTree, @@ -5232,15 +5723,126 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Load a GitRef from its ID. + */ + loadGitRefFromID = (id: GitRefID): GitRef => { + return new GitRef({ + queryTree: [ + ...this._queryTree, + { + operation: "loadGitRefFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a GitRepository from its ID. + */ + loadGitRepositoryFromID = (id: GitRepositoryID): GitRepository => { + return new GitRepository({ + queryTree: [ + ...this._queryTree, + { + operation: "loadGitRepositoryFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a Host from its ID. + */ + loadHostFromID = (id: HostID): Host => { + return new Host({ + queryTree: [ + ...this._queryTree, + { + operation: "loadHostFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a InterfaceTypeDef from its ID. + */ + loadInterfaceTypeDefFromID = (id: InterfaceTypeDefID): InterfaceTypeDef => { + return new InterfaceTypeDef({ + queryTree: [ + ...this._queryTree, + { + operation: "loadInterfaceTypeDefFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a Label from its ID. + */ + loadLabelFromID = (id: LabelID): Label => { + return new Label({ + queryTree: [ + ...this._queryTree, + { + operation: "loadLabelFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a ListTypeDef from its ID. + */ + loadListTypeDefFromID = (id: ListTypeDefID): ListTypeDef => { + return new ListTypeDef({ + queryTree: [ + ...this._queryTree, + { + operation: "loadListTypeDefFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a ModuleConfig from its ID. + */ + loadModuleConfigFromID = (id: ModuleConfigID): ModuleConfig => { + return new ModuleConfig({ + queryTree: [ + ...this._queryTree, + { + operation: "loadModuleConfigFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; /** - * Load a module by ID. + * Load a Module from its ID. */ - loadModuleFromID(id: ModuleID): Module_ { + loadModuleFromID = (id: ModuleID): Module_ => { return new Module_({ queryTree: [ ...this._queryTree, @@ -5249,15 +5851,46 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Load a ObjectTypeDef from its ID. + */ + loadObjectTypeDefFromID = (id: ObjectTypeDefID): ObjectTypeDef => { + return new ObjectTypeDef({ + queryTree: [ + ...this._queryTree, + { + operation: "loadObjectTypeDefFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Load a Port from its ID. + */ + loadPortFromID = (id: PortID): Port => { + return new Port({ + queryTree: [ + ...this._queryTree, + { + operation: "loadPortFromID", + args: { id }, + }, + ], + ctx: this._ctx, + }); + }; /** * Load a Secret from its ID. */ - loadSecretFromID(id: SecretID): Secret { + loadSecretFromID = (id: SecretID): Secret => { return new Secret({ queryTree: [ ...this._queryTree, @@ -5266,15 +5899,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Loads a service from ID. + * Load a Service from its ID. */ - loadServiceFromID(id: ServiceID): Service { + loadServiceFromID = (id: ServiceID): Service => { return new Service({ queryTree: [ ...this._queryTree, @@ -5283,15 +5915,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Load a Socket from its ID. */ - loadSocketFromID(id: SocketID): Socket { + loadSocketFromID = (id: SocketID): Socket => { return new Socket({ queryTree: [ ...this._queryTree, @@ -5300,15 +5931,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Load a TypeDef by ID. + * Load a TypeDef from its ID. */ - loadTypeDefFromID(id: TypeDefID): TypeDef { + loadTypeDefFromID = (id: TypeDefID): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -5317,15 +5947,14 @@ export class Client extends BaseClient { args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Create a new module. */ - module_(): Module_ { + module_ = (): Module_ => { return new Module_({ queryTree: [ ...this._queryTree, @@ -5333,15 +5962,17 @@ export class Client extends BaseClient { operation: "module", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Load the static configuration for a module from the given source directory and optional subpath. */ - moduleConfig(sourceDirectory: Directory, opts?: ClientModuleConfigOpts): ModuleConfig { + moduleConfig = ( + sourceDirectory: Directory, + opts?: ClientModuleConfigOpts + ): ModuleConfig => { return new ModuleConfig({ queryTree: [ ...this._queryTree, @@ -5350,18 +5981,17 @@ export class Client extends BaseClient { args: { sourceDirectory, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Creates a named sub-pipeline. - * @param name Pipeline name. - * @param opts.description Pipeline description. - * @param opts.labels Pipeline labels. + * @param name Name of the sub-pipeline. + * @param opts.description Description of the sub-pipeline. + * @param opts.labels Labels to apply to the sub-pipeline. */ - pipeline(name: string, opts?: ClientPipelineOpts): Client { + pipeline = (name: string, opts?: ClientPipelineOpts): Client => { return new Client({ queryTree: [ ...this._queryTree, @@ -5370,36 +6000,34 @@ export class Client extends BaseClient { args: { name, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Loads a secret from its ID. - * @deprecated Use loadSecretFromID instead + * Reference a secret by name. */ - secret(id: SecretID): Secret { + secret = (name: string): Secret => { return new Secret({ queryTree: [ ...this._queryTree, { operation: "secret", - args: { id }, + args: { name }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Sets a secret given a user defined name to its plaintext and returns the secret. + * * The plaintext value is limited to a size of 128000 bytes. * @param name The user defined name for this secret * @param plaintext The plaintext of the secret */ - setSecret(name: string, plaintext: string): Secret { + setSecret = (name: string, plaintext: string): Secret => { return new Secret({ queryTree: [ ...this._queryTree, @@ -5408,33 +6036,31 @@ export class Client extends BaseClient { args: { name, plaintext }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Loads a socket by its ID. * @deprecated Use loadSocketFromID instead. */ - socket(opts?: ClientSocketOpts): Socket { + socket = (id: SocketID): Socket => { return new Socket({ queryTree: [ ...this._queryTree, { operation: "socket", - args: { ...opts }, + args: { id }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Create a new TypeDef. */ - typeDef(): TypeDef { + typeDef = (): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -5442,48 +6068,47 @@ export class Client extends BaseClient { operation: "typeDef", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Call the provided function with current Client. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: Client) => Client) { - return arg(this) - } + with = (arg: (param: Client) => Client) => { + return arg(this); + }; } /** * A reference to a secret value, which can be handled more safely than the value itself. */ export class Secret extends BaseClient { - private readonly _id?: SecretID = undefined - private readonly _plaintext?: string = undefined + private readonly _id?: SecretID = undefined; + private readonly _plaintext?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: SecretID, - _plaintext?: string, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: SecretID, + _plaintext?: string + ) { + super(parent); - this._id = _id - this._plaintext = _plaintext - } + this._id = _id; + this._plaintext = _plaintext; + } /** - * The identifier for this secret. + * A unique identifier for this Secret. */ - async id(): Promise { + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -5493,19 +6118,18 @@ export class Secret extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * The value of this secret. */ - async plaintext(): Promise { + plaintext = async (): Promise => { if (this._plaintext) { - return this._plaintext + return this._plaintext; } const response: Awaited = await computeQuery( @@ -5515,50 +6139,49 @@ export class Secret extends BaseClient { operation: "plaintext", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } - - - +/** + * A content-addressed service providing TCP connectivity. + */ export class Service extends BaseClient { - private readonly _id?: ServiceID = undefined - private readonly _endpoint?: string = undefined - private readonly _hostname?: string = undefined - private readonly _start?: ServiceID = undefined - private readonly _stop?: ServiceID = undefined + private readonly _id?: ServiceID = undefined; + private readonly _endpoint?: string = undefined; + private readonly _hostname?: string = undefined; + private readonly _start?: ServiceID = undefined; + private readonly _stop?: ServiceID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: ServiceID, - _endpoint?: string, - _hostname?: string, - _start?: ServiceID, - _stop?: ServiceID, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: ServiceID, + _endpoint?: string, + _hostname?: string, + _start?: ServiceID, + _stop?: ServiceID + ) { + super(parent); - this._id = _id - this._endpoint = _endpoint - this._hostname = _hostname - this._start = _start - this._stop = _stop - } + this._id = _id; + this._endpoint = _endpoint; + this._hostname = _hostname; + this._start = _start; + this._stop = _stop; + } /** - * A unique identifier for this service. + * A unique identifier for this Service. */ - async id(): Promise { + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -5568,25 +6191,24 @@ export class Service extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves an endpoint that clients can use to reach this container. - * + * * If no port is specified, the first exposed port is used. If none exist an error is returned. - * + * * If a scheme is specified, a URL is returned. Otherwise, a host:port pair is returned. * @param opts.port The exposed port number for the endpoint * @param opts.scheme Return a URL with the given scheme, eg. http for http:// */ - async endpoint(opts?: ServiceEndpointOpts): Promise { + endpoint = async (opts?: ServiceEndpointOpts): Promise => { if (this._endpoint) { - return this._endpoint + return this._endpoint; } const response: Awaited = await computeQuery( @@ -5597,19 +6219,18 @@ export class Service extends BaseClient { args: { ...opts }, }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves a hostname which can be used by clients to reach this container. */ - async hostname(): Promise { + hostname = async (): Promise => { if (this._hostname) { - return this._hostname + return this._hostname; } const response: Awaited = await computeQuery( @@ -5619,22 +6240,19 @@ export class Service extends BaseClient { operation: "hostname", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; /** * Retrieves the list of ports provided by the service. */ - async ports(): Promise { + ports = async (): Promise => { type ports = { - description: string - port: number - protocol: NetworkProtocol - } + id: PortID; + }; const response: Awaited = await computeQuery( [ @@ -5643,33 +6261,35 @@ export class Service extends BaseClient { operation: "ports", }, { - operation: "description port protocol" + operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - return response.map( - (r) => new Port( - { - queryTree: this.queryTree, - host: this.clientHost, - sessionToken: this.sessionToken, - }, - r.description, - r.port, - r.protocol, - ) - ) - } + (r) => + new Port( + { + queryTree: [ + { + operation: "loadPortFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; /** * Start the service and wait for its health checks to succeed. - * + * * Services bound to a Container do not need to be manually started. */ - async start(): Promise { + start = async (): Promise => { await computeQuery( [ ...this._queryTree, @@ -5677,16 +6297,16 @@ export class Service extends BaseClient { operation: "start", }, ], - this.client - ) + await this._ctx.connection() + ); - return this - } + return this; + }; /** * Stop the service. */ - async stop(): Promise { + stop = async (): Promise => { await computeQuery( [ ...this._queryTree, @@ -5694,37 +6314,37 @@ export class Service extends BaseClient { operation: "stop", }, ], - this.client - ) + await this._ctx.connection() + ); - return this - } + return this; + }; } - - - +/** + * A Unix or TCP/IP socket that can be mounted into a container. + */ export class Socket extends BaseClient { - private readonly _id?: SocketID = undefined + private readonly _id?: SocketID = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: SocketID, - ) { - super(parent) + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: SocketID + ) { + super(parent); - this._id = _id - } + this._id = _id; + } /** - * The content-addressed identifier of the socket. + * A unique identifier for this Socket. */ - async id(): Promise { + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -5734,44 +6354,43 @@ export class Socket extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; } - - - - /** * A definition of a parameter or return type in a Module. */ export class TypeDef extends BaseClient { - private readonly _id?: TypeDefID = undefined - private readonly _kind?: TypeDefKind = undefined - private readonly _optional?: boolean = undefined + private readonly _id?: TypeDefID = undefined; + private readonly _kind?: TypeDefKind = undefined; + private readonly _optional?: boolean = undefined; /** * Constructor is used for internal usage only, do not create object from it. */ - constructor( - parent?: { queryTree?: QueryTree[], host?: string, sessionToken?: string }, - _id?: TypeDefID, - _kind?: TypeDefKind, - _optional?: boolean, - ) { - super(parent) - - this._id = _id - this._kind = _kind - this._optional = _optional - } - async id(): Promise { + constructor( + parent?: { queryTree?: QueryTree[]; ctx: Context }, + _id?: TypeDefID, + _kind?: TypeDefKind, + _optional?: boolean + ) { + super(parent); + + this._id = _id; + this._kind = _kind; + this._optional = _optional; + } + + /** + * A unique identifier for this TypeDef. + */ + id = async (): Promise => { if (this._id) { - return this._id + return this._id; } const response: Awaited = await computeQuery( @@ -5781,18 +6400,23 @@ export class TypeDef extends BaseClient { operation: "id", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } - - /** - * If kind is LIST, the list-specific type definition. - * If kind is not LIST, this will be null. - */ - asList(): ListTypeDef { + return response; + }; + asInterface = (): InterfaceTypeDef => { + return new InterfaceTypeDef({ + queryTree: [ + ...this._queryTree, + { + operation: "asInterface", + }, + ], + ctx: this._ctx, + }); + }; + asList = (): ListTypeDef => { return new ListTypeDef({ queryTree: [ ...this._queryTree, @@ -5800,16 +6424,10 @@ export class TypeDef extends BaseClient { operation: "asList", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } - - /** - * If kind is OBJECT, the object-specific type definition. - * If kind is not OBJECT, this will be null. - */ - asObject(): ObjectTypeDef { + ctx: this._ctx, + }); + }; + asObject = (): ObjectTypeDef => { return new ObjectTypeDef({ queryTree: [ ...this._queryTree, @@ -5817,17 +6435,12 @@ export class TypeDef extends BaseClient { operation: "asObject", }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } - - /** - * The kind of type this is (e.g. primitive, list, object) - */ - async kind(): Promise { + ctx: this._ctx, + }); + }; + kind = async (): Promise => { if (this._kind) { - return this._kind + return this._kind; } const response: Awaited = await computeQuery( @@ -5837,19 +6450,14 @@ export class TypeDef extends BaseClient { operation: "kind", }, ], - this.client - ) - - - return response - } + await this._ctx.connection() + ); - /** - * Whether this type can be set to null. Defaults to false. - */ - async optional(): Promise { + return response; + }; + optional = async (): Promise => { if (this._optional) { - return this._optional + return this._optional; } const response: Awaited = await computeQuery( @@ -5859,12 +6467,29 @@ export class TypeDef extends BaseClient { operation: "optional", }, ], - this.client - ) + await this._ctx.connection() + ); - - return response - } + return response; + }; + + /** + * Adds a function for constructing a new instance of an Object TypeDef, failing if the type is not an object. + */ + withConstructor = (function_: Function_): TypeDef => { + return new TypeDef({ + queryTree: [ + ...this._queryTree, + { + operation: "withConstructor", + args: { + function: function_, + }, + }, + ], + ctx: this._ctx, + }); + }; /** * Adds a static field for an Object TypeDef, failing if the type is not an object. @@ -5872,7 +6497,11 @@ export class TypeDef extends BaseClient { * @param typeDef The type of the field * @param opts.description A doc string for the field, if any */ - withField(name: string, typeDef: TypeDef, opts?: TypeDefWithFieldOpts): TypeDef { + withField = ( + name: string, + typeDef: TypeDef, + opts?: TypeDefWithFieldOpts + ): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -5881,49 +6510,68 @@ export class TypeDef extends BaseClient { args: { name, typeDef, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** - * Adds a function for an Object TypeDef, failing if the type is not an object. + * Adds a function for an Object or Interface TypeDef, failing if the type is not one of those kinds. */ - withFunction(function_: Function_): TypeDef { + withFunction = (function_: Function_): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, { operation: "withFunction", - args: { function_ }, + args: { + function: function_, + }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; + + /** + * Returns a TypeDef of kind Interface with the provided name. + */ + withInterface = (name: string, opts?: TypeDefWithInterfaceOpts): TypeDef => { + return new TypeDef({ + queryTree: [ + ...this._queryTree, + { + operation: "withInterface", + args: { name, ...opts }, + }, + ], + ctx: this._ctx, + }); + }; /** * Sets the kind of the type. */ - withKind(kind: TypeDefKind): TypeDef { + withKind = (kind: TypeDefKind): TypeDef => { + const metadata: Metadata = { + kind: { is_enum: true }, + }; + return new TypeDef({ queryTree: [ ...this._queryTree, { operation: "withKind", - args: { kind }, + args: { kind, __metadata: metadata }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Returns a TypeDef of kind List with the provided type for its elements. */ - withListOf(elementType: TypeDef): TypeDef { + withListOf = (elementType: TypeDef): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -5932,19 +6580,16 @@ export class TypeDef extends BaseClient { args: { elementType }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Returns a TypeDef of kind Object with the provided name. - * - * Note that an object's fields and functions may be omitted if the intent is - * only to refer to an object. This is how functions are able to return their - * own object, or any other circular reference. + * + * Note that an object's fields and functions may be omitted if the intent is only to refer to an object. This is how functions are able to return their own object, or any other circular reference. */ - withObject(name: string, opts?: TypeDefWithObjectOpts): TypeDef { + withObject = (name: string, opts?: TypeDefWithObjectOpts): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -5953,15 +6598,14 @@ export class TypeDef extends BaseClient { args: { name, ...opts }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Sets whether this type can be set to null. */ - withOptional(optional: boolean): TypeDef { + withOptional = (optional: boolean): TypeDef => { return new TypeDef({ queryTree: [ ...this._queryTree, @@ -5970,24 +6614,18 @@ export class TypeDef extends BaseClient { args: { optional }, }, ], - host: this.clientHost, - sessionToken: this.sessionToken, - }) - } + ctx: this._ctx, + }); + }; /** * Call the provided function with current TypeDef. * * This is useful for reusability and readability by not breaking the calling chain. */ - with(arg: (param: TypeDef) => TypeDef) { - return arg(this) - } + with = (arg: (param: TypeDef) => TypeDef) => { + return arg(this); + }; } - - - - - - +export const dag = new Client({ ctx: defaultContext }); diff --git a/sdk/client.ts b/sdk/client.ts new file mode 100644 index 0000000..22ef15e --- /dev/null +++ b/sdk/client.ts @@ -0,0 +1,9 @@ +import { GraphQLClient } from "../deps.ts"; + +export function createGQLClient(port: number, token: string): GraphQLClient { + return new GraphQLClient(`http://127.0.0.1:${port}/query`, { + headers: { + Authorization: "Basic " + btoa(token + ":"), + }, + }); +} diff --git a/sdk/connect.ts b/sdk/connect.ts index bd26cf7..02a97fa 100644 --- a/sdk/connect.ts +++ b/sdk/connect.ts @@ -1,6 +1,6 @@ import { Writable } from "node:stream"; - import { Client } from "./client.gen.ts"; +import { Context } from "./context.ts"; /** * ConnectOpts defines option used to connect to an engine. @@ -39,51 +39,15 @@ export interface ConnectParams { */ export async function connect( cb: CallbackFct, - config: ConnectOpts = {} + _config: ConnectOpts = {} ): Promise { - let client: Client; - // let close: null | (() => void) = null; - - if (Deno.env.has("FLUENTCI_TOKEN") && Deno.env.has("FLUENTCI_SESSION_ID")) { - const client = new Client({ - host: Deno.env.get("FLUENTCI_HOST") || "vm.fluentci.io", - sessionToken: Deno.env.get("FLUENTCI_TOKEN"), - }); - await cb(client).finally(() => { - if (close) { - close(); - } - }); - return; - } - - // Prefer DAGGER_SESSION_PORT if set - const daggerSessionPort = Deno.env.get("DAGGER_SESSION_PORT"); - if (daggerSessionPort) { - const sessionToken = Deno.env.get("DAGGER_SESSION_TOKEN"); - if (!sessionToken) { - throw new Error( - "DAGGER_SESSION_TOKEN must be set when using DAGGER_SESSION_PORT" - ); - } - - if (config.Workdir && config.Workdir !== "") { - throw new Error( - "cannot configure workdir for existing session (please use --workdir or host.directory with absolute paths instead)" - ); - } + const ctx = new Context(); + const client = new Client({ ctx: ctx }); - client = new Client({ - host: `127.0.0.1:${daggerSessionPort}`, - sessionToken: sessionToken, - }); - } else { - throw new Error("DAGGER_SESSION_PORT must be set"); - } + // Initialize connection + await ctx.connection(); await cb(client).finally(() => { - if (close) { - close(); - } + ctx.close(); }); } diff --git a/sdk/context.ts b/sdk/context.ts new file mode 100644 index 0000000..13b47cf --- /dev/null +++ b/sdk/context.ts @@ -0,0 +1,53 @@ +import { GraphQLClient } from "../deps.ts"; + +import { initDefaultContext } from "./builder.ts"; + +interface ContextConfig { + client?: GraphQLClient; +} + +/** + * Context abstracts the connection to the engine. + * + * It's required to implement the default global SDK. + * Its purpose is to store and returns the connection to the graphQL API, if + * no connection is set, it can create its own. + * + * This is also useful for lazy evaluation with the default global client, + * this one should only run the engine if it actually executes something. + */ +export class Context { + private _client?: GraphQLClient; + + constructor(config?: ContextConfig) { + this._client = config?.client; + } + + /** + * Returns a GraphQL client connected to the engine. + * + * If no client is set, it will create one. + */ + public async connection(): Promise { + if (!this._client) { + const defaultCtx = await initDefaultContext(); + this._client = defaultCtx._client as GraphQLClient; + } + + return this._client; + } + + /** + * Close the connection and the engine if this one was started by the node + * SDK. + */ + public close(): void { + // Reset client, so it can restart a new connection if necessary + this._client = undefined; + } +} + +/** + * Expose a default context for the global client + */ +export const defaultContext = new Context(); diff --git a/sdk/utils.ts b/sdk/utils.ts index 075e278..e779fad 100644 --- a/sdk/utils.ts +++ b/sdk/utils.ts @@ -140,14 +140,7 @@ export function buildQuery(q: QueryTree[]): string { return acc; }, ""); - return `{${query - .replaceAll('"StringKind"', "StringKind") - .replaceAll('"VoidKind"', "VoidKind") - .replaceAll('"IntegerKind"', "IntegerKind") - .replaceAll('"BooleanKind"', "BooleanKind") - .replaceAll('"ObjectKind"', "ObjectKind") - .replaceAll('"ListKind"', "ListKind") - .replaceAll("function_", "function")} }`; + return `{${query} }`; } /** diff --git a/src/dagger/jobs.ts b/src/dagger/jobs.ts index 60cb559..dccf85b 100644 --- a/src/dagger/jobs.ts +++ b/src/dagger/jobs.ts @@ -1,6 +1,4 @@ -import { Directory, Secret } from "../../deps.ts"; -import { Client } from "../../sdk/client.gen.ts"; -import { connect } from "../../sdk/connect.ts"; +import { Directory, Secret, dag } from "../../deps.ts"; import { filterObjectByPrefix, withEnvs, @@ -38,7 +36,6 @@ export async function preview( pulumiVersion = "latest", googleApplicationCredentials?: string ): Promise { - let result = ""; const GOOGLE_APPLICATION_CREDENTIALS = Deno.env.get("GOOGLE_APPLICATION_CREDENTIALS") || googleApplicationCredentials; @@ -46,40 +43,38 @@ export async function preview( const PULUMI_VERSION = Deno.env.get("PULUMI_VERSION") || pulumiVersion; - await connect(async (client: Client) => { - const context = getDirectory(client, src); - const secret = getPulumiAccessToken(client, token); - - if (!secret) { - console.error("PULUMI_ACCESS_TOKEN env var is required"); - Deno.exit(1); - } - - const baseCtr = withEnvs( - client - .pipeline(Job.preview) - .container() - .from(`pulumi/pulumi:${PULUMI_VERSION}`), - envs - ); - const ctr = baseCtr - .withSecretVariable("PULUMI_ACCESS_TOKEN", secret) - .withEnvVariable( - "GOOGLE_APPLICATION_CREDENTIALS", - GOOGLE_APPLICATION_CREDENTIALS || "" - ) - .withMountedCache("/root/.pulumi", client.cacheVolume("pulumi-cache")) - .withMountedCache( - "/app/node_modules", - client.cacheVolume("pulumi-node-modules") - ) - .withDirectory("/app", context, { exclude }) - .withWorkdir("/app") - .withExec(["npm", "install"], { skipEntrypoint: true }) - .withExec(["preview", "--non-interactive", "--stack", PULUMI_STACK]); - - result = await ctr.stdout(); - }); + const context = await getDirectory(dag, src); + const secret = await getPulumiAccessToken(dag, token); + + if (!secret) { + console.error("PULUMI_ACCESS_TOKEN env var is required"); + Deno.exit(1); + } + + const baseCtr = withEnvs( + dag + .pipeline(Job.preview) + .container() + .from(`pulumi/pulumi:${PULUMI_VERSION}`), + envs + ); + const ctr = baseCtr + .withSecretVariable("PULUMI_ACCESS_TOKEN", secret) + .withEnvVariable( + "GOOGLE_APPLICATION_CREDENTIALS", + GOOGLE_APPLICATION_CREDENTIALS || "" + ) + .withMountedCache("/root/.pulumi", dag.cacheVolume("pulumi-cache")) + .withMountedCache( + "/app/node_modules", + dag.cacheVolume("pulumi-node-modules") + ) + .withDirectory("/app", context, { exclude }) + .withWorkdir("/app") + .withExec(["npm", "install"], { skipEntrypoint: true }) + .withExec(["preview", "--non-interactive", "--stack", PULUMI_STACK]); + + const result = await ctr.stdout(); return result; } @@ -100,47 +95,41 @@ export async function up( pulumiVersion = "latest", googleApplicationCredentials?: string ): Promise { - let result = ""; const GOOGLE_APPLICATION_CREDENTIALS = Deno.env.get("GOOGLE_APPLICATION_CREDENTIALS") || googleApplicationCredentials; const PULUMI_STACK = Deno.env.get("PULUMI_STACK") || stack; const PULUMI_VERSION = Deno.env.get("PULUMI_VERSION") || pulumiVersion; - await connect(async (client: Client) => { - const context = getDirectory(client, src); - const secret = getPulumiAccessToken(client, token); - const baseCtr = withEnvs( - client - .pipeline(Job.up) - .container() - .from(`pulumi/pulumi:${PULUMI_VERSION}`), - envs - ); - - if (!secret) { - console.error("PULUMI_ACCESS_TOKEN env var is required"); - Deno.exit(1); - } - - const ctr = baseCtr - .withSecretVariable("PULUMI_ACCESS_TOKEN", secret) - .withEnvVariable( - "GOOGLE_APPLICATION_CREDENTIALS", - GOOGLE_APPLICATION_CREDENTIALS || "" - ) - .withMountedCache("/root/.pulumi", client.cacheVolume("pulumi-cache")) - .withMountedCache( - "/app/node_modules", - client.cacheVolume("pulumi-node-modules") - ) - .withDirectory("/app", context, { exclude }) - .withWorkdir("/app") - .withExec(["npm", "install"], { skipEntrypoint: true }) - .withExec(["up", "--yes", "--non-interactive", "--stack", PULUMI_STACK]); - - result = await ctr.stdout(); - }); + const context = await getDirectory(dag, src); + const secret = await getPulumiAccessToken(dag, token); + const baseCtr = withEnvs( + dag.pipeline(Job.up).container().from(`pulumi/pulumi:${PULUMI_VERSION}`), + envs + ); + + if (!secret) { + console.error("PULUMI_ACCESS_TOKEN env var is required"); + Deno.exit(1); + } + + const ctr = baseCtr + .withSecretVariable("PULUMI_ACCESS_TOKEN", secret) + .withEnvVariable( + "GOOGLE_APPLICATION_CREDENTIALS", + GOOGLE_APPLICATION_CREDENTIALS || "" + ) + .withMountedCache("/root/.pulumi", dag.cacheVolume("pulumi-cache")) + .withMountedCache( + "/app/node_modules", + dag.cacheVolume("pulumi-node-modules") + ) + .withDirectory("/app", context, { exclude }) + .withWorkdir("/app") + .withExec(["npm", "install"], { skipEntrypoint: true }) + .withExec(["up", "--yes", "--non-interactive", "--stack", PULUMI_STACK]); + + const result = await ctr.stdout(); return result; } diff --git a/src/dagger/lib.ts b/src/dagger/lib.ts index f7eb56f..32ea58a 100644 --- a/src/dagger/lib.ts +++ b/src/dagger/lib.ts @@ -2,19 +2,23 @@ import { Container } from "../../deps.ts"; import { Directory, DirectoryID, Secret, SecretID } from "../../deps.ts"; import { Client } from "../../sdk/client.gen.ts"; -export const getDirectory = ( +export const getDirectory = async ( client: Client, src: string | Directory | undefined = "." ) => { - if (typeof src === "string" && src.startsWith("core.Directory")) { - return client.directory({ - id: src as DirectoryID, - }); + if (typeof src === "string") { + try { + const directory = client.loadDirectoryFromID(src as DirectoryID); + await directory.id(); + return directory; + } catch (_) { + return client.host().directory(src); + } } return src instanceof Directory ? src : client.host().directory(src); }; -export const getPulumiAccessToken = ( +export const getPulumiAccessToken = async ( client: Client, token?: string | Secret ) => { @@ -25,10 +29,13 @@ export const getPulumiAccessToken = ( ); } if (token && typeof token === "string") { - if (token.startsWith("core.Secret")) { - return client.loadSecretFromID(token as SecretID); + try { + const secret = client.loadSecretFromID(token as SecretID); + await secret.id(); + return secret; + } catch (_) { + return client.setSecret("PULUMI_ACCESS_TOKEN", token); } - return client.setSecret("PULUMI_ACCESS_TOKEN", token); } if (token && token instanceof Secret) { return token;