Files
languageservices/workflow-parser/src/model/workflow-template.ts
T
eric sciple 656a821a94 ESM migration: Add .js extensions for node16 moduleResolution (#257)
Migrate expressions, workflow-parser, and languageservice packages to use
proper ESM imports with .js extensions that work with node16 moduleResolution.

Changes:
- Update tsconfig.build.json in each package to use module: node16 and
  moduleResolution: node16
- Add .js extensions to all relative import paths (Option B approach)
- Fix yaml internal type imports in workflow-parser by defining local types
- Add skipLibCheck to handle @types/node compatibility issues
- Add TypeScript 5.8.3 override in root package.json
- Add ESM migration plan documentation

The languageserver package is deferred due to test hang issues that need
further investigation.

Related #154 - Upgrade moduleResolution from node to node16 or nodenext
Related #110 - Published ESM code has imports without file extensions
Related #64 - expressions: ERR_MODULE_NOT_FOUND attempting to run example
Related #146 - Can not import @actions/workflow-parser

Test results:
- expressions: 1068 tests passed
- workflow-parser: 292 tests passed
- languageservice: 452 tests passed

* docs: update ESM migration plan with findings

- Update languageserver blocker: vscode-languageserver v8.0.2 lacks ESM
  exports (not a test hang issue)
- Document that Option B (manual .js extensions) was chosen over Option A
  due to ts-jest compatibility issues
- Add workaround for yaml package internal types (LinePos, NodeBase)
- Update migration status table with accurate reason for deferral
- Add skipLibCheck note for @types/node compatibility
2025-12-18 13:35:48 -06:00

204 lines
4.6 KiB
TypeScript

import {
BasicExpressionToken,
MappingToken,
ScalarToken,
SequenceToken,
StringToken,
TemplateToken
} from "../templates/tokens/index.js";
export type WorkflowTemplate = {
events: EventsConfig;
jobs: WorkflowJob[];
concurrency: TemplateToken;
env: TemplateToken;
errors?: {
Message: string;
}[];
};
export type ConcurrencySetting = {
group?: StringToken;
cancelInProgress?: boolean;
};
export type ActionsEnvironmentReference = {
name?: TemplateToken;
url?: TemplateToken;
};
export type WorkflowJob = Job | ReusableWorkflowJob;
export type JobType = "job" | "reusableWorkflowJob";
export type BaseJob = {
type: JobType;
id: StringToken;
name?: ScalarToken;
needs?: StringToken[];
if: BasicExpressionToken;
concurrency?: TemplateToken;
strategy?: TemplateToken;
outputs?: MappingToken;
snapshot?: TemplateToken;
};
// `job-factory` in the schema
export type Job = BaseJob & {
type: "job";
env?: MappingToken;
environment?: TemplateToken;
"runs-on"?: TemplateToken;
container?: TemplateToken;
services?: TemplateToken;
steps: Step[];
};
// `workflow-job` in the schema
export type ReusableWorkflowJob = BaseJob & {
type: "reusableWorkflowJob";
ref: StringToken;
"input-definitions"?: MappingToken;
"input-values"?: MappingToken;
"secret-definitions"?: MappingToken;
"secret-values"?: MappingToken;
"inherit-secrets"?: boolean;
jobs?: WorkflowJob[];
};
export type Container = {
image: StringToken;
credentials?: Credential;
env?: MappingToken;
ports?: SequenceToken;
volumes?: SequenceToken;
options?: StringToken;
};
export type Credential = {
username: StringToken | undefined;
password: StringToken | undefined;
};
export type Step = ActionStep | RunStep;
type BaseStep = {
id: string;
name?: ScalarToken;
if: BasicExpressionToken;
"continue-on-error"?: boolean | ScalarToken;
env?: MappingToken;
};
export type RunStep = BaseStep & {
run: ScalarToken;
};
export type ActionStep = BaseStep & {
uses: StringToken;
};
export type EventsConfig = {
schedule?: ScheduleConfig[];
workflow_dispatch?: WorkflowDispatchConfig;
workflow_call?: WorkflowCallConfig;
// Events that support filters
pull_request?: BranchFilterConfig & PathFilterConfig & TypesFilterConfig;
pull_request_target?: BranchFilterConfig & PathFilterConfig & TypesFilterConfig;
push?: BranchFilterConfig & TagFilterConfig & PathFilterConfig;
workflow_run?: WorkflowFilterConfig & BranchFilterConfig & TypesFilterConfig;
// Events that only support activity types
branch_protection_rule?: TypesFilterConfig;
check_run?: TypesFilterConfig;
check_suite?: TypesFilterConfig;
disccusion?: TypesFilterConfig;
disccusion_comment?: TypesFilterConfig;
issue_comment?: TypesFilterConfig;
issues?: TypesFilterConfig;
label?: TypesFilterConfig;
merge_group?: TypesFilterConfig;
milestone?: TypesFilterConfig;
project?: TypesFilterConfig;
project_card?: TypesFilterConfig;
project_column?: TypesFilterConfig;
pull_request_review?: TypesFilterConfig;
pull_request_review_comment?: TypesFilterConfig;
registry_package?: TypesFilterConfig;
repository_dispatch?: TypesFilterConfig;
release?: TypesFilterConfig;
watch?: TypesFilterConfig;
image_versions?: TypesFilterConfig & VersionsFilterConfig & NamesFilterConfig;
// Index signature to allow easier lookup
[eventName: string]: unknown;
};
export type TypesFilterConfig = {
types?: string[];
};
export type VersionsFilterConfig = {
versions?: string[];
};
export type NamesFilterConfig = {
names?: string[];
};
export type BranchFilterConfig = {
branches?: string[];
"branches-ignore"?: string[];
};
export type TagFilterConfig = {
tags?: string[];
"tags-ignore"?: string[];
};
export type PathFilterConfig = {
paths?: string[];
"paths-ignore"?: string[];
};
export type WorkflowDispatchConfig = {
inputs?: {[inputName: string]: InputConfig};
};
export type WorkflowCallConfig = {
inputs?: {[inputName: string]: InputConfig & {default?: string | boolean | number | ScalarToken}};
secrets?: {[secretName: string]: SecretConfig};
// TODO - these are supported in C# and Go but not in TS yet
// outputs: { [outputName: string]: OutputConfig }
};
export enum InputType {
string = "string",
choice = "choice",
boolean = "boolean",
environment = "environment"
}
export type InputConfig = {
type: InputType;
description?: string;
required?: boolean;
default?: string | boolean | number;
options?: string[];
};
export type SecretConfig = {
description?: string;
required?: boolean;
};
export type ScheduleConfig = {
cron: string;
};
export type WorkflowFilterConfig = {
workflows?: string[];
};