Skip to content

Commit

Permalink
Merge branch 'master' into sam/24_11_07/feat/enforce-max-cli-version
Browse files Browse the repository at this point in the history
  • Loading branch information
bodinsamuel authored Nov 7, 2024
2 parents 776b688 + 41e9f44 commit e013469
Show file tree
Hide file tree
Showing 30 changed files with 154 additions and 46 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ GOOGLE_APPLICATION_CREDENTIALS=

# Key to send email
MAILGUN_API_KEY=
# MAILGUN_URL=

# Redis (optional)
#NANGO_REDIS_URL=
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/build-image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- master
- staging/**
pull_request:
merge_group:

jobs:
build-image:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/build-images.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
- master
- staging/**
pull_request:
merge_group:

concurrency:
group: pulls/${{ github.event.pull_request.number || github.ref }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/cli-verification.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- master
- staging/**
pull_request:
merge_group:

concurrency:
group: verify-cli-${{ github.event.pull_request.number || github.ref }}
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,6 @@ jobs:
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Push tag
run: |
docker buildx imagetools create nangohq/nango-jobs:${{ github.sha }} --tag nangohq/nango-jobs:${{ inputs.stage }}
- name: Deploy jobs
run: |
SERVICE_ID=${{ fromJson('{ production: "srv-clvvtdug1b2c73cklps0", staging: "srv-clthttda73kc73ejflg0" }')[inputs.stage] }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- master
- staging/**
pull_request:
merge_group:

concurrency:
group: docker-${{ github.event.pull_request.number || github.ref }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/lint-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- opened
- edited
- synchronize
merge_group:

permissions:
pull-requests: read
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- master
- staging/**
pull_request:
merge_group:

jobs:
lint-code:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/tests-cli-windows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- master
- staging/**
pull_request:
merge_group:

concurrency:
group: tests-windows/${{ github.event.pull_request.number || github.ref }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/tests-node-client.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- master
- staging/**
pull_request:
merge_group:

concurrency:
group: tests-node-client/${{ github.event.pull_request.number || github.ref }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- master
- staging/**
pull_request:
merge_group:

concurrency:
group: tests-${{ github.event.pull_request.number || github.ref }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/validation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- master
- staging/**
pull_request:
merge_group:

concurrency:
group: validation-${{ github.event.pull_request.number || github.ref }}
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ Nango is a single API to interact with all other external APIs. It should be the

<img src="/docs-v2/images/overview.png">

## 👩‍💻 Sample code
# 📺 Demo video

[![what-is-nango](/docs-v2/images/video-thumbnail.png)](https://www.youtube.com/watch?v=pvUpbi04IjQ)

# 👩‍💻 Sample code

Initiate a new OAuth flow from your frontend:

Expand All @@ -47,7 +51,7 @@ nango.listRecords<GithubIssue>({
});
```

# 👩🏻‍🔧 Choose your level of service
# 👩🏻‍🔧 Pre-built and custom integrations

Nango's flexibility ensures it supports any API integration:

Expand Down
Binary file modified docs-v2/images/overview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs-v2/images/video-thumbnail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 13 additions & 8 deletions docs-v2/introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ Nango is a single API to interact with all other external APIs. It should be the
<img src="/images/overview.png" />
</Frame>

# 📺 Demo video

<div style={{ position: 'relative', overflow: 'hidden', paddingTop: '56.25%' }}>
<iframe
style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }}
src="https://www.youtube.com/embed/pvUpbi04IjQ"
title="YouTube video player"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
></iframe>
</div>

# 👩‍💻 Sample code

Initiate a new OAuth flow from your frontend:
Expand Down Expand Up @@ -53,14 +66,6 @@ Nango's flexibility ensures it supports any API integration:

But remember, Nango can work with **any API and any use-case**!

# 📺 Demo video



<div style={{position: 'relative', overflow: 'hidden', paddingTop: '56.25%'}}>
<iframe style={{position: 'absolute', top: 0, left: 0, width: '100%', height: '100%'}} src="https://www.loom.com/embed/d04c67b47e284e86b91b4b99fba548ec?sid=04100b13-c53b-47ce-8150-1a495771ee3f"></iframe>
</div>

# 🚀 Get started

Sign up for free and try the interactive demo:
Expand Down
2 changes: 1 addition & 1 deletion packages/connect-ui/src/views/Go.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ export const Go: React.FC = () => {
{shouldAutoTrigger && (
<div className="text-sm text-dark-500 w-full text-center">
We will connect you to {provider.display_name}
{provider.auth_mode === 'OAUTH2' && ". A popup will open, please make sure your browser don't block popup"}
{provider.auth_mode === 'OAUTH2' && ". A popup will open, please make sure your browser doesn't block popups"}
</div>
)}
<div className="flex flex-col gap-4">
Expand Down
2 changes: 1 addition & 1 deletion packages/logs/lib/models/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,5 +138,5 @@ export const operationTypeToMessage: Record<ConcatOperationList, string> = {
'sync:run': 'Sync execution',
'sync:unpause': 'Sync schedule started',
'webhook:incoming': 'Received a webhook',
'webhook:outgoing': 'Forwarding Webhook'
'webhook:forward': 'Forwarding Webhook'
};
13 changes: 10 additions & 3 deletions packages/logs/lib/models/insights.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import type { estypes } from '@elastic/elasticsearch';
import { indexMessages } from '../es/schema.js';
import { client } from '../es/client.js';
import type { InsightsHistogramEntry } from '@nangohq/types';
import type { ConcatOperationList, InsightsHistogramEntry, OperationList } from '@nangohq/types';

export async function retrieveInsights(opts: { accountId: number; environmentId: number; type: string }) {
export async function retrieveInsights(opts: { accountId: number; environmentId: number; type: OperationList['type'] | ConcatOperationList }) {
const query: estypes.QueryDslQueryContainer = {
bool: {
must: [{ term: { accountId: opts.accountId } }, { term: { environmentId: opts.environmentId } }, { term: { 'operation.type': opts.type } }],
must: [{ term: { accountId: opts.accountId } }, { term: { environmentId: opts.environmentId } }],
must_not: { exists: { field: 'parentId' } },
should: []
}
};

if (opts.type.includes(':')) {
const split = opts.type.split(':');
(query.bool!.must! as estypes.QueryDslQueryContainer[]).push({ term: { 'operation.type': split[0] } }, { term: { 'operation.action': split[1] } });
} else {
(query.bool!.must! as estypes.QueryDslQueryContainer[]).push({ term: { 'operation.type': opts.type } });
}

const res = await client.search<
never,
{
Expand Down
9 changes: 6 additions & 3 deletions packages/server/lib/clients/email.client.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import formData from 'form-data';
import Mailgun from 'mailgun.js';
import { getLogger } from '@nangohq/utils';
import type Client from 'mailgun.js/client';

const logger = getLogger('Server.EmailClient');

export class EmailClient {
private static instance: EmailClient | undefined;
private client: any;
private client: Client;

private constructor(config: { username: string; key: string }) {
private constructor(config: { username: string; key: string; url?: string }) {
const mailgun = new Mailgun(formData);
this.client = mailgun.client(config);
}
Expand All @@ -17,7 +18,8 @@ export class EmailClient {
if (!EmailClient.instance) {
EmailClient.instance = new EmailClient({
username: 'api',
key: process.env['MAILGUN_API_KEY'] || 'EMPTY'
key: process.env['MAILGUN_API_KEY'] || 'EMPTY',
url: process.env['MAILGUN_URL'] || ''
});
}
return EmailClient.instance;
Expand All @@ -31,6 +33,7 @@ export class EmailClient {
logger.info(html);
return;
}

return this.client.messages.create('email.nango.dev', {
from: 'Nango <[email protected]>',
to: [email],
Expand Down
2 changes: 1 addition & 1 deletion packages/server/lib/controllers/v1/logs/postInsights.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { envs, modelOperations } from '@nangohq/logs';

const validation = z
.object({
type: z.enum(['sync', 'action', 'proxy', 'webhook_external'])
type: z.enum(['sync', 'action', 'proxy', 'webhook:incoming'])
})
.strict();

Expand Down
3 changes: 2 additions & 1 deletion packages/types/lib/logs/api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable @typescript-eslint/no-redundant-type-constituents */
import type { Endpoint } from '../api';
import type { PickFromUnion } from '../utils';
import type { MessageRow, MessageState, OperationList, OperationRow } from './messages';

type Concat<T extends OperationList> = T extends { action: string } ? `${T['type']}:${T['action']}` : never;
Expand Down Expand Up @@ -81,7 +82,7 @@ export type PostInsights = Endpoint<{
Path: '/api/v1/logs/insights';
Querystring: { env: string };
Body: {
type: 'action' | 'sync' | 'proxy' | 'webhook_external';
type: PickFromUnion<ConcatOperationListWithGroup, 'action' | 'sync' | 'proxy' | 'webhook:incoming'>;
};
Success: {
data: {
Expand Down
2 changes: 1 addition & 1 deletion packages/types/lib/logs/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export interface OperationAdmin {
}
export interface OperationWebhook {
type: 'webhook';
action: 'incoming' | 'outgoing';
action: 'incoming' | 'forward';
}
export interface OperationDeploy {
type: 'deploy';
Expand Down
3 changes: 3 additions & 0 deletions packages/types/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ export interface Logger {
debug: LogMethod;
child: (...message: any[]) => Logger;
}

type ValidateSelection<T, U> = U extends T ? U : never;
export type PickFromUnion<T, U extends T> = ValidateSelection<T, U>;
1 change: 1 addition & 0 deletions packages/utils/lib/environment/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export const ENVS = z.object({

// Mailgun
MAILGUN_API_KEY: z.string().optional(),
MAILGUN_URL: z.string().url().optional(),

// Postgres
NANGO_DATABASE_URL: z.string().url().optional(),
Expand Down
67 changes: 67 additions & 0 deletions packages/webapp/src/components/CopyText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useState, useEffect, useRef } from 'react';
import type { ClassValue } from 'clsx';
import { Tooltip, TooltipContent, TooltipTrigger } from './ui/Tooltip';
import { IconCopy } from '@tabler/icons-react';
import { cn } from '../utils/utils';

export const CopyText: React.FC<{ text: string; showOnHover?: boolean; className?: ClassValue }> = ({ text, showOnHover, className }) => {
const [tooltipText, setTooltipText] = useState('Copy');
const triggerRef = useRef(null);

const copyToClipboard = async (e: React.MouseEvent) => {
try {
e.stopPropagation();
e.preventDefault();
await navigator.clipboard.writeText(text);
setTooltipText('Copied');
} catch (err) {
//this should never happen!
console.error('Failed to copy:', err);
}
};

useEffect(() => {
const timer = setTimeout(() => {
setTooltipText('Copy');
}, 1000);

return () => {
clearTimeout(timer);
};
}, [tooltipText]);

return (
<Tooltip delayDuration={0}>
<TooltipTrigger asChild>
<button
className={cn(
'group transition-colors inline-flex max-w-full items-center gap-1.5 text-dark-400 border border-transparent px-2 py-0.5 rounded-md hover:border-dark-500 hover:text-white',
'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',
className
)}
onClick={copyToClipboard}
ref={triggerRef}
>
<div className="truncate">{text}</div>
<div className={cn('text-xs text-white', showOnHover && 'transition-opacity opacity-0 group-hover:opacity-100')}>
<IconCopy stroke={1} size={15} />
</div>
</button>
</TooltipTrigger>
<TooltipContent
sideOffset={10}
align="end"
className="text-white"
onPointerDownOutside={(event) => {
// Radix assume a click on a tooltip should close it
// https://github.com/radix-ui/primitives/issues/2029
if (event.target === triggerRef.current || (event.target as any).parentNode === triggerRef.current) {
event.preventDefault();
}
}}
>
{tooltipText}
</TooltipContent>
</Tooltip>
);
};
16 changes: 8 additions & 8 deletions packages/webapp/src/pages/Connection/Authorization.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import PrismPlus from '../../components/ui/prism/PrismPlus';
import type { ActiveLog, ApiConnectionFull, ApiEndUser } from '@nangohq/types';
import { formatDateToShortUSFormat } from '../../utils/utils';
import SecretInput from '../../components/ui/input/SecretInput';
import { CopyButton } from '../../components/ui/button/CopyButton';
import TagsInput from '../../components/ui/input/TagsInput';
import type React from 'react';
import { apiRefreshConnection } from '../../hooks/useConnections';
Expand All @@ -15,6 +14,7 @@ import { mutate } from 'swr';
import { getLogsUrl } from '../../utils/logs';
import { Info } from '../../components/Info';
import { Link } from 'react-router-dom';
import { CopyText } from '../../components/CopyText';

interface AuthorizationProps {
connection: ApiConnectionFull;
Expand Down Expand Up @@ -58,6 +58,13 @@ export const Authorization: React.FC<AuthorizationProps> = ({ connection, errorL
</div>
)}
<div className="grid grid-cols-3 gap-5">
<div className="flex flex-col">
<span className="text-gray-400 text-xs uppercase mb-1">Connection ID</span>
<div className="text-s -ml-2">
<CopyText text={connection.connection_id} className=" text-white" />
</div>
</div>

{endUser?.id && (
<div className="flex flex-col">
<span className="text-gray-400 text-xs uppercase mb-1">User ID</span>
Expand Down Expand Up @@ -110,13 +117,6 @@ export const Authorization: React.FC<AuthorizationProps> = ({ connection, errorL
<span className="text-white">{formatDateToShortUSFormat(connection.credentials.expires_at.toString())}</span>
</div>
)}
<div className="flex flex-col">
<span className="text-gray-400 text-xs uppercase mb-1">Connection ID</span>
<div className="flex items-center gap-2">
<span className="text-white break-all font-code text-xs">{connection.connection_id}</span>
<CopyButton text={connection.connection_id} />
</div>
</div>
</div>

{connection.credentials &&
Expand Down
Loading

0 comments on commit e013469

Please sign in to comment.