@intentius/chant-lexicon-gitlab 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/package.json +27 -0
  2. package/src/codegen/__snapshots__/snapshot.test.ts.snap +33 -0
  3. package/src/codegen/docs-cli.ts +3 -0
  4. package/src/codegen/docs.ts +962 -0
  5. package/src/codegen/fetch.ts +73 -0
  6. package/src/codegen/generate-cli.ts +41 -0
  7. package/src/codegen/generate-lexicon.ts +53 -0
  8. package/src/codegen/generate-typescript.ts +144 -0
  9. package/src/codegen/generate.ts +166 -0
  10. package/src/codegen/naming.ts +52 -0
  11. package/src/codegen/package.ts +64 -0
  12. package/src/codegen/parse.test.ts +195 -0
  13. package/src/codegen/parse.ts +531 -0
  14. package/src/codegen/patches.test.ts +99 -0
  15. package/src/codegen/patches.ts +100 -0
  16. package/src/codegen/rollback.ts +26 -0
  17. package/src/codegen/snapshot.test.ts +109 -0
  18. package/src/coverage.test.ts +39 -0
  19. package/src/coverage.ts +52 -0
  20. package/src/generated/index.d.ts +248 -0
  21. package/src/generated/index.ts +23 -0
  22. package/src/generated/lexicon-gitlab.json +77 -0
  23. package/src/generated/runtime.ts +4 -0
  24. package/src/import/generator.test.ts +151 -0
  25. package/src/import/generator.ts +173 -0
  26. package/src/import/parser.test.ts +160 -0
  27. package/src/import/parser.ts +282 -0
  28. package/src/import/roundtrip.test.ts +89 -0
  29. package/src/index.ts +25 -0
  30. package/src/intrinsics.test.ts +42 -0
  31. package/src/intrinsics.ts +40 -0
  32. package/src/lint/post-synth/post-synth.test.ts +155 -0
  33. package/src/lint/post-synth/wgl010.ts +41 -0
  34. package/src/lint/post-synth/wgl011.ts +54 -0
  35. package/src/lint/post-synth/yaml-helpers.ts +88 -0
  36. package/src/lint/rules/artifact-no-expiry.ts +62 -0
  37. package/src/lint/rules/deprecated-only-except.ts +53 -0
  38. package/src/lint/rules/index.ts +8 -0
  39. package/src/lint/rules/missing-script.ts +65 -0
  40. package/src/lint/rules/missing-stage.ts +62 -0
  41. package/src/lint/rules/rules.test.ts +146 -0
  42. package/src/lsp/completions.test.ts +85 -0
  43. package/src/lsp/completions.ts +18 -0
  44. package/src/lsp/hover.test.ts +60 -0
  45. package/src/lsp/hover.ts +36 -0
  46. package/src/plugin.test.ts +228 -0
  47. package/src/plugin.ts +380 -0
  48. package/src/serializer.test.ts +309 -0
  49. package/src/serializer.ts +226 -0
  50. package/src/testdata/ci-schema-fixture.json +2184 -0
  51. package/src/testdata/create-fixture.ts +46 -0
  52. package/src/testdata/load-fixtures.ts +23 -0
  53. package/src/validate-cli.ts +19 -0
  54. package/src/validate.test.ts +43 -0
  55. package/src/validate.ts +125 -0
  56. package/src/variables.ts +27 -0
@@ -0,0 +1,73 @@
1
+ /**
2
+ * GitLab CI schema fetching — downloads the CI JSON Schema
3
+ * and caches it locally.
4
+ */
5
+
6
+ import { join } from "path";
7
+ import { homedir } from "os";
8
+ import { fetchWithCache, clearCacheFile } from "@intentius/chant/codegen/fetch";
9
+
10
+ /**
11
+ * Pinned schema version — a GitLab release tag that produces a known-good
12
+ * schema. Override at runtime with `--schema-version <tag>` in generate-cli
13
+ * or by setting `schemaVersion` in the generate options.
14
+ *
15
+ * Using a tag (e.g. "v17.8.1-ee") rather than `master` ensures reproducible
16
+ * codegen across environments and CI runs.
17
+ */
18
+ export const GITLAB_SCHEMA_VERSION = "v17.8.1-ee";
19
+
20
+ /**
21
+ * Build the schema URL for a given version ref.
22
+ */
23
+ function schemaUrl(version: string): string {
24
+ return `https://gitlab.com/gitlab-org/gitlab/-/raw/${version}/app/assets/javascripts/editor/schema/ci.json`;
25
+ }
26
+
27
+ /**
28
+ * Get the cache file path for the CI schema.
29
+ */
30
+ export function getCachePath(): string {
31
+ return join(homedir(), ".chant", "gitlab-ci-schema.json");
32
+ }
33
+
34
+ /**
35
+ * Fetch the GitLab CI JSON Schema, returning the raw JSON buffer.
36
+ * Uses local file caching with 24-hour TTL.
37
+ *
38
+ * @param force Bypass cache and download fresh.
39
+ * @param version GitLab ref (tag, branch, or SHA) to fetch from.
40
+ * Defaults to {@link GITLAB_SCHEMA_VERSION}.
41
+ */
42
+ export async function fetchCISchema(force?: boolean, version?: string): Promise<Buffer> {
43
+ const ref = version ?? GITLAB_SCHEMA_VERSION;
44
+ return fetchWithCache(
45
+ {
46
+ url: schemaUrl(ref),
47
+ cacheFile: getCachePath(),
48
+ },
49
+ force,
50
+ );
51
+ }
52
+
53
+ /**
54
+ * Fetch the CI schema and return it as a Map<typeName, Buffer>
55
+ * compatible with the generatePipeline fetchSchemas callback.
56
+ *
57
+ * The CI schema is a single document, so we return a single entry
58
+ * keyed by "GitLab::CI::Pipeline" — the parse step will split it
59
+ * into multiple entities.
60
+ */
61
+ export async function fetchSchemas(force?: boolean, version?: string): Promise<Map<string, Buffer>> {
62
+ const data = await fetchCISchema(force, version);
63
+ const schemas = new Map<string, Buffer>();
64
+ schemas.set("GitLab::CI::Pipeline", data);
65
+ return schemas;
66
+ }
67
+
68
+ /**
69
+ * Clear the cached schema file.
70
+ */
71
+ export function clearCache(): void {
72
+ clearCacheFile(getCachePath());
73
+ }
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * CLI entry point for GitLab CI lexicon generation.
4
+ */
5
+
6
+ import { dirname } from "path";
7
+ import { fileURLToPath } from "url";
8
+ import { generate, writeGeneratedFiles } from "./generate";
9
+ import { GITLAB_SCHEMA_VERSION } from "./fetch";
10
+
11
+ const pkgDir = dirname(dirname(dirname(fileURLToPath(import.meta.url))));
12
+
13
+ async function main() {
14
+ const verbose = process.argv.includes("--verbose") || process.argv.includes("-v");
15
+ const force = process.argv.includes("--force") || process.argv.includes("-f");
16
+
17
+ // Parse --schema-version <ref>
18
+ const versionIdx = process.argv.indexOf("--schema-version");
19
+ const schemaVersion = versionIdx !== -1 ? process.argv[versionIdx + 1] : undefined;
20
+
21
+ console.error(`Generating GitLab CI lexicon (schema: ${schemaVersion ?? GITLAB_SCHEMA_VERSION})...`);
22
+
23
+ const result = await generate({ verbose, force, schemaVersion });
24
+ writeGeneratedFiles(result, pkgDir);
25
+
26
+ console.error(
27
+ `Generated ${result.resources} entities, ${result.properties} property types, ${result.enums} enums`,
28
+ );
29
+
30
+ if (result.warnings.length > 0) {
31
+ console.error(`${result.warnings.length} warnings:`);
32
+ for (const w of result.warnings) {
33
+ console.error(` ${w.file}: ${w.error}`);
34
+ }
35
+ }
36
+ }
37
+
38
+ main().catch((err) => {
39
+ console.error("Generation failed:", err);
40
+ process.exit(1);
41
+ });
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Lexicon JSON generator — produces lexicon-gitlab.json with metadata
3
+ * for all GitLab CI entities.
4
+ */
5
+
6
+ import type { GitLabParseResult } from "./parse";
7
+ import { gitlabShortName } from "./parse";
8
+ import type { NamingStrategy } from "./naming";
9
+ import {
10
+ buildRegistry,
11
+ serializeRegistry,
12
+ type RegistryResource,
13
+ } from "@intentius/chant/codegen/generate-registry";
14
+
15
+ export interface LexiconEntry {
16
+ resourceType: string;
17
+ kind: "resource" | "property";
18
+ lexicon: "gitlab";
19
+ }
20
+
21
+ /**
22
+ * Generate the lexicon-gitlab.json content.
23
+ */
24
+ export function generateLexiconJSON(
25
+ results: GitLabParseResult[],
26
+ naming: NamingStrategy,
27
+ ): string {
28
+ const registryResources: RegistryResource[] = results.map((r) => ({
29
+ typeName: r.resource.typeName,
30
+ attributes: r.resource.attributes,
31
+ properties: r.resource.properties,
32
+ propertyTypes: r.propertyTypes.map((pt) => ({ name: pt.name, cfnType: pt.defType })),
33
+ }));
34
+
35
+ const entries = buildRegistry<LexiconEntry>(registryResources, naming, {
36
+ shortName: gitlabShortName,
37
+ buildEntry: (resource, _tsName, _attrs, _propConstraints) => {
38
+ const r = results.find((res) => res.resource.typeName === resource.typeName);
39
+ return {
40
+ resourceType: resource.typeName,
41
+ kind: (r?.isProperty ? "property" : "resource") as "resource" | "property",
42
+ lexicon: "gitlab" as const,
43
+ };
44
+ },
45
+ buildPropertyEntry: (resourceType, propertyType) => ({
46
+ resourceType: `${resourceType}.${propertyType}`,
47
+ kind: "property" as const,
48
+ lexicon: "gitlab" as const,
49
+ }),
50
+ });
51
+
52
+ return serializeRegistry(entries);
53
+ }
@@ -0,0 +1,144 @@
1
+ /**
2
+ * TypeScript declaration file generator — produces index.d.ts with all
3
+ * GitLab CI entity classes.
4
+ */
5
+
6
+ import type { GitLabParseResult } from "./parse";
7
+ import { gitlabShortName } from "./parse";
8
+ import type { NamingStrategy } from "./naming";
9
+ import { propertyTypeName, extractDefName } from "./naming";
10
+ import {
11
+ writeResourceClass,
12
+ writePropertyClass,
13
+ writeEnumType,
14
+ type DtsProperty,
15
+ type DtsAttribute,
16
+ } from "@intentius/chant/codegen/generate-typescript";
17
+
18
+ interface ResourceEntry {
19
+ tsName: string;
20
+ properties: DtsProperty[];
21
+ attributes: DtsAttribute[];
22
+ remap: Map<string, string>;
23
+ }
24
+
25
+ interface EnumEntry {
26
+ tsName: string;
27
+ values: string[];
28
+ }
29
+
30
+ /**
31
+ * Generate the complete .d.ts file content.
32
+ */
33
+ export function generateTypeScriptDeclarations(
34
+ results: GitLabParseResult[],
35
+ naming: NamingStrategy,
36
+ ): string {
37
+ const lines: string[] = [];
38
+ lines.push("// Code generated by chant gitlab generate. DO NOT EDIT.");
39
+
40
+ const resources: ResourceEntry[] = [];
41
+ const enums: EnumEntry[] = [];
42
+
43
+ for (const r of results) {
44
+ const typeName = r.resource.typeName;
45
+ const tsName = naming.resolve(typeName);
46
+ if (!tsName) continue;
47
+
48
+ const shortName = gitlabShortName(typeName);
49
+ const remap = new Map<string, string>();
50
+ for (const pt of r.propertyTypes) {
51
+ const defName = extractDefName(pt.name, shortName);
52
+ remap.set(pt.name, propertyTypeName(tsName, defName));
53
+ }
54
+ for (const e of r.enums) {
55
+ const defName = extractDefName(e.name, shortName);
56
+ remap.set(e.name, propertyTypeName(tsName, defName));
57
+ }
58
+
59
+ const dtsProps: DtsProperty[] = r.resource.properties.map((p) => ({
60
+ name: p.name,
61
+ type: p.tsType,
62
+ required: p.required,
63
+ description: p.description,
64
+ }));
65
+ const dtsAttrs: DtsAttribute[] = r.resource.attributes.map((a) => ({
66
+ name: a.name,
67
+ type: a.tsType,
68
+ }));
69
+
70
+ resources.push({ tsName, properties: dtsProps, attributes: dtsAttrs, remap });
71
+
72
+ for (const alias of naming.aliases(typeName)) {
73
+ resources.push({ tsName: alias, properties: dtsProps, attributes: dtsAttrs, remap });
74
+ }
75
+
76
+ for (const e of r.enums) {
77
+ const defName = extractDefName(e.name, shortName);
78
+ const eName = propertyTypeName(tsName, defName);
79
+ enums.push({ tsName: eName, values: e.values });
80
+ }
81
+ }
82
+
83
+ // Sort alphabetically
84
+ resources.sort((a, b) => a.tsName.localeCompare(b.tsName));
85
+ enums.sort((a, b) => a.tsName.localeCompare(b.tsName));
86
+
87
+ // Resource classes (all CI entities use writeResourceClass since they're
88
+ // all top-level — the "property" distinction is only in the registry)
89
+ lines.push("");
90
+ lines.push("// --- CI Entity classes ---");
91
+ for (const re of resources) {
92
+ writeResourceClass(lines, re.tsName, re.properties, re.attributes, re.remap);
93
+ }
94
+
95
+ // Enum types
96
+ if (enums.length > 0) {
97
+ lines.push("");
98
+ lines.push("// --- Enum types ---");
99
+ for (const ee of enums) {
100
+ writeEnumType(lines, ee.tsName, ee.values);
101
+ }
102
+ }
103
+
104
+ // Static content
105
+ lines.push("");
106
+ lines.push(staticTypeScript());
107
+ lines.push("");
108
+
109
+ return lines.join("\n");
110
+ }
111
+
112
+ function staticTypeScript(): string {
113
+ const lines: string[] = [];
114
+
115
+ lines.push("// --- CI/CD Variables ---");
116
+ lines.push("");
117
+ lines.push("export declare const CI: {");
118
+ const ciVars = [
119
+ "CommitBranch",
120
+ "CommitRef",
121
+ "CommitSha",
122
+ "CommitTag",
123
+ "DefaultBranch",
124
+ "Environment",
125
+ "JobId",
126
+ "JobName",
127
+ "JobStage",
128
+ "MergeRequestIid",
129
+ "PipelineId",
130
+ "PipelineSource",
131
+ "ProjectDir",
132
+ "ProjectId",
133
+ "ProjectName",
134
+ "ProjectPath",
135
+ "Registry",
136
+ "RegistryImage",
137
+ ];
138
+ for (const v of ciVars) {
139
+ lines.push(` readonly ${v}: string;`);
140
+ }
141
+ lines.push("};");
142
+
143
+ return lines.join("\n");
144
+ }
@@ -0,0 +1,166 @@
1
+ /**
2
+ * GitLab CI generation pipeline — uses core generatePipeline
3
+ * with GitLab-specific fetch, parse, naming, and generation callbacks.
4
+ */
5
+
6
+ import { join } from "path";
7
+ import {
8
+ generatePipeline,
9
+ writeGeneratedArtifacts,
10
+ type GenerateOptions,
11
+ type GenerateResult,
12
+ type GeneratePipelineConfig,
13
+ } from "@intentius/chant/codegen/generate";
14
+ import { fetchSchemas } from "./fetch";
15
+ import { parseCISchema, type GitLabParseResult } from "./parse";
16
+ import { NamingStrategy, propertyTypeName, extractDefName } from "./naming";
17
+ import { gitlabShortName } from "./parse";
18
+ import { generateLexiconJSON } from "./generate-lexicon";
19
+ import { generateTypeScriptDeclarations } from "./generate-typescript";
20
+ import {
21
+ generateRuntimeIndex as coreGenerateRuntimeIndex,
22
+ type RuntimeIndexEntry,
23
+ type RuntimeIndexPropertyEntry,
24
+ } from "@intentius/chant/codegen/generate-runtime-index";
25
+
26
+ export type { GenerateResult };
27
+
28
+ export interface GitLabGenerateOptions extends GenerateOptions {
29
+ /** GitLab ref (tag, branch, or SHA) to fetch the schema from. */
30
+ schemaVersion?: string;
31
+ }
32
+
33
+ // Captured from generate() call so the pipeline config can access it
34
+ let activeSchemaVersion: string | undefined;
35
+
36
+ const gitlabPipelineConfig: GeneratePipelineConfig<GitLabParseResult> = {
37
+ fetchSchemas: async (opts) => {
38
+ return fetchSchemas(opts.force, activeSchemaVersion);
39
+ },
40
+
41
+ parseSchema: (_typeName, data) => {
42
+ // The CI schema is a single document — parseCISchema returns multiple results.
43
+ // The pipeline calls this once per schema entry. We return the first result
44
+ // and use augmentResults to inject the rest.
45
+ const results = parseCISchema(data);
46
+ if (results.length === 0) return null;
47
+ // Return the first result; stash the rest for augmentResults
48
+ pendingResults = results.slice(1);
49
+ return results[0];
50
+ },
51
+
52
+ createNaming: (results) => new NamingStrategy(results),
53
+
54
+ augmentResults: (results, _opts, log) => {
55
+ // Add the remaining results from the single-schema parse
56
+ if (pendingResults.length > 0) {
57
+ results.push(...pendingResults);
58
+ log(`Added ${pendingResults.length} additional CI entities from single schema`);
59
+ pendingResults = [];
60
+ }
61
+ log(`Total: ${results.length} CI entity schemas`);
62
+ return { results };
63
+ },
64
+
65
+ generateRegistry: (results, naming) => {
66
+ return generateLexiconJSON(results, naming as NamingStrategy);
67
+ },
68
+
69
+ generateTypes: (results, naming) => {
70
+ return generateTypeScriptDeclarations(results, naming as NamingStrategy);
71
+ },
72
+
73
+ generateRuntimeIndex: (results, naming) => {
74
+ return generateRuntimeIndex(results, naming as NamingStrategy);
75
+ },
76
+ };
77
+
78
+ // Shared state between parseSchema and augmentResults
79
+ let pendingResults: GitLabParseResult[] = [];
80
+
81
+ /**
82
+ * Run the full GitLab generation pipeline.
83
+ */
84
+ export async function generate(opts: GitLabGenerateOptions = {}): Promise<GenerateResult> {
85
+ pendingResults = [];
86
+ activeSchemaVersion = opts.schemaVersion;
87
+ return generatePipeline(gitlabPipelineConfig, opts);
88
+ }
89
+
90
+ /**
91
+ * Write generated artifacts to disk.
92
+ */
93
+ export function writeGeneratedFiles(result: GenerateResult, baseDir: string): void {
94
+ writeGeneratedArtifacts({
95
+ baseDir,
96
+ files: {
97
+ "lexicon-gitlab.json": result.lexiconJSON,
98
+ "index.d.ts": result.typesDTS,
99
+ "index.ts": result.indexTS,
100
+ "runtime.ts": `/**\n * Runtime factory constructors — re-exported from core.\n */\nexport { createResource, createProperty } from "@intentius/chant/runtime";\n`,
101
+ },
102
+ });
103
+ }
104
+
105
+ /**
106
+ * Generate the runtime index.ts with factory constructor exports.
107
+ */
108
+ function generateRuntimeIndex(
109
+ results: GitLabParseResult[],
110
+ naming: NamingStrategy,
111
+ ): string {
112
+ const resourceEntries: RuntimeIndexEntry[] = [];
113
+ const propertyEntries: RuntimeIndexPropertyEntry[] = [];
114
+
115
+ for (const r of results) {
116
+ const typeName = r.resource.typeName;
117
+ const tsName = naming.resolve(typeName);
118
+ if (!tsName) continue;
119
+
120
+ // CI entities have no read-only attributes
121
+ const attrs: Record<string, string> = {};
122
+
123
+ if (r.isProperty) {
124
+ // Property-kind entities (Artifacts, Cache, Image, etc.)
125
+ propertyEntries.push({ tsName, resourceType: typeName });
126
+ for (const alias of naming.aliases(typeName)) {
127
+ propertyEntries.push({ tsName: alias, resourceType: typeName });
128
+ }
129
+ } else {
130
+ // Resource-kind entities (Job, Default, Workflow)
131
+ resourceEntries.push({ tsName, resourceType: typeName, attrs });
132
+ for (const alias of naming.aliases(typeName)) {
133
+ resourceEntries.push({ tsName: alias, resourceType: typeName, attrs });
134
+ }
135
+ }
136
+
137
+ // Property types
138
+ const shortName = gitlabShortName(typeName);
139
+ const ptAliases = naming.propertyTypeAliases(typeName);
140
+ for (const pt of r.propertyTypes) {
141
+ const defName = extractDefName(pt.name, shortName);
142
+ const ptName = propertyTypeName(tsName, defName);
143
+ const ptType = `${typeName}.${pt.defType}`;
144
+ propertyEntries.push({ tsName: ptName, resourceType: ptType });
145
+
146
+ if (ptAliases) {
147
+ const aliasName = ptAliases.get(defName);
148
+ if (aliasName) {
149
+ propertyEntries.push({ tsName: aliasName, resourceType: ptType });
150
+ }
151
+ }
152
+ }
153
+ }
154
+
155
+ return coreGenerateRuntimeIndex(resourceEntries, propertyEntries, {
156
+ lexiconName: "gitlab",
157
+ intrinsicReExports: {
158
+ names: ["reference"],
159
+ from: "../intrinsics",
160
+ },
161
+ pseudoReExports: {
162
+ names: ["CI"],
163
+ from: "../variables",
164
+ },
165
+ });
166
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * GitLab CI naming strategy — simpler than AWS since CI entities
3
+ * use a flat GitLab::CI:: namespace with few collisions.
4
+ */
5
+
6
+ import {
7
+ NamingStrategy as CoreNamingStrategy,
8
+ type NamingConfig,
9
+ type NamingInput,
10
+ } from "@intentius/chant/codegen/naming";
11
+ import { gitlabShortName, gitlabServiceName, type GitLabParseResult } from "./parse";
12
+
13
+ export { propertyTypeName, extractDefName } from "@intentius/chant/codegen/naming";
14
+
15
+ const gitlabNamingConfig: NamingConfig = {
16
+ priorityNames: {
17
+ "GitLab::CI::Job": "Job",
18
+ "GitLab::CI::Default": "Default",
19
+ "GitLab::CI::Workflow": "Workflow",
20
+ "GitLab::CI::Artifacts": "Artifacts",
21
+ "GitLab::CI::Cache": "Cache",
22
+ "GitLab::CI::Image": "Image",
23
+ "GitLab::CI::Rule": "Rule",
24
+ "GitLab::CI::Retry": "Retry",
25
+ "GitLab::CI::AllowFailure": "AllowFailure",
26
+ "GitLab::CI::Parallel": "Parallel",
27
+ "GitLab::CI::Include": "Include",
28
+ "GitLab::CI::Release": "Release",
29
+ "GitLab::CI::Environment": "Environment",
30
+ "GitLab::CI::Trigger": "Trigger",
31
+ "GitLab::CI::AutoCancel": "AutoCancel",
32
+ },
33
+ priorityAliases: {},
34
+ priorityPropertyAliases: {},
35
+ serviceAbbreviations: {},
36
+ shortName: gitlabShortName,
37
+ serviceName: gitlabServiceName,
38
+ };
39
+
40
+ /**
41
+ * GitLab-specific naming strategy.
42
+ * Extends core NamingStrategy with GitLab naming config.
43
+ */
44
+ export class NamingStrategy extends CoreNamingStrategy {
45
+ constructor(results: GitLabParseResult[]) {
46
+ const inputs: NamingInput[] = results.map((r) => ({
47
+ typeName: r.resource.typeName,
48
+ propertyTypes: r.propertyTypes,
49
+ }));
50
+ super(inputs, gitlabNamingConfig);
51
+ }
52
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * GitLab lexicon packaging — delegates to core packagePipeline
3
+ * with GitLab-specific manifest building and skill collection.
4
+ */
5
+
6
+ import { readFileSync } from "fs";
7
+ import { join, dirname } from "path";
8
+ import { fileURLToPath } from "url";
9
+ import type { IntrinsicDef } from "@intentius/chant/lexicon";
10
+ import {
11
+ packagePipeline,
12
+ collectSkills,
13
+ type PackageOptions,
14
+ type PackageResult,
15
+ } from "@intentius/chant/codegen/package";
16
+ import { generate } from "./generate";
17
+
18
+ export type { PackageOptions, PackageResult };
19
+
20
+ const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
21
+
22
+ /**
23
+ * Package the GitLab lexicon into a distributable BundleSpec.
24
+ */
25
+ export async function packageLexicon(opts: PackageOptions = {}): Promise<PackageResult> {
26
+ const pkgJson = JSON.parse(readFileSync(join(pkgDir, "..", "package.json"), "utf-8"));
27
+
28
+ return packagePipeline(
29
+ {
30
+ generate: (genOpts) => generate({ verbose: genOpts.verbose, force: genOpts.force }),
31
+
32
+ buildManifest: (_genResult) => {
33
+ const intrinsics: IntrinsicDef[] = [
34
+ {
35
+ name: "reference",
36
+ description: "!reference tag — reference another job's properties",
37
+ outputKey: "!reference",
38
+ isTag: true,
39
+ },
40
+ ];
41
+
42
+ return {
43
+ name: "gitlab",
44
+ version: pkgJson.version ?? "0.0.0",
45
+ chantVersion: ">=0.1.0",
46
+ namespace: "GitLab",
47
+ intrinsics,
48
+ pseudoParameters: {},
49
+ };
50
+ },
51
+
52
+ srcDir: pkgDir,
53
+
54
+ collectSkills: () => {
55
+ const { gitlabPlugin } = require("../plugin");
56
+ const skillDefs = gitlabPlugin.skills?.() ?? [];
57
+ return collectSkills(skillDefs);
58
+ },
59
+
60
+ version: pkgJson.version ?? "0.0.0",
61
+ },
62
+ opts,
63
+ );
64
+ }