SPM: loading resources from second common module - resources

i'm encountering an issue that makes me crazy. Dunno if there's a solution available :D
I have a main apps that imports a lot of local SPM modules; some of them are considered base common models, imported by other modules (e.g.
Module1 is a base module with common resources for Module2 and Module3).
Unfortunately when i import all the modules, all the resources inside the Module1 seems not loaded (not found!) correctly.
Module1 (common model)
targets: [
.target(name: Module1,
dependencies: [],
resources: [
.process("Resources")
]),
Module2
targets: [
.target(name: Module2,
dependencies: [
.byName(name: Module1),
],
resources: [
.process("Resources")
]),
Module3
targets: [
.target(name: Module3,
dependencies: [
.byName(name: Module1),
],
resources: [
.process("Resources")
]),
Example of errors i'm encountering:
Calls from main app (.workspace) with imported SPM Module1, 2, 3.
Bundle.module.path(forResource: <xib file in Module1>, ofType: "nib") => nil
Bundle.module.loadNibNamed(<xib file in Module1>, owner: self, options: nil)?.first as? UIView => nil
Do you have any idea how to load correctly all the dependencies?

Related

Bundle NPM Package so it has different import paths with Vite and Typescript

How can I bundle my NPM package in a way that I can have different import paths for different parts of the package? I have found webpack approaches, but I am using Vite and TS.
My package looks like this:
- src
- atoms
- molecules
- organism
- index.ts (currently simply imports and exports everything)
Now I can use this currently like this
import { Button } from '#mypackage/library'
How can I do it, so I get this outcome:
import { Button } from '#mypackage/library/atom'
Here is the relevant part of my package.json
{
"entry": "src/index.ts",
"main": "dist/index.cjs.js",
"module": "dist/index.es.js",
"types": "dist/index.d.ts",
"files": [
"dist",
"src"
],
"exports": {
".": {
"import": "./dist/index.es.js",
"require": "./dist/index.cjs.js",
"types": "./dist/index.d.ts"
},
"./package.json": "./package.json",
"./atoms": "./src/atoms/index.ts",
"./molecules": "./src/molecules/index.ts",
"./organisms": "./src/organisms/index.ts",
"./theme": "./src/theme/index.ts"
},
}
Here is my vite.config.ts
export default defineConfig({
build: {
lib: {
entry: path.resolve(__dirname, 'src/index.ts'),
formats: ['es', 'cjs'],
name: '#workdigtital/component-library-react',
fileName: (format) => `index.${format}.js`
},
rollupOptions: {
external: ['react', 'react-dom'],
output: {
globals: {
react: 'React',
'react-dom': 'ReactDOM'
},
exports: 'named'
}
}
},
plugins: [react(), dts({ insertTypesEntry: true })],
resolve: {
alias: {
'#': path.resolve(__dirname, './src')
}
}
});
If I currently try an import like this, inside another project (Laravel+React), in which installed the library.
import { ThemeProvider } from '#workdigital/component-library-react/theme';
I get the following run time error (But no Typescript errors, even IntelliSense is working):
Failed to load url /resources/js/theme/ThemeProvider (resolved id: /resources/js/theme/ThemeProvider). Does the file exist?
My resulting Dist folder looks like this:
You can't have TypeScript exports, this simply won't work. An npm package should have only JS exports.
If you want to be able to selectively import different parts of your package, you must transpile them to different files.
rollup can do it, but it is lots of work, as you will have to set up a separate target for each exported file. Normally you use rollup to create a single bundle, this what this tool is made for.
tsc with a tsconfig.json will be a much better choice in your case. It does this by default, you only need to specify the output directory and it will produce a separate file for each source.
There is an excellent guide on the TypeScript site about packaging TypeScript libraries, you should probably start there.

Nest can't resolve dependency, but it's definitely there

I have a weird behaviour. Nest is complaining about a missing dependency in a service, but only if that service is Injected by multiple other services
cleaning.module.ts
#Module({
imports: [
//Just a few repos
],
providers: [
ServicesService,
...
AreasService,
RoomsService,
...
],
controllers: [
...
],
exports: [
ServicesService,
...
AreasService,
RoomsService,
...
]})
services.module.ts, areas.module.ts and rooms.module.ts are basically the same
#Module({
imports: [CleaningModule],
providers: [],
controllers: [],
exports: []
})
rooms.service.ts
constructor(#InjectRepository(Room) private readonly repo: Repository<Room>, private areasService: AreasService) { }
services.service.ts
constructor(#InjectRepository(Service) private readonly repo: Repository<Service>, ... private roomsService: RoomsService) { }
With this, I get the following error:
ERROR [ExceptionHandler] Nest can't resolve dependencies of the RoomsService (RoomRepository, ?). Please make sure that the argument dependency at index [1] is available in the CleaningModule context.
So, it's missing AreasService somehow. Which is clearly provided by the CleaningModule.
But the weird thing is, if I remove the injection of the RoomsService in the ServicesService constructor, then everything works just fine. And I don't have the slightest idea why this is the case...
Based on the error it seems like you have a circular file import going on from your roo.service.ts to your area.service.ts. This could be several files deep like room.service.ts imports area.service.ts that another that imports another that imports another that finally imports room.service.ts again or it could be the use of barrel files. If this truly is a circular dependency (room uses area which uses room) then you need to use #Inject(forwardRef(() => OtherService)). Otherwise, you need to figure out a way to avoid the circular import

Loading a static file in Angular during build

I'm want to load the contents of a file and inject it as a string in TypeScript at build time. I understand that this code would ordinarily be server code, but what I want is to have a build step that reads the file and injects its contents as a string.
import { readFileSync } from 'fs';
import { Component } from '#angular/core';
#Component({
template: `<pre>${readFileSync('./example.code')}</pre>`
})
export class ExampleComponent { }
Assuming example.code just has "Hello World" I would want this file to be built as:
template: `<pre>"Hello World"</pre>`
I have found babel-plugin-static-fs which I think should allow me to do this, but I was originally using ng (angular-cli) to build the project. I have done ng eject and updated webpack:
module: {
rules: [
/* snip */
{
"test": /\.ts$/,
"use": [
{
loader: "babel-loader",
options: {
plugins: ['babel-plugin-static-fs']
}
},
{
"loader": "#ngtools/webpack"
}, ] } ] }
However, when I run webpack, I still get
Cannot find module 'fs'
If I reverse the order of the loaders, it seems like babael does not like the # used in may annotations such as the #Component above so that loader does not work.
Is there any way to load a file as static content during an Angular project build?
The issue here is actually related to the tsconfig.app.json file that Angular creates and uses for AoT. This is separate from the tsconfig.json used to actually build the project which does load #types/node as expected.
If you've created a project with ng new, you can change tsconfig.app.json:
- "types": [],
+ "types": ["node"],
This will have the AoT compiler use the type definitions from #types/node.

Confused between modules and bundles property in RequireJS / r.js build files

I am very confused at to what the difference is between the "bundles" property and the "modules" property in a r.js build file that might look something like:
({
"allowSourceOverwrites": false,
"preserveLicenseComments": false,
"findNestedDependencies": false,
"optimizeAllPluginResources": true,
"dir":"../public/bundles",
"baseUrl": "../public/static",
"optimize":"none",
"mainConfigFile": "../public/static/app/js/main.js",
"normalizeDirDefines": "all",
"paths" :{
requireLib : 'vendor/require',
jqueryUI: "empty:",
jqueryUICSS: "empty:"
},
"modules": [
{
name: "shared",
include: [
'jquery',
'async',
'backbone'
],
exclude:[]
}
],
"bundles": {
'shared': [],
'secondary': []
},
"stubModules":['text']
})
I am having a lot of trouble finding good information on how to create multiple bundles for a RequireJS project. When I just use the modules property and eliminate the bundles property, r.js goes looking for a file called shared.js - and I am not sure why.
r.js creates bundles, but the bundles option is not an option that r.js recognizes. If you look in the file that lists all r.js options, you won't find bundles there. If you remove it from your configuration, you'll get the same behavior.
When I just use the modules property and eliminate the bundles property, r.js goes looking for a file called shared.js - and I am not sure why.
r.js looks for shared.js because your modules specifies a module named "shared". r.js will do this unless you tell it that you want to create this module from scratch, and you do this by adding the create: true option to this module's build configuration:
"modules": [
{
name: "shared",
create: true, // <<<--- add this!
include: [
'jquery',
'async',
'backbone'
],
exclude:[]
}
],

Exclude all starting with x in requirejs module

I am "compiling" some files into one requirejs module. I have a configuration like this:
paths:
lib : "../lib"
angular: "../lib/angular"
modules: [
{
name : 'myApp'
exclude: ["lib/jquery", "lib/angular"]
}
]
(syntax is cofeescript)
I want to exclude all files located under "lib" (e.g. starting with lib/) in "myApp" module. I now I can write them one another one like this: ["lib/jquery", "lib/angular"] But more libs and modules will be added in the future so some kind of automatization would be nice.
Is there any way to tell require js that "everything under lib should be excluded on myApp module"? Somethink like this:
modules: [
{
name : 'myApp'
exclude: ["lib/*"]
}
]
I don't know of a wildcard syntax, but you can define the list of excluded files as their own module, and then exclude them by name in all future modules.
Sorry, don't speak coffeescript:
modules: [
{
name: 'core',
include: [ 'lib/jquery', 'lib/angular', 'lib/somethingelse' ]
},
{
name: 'module1',
exclude: [ 'core' ]
},
{
name: 'module2',
exclude: [ 'core' ]
}
]

Resources