Skip to content
Merged
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
27 changes: 22 additions & 5 deletions client/packages/cli/__tests__/e2e/cli.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -700,11 +700,27 @@ export default _schema;
}
});

it('fails without context flag', async () => {
it('defaults to admin context when no context flag is provided', async () => {
const { appId, adminToken } = await createTempApp();
const project = await createTestProject({ appId });
const project = await createTestProject({
appId,
schemaFile: SCHEMA_FILE,
});

try {
const pushResult = await runCli(['push', 'schema', '--yes'], {
cwd: project.dir,
env: {
INSTANT_CLI_AUTH_TOKEN: adminToken,
INSTANT_APP_ID: appId,
},
});
expect(pushResult.exitCode).toBe(0);

await adminTransact(appId, adminToken, [
['update', 'posts', randomUUID(), { title: 'Hello', body: 'World' }],
]);

const result = await runCli(['query', JSON.stringify({ posts: {} })], {
cwd: project.dir,
env: {
Expand All @@ -713,9 +729,10 @@ export default _schema;
},
});

expect(result.exitCode).not.toBe(0);
const output = result.stdout + result.stderr;
expect(output).toMatch(/--admin|--as-email|--as-guest/);
expect(result.exitCode).toBe(0);
const data = JSON.parse(result.stdout);
expect(data.posts).toHaveLength(1);
expect(data.posts[0].title).toBe('Hello');
} finally {
await project.cleanup();
}
Expand Down
6 changes: 0 additions & 6 deletions client/packages/cli/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -718,12 +718,6 @@ async function detectAppIdQuietly(opts) {
async function handleQuery(queryArg, opts) {
const contextCount =
(opts.admin ? 1 : 0) + (opts.asEmail ? 1 : 0) + (opts.asGuest ? 1 : 0);
if (contextCount === 0) {
error(
'Please specify a context: --admin, --as-email <email>, or --as-guest',
);
return process.exit(1);
}
if (contextCount > 1) {
error(
'Please specify exactly one context: --admin, --as-email <email>, or --as-guest',
Expand Down
2 changes: 1 addition & 1 deletion client/packages/version/src/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
// Update the version here and merge your code to main to
// publish a new version of all of the packages to npm.

const version = 'v0.22.166';
const version = 'v0.22.167';

export { version };
24 changes: 24 additions & 0 deletions client/www/pages/docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,30 @@ npx instant-cli@latest pull

This will generate new `instant.schema.ts` and `instant.perms.ts` files, based on your production state.

## Query

You can run InstaQL queries against your app directly from the terminal:

```shell {% showCopy=true %}
npx instant-cli@latest query '{ posts: { comments: {} } }'
```

This outputs clean JSON to stdout, making it easy to pipe into `jq` or use in scripts. It supports JSON5 syntax, so you don't need to quote your keys.

Each query requires an auth context flag:

- `--admin` bypasses permissions (default)
- `--as-email <email>` runs the query as a specific user with permissions applied
- `--as-guest` runs the query as an unauthenticated guest

For example, to see what a specific user can access:

```shell {% showCopy=true %}
npx instant-cli@latest query --as-email alice@example.com '{ posts: {} }'
```

The results match what your client queries return, including cardinality. If your schema defines a relationship as `has: "one"`, you'll get back a single object instead of an array.

## App ID

Whenever you run a CLI command, we look up your app id. You can either provide an app id as an option:
Expand Down
Loading