linmux 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +240 -0
- package/bin/run.js +4 -0
- package/dist/commands/comment/create.js +94 -0
- package/dist/commands/comment/delete.js +74 -0
- package/dist/commands/comment/list.js +84 -0
- package/dist/commands/comment/update.js +80 -0
- package/dist/commands/cycle/current.js +78 -0
- package/dist/commands/cycle/list.js +84 -0
- package/dist/commands/cycle/move.js +91 -0
- package/dist/commands/describe.js +65 -0
- package/dist/commands/graphql/index.js +92 -0
- package/dist/commands/install-skill.js +54 -0
- package/dist/commands/issue/archive.js +75 -0
- package/dist/commands/issue/create.js +115 -0
- package/dist/commands/issue/get.js +84 -0
- package/dist/commands/issue/list.js +93 -0
- package/dist/commands/issue/purge.js +81 -0
- package/dist/commands/issue/search.js +109 -0
- package/dist/commands/issue/transition.js +91 -0
- package/dist/commands/issue/trash.js +75 -0
- package/dist/commands/issue/update.js +126 -0
- package/dist/commands/label/create.js +91 -0
- package/dist/commands/label/list.js +76 -0
- package/dist/commands/list-tools.js +47 -0
- package/dist/commands/me.js +71 -0
- package/dist/commands/project/create.js +101 -0
- package/dist/commands/project/get.js +83 -0
- package/dist/commands/project/list.js +75 -0
- package/dist/commands/project/update-status.js +99 -0
- package/dist/commands/project/update.js +99 -0
- package/dist/commands/raw/batch.js +85 -0
- package/dist/commands/raw/index.js +72 -0
- package/dist/commands/schema.js +69 -0
- package/dist/commands/state/list.js +77 -0
- package/dist/commands/team/get.js +73 -0
- package/dist/commands/team/list.js +73 -0
- package/dist/commands/whoami.js +71 -0
- package/dist/commands/workspace/add.js +97 -0
- package/dist/commands/workspace/list.js +47 -0
- package/dist/commands/workspace/remove.js +63 -0
- package/dist/commands/workspace/replace-token.js +89 -0
- package/dist/commands/workspace/use.js +54 -0
- package/dist/core/client/factory.js +28 -0
- package/dist/core/client/index.js +2 -0
- package/dist/core/config/index.js +4 -0
- package/dist/core/config/paths.js +30 -0
- package/dist/core/config/schema.js +36 -0
- package/dist/core/config/store.js +149 -0
- package/dist/core/errors/error.js +142 -0
- package/dist/core/errors/exit-codes.js +70 -0
- package/dist/core/output/envelope.js +53 -0
- package/dist/core/output/format.js +42 -0
- package/dist/core/output/index.js +3 -0
- package/dist/core/pagination/flags.js +29 -0
- package/dist/core/pagination/index.js +2 -0
- package/dist/core/projection/presets.js +116 -0
- package/dist/core/projection/project.js +282 -0
- package/dist/core/redact/redact.js +45 -0
- package/dist/core/resolvers/cycle.js +60 -0
- package/dist/core/resolvers/index.js +7 -0
- package/dist/core/resolvers/label.js +54 -0
- package/dist/core/resolvers/project-status.js +42 -0
- package/dist/core/resolvers/project.js +43 -0
- package/dist/core/resolvers/state.js +46 -0
- package/dist/core/resolvers/team.js +50 -0
- package/dist/core/transport/fetch-interceptor.js +109 -0
- package/dist/core/transport/index.js +3 -0
- package/dist/core/transport/rate-limit.js +167 -0
- package/dist/core/workspace/resolver.js +70 -0
- package/dist/core/workspace/write-guard.js +43 -0
- package/dist/generated/graphql.js +89428 -0
- package/dist/generated/operations.js +3013 -0
- package/dist/lib/comment-create-runtime.js +96 -0
- package/dist/lib/comment-delete-runtime.js +46 -0
- package/dist/lib/comment-list-runtime.js +182 -0
- package/dist/lib/comment-update-runtime.js +93 -0
- package/dist/lib/cycle-current-runtime.js +90 -0
- package/dist/lib/cycle-list-runtime.js +151 -0
- package/dist/lib/cycle-move-runtime.js +142 -0
- package/dist/lib/describe-runtime.js +180 -0
- package/dist/lib/filter-heuristics.js +59 -0
- package/dist/lib/graphql-runtime.js +202 -0
- package/dist/lib/include-fragments.js +73 -0
- package/dist/lib/install-skill-runtime.js +228 -0
- package/dist/lib/introspection-registry.js +488 -0
- package/dist/lib/issue-archive-runtime.js +89 -0
- package/dist/lib/issue-create-runtime.js +175 -0
- package/dist/lib/issue-get-runtime.js +153 -0
- package/dist/lib/issue-list-runtime.js +164 -0
- package/dist/lib/issue-purge-runtime.js +89 -0
- package/dist/lib/issue-search-runtime.js +114 -0
- package/dist/lib/issue-transition-runtime.js +131 -0
- package/dist/lib/issue-trash-runtime.js +84 -0
- package/dist/lib/issue-update-runtime.js +164 -0
- package/dist/lib/label-create-runtime.js +113 -0
- package/dist/lib/label-list-runtime.js +97 -0
- package/dist/lib/levenshtein.js +42 -0
- package/dist/lib/list-tools-runtime.js +38 -0
- package/dist/lib/me-runtime.js +55 -0
- package/dist/lib/project-create-runtime.js +103 -0
- package/dist/lib/project-get-runtime.js +134 -0
- package/dist/lib/project-list-runtime.js +84 -0
- package/dist/lib/project-update-runtime.js +110 -0
- package/dist/lib/project-update-status-runtime.js +91 -0
- package/dist/lib/raw-batch-runtime.js +229 -0
- package/dist/lib/raw-runtime.js +171 -0
- package/dist/lib/schema-loader.js +41 -0
- package/dist/lib/schema-runtime.js +65 -0
- package/dist/lib/state-list-runtime.js +93 -0
- package/dist/lib/team-get-runtime.js +55 -0
- package/dist/lib/team-list-runtime.js +52 -0
- package/dist/lib/workspace-runtime.js +112 -0
- package/dist/operations/_registry.zod.js +5337 -0
- package/oclif.manifest.json +3631 -0
- package/package.json +99 -0
- package/schema.graphql +30772 -0
- package/skills/linmux/SKILL.md +186 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { BASE_FLAGS, runCommand } from "../../lib/workspace-runtime.js";
|
|
2
|
+
import { runRawBatch } from "../../lib/raw-batch-runtime.js";
|
|
3
|
+
import { Command, Flags } from "@oclif/core";
|
|
4
|
+
//#region src/commands/raw/batch.ts
|
|
5
|
+
/**
|
|
6
|
+
* `linmux raw batch --plan=@file.json` — Phase 3 PLAN 03-05, RAW-05.
|
|
7
|
+
*
|
|
8
|
+
* Safety-gated batch dispatcher. Defaults to --dry-run; requires --yes to execute.
|
|
9
|
+
* Implementation lives in `src/lib/raw-batch-runtime.ts` (two-export pattern S1).
|
|
10
|
+
*
|
|
11
|
+
* This file exports BOTH:
|
|
12
|
+
* - Named `runRawBatch` re-export (for tests + future programmatic use)
|
|
13
|
+
* - Default `RawBatchCommand` oclif class
|
|
14
|
+
*
|
|
15
|
+
* Gate ordering (enforced in runtime):
|
|
16
|
+
* Plan validation → WSP-06 (if mutations) → --allow-mutations → dry-run/yes intent
|
|
17
|
+
*
|
|
18
|
+
* oclif resolves `src/commands/raw/batch.ts` → `linmux raw batch` automatically
|
|
19
|
+
* via topic-tree convention.
|
|
20
|
+
*/
|
|
21
|
+
var RawBatchCommand = class RawBatchCommand extends Command {
|
|
22
|
+
static description = "Execute a batch of registry operations from a JSON plan file. Default dry-run; --yes required to execute.";
|
|
23
|
+
static examples = [
|
|
24
|
+
"<%= config.bin %> raw batch --plan=@./plan.json",
|
|
25
|
+
"<%= config.bin %> raw batch --plan=@./plan.json --workspace acme --allow-mutations --yes",
|
|
26
|
+
"<%= config.bin %> raw batch --plan=@./plan.json --no-dry-run --yes --workspace acme --allow-mutations"
|
|
27
|
+
];
|
|
28
|
+
static enableJsonFlag = true;
|
|
29
|
+
static flags = {
|
|
30
|
+
...BASE_FLAGS,
|
|
31
|
+
workspace: Flags.string({ description: "Workspace name override (precedence over LINEAR_WORKSPACE env / active default)" }),
|
|
32
|
+
"allow-active-workspace-write": Flags.boolean({
|
|
33
|
+
default: false,
|
|
34
|
+
description: "Permit mutations against the active workspace without an explicit --workspace selector (WSP-06 opt-in)"
|
|
35
|
+
}),
|
|
36
|
+
"allow-mutations": Flags.boolean({
|
|
37
|
+
default: false,
|
|
38
|
+
description: "Required for plans containing mutation operations — explicit safety gate"
|
|
39
|
+
}),
|
|
40
|
+
plan: Flags.string({
|
|
41
|
+
required: true,
|
|
42
|
+
description: "Plan file path as @file.json (e.g. --plan=@./plan.json)"
|
|
43
|
+
}),
|
|
44
|
+
"dry-run": Flags.boolean({
|
|
45
|
+
default: true,
|
|
46
|
+
allowNo: true,
|
|
47
|
+
description: "Print planned operations without executing (default true). Pass --no-dry-run --yes to execute."
|
|
48
|
+
}),
|
|
49
|
+
yes: Flags.boolean({
|
|
50
|
+
default: false,
|
|
51
|
+
description: "Confirm execution. Required when --no-dry-run is passed."
|
|
52
|
+
})
|
|
53
|
+
};
|
|
54
|
+
async run() {
|
|
55
|
+
const { flags } = await this.parse(RawBatchCommand);
|
|
56
|
+
const batchFlags = {
|
|
57
|
+
plan: flags.plan,
|
|
58
|
+
pretty: flags.pretty,
|
|
59
|
+
"dry-run": flags["dry-run"],
|
|
60
|
+
yes: flags.yes,
|
|
61
|
+
"allow-mutations": flags["allow-mutations"],
|
|
62
|
+
"allow-active-workspace-write": flags["allow-active-workspace-write"]
|
|
63
|
+
};
|
|
64
|
+
if (flags.workspace !== void 0) batchFlags.workspace = flags.workspace;
|
|
65
|
+
const runArgs = {
|
|
66
|
+
commandPath: "raw batch",
|
|
67
|
+
pretty: flags.pretty ?? false,
|
|
68
|
+
handler: (retryOpts) => runRawBatch({
|
|
69
|
+
flags: batchFlags,
|
|
70
|
+
env: process.env,
|
|
71
|
+
retryOptsOverride: retryOpts
|
|
72
|
+
})
|
|
73
|
+
};
|
|
74
|
+
if (flags.quiet !== void 0) runArgs.quiet = flags.quiet;
|
|
75
|
+
if (flags.noMeta !== void 0) runArgs.noMeta = flags.noMeta;
|
|
76
|
+
if (flags.retry !== void 0) runArgs.retry = flags.retry;
|
|
77
|
+
const out = await runCommand(runArgs);
|
|
78
|
+
if (!flags.json) process.stdout.write(out.stdout);
|
|
79
|
+
if (out.stderr) process.stderr.write(out.stderr);
|
|
80
|
+
if (out.exitCode !== 0) process.exitCode = out.exitCode;
|
|
81
|
+
return JSON.parse(out.stdout);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
//#endregion
|
|
85
|
+
export { RawBatchCommand as default, runRawBatch };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { BASE_FLAGS, runCommand } from "../../lib/workspace-runtime.js";
|
|
2
|
+
import { runRaw } from "../../lib/raw-runtime.js";
|
|
3
|
+
import { Args, Command, Flags } from "@oclif/core";
|
|
4
|
+
//#region src/commands/raw/index.ts
|
|
5
|
+
/**
|
|
6
|
+
* `linmux raw <Operation>` — Phase 3 PLAN 03-02.
|
|
7
|
+
*
|
|
8
|
+
* Dispatches any operation in the generated GraphQL registry.
|
|
9
|
+
* Implementation lives in `src/lib/raw-runtime.ts` (two-export pattern S1 —
|
|
10
|
+
* analog: `src/commands/issue/transition.ts:19-95`).
|
|
11
|
+
*
|
|
12
|
+
* This file exports BOTH:
|
|
13
|
+
* - Named `runRaw` re-export (for tests + future programmatic use)
|
|
14
|
+
* - Default `RawCommand` oclif class
|
|
15
|
+
*
|
|
16
|
+
* Gate ordering (enforced in runtime):
|
|
17
|
+
* WSP-06 (workspace selector) BEFORE --allow-mutations BEFORE dispatch.
|
|
18
|
+
*/
|
|
19
|
+
var RawCommand = class RawCommand extends Command {
|
|
20
|
+
static description = "Dispatch any operation in the generated GraphQL registry (501 ops).";
|
|
21
|
+
static examples = [
|
|
22
|
+
"<%= config.bin %> raw Issues --vars '{\"first\": 10}'",
|
|
23
|
+
"<%= config.bin %> raw IssueCreate --workspace acme --allow-mutations --vars '{\"input\": {\"title\": \"x\", \"teamId\": \"...\"}}'",
|
|
24
|
+
"<%= config.bin %> raw Issues --vars @vars.json"
|
|
25
|
+
];
|
|
26
|
+
static enableJsonFlag = true;
|
|
27
|
+
static args = { operation: Args.string({
|
|
28
|
+
required: true,
|
|
29
|
+
description: "PascalCase operation name (e.g. Issues, IssueCreate)"
|
|
30
|
+
}) };
|
|
31
|
+
static flags = {
|
|
32
|
+
...BASE_FLAGS,
|
|
33
|
+
workspace: Flags.string({ description: "Workspace name override (precedence over LINEAR_WORKSPACE env / active default)" }),
|
|
34
|
+
"allow-active-workspace-write": Flags.boolean({
|
|
35
|
+
default: false,
|
|
36
|
+
description: "Permit mutations against the active workspace without an explicit --workspace selector (WSP-06 opt-in)"
|
|
37
|
+
}),
|
|
38
|
+
"allow-mutations": Flags.boolean({
|
|
39
|
+
default: false,
|
|
40
|
+
description: "Required for mutation operations — explicit safety gate"
|
|
41
|
+
}),
|
|
42
|
+
vars: Flags.string({ description: "Variables as inline JSON or @file.json path (file takes precedence)" })
|
|
43
|
+
};
|
|
44
|
+
async run() {
|
|
45
|
+
const { args, flags } = await this.parse(RawCommand);
|
|
46
|
+
const rawFlags = { pretty: flags.pretty };
|
|
47
|
+
if (flags.workspace !== void 0) rawFlags.workspace = flags.workspace;
|
|
48
|
+
if (flags["allow-active-workspace-write"]) rawFlags["allow-active-workspace-write"] = flags["allow-active-workspace-write"];
|
|
49
|
+
if (flags["allow-mutations"]) rawFlags["allow-mutations"] = flags["allow-mutations"];
|
|
50
|
+
if (flags.vars !== void 0) rawFlags.vars = flags.vars;
|
|
51
|
+
const runArgs = {
|
|
52
|
+
commandPath: "raw",
|
|
53
|
+
pretty: flags.pretty ?? false,
|
|
54
|
+
handler: (retryOpts) => runRaw({
|
|
55
|
+
args,
|
|
56
|
+
flags: rawFlags,
|
|
57
|
+
env: process.env,
|
|
58
|
+
retryOptsOverride: retryOpts
|
|
59
|
+
})
|
|
60
|
+
};
|
|
61
|
+
if (flags.quiet !== void 0) runArgs.quiet = flags.quiet;
|
|
62
|
+
if (flags.noMeta !== void 0) runArgs.noMeta = flags.noMeta;
|
|
63
|
+
if (flags.retry !== void 0) runArgs.retry = flags.retry;
|
|
64
|
+
const out = await runCommand(runArgs);
|
|
65
|
+
if (!flags.json) process.stdout.write(out.stdout);
|
|
66
|
+
if (out.stderr) process.stderr.write(out.stderr);
|
|
67
|
+
if (out.exitCode !== 0) process.exitCode = out.exitCode;
|
|
68
|
+
return JSON.parse(out.stdout);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
//#endregion
|
|
72
|
+
export { RawCommand as default, runRaw };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { BASE_FLAGS, runCommand } from "../lib/workspace-runtime.js";
|
|
2
|
+
import { schemaRuntime } from "../lib/schema-runtime.js";
|
|
3
|
+
import { Command, Flags } from "@oclif/core";
|
|
4
|
+
//#region src/commands/schema.ts
|
|
5
|
+
/**
|
|
6
|
+
* `linmux schema` — Phase 4 PLAN 04-04, INT-03.
|
|
7
|
+
*
|
|
8
|
+
* Returns the Linear GraphQL schema without making any network calls.
|
|
9
|
+
* Sources the vendored `schema.graphql` via schema-loader.ts (lazy-cached).
|
|
10
|
+
*
|
|
11
|
+
* Default: compact SDL (triple-quoted descriptions stripped) for token efficiency.
|
|
12
|
+
* --full: SDL with all descriptions included.
|
|
13
|
+
* --json: Standard introspection JSON (__schema format) for programmatic tooling.
|
|
14
|
+
*
|
|
15
|
+
* No --workspace flag — this command makes zero network calls.
|
|
16
|
+
*/
|
|
17
|
+
async function runSchema(args) {
|
|
18
|
+
const runArgs = {
|
|
19
|
+
commandPath: "schema",
|
|
20
|
+
pretty: args.pretty,
|
|
21
|
+
handler: async (_retryOpts) => {
|
|
22
|
+
return {
|
|
23
|
+
data: (await schemaRuntime({ flags: {
|
|
24
|
+
full: args.full,
|
|
25
|
+
json: args.json
|
|
26
|
+
} })).data,
|
|
27
|
+
meta: {}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
if (args.noMeta !== void 0) runArgs.noMeta = args.noMeta;
|
|
32
|
+
if (args.quiet !== void 0) runArgs.quiet = args.quiet;
|
|
33
|
+
if (args.retry !== void 0) runArgs.retry = args.retry;
|
|
34
|
+
return runCommand(runArgs);
|
|
35
|
+
}
|
|
36
|
+
var Schema = class Schema extends Command {
|
|
37
|
+
static description = "Return the Linear GraphQL schema as compact SDL (descriptions stripped by default), or as introspection JSON with --json.";
|
|
38
|
+
static enableJsonFlag = true;
|
|
39
|
+
static flags = {
|
|
40
|
+
...BASE_FLAGS,
|
|
41
|
+
full: Flags.boolean({
|
|
42
|
+
description: "Include type descriptions in the SDL output (default: stripped for token efficiency)",
|
|
43
|
+
default: false
|
|
44
|
+
}),
|
|
45
|
+
json: Flags.boolean({
|
|
46
|
+
description: "Return introspection JSON (__schema format) instead of SDL text",
|
|
47
|
+
default: false,
|
|
48
|
+
char: "j"
|
|
49
|
+
})
|
|
50
|
+
};
|
|
51
|
+
async run() {
|
|
52
|
+
const { flags } = await this.parse(Schema);
|
|
53
|
+
const callArgs = {
|
|
54
|
+
pretty: flags.pretty,
|
|
55
|
+
full: flags.full,
|
|
56
|
+
json: flags.json
|
|
57
|
+
};
|
|
58
|
+
if (flags.quiet !== void 0) callArgs.quiet = flags.quiet;
|
|
59
|
+
if (flags.noMeta !== void 0) callArgs.noMeta = flags.noMeta;
|
|
60
|
+
if (flags.retry !== void 0) callArgs.retry = flags.retry;
|
|
61
|
+
const out = await runSchema(callArgs);
|
|
62
|
+
if (!flags.json) process.stdout.write(out.stdout);
|
|
63
|
+
if (out.stderr) process.stderr.write(out.stderr);
|
|
64
|
+
if (out.exitCode !== 0) process.exitCode = out.exitCode;
|
|
65
|
+
return JSON.parse(out.stdout);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
//#endregion
|
|
69
|
+
export { Schema as default, runSchema };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { BASE_FLAGS, runCommand } from "../../lib/workspace-runtime.js";
|
|
2
|
+
import { PAGINATION_FLAGS } from "../../core/pagination/flags.js";
|
|
3
|
+
import "../../core/pagination/index.js";
|
|
4
|
+
import { stateListRuntime } from "../../lib/state-list-runtime.js";
|
|
5
|
+
import { Command, Flags } from "@oclif/core";
|
|
6
|
+
//#region src/commands/state/list.ts
|
|
7
|
+
/**
|
|
8
|
+
* `linmux state list` -- Phase 2 PLAN 02-09 Task 1, STA-01.
|
|
9
|
+
*
|
|
10
|
+
* Read command. Lists workflow states either across all teams the viewer can
|
|
11
|
+
* see (no filter) OR scoped to one team via `--team` (UUID, key, or name).
|
|
12
|
+
* Per CONTEXT § Specifics line 116, `--team` is OPTIONAL.
|
|
13
|
+
*
|
|
14
|
+
* Implementation lives in `src/lib/state-list-runtime.ts` per the Phase 1
|
|
15
|
+
* PLAN-04 invariant. Exports BOTH the default Command class AND a named
|
|
16
|
+
* `runStateList(args)` function.
|
|
17
|
+
*/
|
|
18
|
+
async function runStateList(args) {
|
|
19
|
+
const runArgs = {
|
|
20
|
+
commandPath: "state list",
|
|
21
|
+
pretty: args.pretty,
|
|
22
|
+
handler: async (retryOpts) => {
|
|
23
|
+
const runtimeFlags = {};
|
|
24
|
+
if (args.workspace !== void 0) runtimeFlags.workspace = args.workspace;
|
|
25
|
+
if (args.fields !== void 0) runtimeFlags.fields = args.fields;
|
|
26
|
+
if (args.limit !== void 0) runtimeFlags.limit = args.limit;
|
|
27
|
+
if (args.cursor !== void 0) runtimeFlags.cursor = args.cursor;
|
|
28
|
+
if (args.team !== void 0) runtimeFlags.team = args.team;
|
|
29
|
+
const result = await stateListRuntime({
|
|
30
|
+
flags: runtimeFlags,
|
|
31
|
+
env: process.env,
|
|
32
|
+
retryOptsOverride: retryOpts
|
|
33
|
+
});
|
|
34
|
+
return {
|
|
35
|
+
data: result.data,
|
|
36
|
+
meta: result.meta
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
if (args.noMeta !== void 0) runArgs.noMeta = args.noMeta;
|
|
41
|
+
if (args.quiet !== void 0) runArgs.quiet = args.quiet;
|
|
42
|
+
if (args.retry !== void 0) runArgs.retry = args.retry;
|
|
43
|
+
return runCommand(runArgs);
|
|
44
|
+
}
|
|
45
|
+
var StateList = class StateList extends Command {
|
|
46
|
+
static description = "List Linear workflow states. Pass --team <UUID|key|name> to scope to one team; otherwise lists all states the viewer can see.";
|
|
47
|
+
static enableJsonFlag = true;
|
|
48
|
+
static flags = {
|
|
49
|
+
...BASE_FLAGS,
|
|
50
|
+
...PAGINATION_FLAGS,
|
|
51
|
+
workspace: Flags.string({ description: "Workspace name (overrides active default and LINEAR_WORKSPACE)" }),
|
|
52
|
+
fields: Flags.string({
|
|
53
|
+
description: "Field preset (ids|defaults|full) or comma-separated list",
|
|
54
|
+
default: "defaults"
|
|
55
|
+
}),
|
|
56
|
+
team: Flags.string({ description: "Optional team filter (UUID, key, or name)" })
|
|
57
|
+
};
|
|
58
|
+
async run() {
|
|
59
|
+
const { flags } = await this.parse(StateList);
|
|
60
|
+
const callArgs = { pretty: flags.pretty };
|
|
61
|
+
if (flags.workspace !== void 0) callArgs.workspace = flags.workspace;
|
|
62
|
+
if (flags.fields !== void 0) callArgs.fields = flags.fields;
|
|
63
|
+
if (flags.limit !== void 0) callArgs.limit = flags.limit;
|
|
64
|
+
if (flags.cursor !== void 0) callArgs.cursor = flags.cursor;
|
|
65
|
+
if (flags.team !== void 0) callArgs.team = flags.team;
|
|
66
|
+
if (flags.quiet !== void 0) callArgs.quiet = flags.quiet;
|
|
67
|
+
if (flags.noMeta !== void 0) callArgs.noMeta = flags.noMeta;
|
|
68
|
+
if (flags.retry !== void 0) callArgs.retry = flags.retry;
|
|
69
|
+
const out = await runStateList(callArgs);
|
|
70
|
+
if (!flags.json) process.stdout.write(out.stdout);
|
|
71
|
+
if (out.stderr) process.stderr.write(out.stderr);
|
|
72
|
+
if (out.exitCode !== 0) process.exitCode = out.exitCode;
|
|
73
|
+
return JSON.parse(out.stdout);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
//#endregion
|
|
77
|
+
export { StateList as default, runStateList };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { BASE_FLAGS, runCommand } from "../../lib/workspace-runtime.js";
|
|
2
|
+
import { teamGetRuntime } from "../../lib/team-get-runtime.js";
|
|
3
|
+
import { Args, Command, Flags } from "@oclif/core";
|
|
4
|
+
//#region src/commands/team/get.ts
|
|
5
|
+
/**
|
|
6
|
+
* `linmux team get <ref>` -- Phase 2 PLAN 02-09 Task 1, TEM-01.get.
|
|
7
|
+
*
|
|
8
|
+
* Single-entity read. Accepts a UUID, team key (e.g. `ENG`), or team name.
|
|
9
|
+
* Implementation lives in `src/lib/team-get-runtime.ts`.
|
|
10
|
+
*
|
|
11
|
+
* Exports BOTH the default Command class AND a named `runTeamGet(args)`
|
|
12
|
+
* function.
|
|
13
|
+
*/
|
|
14
|
+
async function runTeamGet(args) {
|
|
15
|
+
const runArgs = {
|
|
16
|
+
commandPath: "team get",
|
|
17
|
+
pretty: args.pretty,
|
|
18
|
+
handler: async (retryOpts) => {
|
|
19
|
+
const runtimeFlags = {};
|
|
20
|
+
if (args.workspace !== void 0) runtimeFlags.workspace = args.workspace;
|
|
21
|
+
if (args.fields !== void 0) runtimeFlags.fields = args.fields;
|
|
22
|
+
const result = await teamGetRuntime({
|
|
23
|
+
args: { ref: args.ref },
|
|
24
|
+
flags: runtimeFlags,
|
|
25
|
+
env: process.env,
|
|
26
|
+
retryOptsOverride: retryOpts
|
|
27
|
+
});
|
|
28
|
+
return {
|
|
29
|
+
data: result.data,
|
|
30
|
+
meta: result.meta
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
if (args.noMeta !== void 0) runArgs.noMeta = args.noMeta;
|
|
35
|
+
if (args.quiet !== void 0) runArgs.quiet = args.quiet;
|
|
36
|
+
if (args.retry !== void 0) runArgs.retry = args.retry;
|
|
37
|
+
return runCommand(runArgs);
|
|
38
|
+
}
|
|
39
|
+
var TeamGet = class TeamGet extends Command {
|
|
40
|
+
static description = "Get a single Linear team by UUID, key (e.g. ENG), or name.";
|
|
41
|
+
static enableJsonFlag = true;
|
|
42
|
+
static args = { ref: Args.string({
|
|
43
|
+
required: true,
|
|
44
|
+
description: "Team UUID, key (e.g. ENG), or name"
|
|
45
|
+
}) };
|
|
46
|
+
static flags = {
|
|
47
|
+
...BASE_FLAGS,
|
|
48
|
+
workspace: Flags.string({ description: "Workspace name (overrides active default and LINEAR_WORKSPACE)" }),
|
|
49
|
+
fields: Flags.string({
|
|
50
|
+
description: "Field preset (ids|defaults|full) or comma-separated list",
|
|
51
|
+
default: "defaults"
|
|
52
|
+
})
|
|
53
|
+
};
|
|
54
|
+
async run() {
|
|
55
|
+
const { args, flags } = await this.parse(TeamGet);
|
|
56
|
+
const callArgs = {
|
|
57
|
+
ref: args.ref,
|
|
58
|
+
pretty: flags.pretty
|
|
59
|
+
};
|
|
60
|
+
if (flags.workspace !== void 0) callArgs.workspace = flags.workspace;
|
|
61
|
+
if (flags.fields !== void 0) callArgs.fields = flags.fields;
|
|
62
|
+
if (flags.quiet !== void 0) callArgs.quiet = flags.quiet;
|
|
63
|
+
if (flags.noMeta !== void 0) callArgs.noMeta = flags.noMeta;
|
|
64
|
+
if (flags.retry !== void 0) callArgs.retry = flags.retry;
|
|
65
|
+
const out = await runTeamGet(callArgs);
|
|
66
|
+
if (!flags.json) process.stdout.write(out.stdout);
|
|
67
|
+
if (out.stderr) process.stderr.write(out.stderr);
|
|
68
|
+
if (out.exitCode !== 0) process.exitCode = out.exitCode;
|
|
69
|
+
return JSON.parse(out.stdout);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
//#endregion
|
|
73
|
+
export { TeamGet as default, runTeamGet };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { BASE_FLAGS, runCommand } from "../../lib/workspace-runtime.js";
|
|
2
|
+
import { PAGINATION_FLAGS } from "../../core/pagination/flags.js";
|
|
3
|
+
import "../../core/pagination/index.js";
|
|
4
|
+
import { teamListRuntime } from "../../lib/team-list-runtime.js";
|
|
5
|
+
import { Command, Flags } from "@oclif/core";
|
|
6
|
+
//#region src/commands/team/list.ts
|
|
7
|
+
/**
|
|
8
|
+
* `linmux team list` -- Phase 2 PLAN 02-09 Task 1, TEM-01.list.
|
|
9
|
+
*
|
|
10
|
+
* Read command. Lists workspace-scoped teams. Implementation lives in
|
|
11
|
+
* `src/lib/team-list-runtime.ts` per the Phase 1 PLAN-04 invariant (oclif
|
|
12
|
+
* scans every file under `src/commands/` as a Command class).
|
|
13
|
+
*
|
|
14
|
+
* Exports BOTH the default Command class AND a named `runTeamList(args)`
|
|
15
|
+
* function.
|
|
16
|
+
*/
|
|
17
|
+
async function runTeamList(args) {
|
|
18
|
+
const runArgs = {
|
|
19
|
+
commandPath: "team list",
|
|
20
|
+
pretty: args.pretty,
|
|
21
|
+
handler: async (retryOpts) => {
|
|
22
|
+
const runtimeFlags = {};
|
|
23
|
+
if (args.workspace !== void 0) runtimeFlags.workspace = args.workspace;
|
|
24
|
+
if (args.fields !== void 0) runtimeFlags.fields = args.fields;
|
|
25
|
+
if (args.limit !== void 0) runtimeFlags.limit = args.limit;
|
|
26
|
+
if (args.cursor !== void 0) runtimeFlags.cursor = args.cursor;
|
|
27
|
+
const result = await teamListRuntime({
|
|
28
|
+
flags: runtimeFlags,
|
|
29
|
+
env: process.env,
|
|
30
|
+
retryOptsOverride: retryOpts
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
data: result.data,
|
|
34
|
+
meta: result.meta
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
if (args.noMeta !== void 0) runArgs.noMeta = args.noMeta;
|
|
39
|
+
if (args.quiet !== void 0) runArgs.quiet = args.quiet;
|
|
40
|
+
if (args.retry !== void 0) runArgs.retry = args.retry;
|
|
41
|
+
return runCommand(runArgs);
|
|
42
|
+
}
|
|
43
|
+
var TeamList = class TeamList extends Command {
|
|
44
|
+
static description = "List Linear teams in the resolved workspace.";
|
|
45
|
+
static enableJsonFlag = true;
|
|
46
|
+
static flags = {
|
|
47
|
+
...BASE_FLAGS,
|
|
48
|
+
...PAGINATION_FLAGS,
|
|
49
|
+
workspace: Flags.string({ description: "Workspace name (overrides active default and LINEAR_WORKSPACE)" }),
|
|
50
|
+
fields: Flags.string({
|
|
51
|
+
description: "Field preset (ids|defaults|full) or comma-separated list",
|
|
52
|
+
default: "defaults"
|
|
53
|
+
})
|
|
54
|
+
};
|
|
55
|
+
async run() {
|
|
56
|
+
const { flags } = await this.parse(TeamList);
|
|
57
|
+
const callArgs = { pretty: flags.pretty };
|
|
58
|
+
if (flags.workspace !== void 0) callArgs.workspace = flags.workspace;
|
|
59
|
+
if (flags.fields !== void 0) callArgs.fields = flags.fields;
|
|
60
|
+
if (flags.limit !== void 0) callArgs.limit = flags.limit;
|
|
61
|
+
if (flags.cursor !== void 0) callArgs.cursor = flags.cursor;
|
|
62
|
+
if (flags.quiet !== void 0) callArgs.quiet = flags.quiet;
|
|
63
|
+
if (flags.noMeta !== void 0) callArgs.noMeta = flags.noMeta;
|
|
64
|
+
if (flags.retry !== void 0) callArgs.retry = flags.retry;
|
|
65
|
+
const out = await runTeamList(callArgs);
|
|
66
|
+
if (!flags.json) process.stdout.write(out.stdout);
|
|
67
|
+
if (out.stderr) process.stderr.write(out.stderr);
|
|
68
|
+
if (out.exitCode !== 0) process.exitCode = out.exitCode;
|
|
69
|
+
return JSON.parse(out.stdout);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
//#endregion
|
|
73
|
+
export { TeamList as default, runTeamList };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { BASE_FLAGS, runCommand } from "../lib/workspace-runtime.js";
|
|
2
|
+
import { meRuntime } from "../lib/me-runtime.js";
|
|
3
|
+
import { Command, Flags } from "@oclif/core";
|
|
4
|
+
//#region src/commands/whoami.ts
|
|
5
|
+
/**
|
|
6
|
+
* `linmux whoami` -- Phase 2 PLAN 02-09 Task 1, WHO-01.
|
|
7
|
+
*
|
|
8
|
+
* Alias for `me` -- prints the resolved viewer (user) and organization for
|
|
9
|
+
* the current workspace. Shares `src/lib/me-runtime.ts` with `me`. Both
|
|
10
|
+
* commands emit IDENTICAL envelopes except for `meta.command` (`'me'` vs
|
|
11
|
+
* `'whoami'`). `whoami` exists purely for discoverability per CONTEXT
|
|
12
|
+
* § Specifics line 65 (the pretty-alias pattern).
|
|
13
|
+
*
|
|
14
|
+
* Exports BOTH the default Command class AND a named `runWhoami(args)`
|
|
15
|
+
* function.
|
|
16
|
+
*/
|
|
17
|
+
async function runWhoami(args) {
|
|
18
|
+
const runArgs = {
|
|
19
|
+
commandPath: "whoami",
|
|
20
|
+
pretty: args.pretty,
|
|
21
|
+
handler: async (retryOpts) => {
|
|
22
|
+
const runtimeFlags = {};
|
|
23
|
+
if (args.workspace !== void 0) runtimeFlags.workspace = args.workspace;
|
|
24
|
+
if (args.fields !== void 0) runtimeFlags.fields = args.fields;
|
|
25
|
+
const meInput = {
|
|
26
|
+
flags: runtimeFlags,
|
|
27
|
+
env: process.env,
|
|
28
|
+
retryOptsOverride: retryOpts
|
|
29
|
+
};
|
|
30
|
+
if (args.loadConfigOverride !== void 0) meInput.loadConfigOverride = args.loadConfigOverride;
|
|
31
|
+
if (args.clientFactoryOverride !== void 0) meInput.clientFactoryOverride = args.clientFactoryOverride;
|
|
32
|
+
const result = await meRuntime(meInput);
|
|
33
|
+
return {
|
|
34
|
+
data: result.data,
|
|
35
|
+
meta: result.meta
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
if (args.noMeta !== void 0) runArgs.noMeta = args.noMeta;
|
|
40
|
+
if (args.quiet !== void 0) runArgs.quiet = args.quiet;
|
|
41
|
+
if (args.retry !== void 0) runArgs.retry = args.retry;
|
|
42
|
+
return runCommand(runArgs);
|
|
43
|
+
}
|
|
44
|
+
var Whoami = class Whoami extends Command {
|
|
45
|
+
static description = "Alias for `me` -- prints the resolved viewer + organization.";
|
|
46
|
+
static enableJsonFlag = true;
|
|
47
|
+
static flags = {
|
|
48
|
+
...BASE_FLAGS,
|
|
49
|
+
workspace: Flags.string({ description: "Workspace name (overrides active default and LINEAR_WORKSPACE)" }),
|
|
50
|
+
fields: Flags.string({
|
|
51
|
+
description: "Field preset (ids|defaults|full) or comma-separated list",
|
|
52
|
+
default: "defaults"
|
|
53
|
+
})
|
|
54
|
+
};
|
|
55
|
+
async run() {
|
|
56
|
+
const { flags } = await this.parse(Whoami);
|
|
57
|
+
const callArgs = { pretty: flags.pretty };
|
|
58
|
+
if (flags.workspace !== void 0) callArgs.workspace = flags.workspace;
|
|
59
|
+
if (flags.fields !== void 0) callArgs.fields = flags.fields;
|
|
60
|
+
if (flags.quiet !== void 0) callArgs.quiet = flags.quiet;
|
|
61
|
+
if (flags.noMeta !== void 0) callArgs.noMeta = flags.noMeta;
|
|
62
|
+
if (flags.retry !== void 0) callArgs.retry = flags.retry;
|
|
63
|
+
const out = await runWhoami(callArgs);
|
|
64
|
+
if (!flags.json) process.stdout.write(out.stdout);
|
|
65
|
+
if (out.stderr) process.stderr.write(out.stderr);
|
|
66
|
+
if (out.exitCode !== 0) process.exitCode = out.exitCode;
|
|
67
|
+
return JSON.parse(out.stdout);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
//#endregion
|
|
71
|
+
export { Whoami as default, runWhoami };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { LinearAgentError } from "../../core/errors/error.js";
|
|
2
|
+
import { withFetchInterception } from "../../core/transport/fetch-interceptor.js";
|
|
3
|
+
import { withRateLimitRetry } from "../../core/transport/rate-limit.js";
|
|
4
|
+
import "../../core/transport/index.js";
|
|
5
|
+
import { BASE_FLAGS, runCommand } from "../../lib/workspace-runtime.js";
|
|
6
|
+
import { createLinearClient } from "../../core/client/factory.js";
|
|
7
|
+
import "../../core/client/index.js";
|
|
8
|
+
import { loadConfig, saveConfig } from "../../core/config/store.js";
|
|
9
|
+
import "../../core/config/index.js";
|
|
10
|
+
import { Args, Command, Flags } from "@oclif/core";
|
|
11
|
+
//#region src/commands/workspace/add.ts
|
|
12
|
+
async function runWorkspaceAdd(args) {
|
|
13
|
+
const runArgs = {
|
|
14
|
+
commandPath: "workspace add",
|
|
15
|
+
pretty: args.pretty,
|
|
16
|
+
handler: async (retryOpts) => {
|
|
17
|
+
const config = loadConfig();
|
|
18
|
+
if (Object.hasOwn(config.workspaces, args.name)) throw LinearAgentError.workspace.alreadyExists(args.name);
|
|
19
|
+
const client = createLinearClient({
|
|
20
|
+
name: null,
|
|
21
|
+
token: args.token,
|
|
22
|
+
organizationId: null,
|
|
23
|
+
source: "api-key-env"
|
|
24
|
+
});
|
|
25
|
+
const effectiveRetryOpts = args.retryOptsOverride ?? retryOpts;
|
|
26
|
+
const orgId = await withFetchInterception(async () => {
|
|
27
|
+
const viewer = await withRateLimitRetry(() => client.viewer, effectiveRetryOpts);
|
|
28
|
+
return (await withRateLimitRetry(() => viewer.organization, effectiveRetryOpts)).id;
|
|
29
|
+
});
|
|
30
|
+
let warning;
|
|
31
|
+
const collision = Object.values(config.workspaces).find((w) => w.organizationId === orgId);
|
|
32
|
+
if (collision) warning = `organization already registered as ${collision.name}`;
|
|
33
|
+
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
34
|
+
const entry = {
|
|
35
|
+
name: args.name,
|
|
36
|
+
token: args.token,
|
|
37
|
+
organizationId: orgId,
|
|
38
|
+
createdAt
|
|
39
|
+
};
|
|
40
|
+
const isActive = Object.keys(config.workspaces).length === 0;
|
|
41
|
+
saveConfig({
|
|
42
|
+
active: isActive ? args.name : config.active,
|
|
43
|
+
workspaces: {
|
|
44
|
+
...config.workspaces,
|
|
45
|
+
[args.name]: entry
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
return {
|
|
49
|
+
data: {
|
|
50
|
+
name: args.name,
|
|
51
|
+
organizationId: orgId,
|
|
52
|
+
isActive,
|
|
53
|
+
createdAt,
|
|
54
|
+
...warning !== void 0 ? { warning } : {}
|
|
55
|
+
},
|
|
56
|
+
meta: { workspace: args.name }
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
if (args.noMeta !== void 0) runArgs.noMeta = args.noMeta;
|
|
61
|
+
if (args.quiet !== void 0) runArgs.quiet = args.quiet;
|
|
62
|
+
if (args.retry !== void 0) runArgs.retry = args.retry;
|
|
63
|
+
return runCommand(runArgs);
|
|
64
|
+
}
|
|
65
|
+
var WorkspaceAdd = class WorkspaceAdd extends Command {
|
|
66
|
+
static description = "Register a Linear workspace";
|
|
67
|
+
static enableJsonFlag = true;
|
|
68
|
+
static args = { name: Args.string({
|
|
69
|
+
required: true,
|
|
70
|
+
description: "Local alias for the workspace"
|
|
71
|
+
}) };
|
|
72
|
+
static flags = {
|
|
73
|
+
token: Flags.string({
|
|
74
|
+
required: true,
|
|
75
|
+
description: "Linear personal API key (lin_api_*)"
|
|
76
|
+
}),
|
|
77
|
+
...BASE_FLAGS
|
|
78
|
+
};
|
|
79
|
+
async run() {
|
|
80
|
+
const { args, flags } = await this.parse(WorkspaceAdd);
|
|
81
|
+
const callArgs = {
|
|
82
|
+
name: args.name,
|
|
83
|
+
token: flags.token,
|
|
84
|
+
pretty: flags.pretty
|
|
85
|
+
};
|
|
86
|
+
if (flags.quiet !== void 0) callArgs.quiet = flags.quiet;
|
|
87
|
+
if (flags.noMeta !== void 0) callArgs.noMeta = flags.noMeta;
|
|
88
|
+
if (flags.retry !== void 0) callArgs.retry = flags.retry;
|
|
89
|
+
const out = await runWorkspaceAdd(callArgs);
|
|
90
|
+
if (!flags.json) process.stdout.write(out.stdout);
|
|
91
|
+
if (out.stderr) process.stderr.write(out.stderr);
|
|
92
|
+
if (out.exitCode !== 0) process.exitCode = out.exitCode;
|
|
93
|
+
return JSON.parse(out.stdout);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
//#endregion
|
|
97
|
+
export { WorkspaceAdd as default, runWorkspaceAdd };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { BASE_FLAGS, runCommand } from "../../lib/workspace-runtime.js";
|
|
2
|
+
import { loadConfig } from "../../core/config/store.js";
|
|
3
|
+
import "../../core/config/index.js";
|
|
4
|
+
import { Command } from "@oclif/core";
|
|
5
|
+
//#region src/commands/workspace/list.ts
|
|
6
|
+
async function runWorkspaceList(args) {
|
|
7
|
+
const runArgs = {
|
|
8
|
+
commandPath: "workspace list",
|
|
9
|
+
pretty: args.pretty,
|
|
10
|
+
handler: async (_retryOpts) => {
|
|
11
|
+
const config = loadConfig();
|
|
12
|
+
return {
|
|
13
|
+
data: { workspaces: Object.values(config.workspaces).sort((a, b) => a.name.localeCompare(b.name)).map((w) => ({
|
|
14
|
+
name: w.name,
|
|
15
|
+
organizationId: w.organizationId,
|
|
16
|
+
isActive: config.active === w.name,
|
|
17
|
+
createdAt: w.createdAt,
|
|
18
|
+
...w.lastUsedAt !== void 0 ? { lastUsedAt: w.lastUsedAt } : {}
|
|
19
|
+
})) },
|
|
20
|
+
meta: {}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
if (args.noMeta !== void 0) runArgs.noMeta = args.noMeta;
|
|
25
|
+
if (args.quiet !== void 0) runArgs.quiet = args.quiet;
|
|
26
|
+
if (args.retry !== void 0) runArgs.retry = args.retry;
|
|
27
|
+
return runCommand(runArgs);
|
|
28
|
+
}
|
|
29
|
+
var WorkspaceList = class WorkspaceList extends Command {
|
|
30
|
+
static description = "List registered Linear workspaces";
|
|
31
|
+
static enableJsonFlag = true;
|
|
32
|
+
static flags = { ...BASE_FLAGS };
|
|
33
|
+
async run() {
|
|
34
|
+
const { flags } = await this.parse(WorkspaceList);
|
|
35
|
+
const callArgs = { pretty: flags.pretty };
|
|
36
|
+
if (flags.quiet !== void 0) callArgs.quiet = flags.quiet;
|
|
37
|
+
if (flags.noMeta !== void 0) callArgs.noMeta = flags.noMeta;
|
|
38
|
+
if (flags.retry !== void 0) callArgs.retry = flags.retry;
|
|
39
|
+
const out = await runWorkspaceList(callArgs);
|
|
40
|
+
if (!flags.json) process.stdout.write(out.stdout);
|
|
41
|
+
if (out.stderr) process.stderr.write(out.stderr);
|
|
42
|
+
if (out.exitCode !== 0) process.exitCode = out.exitCode;
|
|
43
|
+
return JSON.parse(out.stdout);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
//#endregion
|
|
47
|
+
export { WorkspaceList as default, runWorkspaceList };
|