Milestone 0: import zappier billing, Verae middleware, and Zapier research

Compose-ready workspace: packages/zappier (rate card, portal, Stripe),
packages/verae-zapier-middleware (timestamp + NATS), packages/verae-zapier
(CLI app), vendor/zapier-platform, and research/zapier vendor corpus.

Gate 0 structure checks pass. Product code and research are not yet wired.
This commit is contained in:
George Lambert 2026-09-09 02:37:36 -04:00
commit b4150c8250
1364 changed files with 6814366 additions and 0 deletions

View file

@ -0,0 +1,6 @@
build
docs
node_modules
*.log
.environment
.env

View file

@ -0,0 +1,7 @@
language: node_js
node_js:
- 8.10.0
before_script: 'npm install -g zapier-platform-cli'
script: 'zapier test'
notifications:
email: false

View file

@ -0,0 +1,5 @@
# "OAuth1" Twitter Example App For Zapier Platform
Requires CLI **7.5.0** and above! A barebones app that has OAuth1 setup, using Twitter for example.
> We recommend using the zapier-platform-cli and `zapier-platform init .`  to create an app - youll be presented with a list of currently available templates to start with.

View file

@ -0,0 +1,83 @@
const _ = require('lodash');
const REQUEST_TOKEN_URL = 'https://api.twitter.com/oauth/request_token';
const AUTHORIZE_URL = 'https://api.twitter.com/oauth/authorize';
const ACCESS_TOKEN_URL = 'https://api.twitter.com/oauth/access_token';
const getRequestToken = async (z, bundle) => {
const response = await z.request({
url: REQUEST_TOKEN_URL,
method: 'POST',
auth: {
oauth_consumer_key: process.env.CLIENT_ID,
oauth_consumer_secret: process.env.CLIENT_SECRET,
oauth_signature_method: 'HMAC-SHA1',
oauth_callback: bundle.inputData.redirect_uri,
oauth_version: '1.0', // Twitter says this should be 1.0
},
});
return response.data;
};
const getAccessToken = async (z, bundle) => {
const response = await z.request({
url: ACCESS_TOKEN_URL,
method: 'POST',
auth: {
oauth_consumer_key: process.env.CLIENT_ID,
oauth_consumer_secret: process.env.CLIENT_SECRET,
oauth_token: bundle.inputData.oauth_token,
oauth_token_secret: bundle.inputData.oauth_token_secret,
oauth_verifier: bundle.inputData.oauth_verifier,
},
});
return response.data;
};
const config = {
type: 'oauth1',
oauth1Config: {
// We have to define getRequestToken and getAccessToken functions to explicitly
// parse the response like it has a form body here, since Twitter responds
// 'text/html' for the Content-Type header
getRequestToken,
getAccessToken,
authorizeUrl: {
url: AUTHORIZE_URL,
params: {
oauth_token: '{{bundle.inputData.oauth_token}}',
},
},
},
test: {
url: 'https://api.twitter.com/1.1/account/settings.json',
},
connectionLabel: '{{screen_name}}',
};
// A middleware that is run before z.request() actually makes the request. Here we're
// adding necessary OAuth1 parameters to `auth` property of the request object.
const includeAccessToken = (req, z, bundle) => {
if (
bundle.authData &&
bundle.authData.oauth_token &&
bundle.authData.oauth_token_secret
) {
// Just put your OAuth1 credentials in req.auth, Zapier will sign the request for
// you.
req.auth = req.auth || {};
_.defaults(req.auth, {
oauth_consumer_key: process.env.CLIENT_ID,
oauth_consumer_secret: process.env.CLIENT_SECRET,
oauth_token: bundle.authData.oauth_token,
oauth_token_secret: bundle.authData.oauth_token_secret,
});
}
return req;
};
module.exports = {
config,
includeAccessToken,
};

View file

@ -0,0 +1,34 @@
const LikeTrigger = require('./triggers/like');
const authentication = require('./authentication');
// We can roll up all our behaviors in an App.
const App = {
// This is just shorthand to reference the installed dependencies you have. Zapier will
// need to know these before we can upload
version: require('./package.json').version,
platformVersion: require('zapier-platform-core').version,
authentication: authentication.config,
// beforeRequest & afterResponse are optional hooks into the provided HTTP client
beforeRequest: [authentication.includeAccessToken],
afterResponse: [],
// If you want to define optional resources to simplify creation of triggers, searches, creates - do that here!
resources: {},
// If you want your trigger to show up, you better include it here!
triggers: {
[LikeTrigger.key]: LikeTrigger,
},
// If you want your searches to show up, you better include it here!
searches: {},
// If you want your creates to show up, you better include it here!
creates: {},
};
// Finally, export the app.
module.exports = App;

View file

@ -0,0 +1,25 @@
{
"name": "zapier-platform-example-app-oauth1-twitter",
"version": "1.0.0",
"description": "An OAuth1 example using Twitter.",
"repository": "zapier/zapier-platform-example-app-oauth1-twitter",
"homepage": "https://zapier.com/",
"author": "Zapier <partners@zapier.com>",
"license": "BSD-3-Clause",
"main": "index.js",
"scripts": {
"test": "mocha --recursive"
},
"engines": {
"node": ">=8.10.0",
"npm": ">=5.6.0"
},
"dependencies": {
"zapier-platform-core": "19.1.0"
},
"devDependencies": {
"mocha": "^5.2.0",
"should": "^13.2.0"
},
"private": true
}

View file

@ -0,0 +1,110 @@
module.exports = {
key: 'like',
noun: 'Like',
display: {
label: 'New Like',
description: 'Triggers when you like a tweet.',
},
operation: {
perform: {
url: 'https://api.twitter.com/1.1/favorites/list.json',
},
sample: {
coordinates: null,
truncated: false,
favorited: true,
created_at: 'Tue Sep 04 15:55:52 +0000 2012',
id_str: '243014525132091393',
in_reply_to_user_id_str: null,
entities: {
urls: [],
hashtags: [],
user_mentions: [],
},
text: "Note to self: don't die during off-peak hours on a holiday weekend.",
contributors: null,
id: 243014525132091400,
retweet_count: 0,
in_reply_to_status_id_str: null,
geo: null,
retweeted: false,
in_reply_to_user_id: null,
in_reply_to_screen_name: null,
source: 'web',
user: {
profile_sidebar_fill_color: '252429',
profile_background_tile: true,
profile_sidebar_border_color: '181A1E',
name: 'Sean Cook',
profile_image_url:
'https://a0.twimg.com/profile_images/1751506047/dead_sexy_normal.JPG',
location: 'San Francisco',
created_at: 'Sat May 09 17:58:22 +0000 2009',
follow_request_sent: false,
is_translator: false,
id_str: '38895958',
profile_link_color: '2FC2EF',
entities: {
description: {
urls: [],
},
},
favourites_count: 594,
url: null,
default_profile: false,
contributors_enabled: true,
profile_image_url_https:
'https://si0.twimg.com/profile_images/1751506047/dead_sexy_normal.JPG',
utc_offset: -28800,
id: 38895958,
listed_count: 191,
profile_use_background_image: true,
followers_count: 10659,
protected: false,
profile_text_color: '666666',
lang: 'en',
profile_background_color: '1A1B1F',
time_zone: 'Pacific Time (US & Canada)',
verified: false,
profile_background_image_url_https:
'https://si0.twimg.com/profile_background_images/495742332/purty_wood.png',
description:
'I taught your phone that thing you like. The Mobile Partner Engineer @Twitter. ',
geo_enabled: true,
notifications: false,
default_profile_image: false,
friends_count: 1186,
profile_background_image_url:
'https://a0.twimg.com/profile_background_images/495742332/purty_wood.png',
statuses_count: 2629,
following: true,
screen_name: 'theSeanCook',
show_all_inline_media: true,
},
place: {
name: 'San Francisco',
country_code: 'US',
country: 'United States',
attributes: {},
url: 'https://api.twitter.com/1/geo/id/5a110d312052166f.json',
id: '5a110d312052166f',
bounding_box: {
coordinates: [
[
[-122.51368188, 37.70813196],
[-122.35845384, 37.70813196],
[-122.35845384, 37.83245301],
[-122.51368188, 37.83245301],
],
],
type: 'Polygon',
},
full_name: 'San Francisco, CA',
place_type: 'city',
},
in_reply_to_status_id: null,
},
},
};