@rimori/client 2.4.0-next.5 → 2.4.0-next.6

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.
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { createClient } from '@supabase/supabase-js';
10
+ // import { createClient } from '@supabase/supabase-js';
11
11
  import path from 'path';
12
12
  import * as readline from 'readline';
13
13
  import { DEFAULT_ANON_KEY, DEFAULT_ENDPOINT } from '../../../utils/endpoint.js';
@@ -112,7 +112,9 @@ export function authenticateWithSupabase(_a) {
112
112
  // Initialize Supabase client (you may need to adjust the URL and key)
113
113
  const supabaseUrl = process.env.SUPABASE_URL || DEFAULT_ENDPOINT;
114
114
  const supabaseKey = process.env.SUPABASE_ANON_KEY || DEFAULT_ANON_KEY;
115
- const supabase = createClient(supabaseUrl, supabaseKey);
115
+ throw new Error('Authentication is disabled until new developer platform is released.');
116
+ // const supabase = createClient(supabaseUrl, supabaseKey);
117
+ const supabase = {};
116
118
  try {
117
119
  const { data, error } = yield supabase.auth.signInWithPassword({
118
120
  email,
@@ -82,6 +82,7 @@ function main() {
82
82
  updateGitignore();
83
83
  }
84
84
  else {
85
+ throw new Error('Registration is disabled until new developer platform is released.');
85
86
  // Step 1: Get user credentials
86
87
  const credentials = yield askForCredentials();
87
88
  console.log('');
@@ -1,4 +1,4 @@
1
- import { SupabaseClient } from '@supabase/supabase-js';
1
+ import { SupabaseClient } from '../plugin/CommunicationHandler';
2
2
  import { LanguageLevel } from '../utils/difficultyConverter';
3
3
  import { Guild } from '../plugin/CommunicationHandler';
4
4
  export interface Buddy {
@@ -1,4 +1,4 @@
1
- import { SupabaseClient } from '@supabase/supabase-js';
1
+ import { SupabaseClient } from '../plugin/CommunicationHandler';
2
2
  import { RimoriClient } from '../plugin/RimoriClient';
3
3
  import { ObjectRequest } from './ObjectController';
4
4
  export interface SharedContentObjectRequest extends ObjectRequest {
@@ -1,6 +1,7 @@
1
- import { SupabaseClient } from '@supabase/supabase-js';
2
1
  import { UserInfo } from '../controller/SettingsController';
3
2
  import { ActivePlugin, Plugin } from '../fromRimori/PluginTypes';
3
+ import { PostgrestClient } from '@supabase/postgrest-js';
4
+ export type SupabaseClient = PostgrestClient;
4
5
  export interface Guild {
5
6
  allowUserPluginSettings: boolean;
6
7
  city: string | null;
@@ -53,6 +54,7 @@ export declare class RimoriCommunicationHandler {
53
54
  private sendHello;
54
55
  private sendFinishedInit;
55
56
  getQueryParam(key: string): string | null;
57
+ private getSupabase;
56
58
  getClient(): Promise<{
57
59
  supabase: SupabaseClient;
58
60
  info: RimoriInfo;
@@ -7,8 +7,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { createClient } from '@supabase/supabase-js';
11
10
  import { EventBus } from '../fromRimori/EventBus';
11
+ import { PostgrestClient } from '@supabase/postgrest-js';
12
12
  export class RimoriCommunicationHandler {
13
13
  constructor(pluginId, standalone) {
14
14
  this.port = null;
@@ -45,9 +45,7 @@ export class RimoriCommunicationHandler {
45
45
  // Initialize Supabase client immediately with provided info
46
46
  if (rimoriInfo) {
47
47
  this.rimoriInfo = rimoriInfo;
48
- this.supabase = createClient(rimoriInfo.url, rimoriInfo.key, {
49
- accessToken: () => Promise.resolve(rimoriInfo.token),
50
- });
48
+ this.supabase = this.getSupabase(rimoriInfo.url, rimoriInfo.key, rimoriInfo.token);
51
49
  }
52
50
  // Handle messages from parent
53
51
  this.port.onmessage = ({ data }) => {
@@ -133,6 +131,16 @@ export class RimoriCommunicationHandler {
133
131
  getQueryParam(key) {
134
132
  return this.queryParams[key] || null;
135
133
  }
134
+ getSupabase(url, key, token) {
135
+ var _a;
136
+ return new PostgrestClient(`${url}/rest/v1`, {
137
+ schema: (_a = this.rimoriInfo) === null || _a === void 0 ? void 0 : _a.dbSchema,
138
+ headers: {
139
+ apikey: key,
140
+ Authorization: `Bearer ${token}`,
141
+ },
142
+ });
143
+ }
136
144
  getClient() {
137
145
  return __awaiter(this, void 0, void 0, function* () {
138
146
  // Return cached client if valid
@@ -174,9 +182,7 @@ export class RimoriCommunicationHandler {
174
182
  var _a, _b;
175
183
  if (((_a = event.data) === null || _a === void 0 ? void 0 : _a.topic) === 'global.supabase.requestAccess' && ((_b = event.data) === null || _b === void 0 ? void 0 : _b.eventId) === eventId) {
176
184
  this.rimoriInfo = event.data.data;
177
- this.supabase = createClient(this.rimoriInfo.url, this.rimoriInfo.key, {
178
- accessToken: () => Promise.resolve(this.rimoriInfo.token),
179
- });
185
+ this.supabase = this.getSupabase(this.rimoriInfo.url, this.rimoriInfo.key, this.rimoriInfo.token);
180
186
  self.onmessage = originalOnMessage; // Restore original handler
181
187
  resolve({ supabase: this.supabase, info: this.rimoriInfo });
182
188
  }
@@ -193,9 +199,7 @@ export class RimoriCommunicationHandler {
193
199
  const { data } = yield EventBus.request(this.pluginId, 'global.supabase.requestAccess');
194
200
  // console.log({ data });
195
201
  this.rimoriInfo = data;
196
- this.supabase = createClient(this.rimoriInfo.url, this.rimoriInfo.key, {
197
- accessToken: () => Promise.resolve(this.rimoriInfo.token),
198
- });
202
+ this.supabase = this.getSupabase(this.rimoriInfo.url, this.rimoriInfo.key, this.rimoriInfo.token);
199
203
  }
200
204
  }
201
205
  return { supabase: this.supabase, info: this.rimoriInfo };
@@ -209,9 +213,7 @@ export class RimoriCommunicationHandler {
209
213
  // Update cached rimoriInfo
210
214
  this.rimoriInfo = newInfo;
211
215
  // Update Supabase client with new token
212
- this.supabase = createClient(newInfo.url, newInfo.key, {
213
- accessToken: () => Promise.resolve(newInfo.token),
214
- });
216
+ this.supabase = this.getSupabase(newInfo.url, newInfo.key, newInfo.token);
215
217
  // Notify all registered callbacks
216
218
  this.updateCallbacks.forEach((callback) => {
217
219
  try {
@@ -1,4 +1,4 @@
1
- import { SupabaseClient } from '@supabase/supabase-js';
1
+ import { SupabaseClient } from './CommunicationHandler';
2
2
  export interface StandaloneConfig {
3
3
  url: string;
4
4
  key: string;
@@ -7,12 +7,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { createClient } from '@supabase/supabase-js';
11
10
  import { EventBus } from '../fromRimori/EventBus';
12
11
  import { DEFAULT_ANON_KEY, DEFAULT_ENDPOINT } from '../utils/endpoint';
13
12
  export class StandaloneClient {
14
13
  constructor(config) {
15
- this.supabase = createClient(config.url, config.key);
14
+ throw new Error('Authentication is disabled until new developer platform is released.');
15
+ // this.supabase = createClient(config.url, config.key);
16
+ this.supabase = {};
16
17
  this.config = config;
17
18
  }
18
19
  static getInstance() {
@@ -1,7 +1,7 @@
1
- import { PostgrestQueryBuilder } from '@supabase/postgrest-js';
2
- import { SupabaseClient } from '@supabase/supabase-js';
3
- import { GenericSchema } from '@supabase/supabase-js/dist/module/lib/types';
1
+ import { PostgrestClientOptions, PostgrestQueryBuilder } from '@supabase/postgrest-js';
2
+ import { SupabaseClient } from '../CommunicationHandler';
4
3
  import { RimoriCommunicationHandler, RimoriInfo } from '../CommunicationHandler';
4
+ import { GenericSchema, GenericTable } from '@supabase/postgrest-js/dist/cjs/types/common/common';
5
5
  /**
6
6
  * Database module for plugin database operations.
7
7
  * Provides access to plugin tables with automatic prefixing and schema management.
@@ -19,7 +19,7 @@ export declare class DbModule {
19
19
  * @param relation The table name (without prefix for plugin tables, with 'global_' for global tables).
20
20
  * @returns A Postgrest query builder for the table.
21
21
  */
22
- from<ViewName extends string & keyof GenericSchema['Views'], View extends GenericSchema['Views'][ViewName]>(relation: string): PostgrestQueryBuilder<GenericSchema, View, ViewName>;
22
+ from<ViewName extends string & keyof GenericSchema['Views'], View extends GenericSchema['Views'][ViewName]>(relation: string): PostgrestQueryBuilder<PostgrestClientOptions, GenericSchema, GenericTable, ViewName, View>;
23
23
  /**
24
24
  * Get the table name for a given plugin table.
25
25
  * Internally all tables are prefixed with the plugin id. This function is used to get the correct table name for a given public table.
@@ -1,6 +1,6 @@
1
- import { EventBusMessage, EventHandler, EventPayload, EventListener } from '../../fromRimori/EventBus';
2
1
  import { MainPanelAction } from '../../fromRimori/PluginTypes';
3
2
  import { AccomplishmentPayload } from '../../controller/AccomplishmentController';
3
+ import { EventBusMessage, EventHandler, EventPayload, EventListener } from '../../fromRimori/EventBus';
4
4
  /**
5
5
  * Event module for plugin event bus operations.
6
6
  * Provides methods for emitting, listening to, and responding to events.
@@ -1,5 +1,5 @@
1
- import { EventBus } from '../../fromRimori/EventBus';
2
1
  import { AccomplishmentController } from '../../controller/AccomplishmentController';
2
+ import { EventBus } from '../../fromRimori/EventBus';
3
3
  /**
4
4
  * Event module for plugin event bus operations.
5
5
  * Provides methods for emitting, listening to, and responding to events.
@@ -1,4 +1,4 @@
1
- import { SupabaseClient } from '@supabase/supabase-js';
1
+ import { SupabaseClient } from '../CommunicationHandler';
2
2
  import { RimoriCommunicationHandler, RimoriInfo } from '../CommunicationHandler';
3
3
  import { EventModule } from './EventModule';
4
4
  export type TriggerAction = {
@@ -2,7 +2,7 @@ import { UserInfo } from '../../controller/SettingsController';
2
2
  import { RimoriCommunicationHandler, RimoriInfo } from '../CommunicationHandler';
3
3
  import { Translator } from '../../controller/TranslationController';
4
4
  import { ActivePlugin, Plugin } from '../../fromRimori/PluginTypes';
5
- import { SupabaseClient } from '@supabase/supabase-js';
5
+ import { SupabaseClient } from '../CommunicationHandler';
6
6
  type Theme = 'light' | 'dark';
7
7
  type ApplicationMode = 'main' | 'sidebar' | 'settings';
8
8
  /**
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@rimori/client",
3
- "version": "2.4.0-next.5",
3
+ "version": "2.4.0-next.6",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "https://github.com/rimori-org/rimori-client.git"
9
9
  },
10
- "license": "apache-2.0",
10
+ "license": "Apache-2.0",
11
11
  "bin": {
12
12
  "rimori-release": "./dist/cli/scripts/release/release.js",
13
13
  "rimori-init": "./dist/cli/scripts/init/main.js"
@@ -27,12 +27,13 @@
27
27
  "format": "prettier --write ."
28
28
  },
29
29
  "dependencies": {
30
- "@supabase/supabase-js": "2.49.4",
30
+ "@supabase/postgrest-js": "^2.87.1",
31
31
  "dotenv": "16.5.0",
32
32
  "i18next": "^25.6.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@eslint/js": "^9.37.0",
36
+ "@types/node": "^25.0.1",
36
37
  "eslint-config-prettier": "^10.1.8",
37
38
  "eslint-plugin-prettier": "^5.5.4",
38
39
  "eslint-plugin-react-hooks": "^7.0.0",
@@ -1,4 +1,4 @@
1
- import { createClient } from '@supabase/supabase-js';
1
+ // import { createClient } from '@supabase/supabase-js';
2
2
  import path from 'path';
3
3
  import * as readline from 'readline';
4
4
  import { DEFAULT_ANON_KEY, DEFAULT_ENDPOINT } from '../../../utils/endpoint.js';
@@ -120,7 +120,9 @@ export async function authenticateWithSupabase({ email, password }: UserCredenti
120
120
  const supabaseUrl = process.env.SUPABASE_URL || DEFAULT_ENDPOINT;
121
121
  const supabaseKey = process.env.SUPABASE_ANON_KEY || DEFAULT_ANON_KEY;
122
122
 
123
- const supabase = createClient(supabaseUrl, supabaseKey);
123
+ throw new Error('Authentication is disabled until new developer platform is released.');
124
+ // const supabase = createClient(supabaseUrl, supabaseKey);
125
+ const supabase = {} as any;
124
126
 
125
127
  try {
126
128
  const { data, error } = await supabase.auth.signInWithPassword({
@@ -83,6 +83,7 @@ async function main(): Promise<void> {
83
83
  // Update gitignore
84
84
  updateGitignore();
85
85
  } else {
86
+ throw new Error('Registration is disabled until new developer platform is released.');
86
87
  // Step 1: Get user credentials
87
88
  const credentials = await askForCredentials();
88
89
  console.log('');
@@ -1,4 +1,4 @@
1
- import { SupabaseClient } from '@supabase/supabase-js';
1
+ import { SupabaseClient } from '../plugin/CommunicationHandler';
2
2
  import { LanguageLevel } from '../utils/difficultyConverter';
3
3
  import { Guild } from '../plugin/CommunicationHandler';
4
4
 
@@ -1,4 +1,4 @@
1
- import { SupabaseClient } from '@supabase/supabase-js';
1
+ import { SupabaseClient } from '../plugin/CommunicationHandler';
2
2
  import { RimoriClient } from '../plugin/RimoriClient';
3
3
  import { ObjectRequest } from './ObjectController';
4
4
 
@@ -1,11 +1,13 @@
1
- import { createClient, SupabaseClient } from '@supabase/supabase-js';
2
1
  import { UserInfo } from '../controller/SettingsController';
3
2
  import { EventBus, EventBusMessage } from '../fromRimori/EventBus';
4
3
  import { ActivePlugin, Plugin } from '../fromRimori/PluginTypes';
4
+ import { PostgrestClient } from '@supabase/postgrest-js';
5
5
 
6
6
  // Add declaration for WorkerGlobalScope
7
7
  declare const WorkerGlobalScope: any;
8
8
 
9
+ export type SupabaseClient = PostgrestClient;
10
+
9
11
  export interface Guild {
10
12
  allowUserPluginSettings: boolean;
11
13
  city: string | null;
@@ -89,9 +91,7 @@ export class RimoriCommunicationHandler {
89
91
  // Initialize Supabase client immediately with provided info
90
92
  if (rimoriInfo) {
91
93
  this.rimoriInfo = rimoriInfo;
92
- this.supabase = createClient(rimoriInfo.url, rimoriInfo.key, {
93
- accessToken: () => Promise.resolve(rimoriInfo.token),
94
- });
94
+ this.supabase = this.getSupabase(rimoriInfo.url, rimoriInfo.key, rimoriInfo.token);
95
95
  }
96
96
 
97
97
  // Handle messages from parent
@@ -180,6 +180,16 @@ export class RimoriCommunicationHandler {
180
180
  return this.queryParams[key] || null;
181
181
  }
182
182
 
183
+ private getSupabase(url: string, key: string, token: string): SupabaseClient {
184
+ return new PostgrestClient(`${url}/rest/v1`, {
185
+ schema: this.rimoriInfo?.dbSchema,
186
+ headers: {
187
+ apikey: key,
188
+ Authorization: `Bearer ${token}`,
189
+ },
190
+ }) as unknown as SupabaseClient;
191
+ }
192
+
183
193
  public async getClient(): Promise<{ supabase: SupabaseClient; info: RimoriInfo }> {
184
194
  // Return cached client if valid
185
195
  if (this.supabase && this.rimoriInfo && this.rimoriInfo.expiration > new Date()) {
@@ -223,9 +233,7 @@ export class RimoriCommunicationHandler {
223
233
  self.onmessage = (event) => {
224
234
  if (event.data?.topic === 'global.supabase.requestAccess' && event.data?.eventId === eventId) {
225
235
  this.rimoriInfo = event.data.data;
226
- this.supabase = createClient(this.rimoriInfo!.url, this.rimoriInfo!.key, {
227
- accessToken: () => Promise.resolve(this.rimoriInfo!.token),
228
- });
236
+ this.supabase = this.getSupabase(this.rimoriInfo!.url, this.rimoriInfo!.key, this.rimoriInfo!.token);
229
237
  self.onmessage = originalOnMessage; // Restore original handler
230
238
  resolve({ supabase: this.supabase, info: this.rimoriInfo! });
231
239
  } else if (originalOnMessage) {
@@ -241,9 +249,7 @@ export class RimoriCommunicationHandler {
241
249
  const { data } = await EventBus.request<RimoriInfo>(this.pluginId, 'global.supabase.requestAccess');
242
250
  // console.log({ data });
243
251
  this.rimoriInfo = data;
244
- this.supabase = createClient(this.rimoriInfo.url, this.rimoriInfo.key, {
245
- accessToken: () => Promise.resolve(this.rimoriInfo!.token),
246
- });
252
+ this.supabase = this.getSupabase(this.rimoriInfo.url, this.rimoriInfo.key, this.rimoriInfo.token);
247
253
  }
248
254
  }
249
255
 
@@ -259,9 +265,7 @@ export class RimoriCommunicationHandler {
259
265
  this.rimoriInfo = newInfo;
260
266
 
261
267
  // Update Supabase client with new token
262
- this.supabase = createClient(newInfo.url, newInfo.key, {
263
- accessToken: () => Promise.resolve(newInfo.token),
264
- });
268
+ this.supabase = this.getSupabase(newInfo.url, newInfo.key, newInfo.token);
265
269
 
266
270
  // Notify all registered callbacks
267
271
  this.updateCallbacks.forEach((callback) => {
@@ -1,4 +1,3 @@
1
- import { SupabaseClient } from '@supabase/supabase-js';
2
1
  import {
3
2
  SharedContent,
4
3
  SharedContentController,
@@ -12,6 +11,7 @@ import { DbModule } from './module/DbModule';
12
11
  import { EventModule } from './module/EventModule';
13
12
  import { AIModule } from './module/AIModule';
14
13
  import { ExerciseModule } from './module/ExerciseModule';
14
+ import { PostgrestClient } from '@supabase/postgrest-js';
15
15
 
16
16
  // Add declaration for WorkerGlobalScope
17
17
  declare const WorkerGlobalScope: any;
@@ -27,7 +27,7 @@ export class RimoriClient {
27
27
  public exercise: ExerciseModule;
28
28
  private rimoriInfo: RimoriInfo;
29
29
 
30
- private constructor(controller: RimoriCommunicationHandler, supabase: SupabaseClient, info: RimoriInfo) {
30
+ private constructor(controller: RimoriCommunicationHandler, supabase: PostgrestClient, info: RimoriInfo) {
31
31
  this.rimoriInfo = info;
32
32
  this.pluginController = controller;
33
33
  this.sharedContentController = new SharedContentController(supabase, this);
@@ -1,4 +1,4 @@
1
- import { createClient, SupabaseClient } from '@supabase/supabase-js';
1
+ import { SupabaseClient } from './CommunicationHandler';
2
2
  import { EventBus } from '../fromRimori/EventBus';
3
3
  import { DEFAULT_ANON_KEY, DEFAULT_ENDPOINT } from '../utils/endpoint';
4
4
 
@@ -11,10 +11,12 @@ export interface StandaloneConfig {
11
11
  export class StandaloneClient {
12
12
  private static instance: StandaloneClient;
13
13
  private config: StandaloneConfig;
14
- private supabase: SupabaseClient;
14
+ private supabase: SupabaseClient & { auth: any }; // TODO: remove any
15
15
 
16
16
  private constructor(config: StandaloneConfig) {
17
- this.supabase = createClient(config.url, config.key);
17
+ throw new Error('Authentication is disabled until new developer platform is released.');
18
+ // this.supabase = createClient(config.url, config.key);
19
+ this.supabase = {} as any;
18
20
  this.config = config;
19
21
  }
20
22
 
@@ -1,7 +1,8 @@
1
- import { PostgrestQueryBuilder } from '@supabase/postgrest-js';
2
- import { SupabaseClient } from '@supabase/supabase-js';
3
- import { GenericSchema } from '@supabase/supabase-js/dist/module/lib/types';
1
+ import { PostgrestClientOptions, PostgrestQueryBuilder } from '@supabase/postgrest-js';
2
+ import { SupabaseClient } from '../CommunicationHandler';
3
+ // import { GenericSchema } from '@supabase/postgrest-js/dist/module/lib/types';
4
4
  import { RimoriCommunicationHandler, RimoriInfo } from '../CommunicationHandler';
5
+ import { GenericSchema, GenericTable } from '@supabase/postgrest-js/dist/cjs/types/common/common';
5
6
 
6
7
  /**
7
8
  * Database module for plugin database operations.
@@ -35,7 +36,7 @@ export class DbModule {
35
36
  */
36
37
  from<ViewName extends string & keyof GenericSchema['Views'], View extends GenericSchema['Views'][ViewName]>(
37
38
  relation: string,
38
- ): PostgrestQueryBuilder<GenericSchema, View, ViewName> {
39
+ ): PostgrestQueryBuilder<PostgrestClientOptions, GenericSchema, GenericTable, ViewName, View> {
39
40
  const tableName = this.getTableName(relation);
40
41
  // Use the schema determined by rimori-main based on release channel
41
42
  // Global tables (starting with 'global_') remain in public schema
@@ -1,6 +1,6 @@
1
- import { EventBus, EventBusMessage, EventHandler, EventPayload, EventListener } from '../../fromRimori/EventBus';
2
1
  import { MainPanelAction } from '../../fromRimori/PluginTypes';
3
2
  import { AccomplishmentController, AccomplishmentPayload } from '../../controller/AccomplishmentController';
3
+ import { EventBus, EventBusMessage, EventHandler, EventPayload, EventListener } from '../../fromRimori/EventBus';
4
4
 
5
5
  /**
6
6
  * Event module for plugin event bus operations.
@@ -1,4 +1,4 @@
1
- import { SupabaseClient } from '@supabase/supabase-js';
1
+ import { SupabaseClient } from '../CommunicationHandler';
2
2
  import { RimoriCommunicationHandler, RimoriInfo } from '../CommunicationHandler';
3
3
  import { EventModule } from './EventModule';
4
4
 
@@ -2,7 +2,7 @@ import { SettingsController, UserInfo } from '../../controller/SettingsControlle
2
2
  import { RimoriCommunicationHandler, RimoriInfo } from '../CommunicationHandler';
3
3
  import { Translator } from '../../controller/TranslationController';
4
4
  import { ActivePlugin, Plugin } from '../../fromRimori/PluginTypes';
5
- import { SupabaseClient } from '@supabase/supabase-js';
5
+ import { SupabaseClient } from '../CommunicationHandler';
6
6
 
7
7
  type Theme = 'light' | 'dark';
8
8
  type ApplicationMode = 'main' | 'sidebar' | 'settings';