Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Insights client specs + javascript insights client #62

Merged
merged 14 commits into from
Jan 6, 2022
7 changes: 7 additions & 0 deletions .github/actions/cache/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ runs:
path: /home/runner/work/api-clients-automation/api-clients-automation/clients/algoliasearch-client-javascript/client-analytics/dist
key: ${{ runner.os }}-js-client-analytics-${{ hashFiles('clients/algoliasearch-client-javascript/client-analytics/**') }}

- name: Restore built JavaScript insights client
if: ${{ inputs.job == 'cts' }}
uses: actions/cache@v2
with:
path: /home/runner/work/api-clients-automation/api-clients-automation/clients/algoliasearch-client-javascript/client-insights/dist
key: ${{ runner.os }}-js-client-insights-${{ hashFiles('clients/algoliasearch-client-javascript/client-insights/**') }}

- name: Restore built Java client
if: ${{ inputs.job == 'cts' }}
uses: actions/cache@v2
Expand Down
4 changes: 4 additions & 0 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ runs:
echo "::set-output name=JS_RECOMMEND_CLIENT_CHANGED::$(git diff --shortstat origin/${{ github.base_ref }}..HEAD -- clients/algoliasearch-client-javascript/recommend | wc -l)"
echo "::set-output name=JS_PERSO_CLIENT_CHANGED::$(git diff --shortstat origin/${{ github.base_ref }}..HEAD -- clients/algoliasearch-client-javascript/client-personalization | wc -l)"
echo "::set-output name=JS_ANALYTICS_CLIENT_CHANGED::$(git diff --shortstat origin/${{ github.base_ref }}..HEAD -- clients/algoliasearch-client-javascript/client-analytics | wc -l)"
echo "::set-output name=JS_INSIGHTS_CLIENT_CHANGED::$(git diff --shortstat origin/${{ github.base_ref }}..HEAD -- clients/algoliasearch-client-javascript/client-insights | wc -l)"
echo "::set-output name=JS_TEMPLATE_CHANGED::$(git diff --shortstat origin/${{ github.base_ref }}..HEAD -- templates/javascript | wc -l)"

echo "::set-output name=JAVA_CLIENT_CHANGED::$(git diff --shortstat origin/${{ github.base_ref }}..HEAD -- clients/algoliasearch-client-java-2 | wc -l)"
Expand Down Expand Up @@ -88,6 +89,9 @@ outputs:
RUN_JS_CLIENT_ANALYTICS:
description: Determine if the `client_javascript_analytics` job should run
value: ${{ github.ref == 'refs/heads/main' || steps.diff.outputs.GITHUB_ACTIONS_CHANGED > 0 || steps.diff.outputs.COMMON_SPECS_CHANGED > 0 || steps.diff.outputs.ANALYTICS_SPECS_CHANGED > 0 || steps.diff.outputs.SCRIPTS_CHANGED > 0 || steps.diff.outputs.JS_ANALYTICS_CLIENT_CHANGED > 0 || steps.diff.outputs.JS_TEMPLATE_CHANGED > 0 }}
RUN_JS_CLIENT_INSIGHTS:
description: Determine if the `client_javascript_insights` job should run
value: ${{ github.ref == 'refs/heads/main' || steps.diff.outputs.GITHUB_ACTIONS_CHANGED > 0 || steps.diff.outputs.COMMON_SPECS_CHANGED > 0 || steps.diff.outputs.INSIGHTS_SPECS_CHANGED > 0 || steps.diff.outputs.SCRIPTS_CHANGED > 0 || steps.diff.outputs.JS_INSIGHTS_CLIENT_CHANGED > 0 || steps.diff.outputs.JS_TEMPLATE_CHANGED > 0 }}

# java client variables
RUN_JAVA_CLIENT:
Expand Down
43 changes: 43 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ jobs:
RUN_JS_CLIENT_RECOMMEND: ${{ steps.setup.outputs.RUN_JS_CLIENT_RECOMMEND }}
RUN_JS_CLIENT_PERSO: ${{ steps.setup.outputs.RUN_JS_CLIENT_PERSO }}
RUN_JS_CLIENT_ANALYTICS: ${{ steps.setup.outputs.RUN_JS_CLIENT_ANALYTICS }}
RUN_JS_CLIENT_INSIGHTS: ${{ steps.setup.outputs.RUN_JS_CLIENT_INSIGHTS }}

RUN_JAVA_CLIENT: ${{ steps.setup.outputs.RUN_JAVA_CLIENT }}

Expand Down Expand Up @@ -107,6 +108,22 @@ jobs:
- name: Lint analytics specs
run: yarn eslint --ext=yml specs/analytics

specs_insights:
runs-on: ubuntu-20.04
needs: setup
if: ${{ always() && needs.setup.outputs.RUN_SPECS_INSIGHTS == 'true' }}
steps:
- uses: actions/checkout@v2

- name: Restore cache
uses: ./.github/actions/cache

- name: Checking insights specs
run: yarn build:specs insights

- name: Lint insights specs
run: yarn eslint --ext=yml specs/insights

client_javascript_search:
runs-on: ubuntu-20.04
needs: [specs_search]
Expand Down Expand Up @@ -207,6 +224,31 @@ jobs:
if: steps.cache.outputs.cache-hit != 'true'
run: yarn build:clients javascript analytics

client_javascript_insights:
runs-on: ubuntu-20.04
needs: [specs_insights]
if: ${{ always() && needs.setup.outputs.RUN_JS_CLIENT_INSIGHTS == 'true' }}
steps:
- uses: actions/checkout@v2

- name: Restore cache
uses: ./.github/actions/cache

- name: Cache insights client
id: cache
uses: actions/cache@v2
with:
path: /home/runner/work/api-clients-automation/api-clients-automation/clients/algoliasearch-client-javascript/client-insights/dist
key: ${{ runner.os }}-js-client-insights-${{ hashFiles('clients/algoliasearch-client-javascript/client-insights/**') }}

- name: Generate insights client
if: steps.cache.outputs.cache-hit != 'true'
run: yarn generate javascript insights

- name: Build insights client
if: steps.cache.outputs.cache-hit != 'true'
run: yarn build:clients javascript insights

client_java_search:
runs-on: ubuntu-20.04
needs: [specs_search]
Expand Down Expand Up @@ -241,6 +283,7 @@ jobs:
- client_javascript_recommend
- client_javascript_perso
- client_javascript_analytics
- client_javascript_insights
- client_java_search

if: ${{ always() && needs.setup.outputs.RUN_CTS == 'true' }}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
dist
.openapi-generator
.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# OpenAPI Generator Ignore
damcou marked this conversation as resolved.
Show resolved Hide resolved
# Generated by openapi-generator https://github.com/openapitools/openapi-generator

# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.

git_push.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// This is the entrypoint for the package
export * from './src/apis';
export * from './model/models';
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* Error.
*/
export type ErrorBase = {
message?: string;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Insights event.
*/
export type InsightEvent = {
/**
* An eventType can be a click, a conversion, or a view.
*/
eventType: InsightEvent.EventTypeEnum;
/**
* A user-defined string used to categorize events.
*/
eventName: string;
/**
* Name of the targeted index.
*/
index: string;
/**
* A user identifier. Depending if the user is logged-in or not, several strategies can be used from a sessionId to a technical identifier.
*/
userToken: string;
/**
* Time of the event expressed in milliseconds since the Unix epoch.
*/
timestamp?: number;
/**
* Algolia queryID. This is required when an event is tied to a search.
*/
queryID?: string;
/**
* An array of index objectID. Limited to 20 objects. An event can’t have both objectIDs and filters at the same time.
*/
objectIDs?: string[];
/**
* An array of filters. Limited to 10 filters. An event can’t have both objectIDs and filters at the same time.
*/
filters?: string[];
/**
* Position of the click in the list of Algolia search results. This field is required if a queryID is provided. One position must be provided for each objectID.
*/
positions?: number[];
};

export namespace InsightEvent {
export enum EventTypeEnum {
Click = 'click',
Conversion = 'conversion',
View = 'view',
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { InsightEvent } from './insightEvent';

/**
* Object containing the events sent.
*/
export type InsightEvents = {
/**
* Array of events sent.
*/
events: InsightEvent[];
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* eslint-disable no-param-reassign */
import type { RequestOptions } from '../utils/types';

export * from './errorBase';
export * from './insightEvent';
export * from './insightEvents';
export * from './pushEventsResponse';

export interface Authentication {
/**
* Apply authentication settings to header and query params.
*/
applyToRequest: (requestOptions: RequestOptions) => Promise<void> | void;
}

export class ApiKeyAuth implements Authentication {
apiKey: string = '';

constructor(private location: string, private paramName: string) {}

applyToRequest(requestOptions: RequestOptions): void {
if (this.location === 'query') {
requestOptions.queryParameters[this.paramName] = this.apiKey;
} else if (
this.location === 'header' &&
requestOptions &&
requestOptions.headers
) {
requestOptions.headers[this.paramName] = this.apiKey;
} else if (
this.location === 'cookie' &&
requestOptions &&
requestOptions.headers
) {
if (requestOptions.headers.Cookie) {
requestOptions.headers.Cookie += `; ${
this.paramName
}=${encodeURIComponent(this.apiKey)}`;
} else {
requestOptions.headers.Cookie = `${this.paramName}=${encodeURIComponent(
this.apiKey
)}`;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export type PushEventsResponse = {
/**
* A message confirming the event push.
*/
message: string;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "@algolia/client-insights",
"version": "5.0.0",
"description": "JavaScript client for @algolia/client-insights",
"repository": "algolia/algoliasearch-client-javascript",
"author": "Algolia",
"private": true,
"license": "MIT",
"main": "dist/api.js",
"types": "dist/api.d.ts",
"scripts": {
"clean": "rm -Rf node_modules/ *.js",
"build": "tsc",
"test": "yarn build && node dist/client.js"
},
"engines": {
"node": "^16.0.0",
"yarn": "^3.0.0"
},
"devDependencies": {
"@types/node": "16.11.11",
"typescript": "4.5.4"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { InsightsApi } from './insightsApi';

export * from './insightsApi';
export * from '../utils/errors';
export { EchoRequester } from '../utils/requester/EchoRequester';

export const APIS = [InsightsApi];
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import type { InsightEvents } from '../model/insightEvents';
import { ApiKeyAuth } from '../model/models';
import type { PushEventsResponse } from '../model/pushEventsResponse';
import { Transporter } from '../utils/Transporter';
import type { Requester } from '../utils/requester/Requester';
import type { Headers, Host, Request, RequestOptions } from '../utils/types';

export enum InsightsApiKeys {
apiKey,
appId,
}

export class InsightsApi {
protected authentications = {
apiKey: new ApiKeyAuth('header', 'X-Algolia-API-Key'),
appId: new ApiKeyAuth('header', 'X-Algolia-Application-Id'),
};

private transporter: Transporter;

private sendRequest<TResponse>(
request: Request,
requestOptions: RequestOptions
): Promise<TResponse> {
if (this.authentications.apiKey.apiKey) {
this.authentications.apiKey.applyToRequest(requestOptions);
}

if (this.authentications.appId.apiKey) {
this.authentications.appId.applyToRequest(requestOptions);
}

return this.transporter.request(request, requestOptions);
}

constructor(
appId: string,
apiKey: string,
options?: { requester?: Requester; hosts?: Host[] }
) {
this.setApiKey(InsightsApiKeys.appId, appId);
this.setApiKey(InsightsApiKeys.apiKey, apiKey);

this.transporter = new Transporter({
hosts: options?.hosts ?? this.getDefaultHosts(),
baseHeaders: {
'content-type': 'application/x-www-form-urlencoded',
},
userAgent: 'Algolia for Javascript',
timeouts: {
connect: 2,
read: 5,
write: 30,
},
requester: options?.requester,
});
}

getDefaultHosts(): Host[] {
return [
{ url: `insights.algolia.io`, accept: 'readWrite', protocol: 'https' },
];
}

setRequest(requester: Requester): void {
this.transporter.setRequester(requester);
}

setHosts(hosts: Host[]): void {
this.transporter.setHosts(hosts);
}

setApiKey(key: InsightsApiKeys, value: string): void {
this.authentications[InsightsApiKeys[key]].apiKey = value;
}

/**
* This command pushes an array of events.
*
* @summary Pushes an array of events.
* @param pushEvents - The pushEvents parameters.
* @param pushEvents.insightEvents - The insightEvents.
*/
pushEvents({ insightEvents }: PushEventsProps): Promise<PushEventsResponse> {
const path = '/1/events';
const headers: Headers = { Accept: 'application/json' };
const queryParameters: Record<string, string> = {};

if (insightEvents === null || insightEvents === undefined) {
throw new Error(
'Required parameter insightEvents was null or undefined when calling pushEvents.'
);
}

if (insightEvents.events === null || insightEvents.events === undefined) {
throw new Error(
'Required parameter insightEvents.events was null or undefined when calling pushEvents.'
);
}

const request: Request = {
method: 'POST',
path,
data: insightEvents,
};

const requestOptions: RequestOptions = {
headers,
queryParameters,
};

return this.sendRequest(request, requestOptions);
}
}

export type PushEventsProps = {
insightEvents: InsightEvents;
};
Loading