Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/commands/guide/pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ApiError } from "@/lib/helpers/error";
import * as CustomFlags from "@/lib/helpers/flag";
import { merge } from "@/lib/helpers/object.isomorphic";
import { MAX_PAGINATION_LIMIT, PageInfo } from "@/lib/helpers/page";
import { isPathArg, resolvePathArg } from "@/lib/helpers/path";
import { resolveResourceDir } from "@/lib/helpers/project-config";
import {
formatErrorRespMessage,
Expand Down Expand Up @@ -163,6 +164,18 @@ export default class GuidePull extends BaseCommand<typeof GuidePull> {
const { guideKey } = this.props.args;
const { resourceDir, cwd: runCwd } = this.runContext;

// When a path is provided, override resolution and use it directly.
if (guideKey && isPathArg(guideKey)) {
const { key, abspath } = resolvePathArg(guideKey);
const exists = await Guide.isGuideDir(abspath);
return {
type: "guide",
key,
abspath,
exists,
};
}

// Inside an existing resource dir, use it if valid for the target guide.
if (resourceDir) {
const target: ResourceTarget = {
Expand Down
5 changes: 4 additions & 1 deletion src/commands/guide/push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ export default class GuidePush extends BaseCommand<typeof GuidePush> {
spinner.start(`‣ Pushing`);

for (const guide of guides) {
const props = merge(this.props, { flags: { annotate: true } });
const props = merge(this.props, {
flags: { annotate: true },
args: { guideKey: guide.key },
});

// eslint-disable-next-line no-await-in-loop
const resp = await this.apiV1.upsertGuide<WithAnnotation>(props, {
Expand Down
13 changes: 13 additions & 0 deletions src/commands/layout/pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ApiError } from "@/lib/helpers/error";
import * as CustomFlags from "@/lib/helpers/flag";
import { merge } from "@/lib/helpers/object.isomorphic";
import { MAX_PAGINATION_LIMIT, PageInfo } from "@/lib/helpers/page";
import { isPathArg, resolvePathArg } from "@/lib/helpers/path";
import { resolveResourceDir } from "@/lib/helpers/project-config";
import {
formatErrorRespMessage,
Expand Down Expand Up @@ -172,6 +173,18 @@ export default class EmailLayoutPull extends BaseCommand<
const { emailLayoutKey } = this.props.args;
const { resourceDir, cwd: runCwd } = this.runContext;

// When a path is provided, override resolution and use it directly.
if (emailLayoutKey && isPathArg(emailLayoutKey)) {
const { key, abspath } = resolvePathArg(emailLayoutKey);
const exists = await EmailLayout.isEmailLayoutDir(abspath);
return {
type: "email_layout",
key,
abspath,
exists,
};
}

// Inside an existing resource dir, use it if valid for the target email layout.
if (resourceDir) {
const target: ResourceTarget = {
Expand Down
5 changes: 4 additions & 1 deletion src/commands/layout/push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ export default class EmailLayoutPush extends BaseCommand<
spinner.start(`‣ Pushing`);

for (const layout of layouts) {
const props = merge(this.props, { flags: { annotate: true } });
const props = merge(this.props, {
flags: { annotate: true },
args: { emailLayoutKey: layout.key },
});

// eslint-disable-next-line no-await-in-loop
const resp = await this.apiV1.upsertEmailLayout<WithAnnotation>(props, {
Expand Down
13 changes: 13 additions & 0 deletions src/commands/message-type/pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ApiError } from "@/lib/helpers/error";
import * as CustomFlags from "@/lib/helpers/flag";
import { merge } from "@/lib/helpers/object.isomorphic";
import { MAX_PAGINATION_LIMIT, PageInfo } from "@/lib/helpers/page";
import { isPathArg, resolvePathArg } from "@/lib/helpers/path";
import { resolveResourceDir } from "@/lib/helpers/project-config";
import {
formatErrorRespMessage,
Expand Down Expand Up @@ -115,6 +116,18 @@ export default class MessageTypePull extends BaseCommand<
const { messageTypeKey } = this.props.args;
const { resourceDir, cwd: runCwd } = this.runContext;

// When a path is provided, override resolution and use it directly.
if (messageTypeKey && isPathArg(messageTypeKey)) {
const { key, abspath } = resolvePathArg(messageTypeKey);
const exists = await MessageType.isMessageTypeDir(abspath);
return {
type: "message_type",
key,
abspath,
exists,
};
}

const messageTypesIndexDirCtx = await resolveResourceDir(
this.projectConfig,
"message_type",
Expand Down
5 changes: 4 additions & 1 deletion src/commands/message-type/push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,10 @@ export default class MessageTypePush extends BaseCommand<
spinner.start(`‣ Pushing`);

for (const messageType of messageTypes) {
const props = merge(this.props, { flags: { annotate: true } });
const props = merge(this.props, {
flags: { annotate: true },
args: { messageTypeKey: messageType.key },
});

// eslint-disable-next-line no-await-in-loop
const resp = await this.apiV1.upsertMessageType<WithAnnotation>(props, {
Expand Down
13 changes: 13 additions & 0 deletions src/commands/partial/pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ApiError } from "@/lib/helpers/error";
import * as CustomFlags from "@/lib/helpers/flag";
import { merge } from "@/lib/helpers/object.isomorphic";
import { MAX_PAGINATION_LIMIT, PageInfo } from "@/lib/helpers/page";
import { isPathArg, resolvePathArg } from "@/lib/helpers/path";
import { resolveResourceDir } from "@/lib/helpers/project-config";
import {
formatErrorRespMessage,
Expand Down Expand Up @@ -165,6 +166,18 @@ export default class PartialPull extends BaseCommand<typeof PartialPull> {
const { partialKey } = this.props.args;
const { resourceDir, cwd: runCwd } = this.runContext;

// When a path is provided, override resolution and use it directly.
if (partialKey && isPathArg(partialKey)) {
const { key, abspath } = resolvePathArg(partialKey);
const exists = await Partial.isPartialDir(abspath);
return {
type: "partial",
key,
abspath,
exists,
};
}

// Inside an existing resource dir, use it if valid for the target partial.
if (resourceDir) {
const target: ResourceTarget = {
Expand Down
5 changes: 4 additions & 1 deletion src/commands/partial/push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,10 @@ export default class PartialPush extends BaseCommand<typeof PartialPush> {
spinner.start(`‣ Pushing`);

for (const partial of partials) {
const props = merge(this.props, { flags: { annotate: true } });
const props = merge(this.props, {
flags: { annotate: true },
args: { partialKey: partial.key },
});

// eslint-disable-next-line no-await-in-loop
const resp = await this.apiV1.upsertPartial<WithAnnotation>(props, {
Expand Down
13 changes: 13 additions & 0 deletions src/commands/workflow/pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ApiError } from "@/lib/helpers/error";
import * as CustomFlags from "@/lib/helpers/flag";
import { merge } from "@/lib/helpers/object.isomorphic";
import { MAX_PAGINATION_LIMIT, PageInfo } from "@/lib/helpers/page";
import { isPathArg, resolvePathArg } from "@/lib/helpers/path";
import { resolveResourceDir } from "@/lib/helpers/project-config";
import {
formatErrorRespMessage,
Expand Down Expand Up @@ -113,6 +114,18 @@ export default class WorkflowPull extends BaseCommand<typeof WorkflowPull> {
const { workflowKey } = this.props.args;
const { resourceDir, cwd: runCwd } = this.runContext;

// When a path is provided, override resolution and use it directly.
if (workflowKey && isPathArg(workflowKey)) {
const { key, abspath } = resolvePathArg(workflowKey);
const exists = await Workflow.isWorkflowDir(abspath);
return {
type: "workflow",
key,
abspath,
exists,
};
}

// Inside an existing resource dir, use it if valid for the target workflow.
if (resourceDir) {
const target: ResourceTarget = {
Expand Down
5 changes: 4 additions & 1 deletion src/commands/workflow/push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,10 @@ export default class WorkflowPush extends BaseCommand<typeof WorkflowPush> {
spinner.start(`‣ Pushing`);

for (const workflow of workflows) {
const props = merge(this.props, { flags: { annotate: true } });
const props = merge(this.props, {
flags: { annotate: true },
args: { workflowKey: workflow.key },
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary args merge in push commands

Low Severity

The args: { workflowKey: workflow.key } merge (and equivalent for all other resource push commands) is unused. All upsert* methods in api-v1.ts destructure only { flags } from the props parameter and never read args. This dead code adds confusion about the API contract. The PR reviewers already flagged this concern.

Additional Locations (2)

Fix in Cursor Fix in Web


// eslint-disable-next-line no-await-in-loop
const resp = await this.apiV1.upsertWorkflow<WithAnnotation>(props, {
Expand Down
26 changes: 26 additions & 0 deletions src/lib/helpers/path.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as path from "node:path";

/**
* Returns true if the argument looks like a filesystem path rather than a
* resource key. Paths contain the OS path separator.
*
* @param arg - The command argument to check
* @returns True if the argument appears to be a path
*/
export const isPathArg = (arg: string): boolean =>
arg.includes(path.sep) || arg.includes("/");

/**
* Resolves a path argument to an absolute path and extracts the resource key
* from the directory basename.
*
* @param arg - The path argument to resolve
* @returns Object with key (basename) and abspath (resolved path)
*/
export const resolvePathArg = (
arg: string,
): { key: string; abspath: string } => {
const abspath = path.resolve(arg);
const key = path.basename(abspath);
return { key, abspath };
};
12 changes: 12 additions & 0 deletions src/lib/marshal/email-layout/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ux } from "@oclif/core";
import * as fs from "fs-extra";

import { DirContext } from "@/lib/helpers/fs";
import { isPathArg, resolvePathArg } from "@/lib/helpers/path";
import {
ProjectConfig,
resolveResourceDir,
Expand Down Expand Up @@ -105,6 +106,17 @@ export const ensureValidCommandTarget = async (

// Email layout key arg is given, which means no --all flag.
if (args.emailLayoutKey) {
if (isPathArg(args.emailLayoutKey)) {
const { key, abspath } = resolvePathArg(args.emailLayoutKey);
const layoutDirCtx: EmailLayoutDirContext = {
type: "email_layout",
key,
abspath,
exists: await isEmailLayoutDir(abspath),
};
return { type: "emailLayoutDir", context: layoutDirCtx };
}

if (resourceDirCtx && resourceDirCtx.key !== args.emailLayoutKey) {
return ux.error(
`Cannot run ${commandId} \`${args.emailLayoutKey}\` inside another layout directory:\n${resourceDirCtx.key}`,
Expand Down
12 changes: 12 additions & 0 deletions src/lib/marshal/guide/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from "quicktype-core";

import { DirContext } from "@/lib/helpers/fs";
import { isPathArg, resolvePathArg } from "@/lib/helpers/path";
import {
ProjectConfig,
resolveResourceDir,
Expand Down Expand Up @@ -146,6 +147,17 @@ export const ensureValidCommandTarget = async (

// Guide key arg is given, which means no --all flag.
if (args.guideKey) {
if (isPathArg(args.guideKey)) {
const { key, abspath } = resolvePathArg(args.guideKey);
const guideDirCtx: GuideDirContext = {
type: "guide",
key,
abspath,
exists: await isGuideDir(abspath),
};
return { type: "guideDir", context: guideDirCtx };
}

if (resourceDirCtx && resourceDirCtx.key !== args.guideKey) {
return ux.error(
`Cannot run ${commandId} \`${args.guideKey}\` inside another guide directory:\n${resourceDirCtx.key}`,
Expand Down
12 changes: 12 additions & 0 deletions src/lib/marshal/message-type/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ux } from "@oclif/core";
import * as fs from "fs-extra";

import { DirContext } from "@/lib/helpers/fs";
import { isPathArg, resolvePathArg } from "@/lib/helpers/path";
import {
ProjectConfig,
resolveResourceDir,
Expand Down Expand Up @@ -106,6 +107,17 @@ export const ensureValidCommandTarget = async (

// Message type key arg is given, which means no --all flag.
if (args.messageTypeKey) {
if (isPathArg(args.messageTypeKey)) {
const { key, abspath } = resolvePathArg(args.messageTypeKey);
const messageTypeDirCtx: MessageTypeDirContext = {
type: "message_type",
key,
abspath,
exists: await isMessageTypeDir(abspath),
};
return { type: "messageTypeDir", context: messageTypeDirCtx };
}

if (resourceDirCtx && resourceDirCtx.key !== args.messageTypeKey) {
return ux.error(
`Cannot run ${commandId} \`${args.messageTypeKey}\` inside another message type directory:\n${resourceDirCtx.key}`,
Expand Down
12 changes: 12 additions & 0 deletions src/lib/marshal/partial/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ux } from "@oclif/core";
import * as fs from "fs-extra";

import { DirContext } from "@/lib/helpers/fs";
import { isPathArg, resolvePathArg } from "@/lib/helpers/path";
import {
ProjectConfig,
resolveResourceDir,
Expand Down Expand Up @@ -103,6 +104,17 @@ export const ensureValidCommandTarget = async (

// Partial key arg is given, which means no --all flag.
if (args.partialKey) {
if (isPathArg(args.partialKey)) {
const { key, abspath } = resolvePathArg(args.partialKey);
const partialDirCtx: PartialDirContext = {
type: "partial",
key,
abspath,
exists: await isPartialDir(abspath),
};
return { type: "partialDir", context: partialDirCtx };
}

if (resourceDirCtx && resourceDirCtx.key !== args.partialKey) {
return ux.error(
`Cannot run ${commandId} \`${args.partialKey}\` inside another partial directory:\n${resourceDirCtx.key}`,
Expand Down
Loading
Loading