Skip to content

Commit

Permalink
Add a format:json (default) to seed_type fetch.
Browse files Browse the repository at this point in the history
This is effectively a workaround for json template extraction being broken (#59).

Part of #45.
  • Loading branch information
jkomoros committed Jul 22, 2023
1 parent f09991d commit 97ab464
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 23 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -495,12 +495,13 @@ Environment:
#### fetch
Fetches a remote resource and returns the text of the resoponse. You can extract the JSON of the response using the `extract` seed_type with the template `{{data|json}}`.
Fetches a remote resource and returns the text of the resoponse.
Parameters:
- `resource` - The URL of the resource to fetch
- `method` - (optional) the HTTP method (GET or PUT). Defaults to GET
- `body` - (optional) the body to provide in the resource if it is not a GET method.
- `format` - (optional) whehter the result should be parsed as json or left as text. Values are `json` (default) and `text`.
Environment:
- `mock` - If true, will return a string representation of the request that would have been sent.
Expand Down
25 changes: 25 additions & 0 deletions seed-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1873,6 +1873,31 @@
"description": "The body to pass"
}
]
},
"format": {
"anyOf": [
{
"$ref": "#/definitions/seedData"
},
{
"$ref": "#/definitions/seedData/anyOf/0/properties/prompt/anyOf/1"
},
{
"anyOf": [
{
"not": {}
},
{
"type": "string",
"enum": [
"json",
"text"
]
}
],
"description": "The format of the result, default json"
}
]
}
},
"required": [
Expand Down
47 changes: 32 additions & 15 deletions src/grow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,13 @@ import {
SeedDataSplit,
SeedDataJoin,
SeedDataFetch,
fetchMethod
fetchMethod,
fetchFormat
} from './types.js';

import {
assertUnreachable, getObjectProperty, mockedResult
assertUnreachable,
getObjectProperty
} from './util.js';

import {
Expand Down Expand Up @@ -433,33 +435,48 @@ const growFetch = async (seed : Seed<SeedDataFetch>, env : Environment) : Promis
let body = null;
if (method != 'GET') body = extractString(await getProperty(seed, env, data.body, ''));

const rawFormat = extractString(await getProperty(seed, env, data.format, 'json'));
const format = fetchFormat.parse(rawFormat.toLowerCase().trim());

if (!isLocalLocation(seed.location)) {
const domain = locationDomain(resource);
const allowFetch = await seed.garden.profile.allowFetch(seed.location, domain);
if (!allowFetch) throw new Error(`User did not allow fetch from ${seed.location} to ${domain}`);
}

let result = '';

if (env.getKnownProtectedKey('mock')) {
const data = {
mock: true,
resource,
method,
body
body,
format
};
return mockedResult(JSON.stringify(data, null, '\t'));
result = JSON.stringify(data);
} else if (isLocalLocation(resource)) {
//If it's a local fetch then use the localFetch machinery.
//TODO: this logic will be wrong in cases where it's hosted on a domain
result = await seed.garden.profile.localFetch(resource);
} else {
const fetchResult = await fetch(resource, {
method,
body
});
if (!fetchResult.ok) throw new Error(`Result status was not ok: ${fetchResult.status}: ${fetchResult.statusText}`);
result = await fetchResult.text();
}

//If it's a local fetch then use the localFetch machinery.
//TODO: this logic will be wrong in cases where it's hosted on a domain
if (isLocalLocation(resource)) {
return seed.garden.profile.localFetch(resource);
switch(format) {
case 'json':
return JSON.parse(result);
case 'text':
return result;
default:
assertUnreachable(format);
}
return result;

const result = await fetch(resource, {
method,
body
});
if (!result.ok) throw new Error(`Result status was not ok: ${result.status}: ${result.statusText}`);
return result.text();
};

const growProperty = async (seed : Seed<SeedDataProperty>, env : Environment) : Promise<Value> => {
Expand Down
10 changes: 9 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -700,12 +700,20 @@ export const fetchMethod = z.union([

export type FetchMethod = z.infer<typeof fetchMethod>;

export const fetchFormat = z.union([
z.literal('json'),
z.literal('text')
]);

export type FetchFormat = z.infer<typeof fetchFormat>;

const seedDataConfigFetch = {
type: z.literal('fetch'),
properties: {
resource: seedPacketLocation.describe('The URL of the resource to fetch'),
method: fetchMethod.optional().describe('The method (default GET)'),
body: z.string().optional().describe('The body to pass')
body: z.string().optional().describe('The body to pass'),
format: fetchFormat.optional().describe('The format of the result, default json')
}
};

Expand Down
14 changes: 8 additions & 6 deletions test/base/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -932,12 +932,14 @@ Suffix`;
const garden = loadTestGarden();
const seed = await garden.seed('fetch-test');
const actual = await seed.grow();
const golden = `Mocked result: {
"resource": "https://raw.githubusercontent.com/jkomoros/prompt-garden/main/seeds/example-basic.json",
"method": "POST",
"body": ""
}`;
assert.deepStrictEqual(actual, golden);
const golden = {
'mock': true,
'format': 'json',
'resource': 'https://raw.githubusercontent.com/jkomoros/prompt-garden/main/seeds/example-basic.json',
'method': 'POST',
'body': ''
};
assert.deepStrictEqual(actual,golden);
});

});
Expand Down

0 comments on commit 97ab464

Please sign in to comment.