Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@getlang/get

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@getlang/get - npm Package Compare versions

Comparing version 0.0.1 to 0.0.2

assets/hero.dark.png

2

dist/ast/print.js

@@ -155,3 +155,3 @@ import { doc } from 'prettier';

const quot = value.includes('`') ? '```' : '`';
const lines = value.replace(/`/g, '\\`').split('\n');
const lines = value.split('\n');
return group([

@@ -158,0 +158,0 @@ quot,

@@ -0,1 +1,2 @@

import type { MaybePromise } from '../utils';
import type { Node, Stmt, Expr } from './ast';

@@ -12,3 +13,2 @@ export declare const SKIP: {

};
type MaybePromise<T> = T | Promise<T>;
type NodeConfig<N extends Node, S, E, A extends boolean = false, TN = TransformNode<N, S, E>, XN = Transform<N, S, E>, Visit = <C extends Node>(child: C) => Transform<C, S, E>, EntryVisitor = (node: N, visit: Visit) => A extends true ? MaybePromise<TN | void | Control> : TN | void | Control, ExitVisitor = (node: TN, originalNode: N) => A extends true ? MaybePromise<XN> : XN, EntryExitVisitor = (node: N, visit: Visit) => A extends true ? MaybePromise<XN | Control> : XN | Control> = ExitVisitor | {

@@ -15,0 +15,0 @@ enter?: EntryVisitor;

@@ -0,1 +1,2 @@

import { wait, waitMap } from '../utils';
import { NodeKind } from './ast';

@@ -35,9 +36,1 @@ export const SKIP = { __skip: true };

}
function wait(value, then) {
return value instanceof Promise ? value.then(then) : then(value);
}
function waitMap(values, mapper) {
return values.reduce((acc, value) => acc instanceof Promise
? acc.then(async (acc) => [...acc, await mapper(value)])
: wait(mapper(value), value => [...acc, value]), []);
}

@@ -47,2 +47,5 @@ export declare abstract class RuntimeError extends Error {

}
export declare class ImportError extends RuntimeError {
name: string;
}
export declare function invariant(condition: unknown, err: string | RuntimeError): asserts condition;

@@ -69,2 +69,5 @@ export class RuntimeError extends Error {

}
export class ImportError extends RuntimeError {
name = 'ImportError';
}
export function invariant(condition, err) {

@@ -71,0 +74,0 @@ if (!condition) {

import type { Program } from '../ast/ast';
import * as http from './net/http';
export declare function execute(program: Program, inputs: Record<string, unknown>, requestFn?: http.RequestFn): Promise<unknown>;
export type InternalHooks = {
request: http.RequestHook;
import: (module: string) => Program | Promise<Program>;
};
declare class Modules {
private importHook;
private cache;
constructor(importHook: InternalHooks['import']);
import(module: string): Program | Promise<Program>;
get(module: string): Program | Promise<Program> | undefined;
}
export declare function execute(program: Program, inputs: Record<string, unknown>, hooks: InternalHooks, modules?: Modules): Promise<unknown>;
export {};

@@ -6,3 +6,3 @@ import { visit, SKIP } from '../ast/visitor';

import * as type from './value';
import { invariant, NullSelectionError, ReferenceError, SyntaxError, } from '../errors';
import { invariant, NullSelectionError, ReferenceError, SyntaxError, ImportError, } from '../errors';
import * as http from './net/http';

@@ -15,2 +15,16 @@ import * as html from './values/html';

import { select } from './select';
class Modules {
importHook;
cache = {};
constructor(importHook) {
this.importHook = importHook;
}
import(module) {
return (this.cache[module] ??= this.importHook(module));
}
get(module) {
return this.cache[module];
}
}
Headers;
function toValue(value) {

@@ -23,2 +37,5 @@ if (value instanceof type.Html) {

}
else if (value instanceof type.Headers) {
return Object.fromEntries(value.raw);
}
else if (value instanceof type.CookieSet) {

@@ -34,3 +51,3 @@ return Object.fromEntries(Object.entries(value.raw).map(e => [e[0], e[1].value]));

}
export async function execute(program, inputs, requestFn) {
export async function execute(program, inputs, hooks, modules = new Modules(hooks.import)) {
const scope = new RootScope();

@@ -40,6 +57,18 @@ let optional = [false];

const visitor = {
DeclImportStmt() { },
ModuleCallExpr() {
return new type.Value('TODO', null);
async DeclImportStmt(node) {
const module = node.id.value;
try {
await modules.import(module);
}
catch (e) {
throw new ImportError(`Failed to import module: ${module}`);
}
},
async ModuleCallExpr(node) {
const module = node.name.value;
const external = await modules.get(module);
invariant(external, new ReferenceError(module));
const output = await execute(external, node.args.raw, hooks, modules);
return new type.Value(output, null);
},
/**

@@ -58,7 +87,14 @@ * Expression nodes

invariant(value, new ReferenceError(node.value.value));
if (value instanceof type.Null) {
invariant(allowNull(), new NullSelectionError(value.selector));
}
return value;
},
async SliceExpr(node) {
const value = await lang.runSlice(node.slice.value, scope.context?.raw);
return value === null ? new type.Null() : new type.Value(value, null);
const { slice } = node;
const fauxSelector = `slice@${slice.line}:${slice.col}`;
const value = await lang.runSlice(slice.value, scope.context?.raw);
return value === null
? new type.Null(fauxSelector)
: new type.Value(value, null);
},

@@ -71,4 +107,4 @@ DrillExpr: {

if (context instanceof type.Null) {
invariant(allowNull(), new NullSelectionError('...'));
return new type.Null();
invariant(allowNull(), new NullSelectionError(context.selector));
return context;
}

@@ -118,3 +154,3 @@ const isListContext = context instanceof type.List;

return new type.CookieSet(cookies.parse(doc), context.base);
case 'resolve': {
case 'link': {
const resolved = http.constructUrl(context.raw, context.base ?? undefined);

@@ -124,4 +160,4 @@ if (resolved) {

}
invariant(allowNull(), new NullSelectionError('@resolve'));
return new type.Null();
invariant(allowNull(), new NullSelectionError('@link'));
return new type.Null('@link');
}

@@ -183,23 +219,29 @@ default:

exit(node) {
optional.pop();
scope.vars[node.name.value] = node.value;
},
},
RequestStmt: {
enter() {
optional.push(true);
},
async exit(node) {
optional.pop();
const method = node.method.value;
const url = node.url.raw;
const body = node.body?.raw || '';
invariant(typeof url === 'string', new TypeError('Request URL expected string'));
invariant(typeof body === 'string', new TypeError('Request body expected string'));
const obj = (entries) => {
const filteredEntries = entries.flatMap(e => e.key.hasUndefined || e.value.hasUndefined
? []
: [[e.key.raw, e.value.raw]]);
return Object.fromEntries(filteredEntries);
};
const headers = obj(node.headers);
const blocks = Object.fromEntries(Object.entries(node.blocks).map(e => [e[0], obj(e[1])]));
const res = await http.request(method, url, headers, blocks, body, hooks.request);
scope.pushContext(new type.Value({ ...res, headers: new type.Headers(res.headers, url) }, url));
},
},
async RequestStmt(node) {
const method = node.method.value;
const url = node.url.raw;
const body = node.body?.raw || '';
invariant(typeof url === 'string', new TypeError('Request URL expected string'));
invariant(typeof body === 'string', new TypeError('Request body expected string'));
const obj = (entries) => {
const filteredEntries = entries.flatMap(e => e.key.hasUndefined || e.value.hasUndefined
? []
: [[e.key.raw, e.value.raw]]);
return Object.fromEntries(filteredEntries);
};
const headers = obj(node.headers);
const blocks = Object.fromEntries(Object.entries(node.blocks).map(e => [e[0], obj(e[1])]));
const res = await http.request(method, url, headers, blocks, body, requestFn);
scope.pushContext(new type.Value({ ...res, headers: new type.Headers(res.headers, url) }, url));
},
ExtractStmt(node) {

@@ -206,0 +248,0 @@ scope.extracted = node.value;

@@ -0,4 +1,5 @@

/// <reference types="node" />
import type { Element } from 'domhandler';
type StringMap = Record<string, string>;
export type RequestFn = (url: string, opts: RequestOpts) => Promise<Response>;
export type RequestHook = (url: string, opts: RequestOpts) => Promise<Response>;
type RequestOpts = {

@@ -21,3 +22,4 @@ method?: string;

export declare const constructUrl: (elementOrString: string | Element, base: string | undefined) => string | null;
export declare const request: (method: string, url: string, _headers: StringMap, blocks: Blocks, bodyRaw: string, fetch?: RequestFn) => Promise<Response>;
export declare const requestHook: RequestHook;
export declare const request: (method: string, url: string, _headers: StringMap, blocks: Blocks, bodyRaw: string, hook: RequestHook) => Promise<Response>;
export {};

@@ -28,3 +28,3 @@ import { RequestError } from '../../errors';

};
const requestFn = async (url, opts) => {
export const requestHook = async (url, opts) => {
const res = await fetch(url, opts);

@@ -37,3 +37,3 @@ return {

};
export const request = async (method, url, _headers, blocks, bodyRaw, fetch = requestFn) => {
export const request = async (method, url, _headers, blocks, bodyRaw, hook) => {
// construct url

@@ -64,3 +64,3 @@ const finalUrl = new URL(url);

try {
return await fetch(urlString, { method, headers, body });
return await hook(urlString, { method, headers, body });
}

@@ -67,0 +67,0 @@ catch (e) {

@@ -18,3 +18,3 @@ import * as html from './values/html';

}
return new type.Null();
return new type.Null(args[0]);
}

@@ -21,0 +21,0 @@ export function select(context, ...args) {

@@ -0,1 +1,2 @@

/// <reference types="node" />
import type { AnyHtmlNode } from 'domhandler';

@@ -32,4 +33,5 @@ import type { AnyNode as AnyJsNode } from 'acorn';

export declare class Null extends Value {
selector: string;
raw: null;
constructor();
constructor(selector: string);
}

@@ -36,0 +38,0 @@ export declare class List<T extends Value> extends Value {

@@ -50,5 +50,7 @@ export class Value {

export class Null extends Value {
selector;
raw = null;
constructor() {
constructor(selector) {
super(null, null);
this.selector = selector;
}

@@ -55,0 +57,0 @@ }

@@ -0,2 +1,3 @@

/// <reference types="node" />
import type { SelectFn } from './types';
export declare const select: SelectFn<Headers, string>;
import { desugar } from './ast/simplified';
import { print } from './ast/print';
import type { Program } from './ast/ast';
import type { RequestFn } from './execute/net/http';
export type { RequestFn };
declare function parse(source: string): any;
declare function execute(source: string, inputs?: Record<string, unknown>, requestFn?: RequestFn): Promise<unknown>;
declare function executeAST(ast: Program, inputs?: Record<string, unknown>, requestFn?: RequestFn): Promise<unknown>;
import type { InternalHooks } from './execute/execute';
export type { Program };
export { NodeKind } from './ast/ast';
export { RuntimeError } from './errors';
declare function parse(source: string): Program;
export type RequestHook = InternalHooks['request'];
export type ImportHook = (module: string) => string | Promise<string>;
export type Hooks = Partial<{
request: RequestHook;
import: ImportHook;
}>;
declare function execute(source: string, inputs?: Record<string, unknown>, hooks?: Hooks): Promise<unknown>;
declare function executeAST(ast: Program, inputs?: Record<string, unknown>, hooks?: Hooks): Promise<unknown>;
export { parse, desugar, execute, print, executeAST };

@@ -7,3 +7,7 @@ import nearley from 'nearley';

import { execute as exec } from './execute/execute';
import { SyntaxError, invariant } from './errors';
import * as http from './execute/net/http';
import { SyntaxError, ImportError, invariant } from './errors';
import { wait } from './utils';
export { NodeKind } from './ast/ast';
export { RuntimeError } from './errors';
function parse(source) {

@@ -22,13 +26,24 @@ const parser = new nearley.Parser(nearley.Grammar.fromCompiled(grammar));

invariant(results.length !== 0, new SyntaxError('Unexpected end of input'));
invariant(results.length === 1, new SyntaxError('Ambiguous source'));
invariant(results.length === 1, new SyntaxError('Unexpected parsing error'));
return results[0];
}
function execute(source, inputs = {}, requestFn) {
function buildHooks(hooks = {}) {
return {
request: hooks.request ?? http.requestHook,
import: (module) => {
if (!hooks.import) {
throw new ImportError('Imports are not supported by the current runtime');
}
return wait(hooks.import(module), src => desugar(parse(src)));
},
};
}
function execute(source, inputs = {}, hooks) {
const ast = parse(source);
const simplified = desugar(ast);
return exec(simplified, inputs, requestFn);
return exec(simplified, inputs, buildHooks(hooks));
}
function executeAST(ast, inputs = {}, requestFn) {
return exec(ast, inputs, requestFn);
function executeAST(ast, inputs = {}, hooks) {
return exec(ast, inputs, buildHooks(hooks));
}
export { parse, desugar, execute, print, executeAST };

@@ -13,3 +13,3 @@ import moo from 'moo';

'cookies',
'resolve',
'link',
'headers',

@@ -16,0 +16,0 @@ 'cookies',

{
"name": "@getlang/get",
"version": "0.0.1",
"version": "0.0.2",
"license": "Apache-2.0",

@@ -8,3 +8,4 @@ "type": "module",

"files": [
"dist"
"dist",
"assets"
],

@@ -11,0 +12,0 @@ "dependencies": {

@@ -1,3 +0,6 @@

<p align="center"><img src="assets/hero.png"></p>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./assets/hero.dark.png">
<img alt="GETlang hero banner" src="./assets/hero.png">
</picture>
Visit [getlang.dev](https://getlang.dev) to view examples, documentation, and a space to try your first Get query!
Visit [getlang.dev](https://getlang.dev) to view examples, take a guided tour, or try your first GET query!
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc