@eventcatalog/sdk 2.4.0 → 2.5.1
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/dist/eventcatalog.d.mts +9 -1
- package/dist/eventcatalog.d.ts +9 -1
- package/dist/eventcatalog.js +22 -2
- package/dist/eventcatalog.js.map +1 -1
- package/dist/eventcatalog.mjs +20 -1
- package/dist/eventcatalog.mjs.map +1 -1
- package/dist/index.d.mts +23 -2
- package/dist/index.d.ts +23 -2
- package/dist/index.js +118 -100
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +120 -102
- package/dist/index.mjs.map +1 -1
- package/dist/types.d.d.mts +11 -2
- package/dist/types.d.d.ts +11 -2
- package/dist/types.d.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { EventCatalogObject } from './eventcatalog.mjs';
|
|
2
2
|
import { Event, Command, Query, Channel, Service, Domain, UbiquitousLanguageDictionary, Team, User, CustomDoc } from './types.d.mjs';
|
|
3
|
+
export { Badge, BaseSchema, ChannelPointer, Message, ResourceGroup, ResourcePointer, Specifications, UbiquitousLanguage } from './types.d.mjs';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Init the SDK for EventCatalog
|
|
@@ -251,7 +252,19 @@ declare const _default: (path: string) => {
|
|
|
251
252
|
id: string;
|
|
252
253
|
version?: string;
|
|
253
254
|
}, options?: {
|
|
254
|
-
path
|
|
255
|
+
path
|
|
256
|
+
/**
|
|
257
|
+
* Returns a command from EventCatalog
|
|
258
|
+
* @param id - The id of the command to retrieve
|
|
259
|
+
* @param version - Optional id of the version to get (supports semver)
|
|
260
|
+
* @returns Command|Undefined
|
|
261
|
+
*/
|
|
262
|
+
? /**
|
|
263
|
+
* Returns a command from EventCatalog
|
|
264
|
+
* @param id - The id of the command to retrieve
|
|
265
|
+
* @param version - Optional id of the version to get (supports semver)
|
|
266
|
+
* @returns Command|Undefined
|
|
267
|
+
*/: string;
|
|
255
268
|
format?: "md" | "mdx";
|
|
256
269
|
override?: boolean;
|
|
257
270
|
}) => Promise<void>;
|
|
@@ -817,6 +830,14 @@ declare const _default: (path: string) => {
|
|
|
817
830
|
dumpCatalog: (options?: {
|
|
818
831
|
includeMarkdown?: boolean;
|
|
819
832
|
}) => Promise<EventCatalogObject>;
|
|
833
|
+
/**
|
|
834
|
+
* Returns the event catalog configuration file.
|
|
835
|
+
* The event catalog configuration file is the file that contains the configuration for the event catalog.
|
|
836
|
+
*
|
|
837
|
+
* @param directory - The directory of the catalog.
|
|
838
|
+
* @returns A JSON object with the configuration for the event catalog.
|
|
839
|
+
*/
|
|
840
|
+
getEventCatalogConfigurationFile: () => Promise<any>;
|
|
820
841
|
/**
|
|
821
842
|
* ================================
|
|
822
843
|
* Resources Utils
|
|
@@ -832,4 +853,4 @@ declare const _default: (path: string) => {
|
|
|
832
853
|
} | undefined>;
|
|
833
854
|
};
|
|
834
855
|
|
|
835
|
-
export { _default as default };
|
|
856
|
+
export { Channel, Command, CustomDoc, Domain, Event, Query, Service, Team, UbiquitousLanguageDictionary, User, _default as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { EventCatalogObject } from './eventcatalog.js';
|
|
2
2
|
import { Event, Command, Query, Channel, Service, Domain, UbiquitousLanguageDictionary, Team, User, CustomDoc } from './types.d.js';
|
|
3
|
+
export { Badge, BaseSchema, ChannelPointer, Message, ResourceGroup, ResourcePointer, Specifications, UbiquitousLanguage } from './types.d.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Init the SDK for EventCatalog
|
|
@@ -251,7 +252,19 @@ declare const _default: (path: string) => {
|
|
|
251
252
|
id: string;
|
|
252
253
|
version?: string;
|
|
253
254
|
}, options?: {
|
|
254
|
-
path
|
|
255
|
+
path
|
|
256
|
+
/**
|
|
257
|
+
* Returns a command from EventCatalog
|
|
258
|
+
* @param id - The id of the command to retrieve
|
|
259
|
+
* @param version - Optional id of the version to get (supports semver)
|
|
260
|
+
* @returns Command|Undefined
|
|
261
|
+
*/
|
|
262
|
+
? /**
|
|
263
|
+
* Returns a command from EventCatalog
|
|
264
|
+
* @param id - The id of the command to retrieve
|
|
265
|
+
* @param version - Optional id of the version to get (supports semver)
|
|
266
|
+
* @returns Command|Undefined
|
|
267
|
+
*/: string;
|
|
255
268
|
format?: "md" | "mdx";
|
|
256
269
|
override?: boolean;
|
|
257
270
|
}) => Promise<void>;
|
|
@@ -817,6 +830,14 @@ declare const _default: (path: string) => {
|
|
|
817
830
|
dumpCatalog: (options?: {
|
|
818
831
|
includeMarkdown?: boolean;
|
|
819
832
|
}) => Promise<EventCatalogObject>;
|
|
833
|
+
/**
|
|
834
|
+
* Returns the event catalog configuration file.
|
|
835
|
+
* The event catalog configuration file is the file that contains the configuration for the event catalog.
|
|
836
|
+
*
|
|
837
|
+
* @param directory - The directory of the catalog.
|
|
838
|
+
* @returns A JSON object with the configuration for the event catalog.
|
|
839
|
+
*/
|
|
840
|
+
getEventCatalogConfigurationFile: () => Promise<any>;
|
|
820
841
|
/**
|
|
821
842
|
* ================================
|
|
822
843
|
* Resources Utils
|
|
@@ -832,4 +853,4 @@ declare const _default: (path: string) => {
|
|
|
832
853
|
} | undefined>;
|
|
833
854
|
};
|
|
834
855
|
|
|
835
|
-
export { _default as default };
|
|
856
|
+
export { Channel, Command, CustomDoc, Domain, Event, Query, Service, Team, UbiquitousLanguageDictionary, User, _default as default };
|
package/dist/index.js
CHANGED
|
@@ -665,101 +665,14 @@ var addMessageToChannel = (directory, collection) => async (id, _message, versio
|
|
|
665
665
|
await writeMessage(pathToResource)(message, { format: extension === ".md" ? "md" : "mdx" });
|
|
666
666
|
};
|
|
667
667
|
|
|
668
|
-
// src/eventcatalog.ts
|
|
669
|
-
var import_fs = __toESM(require("fs"));
|
|
670
|
-
var import_node_path8 = __toESM(require("path"));
|
|
671
|
-
var DUMP_VERSION = "0.0.1";
|
|
672
|
-
var getEventCatalogVersion = async (catalogDir) => {
|
|
673
|
-
try {
|
|
674
|
-
const packageJson = import_fs.default.readFileSync((0, import_node_path8.join)(catalogDir, "package.json"), "utf8");
|
|
675
|
-
const packageJsonObject = JSON.parse(packageJson);
|
|
676
|
-
return packageJsonObject["dependencies"]["@eventcatalog/core"];
|
|
677
|
-
} catch (error) {
|
|
678
|
-
return "unknown";
|
|
679
|
-
}
|
|
680
|
-
};
|
|
681
|
-
var hydrateResource = async (catalogDir, resources, { attachSchema = false } = {}) => {
|
|
682
|
-
return await Promise.all(
|
|
683
|
-
resources.map(async (resource) => {
|
|
684
|
-
const resourcePath = await getResourcePath(catalogDir, resource.id, resource.version);
|
|
685
|
-
let schema = "";
|
|
686
|
-
if (resource.schemaPath && resourcePath?.fullPath) {
|
|
687
|
-
const pathToSchema = import_node_path8.default.join(import_node_path8.default.dirname(resourcePath?.fullPath), resource.schemaPath);
|
|
688
|
-
if (import_fs.default.existsSync(pathToSchema)) {
|
|
689
|
-
schema = import_fs.default.readFileSync(pathToSchema, "utf8");
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
const eventcatalog = schema ? { directory: resourcePath?.directory, schema } : { directory: resourcePath?.directory };
|
|
693
|
-
return {
|
|
694
|
-
...resource,
|
|
695
|
-
_eventcatalog: eventcatalog
|
|
696
|
-
};
|
|
697
|
-
})
|
|
698
|
-
);
|
|
699
|
-
};
|
|
700
|
-
var filterCollection = (collection, options) => {
|
|
701
|
-
return collection.map((item) => ({
|
|
702
|
-
...item,
|
|
703
|
-
markdown: options?.includeMarkdown ? item.markdown : void 0
|
|
704
|
-
}));
|
|
705
|
-
};
|
|
706
|
-
var dumpCatalog = (directory) => async (options) => {
|
|
707
|
-
const { getDomains: getDomains2, getServices: getServices2, getEvents: getEvents2, getQueries: getQueries2, getCommands: getCommands2, getChannels: getChannels2, getTeams: getTeams2, getUsers: getUsers2 } = index_default(directory);
|
|
708
|
-
const { includeMarkdown = true } = options || {};
|
|
709
|
-
const domains = await getDomains2();
|
|
710
|
-
const services = await getServices2();
|
|
711
|
-
const events = await getEvents2();
|
|
712
|
-
const commands = await getCommands2();
|
|
713
|
-
const queries = await getQueries2();
|
|
714
|
-
const teams = await getTeams2();
|
|
715
|
-
const users = await getUsers2();
|
|
716
|
-
const channels = await getChannels2();
|
|
717
|
-
const [
|
|
718
|
-
hydratedDomains,
|
|
719
|
-
hydratedServices,
|
|
720
|
-
hydratedEvents,
|
|
721
|
-
hydratedQueries,
|
|
722
|
-
hydratedCommands,
|
|
723
|
-
hydratedTeams,
|
|
724
|
-
hydratedUsers,
|
|
725
|
-
hydratedChannels
|
|
726
|
-
] = await Promise.all([
|
|
727
|
-
hydrateResource(directory, domains),
|
|
728
|
-
hydrateResource(directory, services),
|
|
729
|
-
hydrateResource(directory, events),
|
|
730
|
-
hydrateResource(directory, queries),
|
|
731
|
-
hydrateResource(directory, commands),
|
|
732
|
-
hydrateResource(directory, teams),
|
|
733
|
-
hydrateResource(directory, users),
|
|
734
|
-
hydrateResource(directory, channels)
|
|
735
|
-
]);
|
|
736
|
-
return {
|
|
737
|
-
version: DUMP_VERSION,
|
|
738
|
-
catalogVersion: await getEventCatalogVersion(directory),
|
|
739
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
740
|
-
resources: {
|
|
741
|
-
domains: filterCollection(hydratedDomains, { includeMarkdown }),
|
|
742
|
-
services: filterCollection(hydratedServices, { includeMarkdown }),
|
|
743
|
-
messages: {
|
|
744
|
-
events: filterCollection(hydratedEvents, { includeMarkdown }),
|
|
745
|
-
queries: filterCollection(hydratedQueries, { includeMarkdown }),
|
|
746
|
-
commands: filterCollection(hydratedCommands, { includeMarkdown })
|
|
747
|
-
},
|
|
748
|
-
teams: filterCollection(hydratedTeams, { includeMarkdown }),
|
|
749
|
-
users: filterCollection(hydratedUsers, { includeMarkdown }),
|
|
750
|
-
channels: filterCollection(hydratedChannels, { includeMarkdown })
|
|
751
|
-
}
|
|
752
|
-
};
|
|
753
|
-
};
|
|
754
|
-
|
|
755
668
|
// src/custom-docs.ts
|
|
756
|
-
var
|
|
669
|
+
var import_node_path8 = __toESM(require("path"));
|
|
757
670
|
var import_node_fs4 = __toESM(require("fs"));
|
|
758
671
|
var import_promises8 = __toESM(require("fs/promises"));
|
|
759
672
|
var import_gray_matter4 = __toESM(require("gray-matter"));
|
|
760
673
|
var import_slugify = __toESM(require("slugify"));
|
|
761
674
|
var getCustomDoc = (directory) => async (filePath) => {
|
|
762
|
-
const fullPath =
|
|
675
|
+
const fullPath = import_node_path8.default.join(directory, filePath);
|
|
763
676
|
const fullPathWithExtension = fullPath.endsWith(".mdx") ? fullPath : `${fullPath}.mdx`;
|
|
764
677
|
const fileExists = import_node_fs4.default.existsSync(fullPathWithExtension);
|
|
765
678
|
if (!fileExists) {
|
|
@@ -778,20 +691,20 @@ var writeCustomDoc = (directory) => async (customDoc, options = { path: "" }) =>
|
|
|
778
691
|
const { fileName, ...rest } = customDoc;
|
|
779
692
|
const name = fileName || (0, import_slugify.default)(customDoc.title, { lower: true });
|
|
780
693
|
const withExtension = name.endsWith(".mdx") ? name : `${name}.mdx`;
|
|
781
|
-
const fullPath =
|
|
782
|
-
import_node_fs4.default.mkdirSync(
|
|
694
|
+
const fullPath = import_node_path8.default.join(directory, options.path || "", withExtension);
|
|
695
|
+
import_node_fs4.default.mkdirSync(import_node_path8.default.dirname(fullPath), { recursive: true });
|
|
783
696
|
const document = import_gray_matter4.default.stringify(customDoc.markdown.trim(), rest);
|
|
784
697
|
import_node_fs4.default.writeFileSync(fullPath, document);
|
|
785
698
|
};
|
|
786
699
|
var rmCustomDoc = (directory) => async (filePath) => {
|
|
787
700
|
const withExtension = filePath.endsWith(".mdx") ? filePath : `${filePath}.mdx`;
|
|
788
|
-
await import_promises8.default.rm((0,
|
|
701
|
+
await import_promises8.default.rm((0, import_node_path8.join)(directory, withExtension), { recursive: true });
|
|
789
702
|
};
|
|
790
703
|
|
|
791
704
|
// src/teams.ts
|
|
792
705
|
var import_promises9 = __toESM(require("fs/promises"));
|
|
793
706
|
var import_node_fs5 = __toESM(require("fs"));
|
|
794
|
-
var
|
|
707
|
+
var import_node_path9 = require("path");
|
|
795
708
|
var import_gray_matter5 = __toESM(require("gray-matter"));
|
|
796
709
|
var getTeam = (catalogDir) => async (id) => {
|
|
797
710
|
const files = await getFiles(`${catalogDir}/${id}.{md,mdx}`);
|
|
@@ -827,16 +740,16 @@ var writeTeam = (catalogDir) => async (team, options = {}) => {
|
|
|
827
740
|
}
|
|
828
741
|
const { markdown, ...frontmatter } = resource;
|
|
829
742
|
const document = import_gray_matter5.default.stringify(markdown, frontmatter);
|
|
830
|
-
import_node_fs5.default.mkdirSync((0,
|
|
831
|
-
import_node_fs5.default.writeFileSync((0,
|
|
743
|
+
import_node_fs5.default.mkdirSync((0, import_node_path9.join)(catalogDir, ""), { recursive: true });
|
|
744
|
+
import_node_fs5.default.writeFileSync((0, import_node_path9.join)(catalogDir, "", `${resource.id}.mdx`), document);
|
|
832
745
|
};
|
|
833
746
|
var rmTeamById = (catalogDir) => async (id) => {
|
|
834
|
-
await import_promises9.default.rm((0,
|
|
747
|
+
await import_promises9.default.rm((0, import_node_path9.join)(catalogDir, `${id}.mdx`), { recursive: true });
|
|
835
748
|
};
|
|
836
749
|
|
|
837
750
|
// src/users.ts
|
|
838
751
|
var import_node_fs6 = __toESM(require("fs"));
|
|
839
|
-
var
|
|
752
|
+
var import_node_path10 = require("path");
|
|
840
753
|
var import_gray_matter6 = __toESM(require("gray-matter"));
|
|
841
754
|
var getUser = (catalogDir) => async (id) => {
|
|
842
755
|
const files = await getFiles(`${catalogDir}/${id}.{md,mdx}`);
|
|
@@ -874,11 +787,108 @@ var writeUser = (catalogDir) => async (user, options = {}) => {
|
|
|
874
787
|
}
|
|
875
788
|
const { markdown, ...frontmatter } = resource;
|
|
876
789
|
const document = import_gray_matter6.default.stringify(markdown, frontmatter);
|
|
877
|
-
import_node_fs6.default.mkdirSync((0,
|
|
878
|
-
import_node_fs6.default.writeFileSync((0,
|
|
790
|
+
import_node_fs6.default.mkdirSync((0, import_node_path10.join)(catalogDir, ""), { recursive: true });
|
|
791
|
+
import_node_fs6.default.writeFileSync((0, import_node_path10.join)(catalogDir, "", `${resource.id}.mdx`), document);
|
|
879
792
|
};
|
|
880
793
|
var rmUserById = (catalogDir) => async (id) => {
|
|
881
|
-
import_node_fs6.default.rmSync((0,
|
|
794
|
+
import_node_fs6.default.rmSync((0, import_node_path10.join)(catalogDir, `${id}.mdx`), { recursive: true });
|
|
795
|
+
};
|
|
796
|
+
|
|
797
|
+
// src/eventcatalog.ts
|
|
798
|
+
var import_fs = __toESM(require("fs"));
|
|
799
|
+
var import_node_path11 = __toESM(require("path"));
|
|
800
|
+
var DUMP_VERSION = "0.0.1";
|
|
801
|
+
var getEventCatalogVersion = async (catalogDir) => {
|
|
802
|
+
try {
|
|
803
|
+
const packageJson = import_fs.default.readFileSync((0, import_node_path11.join)(catalogDir, "package.json"), "utf8");
|
|
804
|
+
const packageJsonObject = JSON.parse(packageJson);
|
|
805
|
+
return packageJsonObject["dependencies"]["@eventcatalog/core"];
|
|
806
|
+
} catch (error) {
|
|
807
|
+
return "unknown";
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
var hydrateResource = async (catalogDir, resources, { attachSchema = false } = {}) => {
|
|
811
|
+
return await Promise.all(
|
|
812
|
+
resources.map(async (resource) => {
|
|
813
|
+
const resourcePath = await getResourcePath(catalogDir, resource.id, resource.version);
|
|
814
|
+
let schema = "";
|
|
815
|
+
if (resource.schemaPath && resourcePath?.fullPath) {
|
|
816
|
+
const pathToSchema = import_node_path11.default.join(import_node_path11.default.dirname(resourcePath?.fullPath), resource.schemaPath);
|
|
817
|
+
if (import_fs.default.existsSync(pathToSchema)) {
|
|
818
|
+
schema = import_fs.default.readFileSync(pathToSchema, "utf8");
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
const eventcatalog = schema ? { directory: resourcePath?.directory, schema } : { directory: resourcePath?.directory };
|
|
822
|
+
return {
|
|
823
|
+
...resource,
|
|
824
|
+
_eventcatalog: eventcatalog
|
|
825
|
+
};
|
|
826
|
+
})
|
|
827
|
+
);
|
|
828
|
+
};
|
|
829
|
+
var filterCollection = (collection, options) => {
|
|
830
|
+
return collection.map((item) => ({
|
|
831
|
+
...item,
|
|
832
|
+
markdown: options?.includeMarkdown ? item.markdown : void 0
|
|
833
|
+
}));
|
|
834
|
+
};
|
|
835
|
+
var getEventCatalogConfigurationFile = (directory) => async () => {
|
|
836
|
+
try {
|
|
837
|
+
const path4 = (0, import_node_path11.join)(directory, "eventcatalog.config.js");
|
|
838
|
+
const configModule = await import(path4);
|
|
839
|
+
return configModule.default;
|
|
840
|
+
} catch (error) {
|
|
841
|
+
console.error("Error getting event catalog configuration file", error);
|
|
842
|
+
return null;
|
|
843
|
+
}
|
|
844
|
+
};
|
|
845
|
+
var dumpCatalog = (directory) => async (options) => {
|
|
846
|
+
const { getDomains: getDomains2, getServices: getServices2, getEvents: getEvents2, getQueries: getQueries2, getCommands: getCommands2, getChannels: getChannels2, getTeams: getTeams2, getUsers: getUsers2 } = index_default(directory);
|
|
847
|
+
const { includeMarkdown = true } = options || {};
|
|
848
|
+
const domains = await getDomains2();
|
|
849
|
+
const services = await getServices2();
|
|
850
|
+
const events = await getEvents2();
|
|
851
|
+
const commands = await getCommands2();
|
|
852
|
+
const queries = await getQueries2();
|
|
853
|
+
const teams = await getTeams2();
|
|
854
|
+
const users = await getUsers2();
|
|
855
|
+
const channels = await getChannels2();
|
|
856
|
+
const [
|
|
857
|
+
hydratedDomains,
|
|
858
|
+
hydratedServices,
|
|
859
|
+
hydratedEvents,
|
|
860
|
+
hydratedQueries,
|
|
861
|
+
hydratedCommands,
|
|
862
|
+
hydratedTeams,
|
|
863
|
+
hydratedUsers,
|
|
864
|
+
hydratedChannels
|
|
865
|
+
] = await Promise.all([
|
|
866
|
+
hydrateResource(directory, domains),
|
|
867
|
+
hydrateResource(directory, services),
|
|
868
|
+
hydrateResource(directory, events),
|
|
869
|
+
hydrateResource(directory, queries),
|
|
870
|
+
hydrateResource(directory, commands),
|
|
871
|
+
hydrateResource(directory, teams),
|
|
872
|
+
hydrateResource(directory, users),
|
|
873
|
+
hydrateResource(directory, channels)
|
|
874
|
+
]);
|
|
875
|
+
return {
|
|
876
|
+
version: DUMP_VERSION,
|
|
877
|
+
catalogVersion: await getEventCatalogVersion(directory),
|
|
878
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
879
|
+
resources: {
|
|
880
|
+
domains: filterCollection(hydratedDomains, { includeMarkdown }),
|
|
881
|
+
services: filterCollection(hydratedServices, { includeMarkdown }),
|
|
882
|
+
messages: {
|
|
883
|
+
events: filterCollection(hydratedEvents, { includeMarkdown }),
|
|
884
|
+
queries: filterCollection(hydratedQueries, { includeMarkdown }),
|
|
885
|
+
commands: filterCollection(hydratedCommands, { includeMarkdown })
|
|
886
|
+
},
|
|
887
|
+
teams: filterCollection(hydratedTeams, { includeMarkdown }),
|
|
888
|
+
users: filterCollection(hydratedUsers, { includeMarkdown }),
|
|
889
|
+
channels: filterCollection(hydratedChannels, { includeMarkdown })
|
|
890
|
+
}
|
|
891
|
+
};
|
|
882
892
|
};
|
|
883
893
|
|
|
884
894
|
// src/index.ts
|
|
@@ -1544,6 +1554,14 @@ var index_default = (path4) => {
|
|
|
1544
1554
|
* @returns A JSON file with the catalog
|
|
1545
1555
|
*/
|
|
1546
1556
|
dumpCatalog: dumpCatalog((0, import_node_path12.join)(path4)),
|
|
1557
|
+
/**
|
|
1558
|
+
* Returns the event catalog configuration file.
|
|
1559
|
+
* The event catalog configuration file is the file that contains the configuration for the event catalog.
|
|
1560
|
+
*
|
|
1561
|
+
* @param directory - The directory of the catalog.
|
|
1562
|
+
* @returns A JSON object with the configuration for the event catalog.
|
|
1563
|
+
*/
|
|
1564
|
+
getEventCatalogConfigurationFile: getEventCatalogConfigurationFile((0, import_node_path12.join)(path4)),
|
|
1547
1565
|
/**
|
|
1548
1566
|
* ================================
|
|
1549
1567
|
* Resources Utils
|