@mindline/sync 1.0.104 → 1.0.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vs/VSWorkspaceState.json +0 -1
- package/.vs/slnx.sqlite +0 -0
- package/.vs/sync/CopilotIndices/17.14.260.54502/CodeChunks.db +0 -0
- package/.vs/sync/CopilotIndices/17.14.260.54502/SemanticSymbols.db +0 -0
- package/.vs/sync/FileContentIndex/069feaec-de6f-456e-9a9f-3a7edff9927d.vsidx +0 -0
- package/.vs/sync/FileContentIndex/3b17981b-603f-4e34-8b49-f18ef10f5f91.vsidx +0 -0
- package/.vs/sync/FileContentIndex/cce6d665-d5bc-4e83-b1ff-dabf19413432.vsidx +0 -0
- package/.vs/sync/v17/.wsuo +0 -0
- package/.vs/sync/v17/DocumentLayout.backup.json +3 -3
- package/.vs/sync/v17/DocumentLayout.json +9 -9
- package/dist/src/index.d.ts +9 -2
- package/dist/sync.es.js +705 -598
- package/dist/sync.es.js.map +1 -1
- package/dist/sync.umd.js +22 -15
- package/dist/sync.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/index.d.ts +4 -1
- package/src/index.ts +292 -15
- package/.vs/sync/FileContentIndex/3881c9ba-413d-444d-b9d4-43b79228192c.vsidx +0 -0
- package/.vs/sync/FileContentIndex/40eca9db-2eca-4bb1-b236-ef05624e799e.vsidx +0 -0
- package/.vs/sync/FileContentIndex/c2ebbf3f-6ffc-45f4-9e41-20101dcbfe33.vsidx +0 -0
- /package/.vs/sync/FileContentIndex/{00d0d744-d920-41f7-81bd-64419c4b96a9.vsidx → db560492-d007-4291-a6b3-50ccdcbd66b4.vsidx} +0 -0
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -337,7 +337,9 @@ declare module "@mindline/sync" {
|
|
|
337
337
|
export function usersGet(instance: IPublicClientApplication, user: User | undefined): { users: string[], error: string };
|
|
338
338
|
// ======================= Mindline SyncConfig API ===============================
|
|
339
339
|
export function auditConfigAdd(instance: IPublicClientApplication, user: User, ac: AuditConfig, debug: boolean): Promise<APIResult>;
|
|
340
|
-
export function auditConfigRetrieve(instance: IPublicClientApplication, user: User, debug: boolean): Promise<APIResult>;
|
|
340
|
+
export function auditConfigRetrieve(instance: IPublicClientApplication, user: User, configurationId: string, debug: boolean): Promise<APIResult>;
|
|
341
|
+
export function auditConfigEdit(instance: IPublicClientApplication, user: User, configurationId: string, config: AuditConfig, debug: boolean): Promise<APIResult>;
|
|
342
|
+
export function auditConfigRemove(instance: IPublicClientApplication, user: User, configurationId: string, debug: boolean): Promise<APIResult>;
|
|
341
343
|
export function auditEventsRetrieve(instance: IPublicClientApplication, user: User, debug: boolean): Promise<APIResult>;
|
|
342
344
|
export function configEdit(instance: IPublicClientApplication, authorizedUser: User, config: SyncConfig, setConfigId: (id: string) => void, setSelectedConfigs: (selectedConfigs: { [id: string]: boolean | number[] }) => void, workspace: Workspace, ii: InitInfo, debug: boolean): APIResult;
|
|
343
345
|
export function configEnable(instance: IPublicClientApplication, authorizedUser: User, configurationId: string, enabled: boolean, debug: boolean): APIResult;
|
|
@@ -351,6 +353,7 @@ declare module "@mindline/sync" {
|
|
|
351
353
|
export function userAdd(instance: IPublicClientApplication, authorizedUser: User, user: User, workspaceId: string): APIResult;
|
|
352
354
|
export function userRemove(instance: IPublicClientApplication, authorizedUser: User, user: User, workspaceId: string): APIResult;
|
|
353
355
|
export function workspaceEdit(instance: IPublicClientApplication, authorizedUser: User, workspaceId: string, workspaceName: string): Promise<APIResult>;
|
|
356
|
+
export function workspaceConfigsGet(instance: IPublicClientApplication, user: User, workspaceId: string, debug: boolean): Promise<APIResult>;
|
|
354
357
|
// ======================= PowerBI Access Token Retrieval ===============================
|
|
355
358
|
export function getPowerBIAccessToken(instance: IPublicClientApplication, user: User): Promise<string>;
|
|
356
359
|
// ======================= Azure REST API ===============================
|
package/src/index.ts
CHANGED
|
@@ -86,6 +86,9 @@ export class mindlineConfig {
|
|
|
86
86
|
static workspacesEndpoint(): string {
|
|
87
87
|
return `https://${mindlineConfig.environmentTag}-configurationapi-westus.azurewebsites.net/api/v1/workspaces`;
|
|
88
88
|
};
|
|
89
|
+
static workspaceConfigsEndpoint(): string {
|
|
90
|
+
return `https://${mindlineConfig.environmentTag}-configurationapi-westus.azurewebsites.net/api/v1/workspace-configurations`;
|
|
91
|
+
};
|
|
89
92
|
// SignalR endpoint
|
|
90
93
|
static signalREndpoint(): string {
|
|
91
94
|
return `https://${mindlineConfig.environmentTag}-signalrdispatcher-westus.azurewebsites.net/statsHub`;
|
|
@@ -2030,8 +2033,14 @@ export async function usersGet(instance: IPublicClientApplication, user: User |
|
|
|
2030
2033
|
export async function auditConfigAdd(instance: IPublicClientApplication, user: User, ac: AuditConfig, debug: boolean): Promise<APIResult> {
|
|
2031
2034
|
return auditConfigPost(instance, user, ac, debug);
|
|
2032
2035
|
}
|
|
2033
|
-
export async function auditConfigRetrieve(instance: IPublicClientApplication, user: User, debug: boolean): Promise<APIResult> {
|
|
2034
|
-
return auditConfigGet(instance, user, debug);
|
|
2036
|
+
export async function auditConfigRetrieve(instance: IPublicClientApplication, user: User, configurationId: string, debug: boolean): Promise<APIResult> {
|
|
2037
|
+
return auditConfigGet(instance, user, configurationId, debug);
|
|
2038
|
+
}
|
|
2039
|
+
export async function auditConfigEdit(instance: IPublicClientApplication, user: User, configurationId: string, config: AuditConfig, debug: boolean): Promise<APIResult> {
|
|
2040
|
+
return auditConfigPut(instance, user, configurationId, config, debug);
|
|
2041
|
+
}
|
|
2042
|
+
export async function auditConfigRemove(instance: IPublicClientApplication, user: User, configurationId: string, debug: boolean): Promise<APIResult> {
|
|
2043
|
+
return auditConfigDelete(instance, user, configurationId, debug);
|
|
2035
2044
|
}
|
|
2036
2045
|
export async function auditEventsRetrieve(instance: IPublicClientApplication, authorizedUser: User, debug: boolean): Promise<APIResult> {
|
|
2037
2046
|
return auditEventsGet(instance, authorizedUser, debug);
|
|
@@ -2098,30 +2107,44 @@ export async function configsRefresh(instance: IPublicClientApplication, authori
|
|
|
2098
2107
|
// clear SyncConfig associations as we are about to reset
|
|
2099
2108
|
workspace.associatedConfigs.length = 0;
|
|
2100
2109
|
// GET configs associated with this workspace
|
|
2101
|
-
let result: APIResult = await
|
|
2110
|
+
let result: APIResult = await workspaceConfigsGet(instance, authorizedUser, workspace.id, debug);
|
|
2102
2111
|
if (!result.result) return result;
|
|
2103
2112
|
// process returned workspace components
|
|
2104
2113
|
let configSelectedId: string = "";
|
|
2105
2114
|
for (let cid of workspace.associatedConfigs) {
|
|
2106
2115
|
let config = ii.cs.find((c: SyncConfig) => c.id === cid);
|
|
2107
2116
|
if (config != null && config.sel) {
|
|
2108
|
-
|
|
2117
|
+
ii.cs.find((c: SyncConfig) => c.id === cid) ??
|
|
2118
|
+
ii.acs.find((a: AuditConfig) => a.id === cid);
|
|
2119
|
+
|
|
2120
|
+
if (config && config.sel) {
|
|
2121
|
+
configSelectedId = config.id;
|
|
2122
|
+
}
|
|
2109
2123
|
}
|
|
2124
|
+
|
|
2125
|
+
// Pass combined list to processor
|
|
2126
|
+
processReturnedConfigs(workspace, ii, result.array!, configSelectedId);
|
|
2127
|
+
// tag components with workspaceIDs
|
|
2128
|
+
ii.tagWithWorkspaces();
|
|
2110
2129
|
}
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2130
|
+
return result;
|
|
2131
|
+
} else {
|
|
2132
|
+
// workspace not found
|
|
2133
|
+
result.result = false;
|
|
2134
|
+
result.error = "Workspace not found.";
|
|
2135
|
+
result.status = 404;
|
|
2136
|
+
return result;
|
|
2114
2137
|
}
|
|
2115
|
-
|
|
2116
|
-
}
|
|
2117
|
-
catch (error: any) {
|
|
2138
|
+
|
|
2139
|
+
} catch (error: any) {
|
|
2118
2140
|
console.log(error.message);
|
|
2119
2141
|
result.error = error.message;
|
|
2142
|
+
result.result = false;
|
|
2143
|
+
result.status = 500;
|
|
2144
|
+
return result;
|
|
2120
2145
|
}
|
|
2121
|
-
result.result = false;
|
|
2122
|
-
result.status = 500;
|
|
2123
|
-
return result;
|
|
2124
2146
|
}
|
|
2147
|
+
|
|
2125
2148
|
export async function configRemove(instance: IPublicClientApplication, authorizedUser: User, config: SyncConfig, workspaceId: string, debug: boolean): Promise<APIResult> {
|
|
2126
2149
|
return configDelete(instance, authorizedUser, config, workspaceId, debug);
|
|
2127
2150
|
}
|
|
@@ -2841,6 +2864,7 @@ export async function adminPost(
|
|
|
2841
2864
|
}
|
|
2842
2865
|
return result;
|
|
2843
2866
|
}
|
|
2867
|
+
|
|
2844
2868
|
//auditConfigPost: write audit config to back end
|
|
2845
2869
|
export async function auditConfigPost(
|
|
2846
2870
|
instance: IPublicClientApplication,
|
|
@@ -2904,14 +2928,197 @@ export async function auditConfigPost(
|
|
|
2904
2928
|
}
|
|
2905
2929
|
return result;
|
|
2906
2930
|
}
|
|
2907
|
-
|
|
2908
|
-
|
|
2931
|
+
|
|
2932
|
+
//auditConfigGET: get audit config from back end
|
|
2933
|
+
export async function auditConfigGet(
|
|
2934
|
+
instance: IPublicClientApplication,
|
|
2935
|
+
user: User,
|
|
2936
|
+
configurationId: string,
|
|
2937
|
+
debug: boolean): Promise<APIResult> {
|
|
2909
2938
|
instance = instance;
|
|
2910
2939
|
user = user;
|
|
2911
2940
|
debug = debug;
|
|
2941
|
+
|
|
2942
|
+
let result: APIResult = new APIResult();
|
|
2943
|
+
|
|
2944
|
+
// Validate user
|
|
2945
|
+
if (user.mail == undefined || user.mail == "") {
|
|
2946
|
+
result.result = false;
|
|
2947
|
+
result.status = 500;
|
|
2948
|
+
result.error = "auditConfigGet: no user provided";
|
|
2949
|
+
return result;
|
|
2950
|
+
}
|
|
2951
|
+
|
|
2952
|
+
//Validate input
|
|
2953
|
+
if (!configurationId || configurationId.trim() === "") {
|
|
2954
|
+
result.result = false;
|
|
2955
|
+
result.error = "auditConfigGet: configurationId is required";
|
|
2956
|
+
result.status = 500;
|
|
2957
|
+
return result;
|
|
2958
|
+
}
|
|
2959
|
+
|
|
2960
|
+
//Define endpoint with query parameter (configurationId)
|
|
2961
|
+
let endpoint: string = mindlineConfig.auditConfigEndpoint();
|
|
2962
|
+
let url: URL = new URL(`${endpoint}/${configurationId}`);
|
|
2963
|
+
|
|
2964
|
+
//Create headers with Entra ID token
|
|
2965
|
+
const headers = await mindlineDefineHeaders(instance, user);
|
|
2966
|
+
|
|
2967
|
+
let options = { method: "GET", headers: headers };
|
|
2968
|
+
|
|
2969
|
+
//Make the GET request
|
|
2970
|
+
try {
|
|
2971
|
+
if (debug) debugger;
|
|
2972
|
+
console.log("Attempting GET to /audit-configuration: " + url.href);
|
|
2973
|
+
|
|
2974
|
+
const response = await fetch(url.href, options);
|
|
2975
|
+
|
|
2976
|
+
if (response.status === 200 && response.statusText === "OK") {
|
|
2977
|
+
let data = await response.json();
|
|
2978
|
+
result.result = true;
|
|
2979
|
+
result.status = response.status;
|
|
2980
|
+
console.log("Successful GET from /audit-configuration:", data);
|
|
2981
|
+
} else {
|
|
2982
|
+
result.error = await processErrors(response);
|
|
2983
|
+
console.log("Failed GET from /audit-configuration: " + url.href);
|
|
2984
|
+
console.log(result.error);
|
|
2985
|
+
result.status = response.status;
|
|
2986
|
+
result.result = false;
|
|
2987
|
+
}
|
|
2988
|
+
} catch (error: any) {
|
|
2989
|
+
result.status = 500;
|
|
2990
|
+
result.result = false;
|
|
2991
|
+
result.error = error.message;
|
|
2992
|
+
console.log("Error during auditConfigGet:", error.message);
|
|
2993
|
+
}
|
|
2994
|
+
|
|
2995
|
+
return result;
|
|
2996
|
+
}
|
|
2997
|
+
|
|
2998
|
+
//auditConfigPUT: put audit config from back end
|
|
2999
|
+
export async function auditConfigPut(
|
|
3000
|
+
instance: IPublicClientApplication,
|
|
3001
|
+
user: User,
|
|
3002
|
+
configurationId: string,
|
|
3003
|
+
config: AuditConfig, // model with name, description, isEnabled, isReadPermissionConsented, email
|
|
3004
|
+
debug: boolean
|
|
3005
|
+
): Promise<APIResult> {
|
|
3006
|
+
let result: APIResult = new APIResult();
|
|
3007
|
+
|
|
3008
|
+
// Validate configurationId
|
|
3009
|
+
if (!configurationId || configurationId.trim() === "") {
|
|
3010
|
+
result.result = false;
|
|
3011
|
+
result.error = "auditConfigPut: invalid configuration ID";
|
|
3012
|
+
result.status = 500;
|
|
3013
|
+
return result;
|
|
3014
|
+
}
|
|
3015
|
+
|
|
3016
|
+
// Build endpoint with query parameter
|
|
3017
|
+
let endpoint: string = mindlineConfig.auditConfigEndpoint();
|
|
3018
|
+
let url: URL = new URL(endpoint);
|
|
3019
|
+
url.searchParams.append("configurationId", configurationId);
|
|
3020
|
+
|
|
3021
|
+
// Create headers with token
|
|
3022
|
+
const headers = await mindlineDefineHeaders(instance, user);
|
|
3023
|
+
|
|
3024
|
+
// Build body
|
|
3025
|
+
let configBody: string = `
|
|
3026
|
+
{
|
|
3027
|
+
"name": "${config.name}",
|
|
3028
|
+
"description": "${config.description}",
|
|
3029
|
+
"isEnabled": ${config.isEnabled},
|
|
3030
|
+
"isReadPermissionConsented": ${config.isReadPermissionConsented},
|
|
3031
|
+
"email": "${config.email}"
|
|
3032
|
+
}`;
|
|
3033
|
+
|
|
3034
|
+
let options = { method: "PUT", headers: headers, body: configBody };
|
|
3035
|
+
|
|
3036
|
+
// Call API
|
|
3037
|
+
try {
|
|
3038
|
+
if (debug) debugger;
|
|
3039
|
+
console.log("Attempting PUT to /audit-configuration: " + url.href);
|
|
3040
|
+
|
|
3041
|
+
const response = await fetch(url.href, options);
|
|
3042
|
+
|
|
3043
|
+
if (response.status === 200 && response.statusText === "OK") {
|
|
3044
|
+
result.result = true;
|
|
3045
|
+
console.log(`Successful PUT to ${url.href}: ${configBody}`);
|
|
3046
|
+
} else {
|
|
3047
|
+
result.error = await processErrors(response);
|
|
3048
|
+
console.error(`Failed PUT to ${url.href}: ${configBody}`);
|
|
3049
|
+
result.status = response.status;
|
|
3050
|
+
result.result = false;
|
|
3051
|
+
}
|
|
3052
|
+
} catch (error: any) {
|
|
3053
|
+
result.error = error.message;
|
|
3054
|
+
result.status = 500;
|
|
3055
|
+
result.result = false;
|
|
3056
|
+
console.error("Error during auditConfigPut:", error.message);
|
|
3057
|
+
}
|
|
3058
|
+
|
|
3059
|
+
return result;
|
|
3060
|
+
}
|
|
3061
|
+
|
|
3062
|
+
//auditConfigDELETE: delete audit config from back end
|
|
3063
|
+
export async function auditConfigDelete(
|
|
3064
|
+
instance: IPublicClientApplication,
|
|
3065
|
+
user: User,
|
|
3066
|
+
configurationId: string,
|
|
3067
|
+
debug: boolean
|
|
3068
|
+
): Promise<APIResult> {
|
|
2912
3069
|
let result: APIResult = new APIResult();
|
|
3070
|
+
|
|
3071
|
+
// Validate user
|
|
3072
|
+
if (!user.mail) {
|
|
3073
|
+
result.result = false;
|
|
3074
|
+
result.status = 500;
|
|
3075
|
+
result.error = "auditConfigDelete: no user provided";
|
|
3076
|
+
return result;
|
|
3077
|
+
}
|
|
3078
|
+
|
|
3079
|
+
// Validate configurationId
|
|
3080
|
+
if (!configurationId || configurationId.trim() === "") {
|
|
3081
|
+
result.result = false;
|
|
3082
|
+
result.status = 500;
|
|
3083
|
+
result.error = "auditConfigDelete: configurationId is required";
|
|
3084
|
+
return result;
|
|
3085
|
+
}
|
|
3086
|
+
|
|
3087
|
+
// Build endpoint with query parameter
|
|
3088
|
+
let endpoint: string = mindlineConfig.auditConfigEndpoint();
|
|
3089
|
+
let url: URL = new URL(endpoint);
|
|
3090
|
+
url.searchParams.append("configurationId", configurationId);
|
|
3091
|
+
|
|
3092
|
+
// Build request headers
|
|
3093
|
+
const headers = await mindlineDefineHeaders(instance, user);
|
|
3094
|
+
const options = { method: "DELETE", headers: headers };
|
|
3095
|
+
|
|
3096
|
+
try {
|
|
3097
|
+
if (debug) debugger;
|
|
3098
|
+
console.log(`Attempting DELETE to /audit-configuration: ${url.href}`);
|
|
3099
|
+
|
|
3100
|
+
const response = await fetch(url.href, options);
|
|
3101
|
+
|
|
3102
|
+
if (response.ok) {
|
|
3103
|
+
result.result = true;
|
|
3104
|
+
console.log(`Successful DELETE for configurationId ${configurationId}`);
|
|
3105
|
+
} else {
|
|
3106
|
+
result.error = await processErrors(response);
|
|
3107
|
+
result.status = response.status;
|
|
3108
|
+
result.result = false;
|
|
3109
|
+
console.error(`Failed DELETE for configurationId ${configurationId}`);
|
|
3110
|
+
}
|
|
3111
|
+
} catch (error: any) {
|
|
3112
|
+
result.status = 500;
|
|
3113
|
+
result.result = false;
|
|
3114
|
+
result.error = error.message;
|
|
3115
|
+
console.error("Error during auditConfigDelete:", error.message);
|
|
3116
|
+
}
|
|
3117
|
+
|
|
2913
3118
|
return result;
|
|
2914
3119
|
}
|
|
3120
|
+
|
|
3121
|
+
|
|
2915
3122
|
export async function auditEventsGet(instance: IPublicClientApplication, user: User, debug: boolean): Promise<APIResult> {
|
|
2916
3123
|
let result: APIResult = new APIResult();
|
|
2917
3124
|
// we need a valid user
|
|
@@ -3355,6 +3562,76 @@ export async function configsGet(
|
|
|
3355
3562
|
}
|
|
3356
3563
|
return result;
|
|
3357
3564
|
}
|
|
3565
|
+
//workspaceConfigsGET
|
|
3566
|
+
export async function workspaceConfigsGet(
|
|
3567
|
+
instance: IPublicClientApplication,
|
|
3568
|
+
user: User | null | undefined,
|
|
3569
|
+
workspaceId: string,
|
|
3570
|
+
debug: boolean
|
|
3571
|
+
): Promise<APIResult> {
|
|
3572
|
+
let result: APIResult = new APIResult();
|
|
3573
|
+
|
|
3574
|
+
if (!workspaceId) {
|
|
3575
|
+
result.result = false;
|
|
3576
|
+
result.status = 500;
|
|
3577
|
+
result.error = "workspaceConfigsGet: no workspace provided";
|
|
3578
|
+
return result;
|
|
3579
|
+
}
|
|
3580
|
+
|
|
3581
|
+
// Create endpoint
|
|
3582
|
+
let endpoint: string = mindlineConfig.workspaceConfigsEndpoint();
|
|
3583
|
+
// Add parameter to endpoint
|
|
3584
|
+
let url: URL = new URL(endpoint);
|
|
3585
|
+
url.searchParams.append("workspaceId", workspaceId);
|
|
3586
|
+
|
|
3587
|
+
// Headers with Bearer token
|
|
3588
|
+
const headers = await mindlineDefineHeaders(instance, user);
|
|
3589
|
+
|
|
3590
|
+
let options = { method: "GET", headers };
|
|
3591
|
+
|
|
3592
|
+
try {
|
|
3593
|
+
if (debug) debugger;
|
|
3594
|
+
console.log("Attempting GET from /workspaceConfigs: " + url.href);
|
|
3595
|
+
|
|
3596
|
+
const response = await fetch(url.href, options);
|
|
3597
|
+
|
|
3598
|
+
if (response.status === 200 && response.statusText === "OK") {
|
|
3599
|
+
const returnedArray: Array<any> = await response.json();
|
|
3600
|
+
|
|
3601
|
+
if (returnedArray) {
|
|
3602
|
+
// Filter by configurationType (sync or auditLog)
|
|
3603
|
+
result.array = returnedArray.map((config) => ({
|
|
3604
|
+
id: config.id,
|
|
3605
|
+
name: config.name,
|
|
3606
|
+
description: config.description,
|
|
3607
|
+
configurationType: config.configurationType,
|
|
3608
|
+
isEnabled: config.isEnabled,
|
|
3609
|
+
}));
|
|
3610
|
+
|
|
3611
|
+
console.log(
|
|
3612
|
+
`workspaceConfigsGet: found ${result.array.length} configs.`
|
|
3613
|
+
);
|
|
3614
|
+
return result;
|
|
3615
|
+
} else {
|
|
3616
|
+
result.error =
|
|
3617
|
+
"workspaceConfigsGet: failed to parse returned configs";
|
|
3618
|
+
result.result = false;
|
|
3619
|
+
result.status = 500;
|
|
3620
|
+
}
|
|
3621
|
+
} else {
|
|
3622
|
+
result.error = await processErrors(response);
|
|
3623
|
+
result.result = false;
|
|
3624
|
+
result.status = response.status;
|
|
3625
|
+
console.log(result.error);
|
|
3626
|
+
}
|
|
3627
|
+
} catch (error: any) {
|
|
3628
|
+
result.error = error.message;
|
|
3629
|
+
result.result = false;
|
|
3630
|
+
result.status = 500;
|
|
3631
|
+
}
|
|
3632
|
+
|
|
3633
|
+
return result;
|
|
3634
|
+
}
|
|
3358
3635
|
//initPost
|
|
3359
3636
|
export async function initPost(
|
|
3360
3637
|
instance: IPublicClientApplication,
|
|
Binary file
|
|
Binary file
|
|
Binary file
|