Ghost/ghost/admin/app/services/config.js
Kevin Ansfield 7b443d4b63 Removed need for .get() with config service
no issue

The `config` service has been a source of confusion when writing with modern Ember patterns because it's use of the deprecated `ProxyMixin` forced all property access/setting to go via `.get()` and `.set()` whereas the rest of the system has mostly (there are a few other uses of ProxyObjects remaining) eliminated the use of the non-native get/set methods.

- removed use of `ProxyMixin` in the `config` service by grabbing the API response after fetching and using `Object.defineProperty()` to add native getters/setters that pass through to a tracked object holding the API response data. Ember's autotracking automatically works across the native getters/setters so we can then use the service as if it was any other native object
- updated all code to use `config.{attrName}` directly for getting/setting instead of `.get()` and `.set()`
- removed unnecessary async around `config.availableTimezones` which wasn't making any async calls
2022-10-07 16:14:57 +01:00

91 lines
2.6 KiB
JavaScript

import RSVP from 'rsvp';
import Service, {inject as service} from '@ember/service';
import timezoneData from '@tryghost/timezone-data';
import {TrackedObject} from 'tracked-built-ins';
import {tracked} from '@glimmer/tracking';
export default class ConfigService extends Service {
@service ajax;
@service ghostPaths;
@service session;
@tracked content = new TrackedObject();
availableTimezones = timezoneData;
fetch() {
let promises = [];
promises.push(this.fetchUnauthenticated());
if (this.session.isAuthenticated) {
promises.push(this.fetchAuthenticated());
}
return RSVP.all(promises);
}
async fetchUnauthenticated() {
const siteUrl = this.ghostPaths.url.api('site');
const {site} = await this.ajax.request(siteUrl);
// normalize url to non-trailing-slash
site.blogUrl = site.url.replace(/\/$/, '');
site.blogTitle = site.title;
delete site.url;
delete site.title;
Object.assign(this.content, site);
this._defineProperties(site);
}
async fetchAuthenticated() {
const configUrl = this.ghostPaths.url.api('config');
const {config} = await this.ajax.request(configUrl);
Object.assign(this.content, config);
this._defineProperties(config);
}
get blogDomain() {
const blogDomain = this.blogUrl
.replace(/^https?:\/\//, '')
.replace(/\/?$/, '');
return blogDomain;
}
get emailDomain() {
const blogDomain = this.blogDomain || '';
const domainExp = blogDomain.match(new RegExp('^([^/:?#]+)(?:[/:?#]|$)', 'i'));
const domain = (domainExp && domainExp[1]) || '';
if (domain.startsWith('www.')) {
return domain.replace(/^(www)\.(?=[^/]*\..{2,5})/, '');
}
return domain;
}
getSiteUrl(path) {
const siteUrl = new URL(this.blogUrl);
const subdir = siteUrl.pathname.endsWith('/') ? siteUrl.pathname : `${siteUrl.pathname}/`;
const fullPath = `${subdir}${path.replace(/^\//, '')}`;
return `${siteUrl.origin}${fullPath}`;
}
_defineProperties(obj) {
for (const name of Object.keys(obj)) {
if (!Object.prototype.hasOwnProperty.call(this, name)) {
Object.defineProperty(this, name, {
get() {
return this.content[name];
},
set(newValue) {
this.content[name] = newValue;
}
});
}
}
}
}